; Documentation for the ACL2 Theorem Prover ; WARNING: GENERATED FILE, DO NOT HAND EDIT! ; The contents of this file are derived from ACL2 Community Book ; books/system/doc/acl2-doc.lisp. ; ACL2 Version 7.1 -- A Computational Logic for Applicative Common Lisp ; Copyright (C) 2015, Regents of the University of Texas ; This version of ACL2 is a descendent of ACL2 Version 1.9, Copyright ; (C) 1997 Computational Logic, Inc. See the documentation topic NOTE-2-0. ; This program is free software; you can redistribute it and/or modify ; it under the terms of the LICENSE file distributed with ACL2. ; 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 ; LICENSE for more details. ; Here are the original authors of books/system/doc/acl2-doc.lisp. ; Additional contributions may have been made to that file by members ; of the ACL2 community. ; Written by: Matt Kaufmann and J Strother Moore ; email: Kaufmann@cs.utexas.edu and Moore@cs.utexas.edu ; Department of Computer Science ; University of Texas at Austin ; Austin, TX 78701 U.S.A. ; WARNING: This file is generated from ACL2 Community Book ; books/system/doc/acl2-doc.lisp. To edit ACL2 documentation modify ; that file, not this one! Instructions are just above the in-package ; form in that book. (in-package "ACL2") (defconst *acl2-system-documentation* ' ((&ALLOW-OTHER-KEYS (POINTERS) "See [macro-args].") (&BODY (POINTERS) "See [macro-args].") (&KEY (POINTERS) "See [macro-args].") (&OPTIONAL (POINTERS) "See [macro-args].") (&REST (POINTERS) "See [macro-args].") (&WHOLE (POINTERS) "See [macro-args].") (* (NUMBERS ACL2-BUILT-INS) "Multiplication macro * is really a macro that expands to calls of the function [binary-*]. So for example (* x y 4 z) represents the same term as (binary-* x (binary-* y (binary-* 4 z))). See [binary-*]. * is a Common Lisp function. See any Common Lisp documentation for more information. Subtopics [Binary-*] Multiplication function") (*ACL2-EXPORTS* (PACKAGES ACL2-BUILT-INS) "Symbols that are often imported into new [packages] to provide easy access to ACL2 functionality. When you define a new package for your own work with [defpkg], you will usually want to import many symbols from the \"ACL2\" package; for instance you will usually want to be able to use symbols like [defthm], [in-theory], [xargs], [state], etc., without an acl2:: prefix. The constant *acl2-exports* lists 1325 symbols, including most documented ACL2 system constants, functions, and macros. You will typically also want to import many symbols from Common Lisp; see [*common-lisp-symbols-from-main-lisp-package*]. (& &allow-other-keys &aux &body &key &optional &rest &whole * *acl2-exports* *common-lisp-specials-and-constants* *common-lisp-symbols-from-main-lisp-package* *main-lisp-package-name* *standard-chars* *standard-ci* *standard-co* *standard-oi* + - / /= 1+ 1- 32-bit-integer-listp 32-bit-integer-listp-forward-to-integer-listp 32-bit-integer-stack 32-bit-integer-stack-length 32-bit-integer-stack-length1 32-bit-integerp 32-bit-integerp-forward-to-integerp < <-on-others <= = > >= ?-fn @ a! abort! abs accumulated-persistence acl2-count acl2-input-channel-package acl2-number-listp acl2-numberp acl2-oracle acl2-output-channel-package acl2-package acons active-runep add-binop add-custom-keyword-hint add-default-hints add-default-hints! add-include-book-dir add-include-book-dir! add-invisible-fns add-ld-keyword-alias add-ld-keyword-alias! add-macro-alias add-macro-fn add-match-free-override add-nth-alias add-override-hints add-override-hints! add-pair add-pair-preserves-all-boundp add-raw-arity add-timers add-to-set add-to-set-eq add-to-set-eql add-to-set-equal alistp alistp-forward-to-true-listp all-boundp all-boundp-preserves-assoc all-vars all-vars1 all-vars1-lst allocate-fixnum-range alpha-char-p alpha-char-p-forward-to-characterp alphorder and and-macro append aref-32-bit-integer-stack aref-t-stack aref1 aref2 args array1p array1p-cons array1p-forward array1p-linear array2p array2p-cons array2p-forward array2p-linear aset-32-bit-integer-stack aset-t-stack aset1 aset2 ash assert$ assert-event assign assoc assoc-add-pair assoc-eq assoc-eq-equal assoc-eq-equal-alistp assoc-equal assoc-keyword assoc-string-equal assoc2 associativity-of-* associativity-of-+ assume atom atom-listp atom-listp-forward-to-true-listp backchain-limit big-clock-entry big-clock-negative-p binary-* binary-+ binary-append bind-free bit boole$ boolean-listp boolean-listp-cons boolean-listp-forward boolean-listp-forward-to-symbol-listp booleanp booleanp-characterp booleanp-compound-recognizer bounded-integer-alistp bounded-integer-alistp-forward-to-eqlable-alistp bounded-integer-alistp2 boundp-global boundp-global1 break$ break-on-error brr brr@ build-state1 butlast caaaar caaadr caaar caadar caaddr caadr caar cadaar cadadr cadar caddar cadddr caddr cadr canonical-pathname car car-cdr-elim car-cons case case-list case-list-check case-match case-split case-split-limitations case-test cbd cdaaar cdaadr cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar cdddar cddddr cdddr cddr cdr cdr-cons cdrn ceiling certify-book certify-book! char char-code char-code-code-char-is-identity char-code-linear char-downcase char-equal char-upcase char< char<= char> char>= character character-alistp character-listp character-listp-append character-listp-coerce character-listp-forward-to-eqlable-listp character-listp-remove-duplicates-eql character-listp-revappend character-listp-string-downcase-1 character-listp-string-upcase1-1 characterp characterp-char-downcase characterp-char-upcase characterp-nth characterp-page characterp-rubout characterp-tab check-vars-not-free checkpoint-forced-goals clause clear-hash-tables clear-memoize-statistics clear-memoize-table clear-memoize-tables close-input-channel close-output-channel close-trace-file closure code-char code-char-char-code-is-identity code-char-type coerce coerce-inverse-1 coerce-inverse-2 coerce-object-to-state coerce-state-to-object community-books commutativity-of-* commutativity-of-+ comp completion-of-* completion-of-+ completion-of-< completion-of-car completion-of-cdr completion-of-char-code completion-of-code-char completion-of-coerce completion-of-complex completion-of-denominator completion-of-imagpart completion-of-intern-in-package-of-symbol completion-of-numerator completion-of-realpart completion-of-symbol-name completion-of-symbol-package-name completion-of-unary-/ completion-of-unary-minus complex complex-0 complex-definition complex-equal complex-implies1 complex-rationalp complex/complex-rationalp compress1 compress11 compress2 compress21 compress211 concatenate cond cond-clausesp cond-macro conjugate cons cons-equal cons-subtrees consp consp-assoc-equal corollary cpu-core-count ctx current-package current-theory cw cw! cw-gstack declare decrement-big-clock defabbrev defabsstobj defabsstobj-missing-events defattach default default-*-1 default-*-2 default-+-1 default-+-2 default-<-1 default-<-2 default-backchain-limit default-car default-cdr default-char-code default-coerce-1 default-coerce-2 default-coerce-3 default-compile-fns default-complex-1 default-complex-2 default-defun-mode default-defun-mode-from-state default-denominator default-hints default-imagpart default-measure-function default-numerator default-print-prompt default-realpart default-ruler-extenders default-symbol-name default-symbol-package-name default-total-parallelism-work-limit default-unary-/ default-unary-minus default-verify-guards-eagerness default-well-founded-relation defaxiom defchoose defcong defconst defdoc defequiv defevaluator defexec define-pc-atomic-macro define-pc-help define-pc-macro define-pc-meta define-trusted-clause-processor deflabel deflock defmacro defmacro-last defn defnd defpkg defproxy defrefinement defstobj defstub deftheory deftheory-static defthm defthm-std defthmd defttag defun defun-inline defun-notinline defun-nx defun-sk defun-std defund defund-inline defund-notinline defund-nx defuns defuns-std delete-assoc delete-assoc-eq delete-assoc-equal delete-include-book-dir delete-include-book-dir! denominator digit-char-p digit-to-char dimensions disable disable-forcing disable-immediate-force-modep disabledp disassemble$ distributivity dmr-start dmr-stop doc doc! docs double-rewrite duplicates e/d e0-ord-< e0-ordinalp ec-call eighth eliminate-destructors eliminate-irrelevance enable enable-forcing enable-immediate-force-modep encapsulate endp eq eql eqlable-alistp eqlable-alistp-forward-to-alistp eqlable-listp eqlable-listp-forward-to-atom-listp eqlablep eqlablep-recog equal equal-char-code er er-progn er-progn-fn er-progn-fn@par er-progn@par evenp evens event evisc-tuple executable-counterpart-theory exit explode-atom explode-nonnegative-integer expt expt-type-prescription-non-zero-base extend-32-bit-integer-stack extend-t-stack extend-world extra-info f-get-global f-put-global fast-alist-clean fast-alist-clean! fast-alist-fork fast-alist-fork! fast-alist-free fast-alist-free-on-exit fast-alist-len fast-alist-summary fc-report fertilize fgetprop fifth file-clock file-clock-p file-clock-p-forward-to-integerp finalize-event-user first first-n-ac fix fix-true-list flet floor flush-compress flush-hons-get-hash-table-link fms fms! fms!-to-string fms-to-string fmt fmt! fmt!-to-string fmt-to-comment-window fmt-to-string fmt1 fmt1! fmt1!-to-string fmt1-to-string fncall-term force fourth function-symbolp function-theory gag-mode gc$ gc-verbose gcs generalize get-command-sequence get-global get-output-stream-string$ get-slow-alist-action get-timer get-wormhole-status getenv$ getprop getprop-default getprops getprops1 global-table global-table-cars global-table-cars1 global-val good-atom-listp good-bye granularity ground-zero guard guard-obligation hard-error has-propsp has-propsp1 header help hide hist hons hons-acons hons-acons! hons-assoc-equal hons-clear hons-clear! hons-copy hons-copy-persistent hons-equal hons-equal-lite hons-get hons-resize hons-resize-fn hons-shrink-alist hons-shrink-alist! hons-summary hons-wash hons-wash! i-am-here i-close i-large i-limited i-small id idates identity if if* iff iff-implies-equal-implies-1 iff-implies-equal-implies-2 iff-implies-equal-not iff-is-an-equivalence ifix ignore illegal imagpart imagpart-complex immediate-force-modep implies improper-consp in-arithmetic-theory in-package in-tau-intervalp in-theory include-book incompatible increment-timer induct initialize-event-user int= integer integer-0 integer-1 integer-abs integer-implies-rational integer-length integer-listp integer-listp-forward-to-rational-listp integer-step integerp intern intern$ intern-in-package-of-symbol intern-in-package-of-symbol-symbol-name intersection$ intersection-eq intersection-equal intersection-theories intersectp intersectp-eq intersectp-equal inverse-of-* inverse-of-+ invisible-fns-table keyword-package keyword-value-listp keyword-value-listp-assoc-keyword keyword-value-listp-forward-to-true-listp keywordp keywordp-forward-to-symbolp known-package-alist known-package-alistp known-package-alistp-forward-to-true-list-listp-and-alistp kwote kwote-lst lambda last last-prover-steps ld ld-error-action ld-error-triples ld-evisc-tuple ld-keyword-aliases ld-missing-input-ok ld-post-eval-print ld-pre-eval-filter ld-pre-eval-print ld-prompt ld-query-control-alist ld-redefinition-action ld-skip-proofsp ld-verbose legal-case-clausesp len len-update-nth length let* lexorder list list* list*-macro list-all-package-names list-all-package-names-lst list-macro listp local logand logandc1 logandc2 logbitp logcount logeqv logic logior lognand lognor lognot logorc1 logorc2 logtest logxor lower-case-p lower-case-p-char-downcase lower-case-p-forward-to-alpha-char-p lowest-terms lp macro-aliases macro-args main-timer main-timer-type-prescription make-character-list make-character-list-make-character-list make-event make-fast-alist make-fmt-bindings make-input-channel make-list make-list-ac make-mv-nths make-ord make-output-channel make-tau-interval make-var-lst make-var-lst1 make-wormhole-status makunbound-global max maximum-length may-need-slashes mbe mbt member member-eq member-equal member-symbol-name memoize memoize-summary memsum meta-extract-contextual-fact meta-extract-formula meta-extract-global-fact meta-extract-global-fact+ meta-extract-rw+-term mfc min minimal-theory minusp mod mod-expt monitor monitored-runes more more! more-doc msg must-be-equal mutual-recursion mutual-recursion-guardp mv mv-let mv-list mv-nth mv? mv?-let nat-listp natp needs-slashes never-memoize newline nfix nil nil-is-not-circular ninth no-duplicatesp no-duplicatesp-eq no-duplicatesp-equal non-exec nonnegative-integer-quotient nonnegative-product nonzero-imagpart not nqthm-to-acl2 nth nth-0-cons nth-0-read-run-time-type-prescription nth-add1 nth-aliases nth-update-nth nthcdr null number-subtrees numerator o-finp o-first-coeff o-first-expt o-infp o-p o-rst o< o<= o> o>= observation observation-cw oddp odds ok-if oops open-channel-listp open-channel1 open-channel1-forward-to-true-listp-and-consp open-channels-p open-channels-p-forward open-input-channel open-input-channel-any-p open-input-channel-any-p1 open-input-channel-p open-input-channel-p1 open-input-channels open-output-channel open-output-channel! open-output-channel-any-p open-output-channel-any-p1 open-output-channel-p open-output-channel-p1 open-output-channels open-trace-file or or-macro oracle-apply oracle-apply-raw oracle-funcall ordered-symbol-alistp ordered-symbol-alistp-add-pair ordered-symbol-alistp-add-pair-forward ordered-symbol-alistp-delete-assoc-eq ordered-symbol-alistp-forward-to-symbol-alistp ordered-symbol-alistp-getprops otherwise our-digit-char-p override-hints p! pairlis$ pairlis2 pand pargs pbt pc pcb pcb! pcs pe pe! peek-char$ pf pkg-imports pkg-witness pl pl2 plet plist-worldp plist-worldp-forward-to-assoc-eq-equal-alistp plusp pointers pop-timer por position position-ac position-eq position-eq-ac position-equal position-equal-ac positive posp power-eval pprogn pr pr! preprocess prin1$ prin1-with-slashes prin1-with-slashes1 princ$ print-gv print-object$ print-object$-ser print-rational-as-decimal print-timer profile prog2$ progn progn! progn$ program proof-tree proofs-co proper-consp props prove pseudo-term-listp pseudo-term-listp-forward-to-true-listp pseudo-termp pso pso! psof psog pspv pstack puff puff* push-timer push-untouchable put-assoc put-assoc-eq put-assoc-eql put-assoc-equal put-global putprop quick-and-dirty-subsumption-replacement-step quit quote quotep r-eqlable-alistp r-symbol-alistp random$ rassoc rassoc-eq rassoc-equal ratio rational rational-implies1 rational-implies2 rational-listp rational-listp-forward-to-true-listp rationalp rationalp-* rationalp-+ rationalp-expt-type-prescription rationalp-implies-acl2-numberp rationalp-unary-- rationalp-unary-/ read-acl2-oracle read-acl2-oracle-preserves-state-p1 read-byte$ read-char$ read-file-listp read-file-listp-forward-to-true-list-listp read-file-listp1 read-file-listp1-forward-to-true-listp-and-consp read-files read-files-p read-files-p-forward-to-read-file-listp read-idate read-object read-run-time read-run-time-preserves-state-p1 readable-file readable-file-forward-to-true-listp-and-consp readable-files readable-files-listp readable-files-listp-forward-to-true-list-listp-and-alistp readable-files-p readable-files-p-forward-to-readable-files-listp real-listp real/rationalp realfix realpart realpart-complex realpart-imagpart-elim rebuild redef redef! redef+ redef- redo-flat regenerate-tau-database rem remove remove-binop remove-custom-keyword-hint remove-default-hints remove-default-hints! remove-duplicates remove-duplicates-eq remove-duplicates-eql remove-duplicates-equal remove-eq remove-equal remove-invisible-fns remove-macro-alias remove-macro-fn remove-nth-alias remove-override-hints remove-override-hints! remove-raw-arity remove-untouchable remove1 remove1-eq remove1-equal reset-fc-reporting reset-kill-ring reset-ld-specials reset-prehistory reset-print-control resize-list rest restore-memoization-settings retract-world retrieve return-last return-last-table revappend reverse rewrite-stack-limit rfix round satisfies save-and-clear-memoization-settings save-exec search second serialize-read serialize-write set-absstobj-debug set-accumulated-persistence set-backchain-limit set-body set-bogus-defun-hints-ok set-bogus-mutual-recursion-ok set-case-split-limitations set-cbd set-checkpoint-summary-limit set-compile-fns set-compiler-enabled set-debugger-enable set-default-backchain-limit set-default-hints set-default-hints! set-deferred-ttag-notes set-difference$ set-difference-eq set-difference-equal set-difference-theories set-enforce-redundancy set-equalp-equal set-evisc-tuple set-fc-criteria set-fc-report-on-the-fly set-fmt-hard-right-margin set-fmt-soft-right-margin set-gag-mode set-guard-checking set-ignore-ok set-inhibit-output-lst set-inhibit-warnings set-inhibit-warnings! set-inhibited-summary-types set-invisible-fns-table set-iprint set-irrelevant-formals-ok set-ld-keyword-aliases set-ld-keyword-aliases! set-ld-redefinition-action set-ld-skip-proofs set-ld-skip-proofsp set-let*-abstraction set-let*-abstractionp set-match-free-default set-match-free-error set-measure-function set-non-linear set-non-linearp set-override-hints set-override-hints! set-parallel-execution set-print-base set-print-case set-print-circle set-print-clause-ids set-print-escape set-print-length set-print-level set-print-lines set-print-radix set-print-readably set-print-right-margin set-prover-step-limit set-raw-mode set-raw-mode-on! set-raw-proof-format set-rewrite-stack-limit set-ruler-extenders set-rw-cache-state set-rw-cache-state! set-saved-output set-serialize-character set-slow-alist-action set-splitter-output set-state-ok set-tau-auto-mode set-timer set-total-parallelism-work-limit set-total-parallelism-work-limit-error set-trace-evisc-tuple set-verify-guards-eagerness set-w set-waterfall-parallelism set-waterfall-parallelism-hacks-enabled set-waterfall-parallelism-hacks-enabled! set-waterfall-printing set-well-founded-relation set-wormhole-data set-wormhole-entry-code set-write-acl2x setenv$ seventh sgetprop show-accumulated-persistence show-bdd show-bodies show-custom-keyword-hint-expansion show-fc-criteria shrink-32-bit-integer-stack shrink-t-stack signed-byte signed-byte-p signum simplify sixth skip-proofs some-slashable spec-mv-let splitter-output stable-under-simplificationp standard-char standard-char-listp standard-char-listp-append standard-char-listp-forward-to-character-listp standard-char-p standard-char-p-nth standard-co standard-oi standard-part standard-string-alistp standard-string-alistp-forward-to-alistp standardp start-proof-tree state state-global-let* state-global-let*-cleanup state-global-let*-get-globals state-global-let*-put-globals state-p state-p-implies-and-forward-to-state-p1 state-p1 state-p1-forward state-p1-update-main-timer state-p1-update-nth-2-world step-limit stobj-let stop-proof-tree string string-append string-append-lst string-downcase string-downcase1 string-equal string-equal1 string-is-not-circular string-listp string-upcase string-upcase1 string< string<-irreflexive string<-l string<-l-asymmetric string<-l-irreflexive string<-l-transitive string<-l-trichotomy string<= string> string>= stringp stringp-symbol-package-name strip-cars strip-cdrs sublis subseq subseq-list subsetp subsetp-eq subsetp-equal subst substitute substitute-ac summary symbol symbol-< symbol-<-asymmetric symbol-<-irreflexive symbol-<-transitive symbol-<-trichotomy symbol-alistp symbol-alistp-forward-to-eqlable-alistp symbol-doublet-listp symbol-equality symbol-listp symbol-listp-forward-to-true-listp symbol-name symbol-name-intern-in-package-of-symbol symbol-package-name symbolp symbolp-intern-in-package-of-symbol synp syntaxp sys-call sys-call+ sys-call-status t t-stack t-stack-length t-stack-length1 table table-alist take tau-data tau-database tau-interval-dom tau-interval-hi tau-interval-hi-rel tau-interval-lo tau-interval-lo-rel tau-intervalp tau-status tau-system tenth term-order the the-check the-fixnum the-fixnum! theory theory-invariant third thm time$ time-tracker time-tracker-tau timer-alistp timer-alistp-forward-to-true-list-listp-and-symbol-alistp toggle-pc-macro top-level trace! trace$ trace* trans trans! trans1 trichotomy true-list-listp true-list-listp-forward-to-true-listp true-list-listp-forward-to-true-listp-assoc-equal true-listp true-listp-cadr-assoc-eq-for-open-channels-p true-listp-update-nth truncate ttags-seen type typed-io-listp typed-io-listp-forward-to-true-listp typespec-check u ubt ubt! ubt-prehistory ubu ubu! unary-- unary-/ unary-function-symbol-listp unicity-of-0 unicity-of-1 union$ union-eq union-equal union-theories universal-theory unmemoize unmonitor unquote unsave unsigned-byte unsigned-byte-p untrace$ untrans-table untranslate update-32-bit-integer-stack update-acl2-oracle update-acl2-oracle-preserves-state-p1 update-big-clock-entry update-file-clock update-global-table update-idates update-list-all-package-names-lst update-nth update-open-input-channels update-open-output-channels update-read-files update-t-stack update-user-stobj-alist update-user-stobj-alist1 update-written-files upper-case-p upper-case-p-char-upcase upper-case-p-forward-to-alpha-char-p user-stobj-alist user-stobj-alist1 value value-triple verbose-pstack verify verify-guards verify-guards+ verify-guards-formula verify-termination w walkabout warning! waterfall-parallelism waterfall-printing wet with-fast-alist with-guard-checking with-live-state with-local-state with-local-stobj with-output with-output-lock with-prover-step-limit with-prover-step-limit! with-prover-time-limit with-serialize-character with-stolen-alist without-evisc wof world wormhole wormhole-data wormhole-entry-code wormhole-eval wormhole-p wormhole-statusp wormhole1 writable-file-listp writable-file-listp-forward-to-true-list-listp writable-file-listp1 writable-file-listp1-forward-to-true-listp-and-consp write-byte$ writeable-files writeable-files-p writeable-files-p-forward-to-writable-file-listp written-file written-file-forward-to-true-listp-and-consp written-file-listp written-file-listp-forward-to-true-list-listp-and-alistp written-files written-files-p written-files-p-forward-to-written-file-listp xargs xor xxxjoin zero zerop zip zp zpf)") (*COMMON-LISP-SYMBOLS-FROM-MAIN-LISP-PACKAGE* (PACKAGES ACL2-BUILT-INS) "Symbols that are often imported into new packages to provide easy access to Common Lisp functionality. When you define a new package for your own work with [defpkg], you will usually want to import many symbols from the \"COMMON-LISP\" package so that you can access them without a common-lisp:: or acl2:: prefix. The constant *common-lisp-symbols-from-main-lisp-package* lists the 978 symbols of the COMMON-LISP package found in {dpAns | http://dx.doi.org/10.1145/147135.147249}. You will typically also want to import many symbols from ACL2; see [*ACL2-exports*]. (&allow-other-keys *print-miser-width* &aux *print-pprint-dispatch* &body *print-pretty* &environment *print-radix* &key *print-readably* &optional *print-right-margin* &rest *query-io* &whole *random-state* * *read-base* ** *read-default-float-format* *** *read-eval* *break-on-signals* *read-suppress* *compile-file-pathname* *readtable* *compile-file-truename* *standard-input* *compile-print* *standard-output* *compile-verbose* *terminal-io* *debug-io* *trace-output* *debugger-hook* + *default-pathname-defaults* ++ *error-output* +++ *features* - *gensym-counter* / *load-pathname* // *load-print* /// *load-truename* /= *load-verbose* 1+ *macroexpand-hook* 1- *modules* < *package* <= *print-array* = *print-base* > *print-case* >= *print-circle* abort *print-escape* abs *print-gensym* acons *print-length* acos *print-level* acosh *print-lines* add-method adjoin atom boundp adjust-array base-char break adjustable-array-p base-string broadcast-stream allocate-instance bignum broadcast-stream-streams alpha-char-p bit built-in-class alphanumericp bit-and butlast and bit-andc1 byte append bit-andc2 byte-position apply bit-eqv byte-size apropos bit-ior caaaar apropos-list bit-nand caaadr aref bit-nor caaar arithmetic-error bit-not caadar arithmetic-error-operands bit-orc1 caaddr arithmetic-error-operation bit-orc2 caadr array bit-vector caar array-dimension bit-vector-p cadaar array-dimension-limit bit-xor cadadr array-dimensions block cadar array-displacement boole caddar array-element-type boole-1 cadddr array-has-fill-pointer-p boole-2 caddr array-in-bounds-p boole-and cadr array-rank boole-andc1 call-arguments-limit array-rank-limit boole-andc2 call-method array-row-major-index boole-c1 call-next-method array-total-size boole-c2 car array-total-size-limit boole-clr case arrayp boole-eqv catch ash boole-ior ccase asin boole-nand cdaaar asinh boole-nor cdaadr assert boole-orc1 cdaar assoc boole-orc2 cdadar assoc-if boole-set cdaddr assoc-if-not boole-xor cdadr atan boolean cdar atanh both-case-p cddaar cddadr clear-input copy-tree cddar clear-output cos cdddar close cosh cddddr clrhash count cdddr code-char count-if cddr coerce count-if-not cdr compilation-speed ctypecase ceiling compile debug cell-error compile-file decf cell-error-name compile-file-pathname declaim cerror compiled-function declaration change-class compiled-function-p declare char compiler-macro decode-float char-code compiler-macro-function decode-universal-time char-code-limit complement defclass char-downcase complex defconstant char-equal complexp defgeneric char-greaterp compute-applicable-methods define-compiler-macro char-int compute-restarts define-condition char-lessp concatenate define-method-combination char-name concatenated-stream define-modify-macro char-not-equal concatenated-stream-streams define-setf-expander char-not-greaterp cond define-symbol-macro char-not-lessp condition defmacro char-upcase conjugate defmethod char/= cons defpackage char< consp defparameter char<= constantly defsetf char= constantp defstruct char> continue deftype char>= control-error defun character copy-alist defvar characterp copy-list delete check-type copy-pprint-dispatch delete-duplicates cis copy-readtable delete-file class copy-seq delete-if class-name copy-structure delete-if-not class-of copy-symbol delete-package denominator eq deposit-field eql describe equal describe-object equalp destructuring-bind error digit-char etypecase digit-char-p eval directory eval-when directory-namestring evenp disassemble every division-by-zero exp do export do* expt do-all-symbols extended-char do-external-symbols fboundp do-symbols fceiling documentation fdefinition dolist ffloor dotimes fifth double-float file-author double-float-epsilon file-error double-float-negative-epsilon file-error-pathname dpb file-length dribble file-namestring dynamic-extent file-position ecase file-stream echo-stream file-string-length echo-stream-input-stream file-write-date echo-stream-output-stream fill ed fill-pointer eighth find elt find-all-symbols encode-universal-time find-class end-of-file find-if endp find-if-not enough-namestring find-method ensure-directories-exist find-package ensure-generic-function find-restart find-symbol get-internal-run-time finish-output get-macro-character first get-output-stream-string fixnum get-properties flet get-setf-expansion float get-universal-time float-digits getf float-precision gethash float-radix go float-sign graphic-char-p floating-point-inexact handler-bind floating-point-invalid-operation handler-case floating-point-overflow hash-table floating-point-underflow hash-table-count floatp hash-table-p floor hash-table-rehash-size fmakunbound hash-table-rehash-threshold force-output hash-table-size format hash-table-test formatter host-namestring fourth identity fresh-line if fround ignorable ftruncate ignore ftype ignore-errors funcall imagpart function import function-keywords in-package function-lambda-expression incf functionp initialize-instance gcd inline generic-function input-stream-p gensym inspect gentemp integer get integer-decode-float get-decoded-time integer-length get-dispatch-macro-character integerp get-internal-real-time interactive-stream-p intern lisp-implementation-type internal-time-units-per-second lisp-implementation-version intersection list invalid-method-error list* invoke-debugger list-all-packages invoke-restart list-length invoke-restart-interactively listen isqrt listp keyword load keywordp load-logical-pathname-translations labels load-time-value lambda locally lambda-list-keywords log lambda-parameters-limit logand last logandc1 lcm logandc2 ldb logbitp ldb-test logcount ldiff logeqv least-negative-double-float logical-pathname least-negative-long-float logical-pathname-translations least-negative-normalized-double-float logior least-negative-normalized-long-float lognand least-negative-normalized-short-float lognor least-negative-normalized-single-float lognot least-negative-short-float logorc1 least-negative-single-float logorc2 least-positive-double-float logtest least-positive-long-float logxor least-positive-normalized-double-float long-float least-positive-normalized-long-float long-float-epsilon least-positive-normalized-short-float long-float-negative-epsilon least-positive-normalized-single-float long-site-name least-positive-short-float loop least-positive-single-float loop-finish length lower-case-p let machine-instance let* machine-type machine-version mask-field macro-function max macroexpand member macroexpand-1 member-if macrolet member-if-not make-array merge make-broadcast-stream merge-pathnames make-concatenated-stream method make-condition method-combination make-dispatch-macro-character method-combination-error make-echo-stream method-qualifiers make-hash-table min make-instance minusp make-instances-obsolete mismatch make-list mod make-load-form most-negative-double-float make-load-form-saving-slots most-negative-fixnum make-method most-negative-long-float make-package most-negative-short-float make-pathname most-negative-single-float make-random-state most-positive-double-float make-sequence most-positive-fixnum make-string most-positive-long-float make-string-input-stream most-positive-short-float make-string-output-stream most-positive-single-float make-symbol muffle-warning make-synonym-stream multiple-value-bind make-two-way-stream multiple-value-call makunbound multiple-value-list map multiple-value-prog1 map-into multiple-value-setq mapc multiple-values-limit mapcan name-char mapcar namestring mapcon nbutlast maphash nconc mapl next-method-p maplist nil nintersection package-error ninth package-error-package no-applicable-method package-name no-next-method package-nicknames not package-shadowing-symbols notany package-use-list notevery package-used-by-list notinline packagep nreconc pairlis nreverse parse-error nset-difference parse-integer nset-exclusive-or parse-namestring nstring-capitalize pathname nstring-downcase pathname-device nstring-upcase pathname-directory nsublis pathname-host nsubst pathname-match-p nsubst-if pathname-name nsubst-if-not pathname-type nsubstitute pathname-version nsubstitute-if pathnamep nsubstitute-if-not peek-char nth phase nth-value pi nthcdr plusp null pop number position numberp position-if numerator position-if-not nunion pprint oddp pprint-dispatch open pprint-exit-if-list-exhausted open-stream-p pprint-fill optimize pprint-indent or pprint-linear otherwise pprint-logical-block output-stream-p pprint-newline package pprint-pop pprint-tab read-char pprint-tabular read-char-no-hang prin1 read-delimited-list prin1-to-string read-from-string princ read-line princ-to-string read-preserving-whitespace print read-sequence print-not-readable reader-error print-not-readable-object readtable print-object readtable-case print-unreadable-object readtablep probe-file real proclaim realp prog realpart prog* reduce prog1 reinitialize-instance prog2 rem progn remf program-error remhash progv remove provide remove-duplicates psetf remove-if psetq remove-if-not push remove-method pushnew remprop quote rename-file random rename-package random-state replace random-state-p require rassoc rest rassoc-if restart rassoc-if-not restart-bind ratio restart-case rational restart-name rationalize return rationalp return-from read revappend read-byte reverse room simple-bit-vector rotatef simple-bit-vector-p round simple-condition row-major-aref simple-condition-format-arguments rplaca simple-condition-format-control rplacd simple-error safety simple-string satisfies simple-string-p sbit simple-type-error scale-float simple-vector schar simple-vector-p search simple-warning second sin sequence single-float serious-condition single-float-epsilon set single-float-negative-epsilon set-difference sinh set-dispatch-macro-character sixth set-exclusive-or sleep set-macro-character slot-boundp set-pprint-dispatch slot-exists-p set-syntax-from-char slot-makunbound setf slot-missing setq slot-unbound seventh slot-value shadow software-type shadowing-import software-version shared-initialize some shiftf sort short-float space short-float-epsilon special short-float-negative-epsilon special-operator-p short-site-name speed signal sqrt signed-byte stable-sort signum standard simple-array standard-char simple-base-string standard-char-p standard-class sublis standard-generic-function subseq standard-method subsetp standard-object subst step subst-if storage-condition subst-if-not store-value substitute stream substitute-if stream-element-type substitute-if-not stream-error subtypep stream-error-stream svref stream-external-format sxhash streamp symbol string symbol-function string-capitalize symbol-macrolet string-downcase symbol-name string-equal symbol-package string-greaterp symbol-plist string-left-trim symbol-value string-lessp symbolp string-not-equal synonym-stream string-not-greaterp synonym-stream-symbol string-not-lessp t string-right-trim tagbody string-stream tailp string-trim tan string-upcase tanh string/= tenth string< terpri string<= the string= third string> throw string>= time stringp trace structure translate-logical-pathname structure-class translate-pathname structure-object tree-equal style-warning truename truncate values-list two-way-stream variable two-way-stream-input-stream vector two-way-stream-output-stream vector-pop type vector-push type-error vector-push-extend type-error-datum vectorp type-error-expected-type warn type-of warning typecase when typep wild-pathname-p unbound-slot with-accessors unbound-slot-instance with-compilation-unit unbound-variable with-condition-restarts undefined-function with-hash-table-iterator unexport with-input-from-string unintern with-open-file union with-open-stream unless with-output-to-string unread-char with-package-iterator unsigned-byte with-simple-restart untrace with-slots unuse-package with-standard-io-syntax unwind-protect write update-instance-for-different-class write-byte update-instance-for-redefined-class write-char upgraded-array-element-type write-line upgraded-complex-part-type write-sequence upper-case-p write-string use-package write-to-string use-value y-or-n-p user-homedir-pathname yes-or-no-p values zerop)") (*STANDARD-CI* (IO ACL2-BUILT-INS) "An ACL2 character-based analogue of CLTL's *standard-input* The value of the ACL2 constant *standard-ci* is an open character input channel that is synonymous to Common Lisp's *standard-input*. ACL2 character input from *standard-ci* is actually obtained by reading [characters] from the stream named by Common Lisp's *standard-input*. That is, by changing the setting of *standard-input* in raw Common Lisp you can change the source from which ACL2 reads on the channel *standard-ci*. See [*standard-co*].") (*STANDARD-CO* (IO ACL2-BUILT-INS) "The ACL2 analogue of CLTL's *standard-output* The value of the ACL2 constant *standard-co* is an open character output channel that is synonymous to Common Lisp's *standard-output*. ACL2 character output to *standard-co* will go to the stream named by Common Lisp's *standard-output*. That is, by changing the setting of *standard-output* in raw Common Lisp you can change the actual destination of ACL2 output on the channel named by *standard-co*. Observe that this happens without changing the logical value of *standard-co* (which is some channel symbol). Changing the setting of *standard-output* in raw Common Lisp essentially just changes the map that relates ACL2 to the physical world of terminals, files, etc. To see the value of this observation, consider the following. Suppose you write an ACL2 function which does character output to the constant channel *standard-co*. During testing you see that the output actually goes to your terminal. Can you use the function to output to a file? Yes, if you are willing to do a little work in raw Common Lisp: open a stream to the file in question, set *standard-output* to that stream, call your ACL2 function, and then close the stream and restore *standard-output* to its nominal value. Similar observations can be made about the two ACL2 input channels, [*standard-oi*] and [*standard-ci*], which are analogues of *standard-input*. Another reason you might have for wanting to change the actual streams associated with [*standard-oi*] and *standard-co* is to drive the ACL2 top-level loop, [ld], on alternative input and output streams. This end can be accomplished easily within ACL2 by either calling [ld] on the desired channels or file names or by resetting the ACL2 [state] global variables '[standard-oi] and '[standard-co] which are used by [ld]. See [standard-oi] and see [standard-co].") (*STANDARD-OI* (IO ACL2-BUILT-INS) "An ACL2 object-based analogue of CLTL's *standard-input* The value of the ACL2 constant *standard-oi* is an open object input channel that is synonymous to Common Lisp's *standard-input*. ACL2 object input from *standard-oi* is actually obtained by reading from the stream named by Common Lisp's *standard-input*. That is, by changing the setting of *standard-input* in raw Common Lisp you can change the source from which ACL2 reads on the channel *standard-oi*. See [*standard-co*].") (+ (NUMBERS ACL2-BUILT-INS) "Addition macro + is really a macro that expands to calls of the function [binary-+]. So for example (+ x y 4 z) represents the same term as (binary-+ x (binary-+ y (binary-+ 4 z))). See [binary-+]. Macro: <+> (defmacro + (&rest rst) (if rst (if (cdr rst) (xxxjoin 'binary-+ rst) (cons 'binary-+ (cons 0 (cons (car rst) nil)))) 0)) Subtopics [Binary-+] Addition function") (- (NUMBERS ACL2-BUILT-INS) "Macro for subtraction and negation See [binary-+] for addition and see [unary--] for negation. Note that - represents subtraction as follows: (- x y) represents the same term as (+ x (- y)) which is really (binary-+ x (unary-- y)). Also note that - represents arithmetic negation as follows: (- x) expands to (unary-- x). Macro: <-> (defmacro - (x &optional (y 'nil binary-casep)) (if binary-casep (let ((y (if (and (consp y) (eq (car y) 'quote) (consp (cdr y)) (acl2-numberp (car (cdr y))) (eq (cdr (cdr y)) nil)) (car (cdr y)) y))) (if (acl2-numberp y) (cons 'binary-+ (cons (unary-- y) (cons x nil))) (cons 'binary-+ (cons x (cons (cons 'unary-- (cons y nil)) nil))))) (let ((x (if (and (consp x) (eq (car x) 'quote) (consp (cdr x)) (acl2-numberp (car (cdr x))) (eq (cdr (cdr x)) nil)) (car (cdr x)) x))) (if (acl2-numberp x) (unary-- x) (cons 'unary-- (cons x nil))))))") (/ (NUMBERS ACL2-BUILT-INS) "Macro for division and reciprocal See [binary-*] for multiplication and see [unary-/] for reciprocal. Note that / represents division as follows: (/ x y) represents the same term as (* x (/ y)) which is really (binary-* x (unary-/ y)). Also note that / represents reciprocal as follows: (/ x) expands to (unary-/ x). / is a Common Lisp macro. See any Common Lisp documentation for more information. Macro: (defmacro / (x &optional (y 'nil binary-casep)) (cond (binary-casep (list 'binary-* x (list 'unary-/ y))) (t (list 'unary-/ x))))") (/= (NUMBERS ACL2-BUILT-INS) "Test inequality of two numbers (/= x y) is logically equivalent to (not (equal x y)). Unlike [equal], /= has a [guard] requiring both of its arguments to be numbers. Generally, /= is executed more efficiently than a combination of [not] and [equal]. For a discussion of the various ways to test against 0, See [zero-test-idioms]. /= is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun /= (x y) (declare (xargs :guard (and (acl2-numberp x) (acl2-numberp y)))) (not (equal x y)))") (1+ (NUMBERS ACL2-BUILT-INS) "Increment by 1 (1+ x) is the same as (+ 1 x). See [+]. 1+ is a Common Lisp function. See any Common Lisp documentation for more information. Macro: <1+> (defmacro 1+ (x) (list '+ 1 x))") (1- (NUMBERS ACL2-BUILT-INS) "Decrement by 1 (1- x) is the same as (- x 1). See [-]. 1- is a Common Lisp function. See any Common Lisp documentation for more information. Macro: <1-> (defmacro 1- (x) (list '- x 1))") (< (NUMBERS ACL2-BUILT-INS) "Less-than Completion Axiom (completion-of-<): (equal (< x y) (if (and (rationalp x) (rationalp y)) (< x y) (let ((x1 (if (acl2-numberp x) x 0)) (y1 (if (acl2-numberp y) y 0))) (or (< (realpart x1) (realpart y1)) (and (equal (realpart x1) (realpart y1)) (< (imagpart x1) (imagpart y1))))))) [Guard] for (< x y): (and (rationalp x) (rationalp y)) Notice that like all arithmetic functions, < treats non-numeric inputs as 0. This function has the usual meaning on the rational numbers, but is extended to the complex rational numbers using the lexicographic order: first the real parts are compared, and if they are equal, then the imaginary parts are compared.") (<= (NUMBERS ACL2-BUILT-INS) "Less-than-or-equal test <= is a macro, and (<= x y) expands to the same thing as (not (< y x)). See [<]. <= is a Common Lisp function. See any Common Lisp documentation for more information. Macro: <<=> (defmacro <= (x y) (list 'not (list '< y x)))") (= (NUMBERS EQUAL EQUALITY-VARIANTS ACL2-BUILT-INS) "Test equality of two numbers (= x y) is logically equivalent to (equal x y). Unlike [equal], = has a [guard] requiring both of its arguments to be numbers. Generally, = is executed more efficiently than [equal]. For a discussion of the various ways to test against 0, See [zero-test-idioms]. = is a Common Lisp function. See any Common Lisp documentation for more information. Function: <=> (defun = (x y) (declare (xargs :guard (and (acl2-numberp x) (acl2-numberp y)))) (equal x y))") (> (NUMBERS ACL2-BUILT-INS) "Greater-than test > is a macro, and (> x y) expands to the same thing as (< y x). See [<]. > is a Common Lisp function. See any Common Lisp documentation for more information. Macro: <>> (defmacro > (x y) (list '< y x))") (>= (NUMBERS ACL2-BUILT-INS) "Greater-than-or-equal test >= is a macro, and (>= x y) expands to the same thing as (not (< x y)). See [<]. >= is a Common Lisp function. See any Common Lisp documentation for more information. Macro: <>=> (defmacro >= (x y) (list 'not (list '< x y)))") (@ (PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "Get the value of a global variable in [state] Examples: (+ (@ y) 1) (assign a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B)) General Form: (@ symbol) where symbol is any symbol to which you have [assign]ed a global value. This macro expands into (f-get-global 'symbol state), which retrieves the stored value of the symbol. The macro f-get-global is closely related to [@]: (@ var) macroexpands to (f-get-global 'var state). The macro [assign] makes it convenient to set the value of a symbol. The :[ubt] operation has no effect on the global-table of [state]. Thus, you may use these globals to hang onto useful data structures even though you may undo back past where you computed and saved them.") (A! (LD) "To return to the top-level of ACL2's command loop When (a!) is evaluated inside of ACL2's command loop, the current computation is aborted and control returns to the top of the command loop, exactly as though the user had interrupted and aborted the current computation. (Note: Versions of ACL2 up to Version_3.4 provided `#.' for this purpose, but no longer; see [sharp-dot-reader].) If you are at an ACL2 prompt (as opposed to a raw Lisp break), then you may type :a! in place of (a!); see [keyword-commands]. For a related feature that only pops up one level, see [p!]. Logically speaking, (a!) = nil. But imagine that it is defined in such a way that it causes a stack overflow or other resource exhaustion when called.") (ABORT! (LD) "To return to the top-level of ACL2's command loop This is an alias for a!; see [a!]. For a related feature that only pops up one level, see [p!].") (ABOUT-ACL2 (ACL2) "General information About ACL2 This is ACL2 Version 7.1, [copyright] (C) 2015, Regents of the University of Texas, authored by Matt Kaufmann and J Strother Moore. See the {ACL2 home page | http://www.cs.utexas.edu/users/moore/acl2/} for additional information including tutorials, installation instructions, mailing lists, related publications, ACL2 workshops and seminars, acknowledgements, and other ACL2 releases. See [documentation] for how to access the ACL2 User's Manual. For statistics on ACL2 code size, see file doc/acl2-code-size.txt. Subtopics [Acknowledgments] Some contributors to the well-being of ACL2 [ACL2-help] The acl2-help mailing list [Bibliography] Reports about ACL2 [Building-ACL2] How to build an ACL2 executable [Common-lisp] Relation to Common Lisp, including deviations from the spec [Copyright] ACL2 copyright, license, sponsorship [Git-quick-start] Git quick start guide [Release-notes] Pointers to what has changed [Version] ACL2 Version Number") (ABOUT_MODELS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "About Models [{IMAGE}] ACL2 is used to construct mathematical models of computer hardware and software (i.e., ``digital systems''). {IMAGE} A mathematical model is a set of mathematical formulas used to predict the behavior of some artifact. The use of mathematical models allows faster and cheaper delivery of better systems. Models need not be complete or perfectly accurate to be useful to the trained engineer. Click [here] for more discussion of these assertions in an engineering context. [{IMAGE}]") (ABOUT_THE_ACL2_HOME_PAGE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "About the ACL2 Home Page [{IMAGE}] The ACL2 Home Page is integrated into the ACL2 online documentation. Over 4 megabytes of hypertext is available here. The vast majority of the text is user-level documentation. For example, to find out about [rewrite] [{ICON}] rules you could click on the link. (If you do that, remember to use your browser's Back Button to come back here.) The tiny warning signs [{ICON}] mark links that lead out of the introductory-level material and into the user documentation. We advise against following such links upon your first reading of the documentation. At the end of the tours you will have a chance to revisit them quickly to explore alternative paths more fully. Finally, every page contains two icons at the bottom. The ACL2 icon leads you back to the ACL2 Home Page. The Index icon allows you to browse an alphabetical listing of all the topics in ACL2's online documentation. But both icons take you off the main route of the tour. [{IMAGE}]") (ABOUT_THE_ADMISSION_OF_RECURSIVE_DEFINITIONS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "About the Admission of Recursive Definitions You can't just add any formula as an axiom or definition and expect the logic to stay sound! For example, if we were permitted to define (APP X Y) so that it was equal to (NOT (APP X Y)) then we could prove anything. The purported ``definition'' of APP must have several properties to be admitted to the logic as a new axiom. The key property a recursive definition must have is that the recursion terminate. This, along with some syntactic criteria, ensures us that there exists a function satisfying the definition. Termination must be proved before the definition is admitted. This is done in general by finding a measure of the arguments of the function and a well-founded relation such that the arguments ``get smaller'' every time a recursive branch is taken. For app the measure is the ``size'' of the first argument, x, as determined by the primitive function [ACL2-count] [{ICON}]. The well-founded relation used in this example is [o-p] [{ICON}], which is the standard ordering on the ordinals less than ``epsilon naught.'' These particular choices for app were made ``automatically'' by ACL2. But they are in fact determined by various ``default'' settings. The user of ACL2 can change the defaults or specify a ``hint'' to the [defun] [{ICON}] command to specify the measure and relation. You should now return to [the Walking Tour].") (ABOUT_THE_PROMPT (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "About the Prompt The string ``ACL2 !>'' is the ACL2 prompt. The prompt tells the user that an ACL2 [command] [{ICON}]is expected. In addition, the prompt tells us a little about the current state of the ACL2 command interpreter. We explain the prompt briefly below. But first we talk about the command interpreter. An ACL2 command is generally a Lisp expression to be evaluated. There are some unusual commands (such as :[q] [{ICON}] for quitting ACL2) which cause other behavior. But most commands are read, evaluated, and then have their results printed. Thus, we call the command interpreter a ``read-eval-print loop.'' The ACL2 command interpreter is named [ld] [{ICON}] (after Lisp's ``load''). When a command is read, all the symbols in it are converted to uppercase. Thus, typing (defun app ...) is the same as typing (DEFUN APP ...) or (defun App ...). There are ways to force lowercase case characters into symbols but we won't discuss them here. A consequence of Common Lisp's default uppercasing is that you'll see a general lack of concern over the case used when symbols are displayed in this documentation. In addition, symbols ``belong'' to ``packages'' which give the user a way to control namespaces. The prompt tells us which package is the default one, namely \"ACL2\". That means when we call car, for example, we are invoking the standard definition of that symbol. If the packager were \"JONES\" then car would refer to the definition of that symbol in that package (which may or may not be different depending on what symbols were imported into that package. A command like (defun app (x y) ...) causes ACL2 to evaluate the [defun] [{ICON}] function on app, (x y) and .... When that command is evaluated it prints some information to the terminal explaining the processing of the proposed definition. It returns the symbol APP as its value, which is printed by the command interpreter. (Actually, defun is not a function but a [macro] [{ICON}] which expands to a form that involves [state] [{ICON}], a necessary precondition to printing output to the terminal and to ``changing'' the set of axioms. But we do not discuss this further here.) The defun command is an example of a special kind of command called an ``event.'' [Events] [{ICON}] are those commands that change the ``logical world'' by adding such things as axioms or theorems to ACL2's database. See [world] [{ICON}]. But not every command is an event command. A command like (app '(1 2 3) '(4 5 6 7)) is an example of a non-event. It is processed the same general way: the function app is applied to the indicated arguments and the result is printed. The function app does not print anything and does not change the ``world.'' A third kind of command is one that display information about the current logical world or that ``roll back'' to previous versions of the world. Such commands are called ``[history]'' [{ICON}] commands. What does the ACL2 prompt tell us about the read-eval-print loop? The prompt ``ACL2 !>'' tells us that the command will be read with [current-package] [{ICON}] set to \"ACL2\", that guard checking (see [set-guard-checking] [{ICON}]) is on (``!''), and that we are at the top-level (there is only one ``>''). For more about the prompt, see [default-print-prompt] [{ICON}]. You should now return to [the Walking Tour].") (ABOUT_TYPES (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "About Types The universe of ACL2 objects includes objects of many different types. For example, t is a ``symbol'' and 3 is an ``integer.'' Roughly speaking the objects of ACL2 can be partitioned into the following types: [Numbers] 3, -22/7, #c(3 5/2) [Characters] #\\A, #\\a, #\\Space [Strings] \"This is a string.\" [Symbols] 'abc, 'smith::abc [Conses (or Ordered Pairs)] '((a . 1) (b . 2)) When proving theorems it is important to know the types of object returned by a term. ACL2 uses a complicated heuristic algorithm, called [type-set] [{ICON}], to determine what types of objects a term may produce. The user can more or less program the type-set algorithm by proving [type-prescription] [{ICON}] rules. ACL2 is an ``untyped'' logic in the sense that the syntax is not typed: It is legal to apply a function symbol of n arguments to any n terms, regardless of the types of the argument terms. Thus, it is permitted to write such odd expressions as (+ t 3) which sums the symbol t and the integer 3. Common Lisp does not prohibit such expressions. We like untyped languages because they are simple to describe, though proving theorems about them can be awkward because, unless one is careful in the way one defines or states things, unusual cases (like (+ t 3)) can arise. To make theorem proving easier in ACL2, the axioms actually define a value for such terms. The value of (+ t 3) is 3; under the ACL2 axioms, non-numeric arguments to + are treated as though they were 0. You might immediately wonder about our claim that ACL2 is Common Lisp, since (+ t 3) is ``an error'' (and will sometimes even ``signal an error'') in Common Lisp. It is to handle this problem that ACL2 has guards. We will discuss guards later in the Walking Tour. However, many new users simply ignore the issue of guards entirely and that is what we recommend for now. You should now return to [the Walking Tour].") (ABS (NUMBERS ACL2-BUILT-INS) "The absolute value of a real number (Abs x) is -x if x is negative and is x otherwise. The [guard] for abs requires its argument to be a rational ([real], in ACL2(r)) number. Abs is a Common Lisp function. See any Common Lisp documentation for more information. From ``Common Lisp the Language'' page 205, we must not allow complex x as an argument to abs in ACL2, because if we did we would have to return a number that might be a floating point number and hence not an ACL2 object. Function: (defun abs (x) (declare (xargs :guard (real/rationalp x))) (if (minusp x) (- x) x))") (ACCESS (DEFREC ACL2-BUILT-INS) "Accessor macro for [defrec] structures. The access macro is built into ACL2, and allows you to access particular fields from structures that have been introduced with [defrec]. For instance: (access employee x :name) would return the name field from the employee x. See [defrec] for more information.") (ACCUMULATED-PERSISTENCE (DEBUGGING) "To get statistics on which [rune]s are being tried Useful Forms: (accumulated-persistence t) ; Activate statistics gathering. (accumulated-persistence :all) ; As above, ``enhanced'' (see below) (show-accumulated-persistence :frames) ; Display statistics ordered by (show-accumulated-persistence :tries) ; frames built, times tried, (show-accumulated-persistence :ratio) ; or their ratio. (accumulated-persistence nil) ; Deactivate. Advanced forms: (show-accumulated-persistence :frames-s) ; The `s', `f', and `a' suffixes (show-accumulated-persistence :frames-f) ; stand for `success' (`useful'), (show-accumulated-persistence :frames-a) ; `failure' (`useless'), and `all', (show-accumulated-persistence :tries-s) ; respectively. The only effect of (show-accumulated-persistence :tries-f) ; the `s' and `f' versions is to (show-accumulated-persistence :tries-a) ; sort first by useful or useless ; applications, respectively (see ; below). The `a' versions avoid ; showing the useful/useless ; breakdown. (show-accumulated-persistence :runes) ; Just show runes alphabetically. Note: set-accumulated-persistence is equivalent to accumulated-persistence. See the end of this item for a discussion of ``enhanced statistics gathering,'' which can be useful for more fine-grained proof debugging. Generally speaking, the more ACL2 knows, the slower it runs. That is because the search space grows with the number of alternative rules. Often, the system tries to apply rules that you have forgotten were even there, if you knew about them in the first place! ``Accumulated-persistence'' is a statistic (originally developed for Nqthm) that helps you identify the rules that are causing ACL2's search space to explode. For other proof debugging utilities, see [break-rewrite] and see [dmr]. Accumulated persistence tracking can be turned on or off. It is generally off. When on, proofs may take perhaps 50% more time than otherwise! But some useful numbers are collected. When it is turned on, by ACL2 !>(accumulated-persistence t) an accumulation site is initialized and henceforth data about which rules are being tried is accumulated into that site. That accumulated data can be displayed with show-accumulated-persistence, as described in detail below. When accumulated persistence is turned off, with (accumulated-persistence nil), the accumulation site is wiped out and the data in it is lost. The ``accumulated persistence'' of a [rune] is the number of [rune]s the system has attempted to apply (since accumulated persistence was last activated) while the given [rune] was being tried. Consider a :[rewrite] rule named [rune]. For simplicity, let us imagine that [rune] is tried only once in the period during which accumulated persistence is being monitored. Recall that to apply a rewrite rule we must match the left-hand side of the conclusion to some term we are trying to rewrite, establish the hypotheses of [rune] by rewriting, and, if successful, then rewrite the right-hand side of the conclusion. We say [rune] is ``being tried'' from the time we have matched its left-hand side to the time we have either abandoned the attempt or finished rewriting its right-hand side. (By ``match'' we mean to include any loop-stopper requirement; see [loop-stopper].) During that period of time other rules might be tried, e.g., to establish the hypotheses. The rules tried while [rune] is being tried are ``billed'' to [rune] in the sense that they are being considered here only because of the demands of [rune]. Thus, if no other rules are tried during that period, the accumulated persistence of [rune] is 1 --- we ``bill'' [rune] once for its own application attempt. If, on the other hand, we tried 10 rules on behalf of that application of [rune], then [rune]'s accumulated persistence would be 11. One way to envision accumulated persistence is to imagine that every time a [rune] is tried it is pushed onto a stack. The rules tried on behalf of a given application of a [rune] are thus pushed and popped on the stack above that [rune]. A lot of work might be done on its behalf --- the stack above the [rune] grows and shrinks repeatedly as the search continues for a way to use the [rune]. All the while, the [rune] itself ``persists'' in the stack, until we finish with the attempt to apply it, at which time we pop it off. The accumulated persistence of a [rune] application is thus the number of stack frames built while that [rune] was on the stack. Note that accumulated persistence is tallied whether or not the attempt to apply a [rune] is successful. Each of the rules tried on its behalf might have failed and the attempt to apply the [rune] might have also failed. The ACL2 proof script would make no mention of the [rune] or the rules tried on its behalf because they did not contribute to the proof. But time was spent pursuing the possible application of the [rune] and accumulated persistence is a measure of that time. A high accumulated persistence might come about in two extreme ways. One is that the rule causes a great deal of work every time it is tried. The other is that the rule is ``cheap'' but is tried very often. We therefore keep track of the number of times each rule is tried as well as its persistence. The ratio between the two is the average amount of work done on behalf of the rule each time it is tried. When the accumulated persistence totals are displayed by the function show-accumulated-persistence we sort them so that the most expensive [rune]s are shown first. We can sort according to one of three basic keys: :frames - the number of frames built on behalf of the rune :tries - the number of times the rune was tried :ratio - frames built per try The key simply determines the order in which the information is presented. If no argument is supplied to show-accumulated-persistence, :frames is used. The display breaks each total into ``useful'' and ``useless'' subtotals. A ``useful'' rule try is one that is viewed as contributing to the progress of the proof, and the rest are ``useless'' rule applications. For example, if a :[rewrite] rule is tried but its hypotheses are not successfully relieved, then that rule application and all work done on behalf of those hypotheses is ``useless'' work. In general, an attempt to apply a [rune] is viewed as ``useful'' unless the attempt fails or the attempt is on the stack (as described above) for a [rune] application that ultimately fails. A large number of ``useless'' :frames or :tries along with correspondingly small ``useful'' counts may suggest [rune]s to consider disabling (see [disable] and see [in-theory]). Thus, here is a more complete list of the arguments that may be supplied to show-accumulated-persistence. Suffixes ``s'', ``f'', and ``a'' are intended to suggest ``success'' (``useful''), ``failure'' (``useless''), and ``all''. :frames - sort by the number of frames built on behalf of the rune :frames-s - as above, but sort by useful applications :frames-f - as above, but sort by useless applications :frames-a - as above, but inhibit display of ``useful'' and ``useless'' subtotals :tries - sort by the number of times the rune was tried :tries-s - as above, but sort by useful applications :tries-f - as above, but sort by useless applications :tries-a - as above, but inhibit display of ``useful'' and ``useless'' subtotals :ratio - sort by frames built per try :useless - show only the runes tried whose tries were all ``useless'' For a given line of the report, every frame credited to a ``useful'' (respectively, ``useless'') rule application is considered ``useful'' (respectively, ``useless''). We illustrate with the following example. (progn (defstub hyp (x) t) (defstub concl (x) t) (defstub bad (x) t) (defstub good (x) t) (defaxiom good-ax (implies (good x) (hyp x))) (defaxiom bad-ax (implies (bad x) (hyp x))) (defaxiom hyp-implies-concl (implies (hyp x) (concl x))) ) (accumulated-persistence t) (thm (implies (good x) (concl x))) (show-accumulated-persistence) To prove the [thm] form, ACL2 attempts to rewrite (concl x) to true by applying rule hyp-implies-concl. It then attempts to establish (hyp x) first by trying rule bad-ax, which fails, and second by trying rule good-ax, which succeeds. As expected, the report labels as ``useless'' the failure of the attempt to establish the hypothesis, (bad x). -------------------------------- 1 1 ( 1.00) (:REWRITE BAD-AX) 0 0 [useful] 1 1 [useless] -------------------------------- Now consider the top-level application of rule hyp-implies-concl. Even though the above report shows the application of bad-ax as ``useless'', note that this rule was applied on behalf of the successful (``useful'') application of hyp-implies-concl, and hence is incorporated into the ``useful'' line for hyp-implies-concl, as follows. -------------------------------- 3 1 ( 3.00) (:REWRITE HYP-IMPLIES-CONCL) 3 1 [useful] 0 0 [useless] -------------------------------- In summary: categorization of :frames as ``useful'' or ``useless'' is based on whether they support ``useful'' or ``useless'' :tries. Note that a [rune] with high accumulated persistence may not actually be the ``culprit.'' For example, suppose rune1 is reported to have a :ratio of 101, meaning that on the average a hundred and one frames were built each time rune1 was tried. Suppose rune2 has a :ratio of 100. It could be that the attempt to apply rune1 resulted in the attempted application of rune2 and no other [rune]. Thus, in some sense, rune1 is ``cheap'' and rune2 is the ``culprit'' even though it is reported as costing less than rune1. If a proof is aborted, then in general, [show-accumulated-persistence] will only display totals for runes whose attempted application is complete: that is, if the rewriter was in the process of relieving hypotheses for a rule, then information for that rule will not be included in the tally. We say ``in general'' because, as indicated near the top of the output from [show-accumulated-persistence] when such incomplete information is omitted, you can get this information by using argument :frames-a or :tries-a. There are other subtleties in how rune applications are tallied, documented elsewhere: see [accumulated-persistence-subtleties]. We conclude with a discussion of ``enhanced'' statistics gathering, which is enabled by supplying accumulated-persistence the argument :ALL: (accumulated-persistence :all) At some additional performance expense (but probably well under a factor of 2 altogether), ACL2 then gathers additional statistics for individual hypotheses of rules as well as their conclusions. To understand how this works, suppose rn is a [rune]. Then we prepend the keyword :CONC to rn to form what we call its ``conclusion xrune'', and for its I-th hypothesis we prepend :HYP I to rn to form its I-th ``hypothesis xrune.'' Here, ``xrune'' is pronounced ``ex rune'', and is mnemonic for ``extended rune.'' For example, if (REWRITE FOO) is a [rune] then (:CONC REWRITE FOO) is its conclusion xrune, and (:HYP 2 REWRITE FOO) is a hypothesis xrune corresponding to the second hypothesis of the corresponding rewrite rule. With (accumulated-persistence :all), we instruct ACL2 to track not only runes but also xrunes. Then, (show-accumulated-persistence) will display information for all xrunes in a format that we consider to be ``raw'', in the sense that data for xrunes are displayed just as for runes. But a ``merged'' format is also available. Here is a summary of display commands, followed below by further discussion. (show-accumulated-persistence :frames t) ; t is optional, i.e., the default ; Display enhanced statistics sorted by frames, in a ``raw'' format. (show-accumulated-persistence :frames :merge) ; Display enhanced statistics sorted by frames, in a ``merged'' format. (show-accumulated-persistence :frames nil) ; Display regular statistics sorted by frames, without the enhancements. ; More generally, the descriptions just above apply for any legal first ; argument: (show-accumulated-persistence KEY t) (show-accumulated-persistence KEY :merge) (show-accumulated-persistence KEY nil) ; Note also these alternate forms, equivalent to the first of the two forms ; just above, i.e., the form with second argument of t: (show-accumulated-persistence KEY :raw) (show-accumulated-persistence KEY) There is a significant difference between how runes are tracked and how ACL2 tracks hypothesis and conclusion xrunes: unlike regular runes, these xrunes do not contribute to the accumulated :frames counts. Rather, they serve as accumulation sites without contributing their :tries to any accumulation. Consider for example the snippet below, taken from a report created with the :merge option (to be discussed further below), i.e., by evaluating the form (show-accumulated-persistence :frames :merge). :frames :tries :ratio rune -------------------------------- 462 211 ( 2.18) (:REWRITE PERM-MEM) 13 6 [useful] 449 205 [useless] ............................. 251 47 ( 5.34) (:HYP 2 :REWRITE PERM-MEM) 6 6 [useful] 245 41 [useless] ............................. 0 211 ( 0.00) (:HYP 1 :REWRITE PERM-MEM) 0 6 [useful] 0 205 [useless] ............................. 0 7 ( 0.00) (:CONC :REWRITE PERM-MEM) 0 6 [useful] 0 1 [useless] -------------------------------- Notice that while :tries are recorded for the xrune (:HYP 1 :REWRITE PERM-MEM), no :frames are recorded. This is because no stack frames were built for runes while this xrune was on the stack --- only for the xrune itself, which as we explained above is not accumulated into the total :frames counts. As it turns out, this lack of stack frames is explained by the fact that the rewrite rule PERM-MEM has a free variable in the first hypothesis. ACL2 !>:pe perm-mem 18 (DEFTHM PERM-MEM (IMPLIES (AND (PERM X Y) (MEM A X)) (MEM A Y)) :RULE-CLASSES ((:REWRITE :MATCH-FREE :ONCE))) ACL2 !> The second hypothesis, however, does cause additional rewriting in order to rewrite it to true, resulting in 251 stack frames for runes. We see that the conclusion does not lead to creation of any rune stack frames, which might seem to suggest that only 251 stack frames for runes were created on behalf of this rule application --- yet, we see that 462 frames were actually created. The difference is the 211 frames created for the rewrite rule itself. Even if the total had been a bit more than 462, one need not be surprised, as there could be some work recorded during application of the rewrite rule, such as type-prescription reasoning, that is not done during rewriting of a hypothesis or the conclusion. Now suppose we have executed (accumulated-persistence :all) and attempted some proofs, and now we are ready to see statistics. The form (show-accumulated-persistence) displays statistics exactly as described above, treating these extra xrunes just as though they are runes; similarly for the form (show-accumulated-persistence KEY), for any legal KEY. A second optional argument may however be supplied to show-accumulated-persistence. The default for that second argument is t, and a second argument of :raw is treated the same as t; thus, these arguments provide the behavior just described, where data for xrunes are displayed just as for runes. You may restrict output to runes, ignoring hypothesis and conclusion xrunes, by giving a second argument of nil. (This gives the same behavior as if we had started with the command (accumulated-persistence t) instead of the command (accumulated-persistence :all).) Finally, you may give a second argument of :merge, in which case output will be sorted and displayed as though only runes were tracked (not the extra xrunes), but each data item for a non-rune xrune will be merged so that it is displayed in suitable order just below its corresponding rune, as in the PERM-MEM example displayed above. We close by mentioning two aspects of enhanced statistics display for :CONC xrunes that have potential to be confusing. First consider the following example. :frames :tries :ratio rune -------------------------------- 14 4 ( 3.50) (:REWRITE DEFAULT-+-2) 0 0 [useful] 14 4 [useless] ............................. 10 4 ( 2.50) (:HYP 1 :REWRITE DEFAULT-+-2) 0 0 [useful] 10 4 [useless] -------------------------------- It may be surprising that no data is displayed for the corresponding :CONC xrune. The explanation, however, is simple: the hypothesis never rewrote to true, so the conclusion was never rewritten. This is consistent with the marking as ``useless'' of all :frames and :tries for the rune and the hypothesis xrune. Note by the way, once again, that the hypothesis xrune does not contribute to any :frames count. Another reason not to see data displayed for a :CONC xrune is that if a rule has no hypotheses, then no such data is collected. This decision was made because in the case of no hypotheses, we expect it to be very rare that information for the :CONC xrune will add any useful insight. On a final note: (show-accumulated-persistence :runes) may be used simply to see a list of all [rune]s (or xrunes) displayed alphabetically. Users are encouraged to think about other meters we could install in ACL2 to help diagnose performance problems. Subtopics [Accumulated-persistence-subtleties] Some subtle aspects of the counting done by [accumulated-persistence] [Dmr] Dynamically monitor rewrites and other prover activity") (ACCUMULATED-PERSISTENCE-SUBTLETIES (ACCUMULATED-PERSISTENCE) "Some subtle aspects of the counting done by [accumulated-persistence] In this topic we cover the overcounting of ``useful'' and of recursive [rune] application attempts, and we describe how ``useless'' [rune] application attempts can actually be critical for a proof's success. Overcounting of ``useful'' and of recursive rune application attempts. Not every [rune] application may be necessary for a proof's success. Consider for example: (thm (equal (car (cons a (cdr (cons b x)))) a)) Then show-accumulated-persistence will tell us that :[rewrite] rules car-cons and cdr-cons each had one useful application. However, the rule cdr-cons is used to simplify (cdr (cons b x)) to x, and this simplification is unecessary for the proof. Indeed, the proof succeeds even when preceded by the event: (in-theory (disable cdr-cons)). We thus see that a [rune] application labeled as ``useful'' may be simplifying a term that is not relevant to the proof. As of this writing, we consider every :[forward-chaining] rule application to be ``useful'', for simplicity of the implementation. Moreover, our counting of these rules is such that a single rule may be counted more than once. Next we show how recursive rule applications are overcounted. Consider the following example. (defun mem (a x) (if (atom x) nil (or (equal a (car x)) (mem a (cdr x))))) Now suppose we consider the sequence of theorems (mem a (list a)), (mem a (list 1 a)), (mem a (list 1 2 a)), (mem a (list 1 2 3 a)), and so on. We will see that the :frames reported for each increases quadratically, even though the :tries increases linearly; so in this case the :tries statistics are more appropriate. Each time the definition of mem is applied, a new stack frame is pushed (see [accumulated-persistence]), and all subsequent applications of that definition are accumulated into the :frames count for that stack frame. The final :frames count will be the sum of the counts for those individual frames, which form a linear sequence whose sum is therefore quadratic in the number of applications of the definition of mem. How ``useless'' attempts can be critical for a proof's success. The command (accumulated-persistence :useless)] will list rules that did not contribute directly to the proof (see [accumulated-persistence], in particular the discussion of ``useless'' there). However, a ``useless'' rule can on rare occasions be critical to the success of a proof. In the following example, we have a ``bad'' rule that can take the proof in the wrong direction, but a ``useless'' rule does a rewrite that prevents the succesful relieving of a hypothesis of the ``bad'' rule. In summary: ; Assume p0. We want to prove p1. ; Key rule: p0 -> p1 = t ; Bad rule that could ruin the proof: p3 -> p1 = p2 ; But unfortunately, we know p3: p0 -> p3 ; Important ``useless'' rule, preventing ``bad rule'' above from firing: p3 = p4 The following event captures the rules described above. (encapsulate ((p0 (x) t) (p1 (x) t) (p2 (x) t) (p3 (x) t) (p4 (x) t)) (local (defun p0 (x) x)) (local (defun p1 (x) x)) (local (defun p2 (x) x)) (local (defun p3 (x) x)) (local (defun p4 (x) x)) ; Key rule: (defthm p0-implies-p1 (implies (p0 x) (p1 x))) ; Bad rule that could ruin the proof: (defthm p3-implies-p1-is-p2 (implies (p3 x) (equal (p1 x) (p2 x)))) ; But unfortunately, we know p3: (defthm p0-implies-p3 (implies (p0 x) (p3 x))) ; Important ``useless'' rule, preventing p3-implies-p1-is-p2 from firing: (defthm p3-is-p4 (equal (p3 x) (p4 x)))) Now we can see that p3-is-p4 is labeled as ``useless'', by evaluating these commands. (accumulated-persistence t) (thm (implies (p0 x) (p1 x))) (show-accumulated-persistence) If instead we first evaluate (in-theory (disable p3-is-p4)) before the thm above, then the proof fails, even though p3-is-p4 was labeled as ``useless''! Nevertheless, in general it is probably safe to disable rules reported as ``useless'' by (show-accumulated-persistence :useless), and doing so may speed up a proof considerably. Remark. The example above suggests a surprising fact: on rare occasions, a proof may fail when you give an :[in-theory] hint consisting of exactly the [rune]s reported in a proof that succeeds. For, imagine a rule R that is needed in part of the proof but is ``bad'' in a second part, and that some other, ``useless'' rule prevents the application of R in that second part. The example above suggests that disabling this ``useless'' rule can allow the second application of R, thus preventing the proof.") (ACKNOWLEDGMENTS (ABOUT-ACL2) "Some contributors to the well-being of ACL2 The development of ACL2 was initially made possible by funding from the U. S. Department of Defense, including ARPA and ONR. We thank all the organizations that have contributed support, including the following (in alphabetical order). * AMD, for providing significant time over several years for Matt Kaufmann to carry out ACL2 research, support, and development * Computational Logic, Inc. and its president, Don Good, where the first eight years of ACL2 development occurred * Centaur Technology * DARPA * Digital Equipment Corporation * EDS, which provided some time for Matt Kaufmann's ACL2 work 1998-1999 * ForrestHunt and, more generally, Warren A. Hunt, Jr. (see below) * IBM * NSF * ONR * Rockwell Collins * SRC * Sun Microsystems * University of Texas at Austin (in particular support to J Moore through the Admiral B. R. Inman Chair of Computing Theory) We are especially grateful to Warren A. Hunt, Jr. for his unrivaled efforts in securing support for the entire ACL2 research group at both Computational Logic, Inc., and the University of Texas at Austin. Without his efforts, we would have spent less time working on the system and fewer students would have been funded to apply it. ACL2 was started in August, 1989 by Boyer and Moore working together. They co-authored the first versions of axioms.lisp and basis.lisp, with Boyer taking the lead in the formalization of ``[state]'' and the most primitive [io] functions. Boyer also had a significant hand in the development of the early versions of the files interface-raw.lisp and translate.lisp. For several years, Moore alone was responsible for developing the ACL2 system code, though he consulted often with both Boyer and Kaufmann. In August, 1993, Kaufmann became jointly responsible with Moore for developing the system. Boyer has continued to provide valuable consulting on an informal basis. Bishop Brock was the heaviest early user of ACL2, and provided many suggestions for improvements. In particular, the :cases and :restrict [hints] were his idea; he developed an early version of congruence-based reasoning for Nqthm; and he helped in the development of some early [books] about arithmetic. In a demonstration of his courage and faith in us, he pushed for Computational Logic, Inc., to agree to the Motorola CAP contract -- which required formalizing a commercial DSP in the untested ACL2 -- and moved to Scottsdale, AZ, to do the work with the Motorola design team. His demonstration of ACL2's utility was an inspiration, even to those of us designing ACL2. John Cowles also helped in the development of some early [books] about arithmetic, and also provided valuable feedback and bug reports. Other early users of ACL2 at Computational Logic, Inc. helped influence its development. In particular, Warren Hunt helped with the port to Macintosh Common Lisp, and Art Flatau and Mike Smith provided useful general feedback. Mike Smith helped develop the Emacs portion of the implementation of proof trees. Bill Schelter made some enhancements to akcl (now gcl) that helped to enhance ACL2 performance in that Common Lisp implementation, and more generally, responded helpfully to our bug reports. Camm Maguire has since provided wonderful gcl support, and has created a Debian package for ACL2 built on GCL. We are also grateful to developers of other Common Lisp implementations. Kent Pitman helped in our interaction with the ANSI Common Lisp standardization committee, X3J13. John Cowles helped with the port to Windows (98) by answering questions and running tests. Ruben Gamboa created a modification of ACL2 to allow reasoning about the real numbers using non-standard analysis. His work has been incorporated into the ACL2 distribution; see [real]. Rob Sumners has made numerous useful suggestions. In particular, he has designed and implemented improvements for [stobj]s and been key in our development of locally-bound stobjs; see [note-2-6]. Robert Krug has designed and implemented many changes in the vicinity of the linear arithmetic package and its connection to type-set and rewrite. He was also instrumental in the development of [extended-metafunctions]. Pete Manolios has made numerous useful suggestions. In particular, Pete helped us to organize the first workshop and was a wonderful equal partner with the two of us (Kaufmann and Moore) in producing the books that arose from that workshop. Pete and his student, Daron Vroon, provided the current implementation of [ordinals]. Jared Davis, Sol Swords, and David Rager have our gratitude for starting the {ACL2+Books repository | https://github.com/acl2/acl2/}. We thank David L. Rager for contributing an initial version of the support for [parallelism] in an experimental extension of ACL2. Bob Boyer and Warren A. Hunt, Jr. developed a canonical representation for ACL2 data objects, applicative hash tables, and a function memoization mechanism to facilitate reuse of previously computed results. Subsequently, Jared Davis and Sol Swords made further contributions. We thank them all for this work, most of which has been incorporated into ACL2; see [hons-and-memoization]. We also thank the contributors to the ACL2 workshops for some suggested improvements and for the extensive collection of publicly distributed benchmark problems. And we thank participants at the ACL2 seminar at the University of Texas for useful feedback. More generally, we thank the ACL2 community for feedback, contributed [books] (see [community-books]), and their interest in the ACL2 project. Regarding the documentation: Bill Young wrote significant portions of the original acl2-tutorial section of the ACL2 documentation, including what is now called [alternative-introduction]. This was an especially important task in the early years when there was no guide for how to use ACL2 and we are very grateful. He, Bishop Brock, Rich Cohen, and Noah Friedman read over considerable amounts of the documentation, and made many useful comments. Others, particularly Bill Bevier and John Cowles, have also made useful comments on the [documentation]. Art Flatau helped develop the ACL2 markup language in which ACL2 [documentation] was originally developed, along with translators from that language to Texinfo and HTML. Michael ``Bogo'' Bogomolny created a search engine, beginning with Version 2.6, and for that purpose modified the HTML translator to create one file per topic (a good idea in any case). Laura Lawless provided many hours of help in marking up appropriate parts of the [documentation] in typewriter font. Noah Friedman developed an Emacs tool that helped us insert ``invisible links'' into the [documentation], which improve the usability of that documentation under HTML readers such as Mosaic. Richard Stallman contributed a texinfo patch, to be found in the file doc/texinfo.tex. Jared Davis created the [xdoc] system that is now the basis not only for the ACL2 system [documentation] (file books/system/doc/acl2-doc.lisp), but also for the [community-books] documentation. We thank Blake Grugett for designing the current version of the ACL2 logo (which for example appears on the ACL2 home page), based on an original design created in the 1990s by Computational Logic, Inc.") (ACL2 NIL "ACL2 documentation (system only, not including the community books) This is the ACL2 documentation. For the ACL2+Books Manual, which that includes both the ACL2 documentation and the ACL2 [community-books], see the {ACL2+Books Manual | http://www.cs.utexas.edu/users/moore/acl2/v7-1/combined-manual/index.html}. Subtopics [About-ACL2] General information About ACL2 [ACL2-tutorial] Tutorial introduction to ACL2 [Bdd] Ordered binary decision diagrams with rewriting [Books] Books are files of ACL2 [events]---they are the main way to split up large ACL2 developments into separate modules. [Debugging] Tools for debugging failed or slow proofs, or misbehaving functions. [Documentation] Information about options for downloading and viewing the ACL2 documentation, contributing documentation, and the available tools for documenting your own books. [Events] Functions that extend the logic [History] Functions that display or change history [Hons-and-memoization] Hash cons, function memoization, and applicative hash tables [Interfacing-tools] Libraries and tools for doing basic [file i/o], using raw [Common Lisp libraries], working with the [operating system], and interfacing with [other programs]. [Macros] Macros allow you to extend the syntax of ACL2. [Miscellaneous] A miscellany of documented functions and concepts (often cited in more accessible [documentation]) [Parallelism] Experimental extension for parallel execution and proofs [Programming] Programming in ACL2 [Proof-checker] An interactive tool for controlling ACL2's proof processes. [Prover-output] Methods for controlling the output produced by ACL2 during proofs and in other situations. [Real] ACL2(r) support for real numbers [Rule-classes] Adding rules to the database [Theories] Sets of [rune]s to [enable]/[disable] in concert") (ACL2-AS-STANDALONE-PROGRAM (ACL2-TUTORIAL) "Calling ACL2 from another program ACL2 is intended for interactive use. It is generally unrealistic to expect it to prove theorems fully automatically; see [the-method], and see [introduction-to-the-theorem-prover] for a more detailed tutorial. Nevertheless, here we describe an approach for how to call the ACL2 theorem prover noninteractively. These steps can of course be modified according to your needs. Here, we illustrate how to call ACL2 from another Lisp program (or an arbitrary program) to attempt to prove an arithmetic theorem. See also [interfacing-tools]. In particular, if you want to make a command-line tool to ACL2 with options, you may be interested in [oslib::argv], [getopt], and especially [getopt-demo::demo2]. Alternately, if you want to develop a server application on top of ACL2, you might consider [bridge]. Step 1 Build a suitable ACL2 image by starting ACL2 and then executing the following forms. In particular, these define a macro, try-thm, that causes ACL2 to exit with with an exit status indicating success or failure of a proof attempt. (include-book \"arithmetic-5/top\" :dir :system) (defmacro try-thm (&rest args) `(mv-let (erp val state) (with-prover-time-limit 3 (thm ,@args)) (declare (ignore val)) (prog2$ (if erp (exit 1) (exit 0)) state)))) (reset-prehistory) ; optional :q (save-exec \"arith-acl2\" \"Included arithmetic-4/top\") If you prefer, above you can replace 3 by some other number of seconds as a time limit for the prover. Also, you can replace (with-prover-time-limit 3 (thm ,@args)) by (with-output :off :all (with-prover-time-limit 3 (thm ,@args))) if you want to turn off output. It may be best to leave the output on, instead eliminating it in the calling program (see Step 3 below). Step 2 Try a little test. In that same directory try this: echo '(try-thm (equal x x))' | ./arith-acl2 echo $? The exit status should be 0, indicating success. Now try this: echo '(try-thm (not (equal x x)))' | ./arith-acl2 echo $? The exit status should be 1, indicating failure. Step 3 Create a shell script that automates Step 2, for example: #!/bin/sh (echo \"(try-thm $1)\" | ./arith-acl2) >& /dev/null exit $? Step 4 Try your script from a Lisp program, if you like. Here is how you can do it in SBCL, for example. (Different Lisps have different ways to do this, as summarized in function system-call in ACL2 source file acl2-init.lisp.) (defun provable? (x) (let ((status (process-exit-code (sb-ext:run-program \"./try-thm.sh\" (list (format nil \"~s\" x)) :output t :search t)))) (eql status 0))) Then here is a log: * (provable? '(equal x y)) NIL * (provable? '(equal x x)) T * Certainly refinements are possible -- for example the above doesn't distinguish between unprovable and ill-formed input. But it's a start.") (ACL2-BUILT-INS (PROGRAMMING) "''Catch-all'' topic for built-in ACL2 functions This [documentation] topic is a parent topic under which we include documentation for built-in functions, macros, and special forms that are typically used in [programming]. For others, including those typically used as top-level commands or those that create [events] ([defun], [defmacro], [defthm], and so on), documentation may be found as a subtopic of some other parent topic. We do not document some of the more obscure functions provided by ACL2 that do not correspond to functions of Common Lisp. See any documentation for Common Lisp for more details on many of these functions. Subtopics [*] Multiplication macro [*ACL2-exports*] Symbols that are often imported into new [packages] to provide easy access to ACL2 functionality. [*common-lisp-symbols-from-main-lisp-package*] Symbols that are often imported into new packages to provide easy access to Common Lisp functionality. [*standard-ci*] An ACL2 character-based analogue of CLTL's *standard-input* [*standard-co*] The ACL2 analogue of CLTL's *standard-output* [*standard-oi*] An ACL2 object-based analogue of CLTL's *standard-input* [+] Addition macro [-] Macro for subtraction and negation [/] Macro for division and reciprocal [/=] Test inequality of two numbers [1+] Increment by 1 [1-] Decrement by 1 [<] Less-than [<=] Less-than-or-equal test [=] Test equality of two numbers [>] Greater-than test [>=] Greater-than-or-equal test [@] Get the value of a global variable in [state] [Abs] The absolute value of a real number [Access] Accessor macro for [defrec] structures. [ACL2-count] A commonly used measure for justifying recursion [ACL2-number-listp] Recognizer for a true list of numbers [ACL2-numberp] Recognizer for numbers [Acons] Constructor for association lists [Add-to-set] Add a symbol to a list [Alistp] Recognizer for association lists [Allocate-fixnum-range] Set aside fixnums in GCL [Alpha-char-p] Recognizer for alphabetic characters [Alphorder] Total order on atoms [And] Conjunction [Append] [concatenate] zero or more lists [Aref1] Access the elements of a 1-dimensional array [Aref2] Access the elements of a 2-dimensional array [Array1p] Recognize a 1-dimensional array [Array2p] Recognize a 2-dimensional array [Aset1] Set the elements of a 1-dimensional array [Aset2] Set the elements of a 2-dimensional array [Ash] Arithmetic shift operation [Assert$] Cause a hard error if the given test is false [Assert*] Create a [guard] proof obligation that given test holds [Assign] Assign to a global variable in [state] [Assoc] Look up key in association list [Assoc-keyword] Look up key in a [keyword-value-listp] [Assoc-string-equal] Look up key, a string, in association list [Atom] Recognizer for atoms [Atom-listp] Recognizer for a true list of [atom]s [Binary-*] Multiplication function [Binary-+] Addition function [Binary-append] [concatenate] two lists [Boole$] Perform a bit-wise logical operation on 2 two's complement integers [Boolean-listp] Recognizer for a true list of booleans [Booleanp] Recognizer for booleans [Break$] Cause an immediate Lisp break [Break-on-error] Break when encountering a hard or soft error caused by ACL2 [Butlast] All but a final segment of a list [Caaaar] [car] of the [caaar] [Caaadr] [car] of the [caadr] [Caaar] [car] of the [caar] [Caadar] [car] of the [cadar] [Caaddr] [car] of the [caddr] [Caadr] [car] of the [cadr] [Caar] [car] of the [car] [Cadaar] [car] of the [cdaar] [Cadadr] [car] of the [cdadr] [Cadar] [car] of the [cdar] [Caddar] [car] of the [cddar] [Cadddr] [car] of the [cdddr] [Caddr] [car] of the [cddr] [Cadr] [car] of the [cdr] [Canonical-pathname] The true absolute filename, with soft links resolved [Car] Returns the first element of a non-empty list, else nil [Case] Conditional based on if-then-else using [eql] [Case-match] Pattern matching or destructuring [Cbd] Connected book directory string [Cdaaar] [cdr] of the [caaar] [Cdaadr] [cdr] of the [caadr] [Cdaar] [cdr] of the [caar] [Cdadar] [cdr] of the [cadar] [Cdaddr] [cdr] of the [caddr] [Cdadr] [cdr] of the [cadr] [Cdar] [cdr] of the [car] [Cddaar] [cdr] of the [cdaar] [Cddadr] [cdr] of the [cdadr] [Cddar] [cdr] of the [cdar] [Cdddar] [cdr] of the [cddar] [Cddddr] [cdr] of the [cdddr] [Cdddr] [cdr] of the [cddr] [Cddr] [cdr] of the [cdr] [Cdr] Returns the second element of a [cons] pair, else nil [Ceiling] Division returning an integer by truncating toward positive infinity [Change] Mutator macro for [defrec] structures. [Char] The [nth] element (zero-based) of a string [Char-code] The numeric code for a given character [Char-downcase] Turn upper-case [characters] into lower-case [characters] [Char-equal] Character equality without regard to case [Char-upcase] Turn lower-case [characters] into upper-case [characters] [Char<] Less-than test for [characters] [Char<=] Less-than-or-equal test for [characters] [Char>] Greater-than test for [characters] [Char>=] Greater-than-or-equal test for [characters] [Character-alistp] Recognizer for association lists with characters as keys [Character-listp] Recognizer for a true list of characters [Characterp] Recognizer for [characters] [Code-char] The character corresponding to a given numeric code [Coerce] Coerce a character list to a string and a string to a list [Comp] Compile some ACL2 functions [Comp-gcl] Compile some ACL2 functions leaving .c and .h files [Complex] Create an ACL2 number [Complex-rationalp] Recognizes complex rational numbers [Complex/complex-rationalp] Recognizer for complex numbers [Compress1] Remove irrelevant pairs from a 1-dimensional array [Compress2] Remove irrelevant pairs from a 2-dimensional array [Concatenate] Concatenate lists or strings together [Cond] Conditional based on if-then-else [Conjugate] Complex number conjugate [Cons] Pair and list constructor [Cons-subtrees] Build a fast alist whose keys are the subtrees of X [Consp] Recognizer for [cons] pairs [Count] Count the number of occurrences of an item in a string or true-list [Cpu-core-count] The number of cpu cores [Cw] Print to the comment window [Cw!] Print to the comment window [Declare] Extra declarations that can occur in function definitions, [let] bindings, and so forth. [Default] Return the :default from the [header] of a 1- or 2-dimensional array [Delete-assoc] Remove the first pair from an association list for a given key [Denominator] Divisor of a ratio in lowest terms [Digit-char-p] The number, if any, corresponding to a given character [Digit-to-char] Map a digit to a character [Dimensions] Return the :dimensions from the [header] of a 1- or 2-dimensional array [Ec-call] Execute a call in the ACL2 logic instead of raw Lisp [Eighth] Eighth member of the list [Endp] Recognizer for empty lists [Eq] Equality of symbols [Eql] Test equality (of two numbers, symbols, or [characters]) [Eqlable-alistp] Recognizer for a true list of pairs whose [car]s are suitable for [eql] [Eqlable-listp] Recognizer for a true list of objects each suitable for [eql] [Eqlablep] The [guard] for the function [eql] [Equal] True equality [Er] Print an error message and ``cause an error'' [Er-progn] Perform a sequence of state-changing ``error triples'' [Error1] Print an error message and cause a ``soft error'' [Evenp] Test whether an integer is even [Explode-atom] Convert any [atom] into a [character-listp] that contains its printed representation, rendering numbers in your choice of print base. [Explode-nonnegative-integer] The list of [characters] in the radix-r form of a number [Expt] Exponential function [F-get-global] Get the value of a global variable in [state] [F-put-global] Assign to a global variable in [state] [Fast-alist-clean] ([fast-alist-clean] alist) can be used to eliminate \"shadowed pairs\" from a fast alist. [Fast-alist-clean!] ([fast-alist-clean!] alist) is an alternative to [fast-alist-clean] that produces a [normed] result. [Fast-alist-fork] ([fast-alist-fork] alist ans) can be used to eliminate \"shadowed pairs\" from an alist or to copy [fast-alists]. [Fast-alist-fork!] ([fast-alist-fork!] alist ans) is an alternative to [fast-alist-fork] that produces a [normed] result. [Fast-alist-free] ([fast-alist-free] alist) throws away the hash table associated with a fast alist. [Fast-alist-free-on-exit] Free a fast alist after the completion of some form. [Fast-alist-len] ([fast-alist-len] alist) counts the number of unique keys in a fast alist. [Fast-alist-summary] ([fast-alist-summary]) prints some basic statistics about any current fast alists. [Fifth] Fifth member of the list [First] First member of the list [Fix] Coerce to a number [Fix-true-list] Coerce to a true list [Flet] Local binding of function symbols [Floor] Division returning an integer by truncating toward negative infinity [Flush-compress] Flush the under-the-hood array for the given name [Flush-hons-get-hash-table-link] Deprecated feature [Fms] ([fms] str alist co-channel state evisc) => state [Fms!] ([fms!] str alist co-channel state evisc) => state [Fmt] Formatted printing [Fmt!] ([fmt!] str alist co-channel state evisc) => state [Fmt-to-comment-window] Print to the comment window [Fmt1] ([fmt1] str alist col co-channel state evisc) => ([mv] col state) [Fmt1!] ([fmt1!] str alist col channel state evisc) => ([mv] col state) [Formula] The formula of a name or [rune] [Fourth] Fourth member of the list [Gc$] Invoke the garbage collector [Get-internal-time] Runtime vs. realtime in ACL2 timings [Getenv$] Read an environment variable [Getprop] Access fast property lists [Good-atom-listp] Recognizer for a true list of ``good'' [atom]s [Good-bye] Quit entirely out of Lisp [Hard-error] Print an error message and stop execution [Header] Return the header of a 1- or 2-dimensional array [Hons] ([hons] x y) returns a [normed] object equal to ([cons] x y). [Hons-acons] ([hons-acons] key val alist) is the main way to create or extend [fast-alists]. [Hons-acons!] ([hons-acons!] key val alist) is an alternative to [hons-acons] that produces [normed], fast alists. [Hons-assoc-equal] ([hons-assoc-equal] key alist) is not fast; it serves as the logical definition for [hons-get]. [Hons-clear] ([hons-clear] gc) is a drastic garbage collection mechanism that clears out the underlying Hons Space. [Hons-clear!] A version of [hons-clear] for [parallel] execution [Hons-copy] ([hons-copy] x) returns a [normed] object that is equal to X. [Hons-copy-persistent] ([hons-copy-persistent] x) returns a [normed] object that is equal to X and which will be re-normed after any calls to [hons-clear]. [Hons-equal] ([hons-equal] x y) is a recursive equality check that optimizes when parts of its arguments are [normed]. [Hons-get] ([hons-get] key alist) is the efficient lookup operation for [fast-alists]. [Hons-resize] ([hons-resize] ...) can be used to manually adjust the sizes of the hash tables that govern which ACL2 Objects are considered [normed]. [Hons-shrink-alist] Deprecated feature [Hons-shrink-alist!] Deprecated feature [Hons-summary] ([hons-summary]) prints basic information about the sizes of the tables in the current Hons Space. [Hons-wash] ([hons-wash]) is like [gc$] but can also garbage collect [normed] objects (CCL and GCL Only). [Hons-wash!] A version of [hons-wash] for [parallel] execution [Identity] The identity function [If] If-then-else function [Iff] Logical ``if and only if'' [Ifix] Coerce to an integer [Illegal] Print an error message and stop execution [Imagpart] Imaginary part of a complex number [Implies] Logical implication [Improper-consp] Recognizer for improper (non-null-terminated) non-empty lists [In-package] Select current package [In-tau-intervalp] Boolean membership in a tau interval [Int=] Test equality of two integers [Integer-length] Number of bits in two's complement integer representation [Integer-listp] Recognizer for a true list of integers [Integer-range-p] Recognizer for integers between two bounds. [Integerp] Recognizer for whole numbers [Intern] Create a new symbol in a given package [Intern$] Create a new symbol in a given package [Intern-in-package-of-symbol] Create a symbol with a given name [Intersection$] Elements of one list that are not elements of another [Intersectp] Test whether two lists intersect [Keyword-value-listp] Recognizer for true lists whose even-position elements are keywords [Keywordp] Recognizer for keywords [Kwote] Quote an arbitrary object [Kwote-lst] Quote an arbitrary true list of objects [Last] The last [cons] (not element) of a list [Last-prover-steps] The number of prover steps most recently taken [Len] Length of a list [Length] Length of a string or proper list [Let] Binding of lexically scoped (local) variables [Let*] Binding of lexically scoped (local) variables [Lexorder] Total order on ACL2 objects [List] Build a list [List*] Build a list [Listp] Recognizer for (not necessarily proper) lists [Logand] Bitwise logical `and' of zero or more integers [Logandc1] Bitwise logical `and' of two ints, complementing the first [Logandc2] Bitwise logical `and' of two ints, complementing the second [Logbitp] The ith bit of an integer [Logcount] Number of ``on'' bits in a two's complement number [Logeqv] Bitwise logical equivalence of zero or more integers [Logior] Bitwise logical inclusive or of zero or more integers [Lognand] Bitwise logical `nand' of two integers [Lognor] Bitwise logical `nor' of two integers [Lognot] Bitwise not of a two's complement number [Logorc1] Bitwise logical inclusive or of two ints, complementing the first [Logorc2] Bitwise logical inclusive or of two ints, complementing the second [Logtest] Test if two integers share a `1' bit [Logxor] Bitwise logical exclusive or of zero or more integers [Lower-case-p] Recognizer for lower case characters [Make] Constructor macro for [defrec] structures. [Make-character-list] [coerce] to a list of characters [Make-fast-alist] ([make-fast-alist] alist) creates a fast-alist from the input alist, returning alist itself or, in some cases, a new object equal to it. [Make-list] Make a list of a given size [Make-ord] A constructor for ordinals. [Make-tau-interval] Make a tau interval [Max] The larger of two numbers [Maximum-length] Return the :maximum-length from the [header] of an array [Mbe] Attach code for execution [Mbe1] Attach code for execution [Mbt] Introduce a test into the logic that, however, evaluates to t [Mbt*] Introduce a guard proof obligation [Member] Membership predicate [Min] The smaller of two numbers [Minusp] Test whether a number is negative [Mod] Remainder using [floor] [Mod-expt] Exponential function [Msg] Construct a ``message'' suitable for the ~@ directive of [fmt] [Must-be-equal] Attach code for execution [Mv] Returning a multiple value [Mv-let] Calling multi-valued ACL2 functions [Mv-list] Converting multiple-valued result to a single-valued list [Mv-nth] The mv-nth element (zero-based) of a list [Mv?] Return one or more values [Mv?-let] Calling possibly multi-valued ACL2 functions [Nat-listp] Recognizer for a true list of natural numbers [Natp] A recognizer for the natural numbers [Nfix] Coerce to a natural number [Ninth] Ninth member of the list [No-duplicatesp] Check for duplicates in a list [Non-exec] Mark code as non-executable [Nonnegative-integer-quotient] Natural number division function [Not] Logical negation [Nth] The nth element (zero-based) of a list [Nthcdr] Final segment of a list [Null] Recognizer for the empty list [Number-subtrees] ([number-subtrees] x) returns the number of distinct subtrees of X, in the sense of [equal] [Numerator] Dividend of a ratio in lowest terms [O-finp] Recognizes if an ordinal is finite [O-first-coeff] Returns the first coefficient of an ordinal [O-first-expt] The first exponent of an ordinal [O-infp] Recognizes if an ordinal is infinite [O-p] A recognizer for the ordinals up to epsilon-0 [O-rst] Returns the rest of an infinite ordinal [O<] The well-founded less-than relation on ordinals up to epsilon-0 [O<=] The less-than-or-equal relation for the ordinals [O>] The greater-than relation for the ordinals [O>=] The greater-than-or-equal relation for the ordinals [Observation] Print an observation [Oddp] Test whether an integer is odd [Open-output-channel!] When trust tags are needed to open output channels [Or] Disjunction [Oracle-apply] Call a function argument on the given list of arguments [Oracle-apply-raw] Call a function argument on the given list of arguments, no restrictions [Oracle-funcall] Call a function argument on the remaining arguments [Pairlis$] Zipper together two lists [Pand] Parallel, Boolean version of [and] [Pargs] Parallel evaluation of arguments in a function call [Pkg-witness] Return a specific symbol in the indicated package [Plet] Parallel version of [let] [Plusp] Test whether a number is positive [Por] Parallel, Boolean version of [or] [Position] Position of an item in a string or a list [Posp] A recognizer for the positive integers [Pprogn] Evaluate a sequence of forms that return [state] [Princ$] Print an atom [Print-base-p] Recognizer for print bases that are understood by functions such as [explode-nonnegative-integer] and [explode-atom]. [Prog2$] Execute two forms and return the value of the second one [Progn$] Execute a sequence of forms and return the value of the last one [Proofs-co] The proofs character output channel [Proper-consp] Recognizer for proper (null-terminated) non-empty lists [Pseudo-termp] A predicate for recognizing term-like s-expressions [Put-assoc] Modify an association list by associating a value with a key [Putprop] Update fast property lists [Quote] Create a constant [R-eqlable-alistp] Recognizer for a true list of pairs whose [cdr]s are suitable for [eql] [R-symbol-alistp] Recognizer for association lists with symbols as values [Random$] Obtain a random value [Rassoc] Look up value in association list [Rational-listp] Recognizer for a true list of rational numbers [Rationalp] Recognizer for rational numbers (ratios and integers) [Read-ACL2-oracle] Pop the oracle field of the state [Read-run-time] Read elapsed runtime [Real-listp] ACL2(r) recognizer for a true list of real numbers [Real/rationalp] Recognizer for rational numbers (including real number in ACL2(r)) [Realfix] Coerce to a real number [Realpart] Real part of a complex number [Rem] Remainder using [truncate] [Remove] Remove all occurrences [Remove-duplicates] Remove duplicates from a string or a list [Remove1] Remove first occurrences, testing using [eql] [Resize-list] List resizer in support of stobjs [Rest] Rest ([cdr]) of the list [Return-last] Return the last argument, perhaps with side effects [Revappend] Concatentate the [reverse] of one list to another [Reverse] Reverse a list or string [Rfix] Coerce to a rational number [Round] Division returning an integer by rounding off [Search] Search for a string or list in another string or list [Second] Second member of the list [Serialize-read] Read a serialized ACL2 object from a file [Serialize-write] Write an ACL2 object into a file [Set-difference$] Elements of one list that are not elements of another [Set-fmt-hard-right-margin] Set the right margin for formatted output [Set-fmt-soft-right-margin] Set the soft right margin for formatted output [Set-print-base] Control radix in which numbers are printed [Set-print-base-radix] Control radix in which numbers are printed and printing of the radix [Set-print-case] Control whether symbols are printed in upper case or in lower case [Set-print-radix] Control printing of the radix for numbers [Setenv$] Set an environment variable [Seventh] Seventh member of the list [Signed-byte-p] Recognizer for signed integers that fit in a specified bit width [Signum] Indicator for positive, negative, or zero [Sixth] Sixth member of the list [Spec-mv-let] Modification of [mv-let] supporting speculative and parallel execution [Standard-char-listp] Recognizer for a true list of standard characters [Standard-char-p] Recognizer for standard characters [Standard-co] The character output channel to which [ld] prints [Standard-oi] The standard object input ``channel'' [Standard-string-alistp] Recognizer for association lists with standard strings as keys [State-global-let*] Bind [state] global variables [String] [coerce] to a string [String-append] [concatenate] two strings [String-downcase] In a given string, turn upper-case [characters] into lower-case [String-equal] String equality without regard to case [String-listp] Recognizer for a true list of strings [String-upcase] In a given string, turn lower-case [characters] into upper-case [String<] Less-than test for strings [String<=] Less-than-or-equal test for strings [String>] Greater-than test for strings [String>=] Less-than-or-equal test for strings [Stringp] Recognizer for strings [Strip-cars] Collect up all first components of pairs in a list [Strip-cdrs] Collect up all second components of pairs in a list [Sublis] Substitute an alist into a tree [Subseq] Subsequence of a string or list [Subsetp] Test if every [member] of one list is a [member] of the other [Subst] A single substitution into a tree [Substitute] Substitute into a string or a list, using [eql] as test [Symbol-<] Less-than test for symbols [Symbol-alistp] Recognizer for association lists with symbols as keys [Symbol-listp] Recognizer for a true list of symbols [Symbol-name] The name of a symbol (a string) [Symbol-package-name] The name of the package of a symbol (a string) [Symbolp] Recognizer for symbols [Sys-call] Make a system call to the host operating system [Sys-call+] Make a system call to the host OS, returning status and output [Sys-call-status] Exit status from the preceding system call [Take] Initial segment (first n elements) of a list [Tenth] Tenth member of the list [Term-order] The ordering relation on terms used by ACL2 [The] The is a special form that can be used to optimize the execution efficiency of [guard]-verified ACL2 definitions, or (less frequently) to carry out a low-level run-time type checks. (Advanced) [Third] Third member of the list [Time$] Time an evaluation [Time-tracker] Display time spent during specified evaluation [True-list-listp] Recognizer for true (proper) lists of true lists [True-listp] Recognizer for proper (null-terminated) lists [Truncate] Division returning an integer by truncating toward 0 [Unary--] Arithmetic negation function [Unary-/] Reciprocal function [Union$] Elements of one list that are not elements of another [Unquote] Obtain the object being quoted [Unsigned-byte-p] Recognizer for natural numbers that fit in a specified bit width [Update-nth] Modify a list by putting the given value at the given position [Update-nth-array] Update a stobj array [Upper-case-p] Recognizer for upper case characters [Value-triple] Compute a value, optionally checking that it is not nil [With-fast-alist] ([with-fast-alist] name form) causes name to be a fast alist for the execution of form. [With-guard-checking] Suppressing or enable guard-checking for a form [With-live-state] Allow a reference to state in raw Lisp [With-local-state] Locally bind state [With-local-stobj] Locally bind a single-threaded object [With-output-lock] Provides a mutual-exclusion mechanism for performing output in parallel [With-serialize-character] Control output mode for print-object$ [With-stolen-alist] ([with-stolen-alist] name form) ensures that name is a fast alist at the start of the execution of form. At the end of execution, it ensures that name is a fast alist if and only if it was originally. That is, if name was not a fast alist originally, its hash table link is freed, and if it was a fast alist originally but its table was modified during the execution of form, that table is restored. Note that any extended table created from the original fast alist during form must be manually freed. [Without-evisc] Print output in full [Xor] Logical ``exclusive or'' [Zerop] Test an acl2-number against 0 [Zip] Testing an ``integer'' against 0 [Zp] Testing a ``natural'' against 0 [Zpf] Testing a nonnegative fixnum against 0") (ACL2-COUNT (BASICS ACL2-BUILT-INS) "A commonly used measure for justifying recursion (Acl2-count x) returns a nonnegative integer that indicates the ``size'' of its argument x. All [characters] and symbols have acl2-count 0. The acl2-count of a string is the number of [characters] in it, i.e., its length. The acl2-count of a [cons] is one greater than the sum of the acl2-counts of the [car] and [cdr]. The acl2-count of an integer is its absolute value. The acl2-count of a rational is the sum of the acl2-counts of the numerator and denominator. The acl2-count of a complex rational is one greater than the sum of the acl2-counts of the real and imaginary parts. Function: (defun acl2-count (x) (declare (xargs :guard t)) (if (consp x) (+ 1 (acl2-count (car x)) (acl2-count (cdr x))) (if (rationalp x) (if (integerp x) (integer-abs x) (+ (integer-abs (numerator x)) (denominator x))) (if (complex/complex-rationalp x) (+ 1 (acl2-count (realpart x)) (acl2-count (imagpart x))) (if (stringp x) (length x) 0)))))") (ACL2-CUSTOMIZATION (MISCELLANEOUS) "File of initial commands for ACL2 to run at [startup] ACL2 provides a mechanism to load automatically a so-called ``ACL2 customization file,'' via [ld], the first time [lp] is called in an ACL2 session. ACL2 looks for this file as follows. 1. If the host Lisp reads a non-empty value for the system's environment variable ACL2_CUSTOMIZATION, then that string value is used for the customization file name. In this case, if the file does not exist or if the string is \"NONE\" then there is no customization file. Notes: * If the customization file name is a relative pathname (see [pathname]), then the pathname is considered relative to the connected book directory (see [cbd]). * If this variable is not already defined, then its value is set to NONE when books are certified using [cert.pl] or other, legacy Make-based certification tools. 2. Otherwise (empty environment variable value), file \"acl2-customization.lsp\" or \"acl2-customization.lisp\" on the connected book directory (see [cbd]), generally the current directory, is the customization file (in that order) if either exists. 3. Otherwise file \"acl2-customization.lsp\" or \"acl2-customization.lisp\" on your home directory is the customization file (in that order), if either exists (except, this case is skipped on Windows operating systems. Except for the fact that this [ld] command is not typed explicitly by you, it is a standard [ld] command, with one exception: any settings of [ld] specials are remembered once this call of [ld] has completed. For example, suppose that you start your customization file with (set-ld-skip-proofsp t state), so that proofs are skipped as it is loaded with [ld]. Then the [ld] special [ld-skip-proofsp] will remain t after the [ld] has completed, causing proofs to be skipped in your ACL2 session, unless your customization file sets this variable back to nil, say with (set-ld-skip-proofsp nil state). If the customization file exists, it is loaded with [ld] using the usual default values for the [ld] specials (see [ld]). Thus, if an error is encountered, no subsequent forms in the file will be evaluated. To create a customization file it is recommended that you first give it a name other than \"acl2-customization.lsp\" or \"acl2-customization.lisp\" so that ACL2 does not try to include it prematurely when you next enter [lp]. Then, while in the uncustomized [lp], explicitly invoke [ld] on your evolving (but renamed) customization file until all forms are successfully evaluated. The same procedure is recommended if for some reason ACL2 cannot successfully evaluate all forms in your customization file: temporarily rename your customization file so that ACL2 does not try to [ld] it automatically and then debug the new file by explicit calls to [ld]. WARNING! If you certify a book after the (automatic) loading of a customization file, the forms in that file will be part of the [portcullis] of the [books] you certify! That is, the forms in your customization file at certification time will be loaded whenever anybody uses the [books] you are certifying. Since customization files generally contain idiosyncratic [command]s, you may not want yours to be part of the [books] you create for others. Thus, if you have a customization file then you may want to invoke :[ubt] 1 before certifying any [books]; alternatively, see [certify-book!] for automatic invocation of [ubt]. On the other hand, if you wish to prevent undoing commands from the customization file, see [reset-prehistory]. Finally, we note that except on Windows-based systems, if there is a file acl2-init.lsp in your home directory, then it will be loaded into raw Lisp when ACL2 is invoked.") (ACL2-DEFAULTS-TABLE (TABLE) "A [table] specifying certain defaults, e.g., the default [defun-mode] Example Forms: (table acl2-defaults-table :defun-mode) ; current default defun-mode (table acl2-defaults-table :defun-mode :program) ; set default defun-mode to :program See [table] for a discussion of tables in general. The legal keys for this [table] are shown below. They may be accessed and changed via the general mechanisms provided by [table]s. However, there are often more convenient ways to access and/or change the defaults. (See also the note below.) :defun-mode the default [defun-mode], which must be :[program] or :[logic]. See [defun-mode] for a general discussion of [defun-mode]s. The :[defun-mode] key may be conveniently set by keyword commands naming the new [defun-mode], :[program] and :[logic]. See [program] and see [logic]. :enforce-redundancy if t, cause ACL2 to insist that most events are redundant (see [redundant-events]); if :warn, cause a warning instead of an error for such non-redundant events; else, nil. See [set-enforce-redundancy]. :verify-guards-eagerness an integer between 0 and 2 indicating how eager the system is to verify the [guard]s of a [defun] event. See [set-verify-guards-eagerness]. :compile-fns When this key's value is t, functions are compiled when they are [defun]'d; otherwise, the value is nil. (Except, this key's value is ignored when explicit compilation is suppressed; see [compilation].) To set the flag, see [set-compile-fns]. :measure-function the default measure function used by [defun] when no :measure is supplied in [xargs]. The default measure function must be a function symbol of one argument. Let mfn be the default measure function and suppose no :measure is supplied with some recursive function definition. Then [defun] finds the first formal, var, that is tested along every branch and changed in each recursive call. The system then ``guesses'' that (mfn var) is the :measure for that [defun]. :well-founded-relation the default well-founded relation used by [defun] when no :[well-founded-relation] is supplied in [xargs]. The default well-founded relation must be a function symbol, rel, of two arguments about which a :[well-founded-relation] rule has been proved. See [well-founded-relation]. :bogus-defun-hints-ok When this key's value is t, ACL2 allows :hints for nonrecursive function definitions. Otherwise, the value is the nil (the default) or :warn (which makes the check but merely warns when the check fails). See [set-bogus-defun-hints-ok]. :bogus-mutual-recursion-ok When this key's value is t, ACL2 skips the check that every function in a [mutual-recursion] (or [defuns]) ``clique'' calls at least one other function in that ``clique.'' Otherwise, the value is nil (the default) or :warn (which makes the check but merely warns when the check fails). See [set-bogus-mutual-recursion-ok]. :irrelevant-formals-ok When this key's value is t, the check for irrelevant formals is bypassed; otherwise, the value is the keyword nil (the default) or :warn (which makes the check but merely warns when the check fails). See [irrelevant-formals] and see [set-irrelevant-formals-ok]. :ignore-ok When this key's value is t, the check for ignored variables is bypassed; otherwise, the value is the keyword nil (the default) or :warn (which makes the check but merely warns when the check fails). See [set-ignore-ok]. :bdd-constructors This key's value is a list of function symbols used to define the notion of ``BDD normal form.'' See [bdd-algorithm] and see [hints]. :ttag This key's value, when non-nil, allows certain operations that extend the trusted code base beyond what is provided by ACL2. See [defttag]. See [defttag]. :state-ok This key's value is either t or nil and indicates whether the user is aware of the syntactic restrictions on the variable symbol STATE. See [set-state-ok]. :backchain-limit This key's value is a list of two ``numbers.'' Either ``number'' may optionally be nil, which is treated like positive infinity. The numbers control backchaining through hypotheses during type-set reasoning and rewriting. See [backchain-limit]. :default-backchain-limit This key's value is a list of two ``numbers.'' Either ``number'' may optionally be nil, which is treated like positive infinity. The numbers are used respectively to set the backchain limit of a rule if one has not been specified. See [backchain-limit]. :step-limit This key's value is either nil or a natural number not exceeding the value of *default-step-limit*. If the value is nil or the value of *default-step-limit*, there is no limit on the number of ``steps'' that ACL2 counts during a proof: currently, the number of top-level rewriting calls. Otherwise, the value is the maximum number of such calls allowed during evaluation of any event. See [set-prover-step-limit]. :rewrite-stack-limit This key's value is a nonnegative integer less than (expt 2 28). It is used to limit the depth of calls of ACL2 rewriter functions. See [rewrite-stack-limit]. :let*-abstractionp This key affects how the system displays subgoals. The value is either t or nil. When t, let* expressions are introduced before printing to eliminate common subexpressions. The actual goal being worked on is unchanged. :case-split-limitations This key's value is a list of two ``numbers.'' Either ``number'' may optionally be nil, which is treated like positive infinity. The numbers control how the system handles case splits in the simplifier. See [set-case-split-limitations]. :include-book-dir-alist This key's value is used by [include-book]'s :DIR argument to associate a directory with a keyword. An exception is the keyword :SYSTEM for the books/ directory; see [include-book], in particular the section on ``Books Directory.'' Also see [add-include-book-dir] and [add-include-book-dir!]. :match-free-default This key's value is either :all, :once, or nil. See [set-match-free-default]. :match-free-override This key's value is a list of runes. See [add-match-free-override]. :match-free-override-nume This key's value is an integer used in the implementation of [add-match-free-override], so that only existing runes are affected by that event. :non-linearp This key's value is either t or nil and indicates whether the user wishes ACL2 to extend the linear arithmetic decision procedure to include non-linear reasoning. See [non-linear-arithmetic]. :tau-auto-modep This key's value is either t or nil and indicates whether the user wishes ACL2 to look for opportunities to create :[tau-system] rules from all suitable defuns and from all suitable defthms (with non-nil :[rule-classes]). See [set-tau-auto-mode]. :ruler-extenders This key's value may be a list of symbols, indicating those function symbols that are not to block the collection of rulers; see [defun]. Otherwise the value is :all to indicate all function symbols, i.e., so that no function symbol blocks the collection of rulers. If a list is specified (rather than :all), then it may contain the keyword :lambdas, which has the special role of specifying all lambda applications. No other keyword is permitted in the list. See [ruler-extenders]. :memoize-ideal-okp This key is only legal in a [hons-enabled] executable (see [hons-and-memoization]). Its value must be either t, nil, or :warn. If the value is nil or not present, then it is illegal by default to [memoize] a :[logic] mode function that has not been [guard]-verified (see [verify-guards]), sometimes called an ``ideal-mode'' function. This illegality is the default because such calls of such functions in the ACL2 loop are generally evaluated in the logic (using so-called ``executable counterpart'' definitions), rather than directly by executing calls of the corresponding (memoized) raw Lisp function. However, such a raw Lisp call can be made when the function is called by a :[program] mode function, so we allow you to override the default behavior by associating the value t or :warn with the key :memoize-ideal-okp, where with :warn you get a suitable warning. Note that you can also allow memoization of ideal-mode functions by supplying argument :ideal-okp to your memoization event (see [memoize]), in which case the value of :memoize-ideal-okp in the acl2-defaults-table is irrelevant. Note: Unlike all other [table]s, acl2-defaults-table can affect the soundness of the system. The [table] mechanism therefore enforces on it a restriction not imposed on other [table]s: when [table] is used to update the acl2-defaults-table, the key and value must be variable-free forms. Thus, while (table acl2-defaults-table :defun-mode :program), (table acl2-defaults-table :defun-mode ':program), and (table acl2-defaults-table :defun-mode (compute-mode *my-data*)) are all examples of legal [events] (assuming compute-mode is a function of one non-[state] argument that produces a [defun-mode] as its single value), (table acl2-defaults-table :defun-mode (compute-mode (w state))) is not legal because the value form is [state]-sensitive. Consider for example the following three [events] which one might make into the text of a book. (in-package \"ACL2\") (table acl2-defaults-table :defun-mode (if (ld-skip-proofsp state) :logic :program)) (defun crash-and-burn (x) (car x)) The second event is illegal because its value form is [state]-sensitive. If it were not illegal, then it would set the :[defun-mode] to :[program] when the book was being certified but would set the [defun-mode] to :[logic] when the book was being loaded by [include-book]. That is because during certification, [ld-skip-proofsp] is nil (proof obligations are generated and proved), but during book inclusion [ld-skip-proofsp] is non-nil (those obligations are assumed to have been satisfied.) Thus, the above book, when loaded, would create a function in :[logic] mode that does not actually meet the conditions for such status. For similar reasons, [table] [events] affecting acl2-defaults-table are illegal within the scope of [local] forms. That is, the text (in-package \"ACL2\") (local (table acl2-defaults-table :defun-mode :program)) (defun crash-and-burn (x) (car x)) is illegal because acl2-defaults-table is changed locally. If this text were acceptable as a book, then when the book was certified, crash-and-burn would be processed in :[program] mode, but when the certified book was included later, crash-and-burn would have :[logic] mode because the [local] event would be skipped. The text (in-package \"ACL2\") (program) ;which is (table acl2-defaults-table :defun-mode :program) (defun crash-and-burn (x) (car x)) is acceptable and defines crash-and-burn in :[program] mode, both during certification and subsequent inclusion. We conclude with an important observation about the relation between acl2-defaults-table and [include-book], [certify-book], and [encapsulate]. Including or certifying a book never has an effect on the acl2-defaults-table, nor does executing an [encapsulate] event; we always restore the value of this [table] as a final act. (Also see [include-book], see [encapsulate], and see [certify-book].) That is, no matter how a book fiddles with the acl2-defaults-table, its value immediately after including that book is the same as immediately before including that book. If you want to set the acl2-defaults-table in a way that persists, you need to do so using [command]s that are not inside [books]. It may be useful to set your favorite defaults in your [ACL2-customization] file; see [ACL2-customization].") (ACL2-DOC (DOCUMENTATION) "A custom Emacs browser for reading ACL2 [documentation] As discussed elsewhere (see [documentation]), the web-based {ACL2+Books Manual | http://www.cs.utexas.edu/users/moore/acl2/v7-1/combined-manual/index.html} provides a way to browse the combined documentation for the ACL2 system and community books. This documentation can also be read at the terminal using the :[doc] command, though documentation for [books] will only be included for those books that have been included in the session. In this topic we describe how to browse the documentation using ACL2-Doc, a browser for reading ACL2 and books documentation inside Emacs. While ACL2-Doc is much like Emacs Info, it is a separate system that provides some additional functionality. In order to use ACL2-Doc, load the distributed file emacs/acl2-doc.el into Emacs. This will happen automatically if you load emacs/emacs-acl2.el, which will happen automatically if you put the following form in your ~/.emacs file, replacing DIR by a path to your ACL2 installation. (load \"DIR/emacs/emacs-acl2.el\") Then to start the browser at the top-level topic, either execute the Emacs command meta-x acl2-doc or else type: Control-t g By default you will browse the ACL2+Books Manual, though if you are using a git version between ACL2 releases then you may be queried; more on that below. You can enter the ACL2-Doc browser at a specific documentation topic as follows (in analogy to Emacs command Meta-.): Control-t . In each of the cases above, you will now be in a buffer called \"acl2-doc\", which will be displaying the top-level ACL2 topic in a special mode, the ACL2-Doc major mode. That mode provides the following key bindings; you can also see these by typing Control-h m while in that buffer. acl2-doc-go! g acl2-doc-go h acl2-doc-help i acl2-doc-index , acl2-doc-index-next < acl2-doc-index-previous l acl2-doc-last n acl2-doc-search-next p acl2-doc-search-previous q acl2-doc-quit r acl2-doc-return s acl2-doc-search S acl2-doc-re-search t acl2-doc-top u acl2-doc-up w acl2-doc-where SPC scroll-up TAB acl2-doc-tab Control-TAB acl2-doc-tab-back D acl2-doc-rendered-combined-download H acl2-doc-history I acl2-doc-initialize You can see the documentation for each of these in the usual way, using Control-h k {key} or Control-h f {command}. Here is what you will find in each case if you do that. acl2-doc-go! Go to the topic occurring at the cursor position. g acl2-doc-go Go to the specified topic; performs completion. h acl2-doc-help Go to the ACL2-DOC topic to read about how to use the ACL2-Doc browser. i acl2-doc-index Go to the specified topic or else one containing it as a substring; performs completion. If the empty string is supplied, then go to the index buffer. Otherwise, with prefix argument, consider only descendents of the topic supplied in response to a prompt. Note that the index buffer is in ACL2-Doc mode; thus, in particular, you can type while standing on a topic in order to go directly to that topic. , acl2-doc-index-next Find the next topic containing, as a substring, the topic of the most recent i command. Note: if this is the first \",\" or \"<\" after an exact match from \"i\", then start the topic search alphabetically from the beginning, but avoid a second hit on the original topic. < acl2-doc-index-previous Find the previous topic containing, as a substring, the topic of the most recent i command. Note: if this is the first \",\" or \"<\" after an exact match from \"i\", then start the topic search alphabetically (backwards) from that exact match. l acl2-doc-last Go to the last topic visited. n acl2-doc-search-next Find the next occurrence for the most recent search or regular expression search. p acl2-doc-search-previous Find the previous occurrence for the most recent search or regular expression search. Note: as for \"n\", the cursor will end up at the end of the match. q acl2-doc-quit Quit the ACL2-Doc browser. r acl2-doc-return Return to the last topic visited, popping the stack of such topics. s acl2-doc-search Search forward from the top of the manual for the input string. If the search succeeds, then go to that topic with the cursor put immediately after the found text, with the topic name displayed in the minibuffer. With prefix argument, consider (also for subsequent \"n\" and \"p\" commands) only descendents of the topic supplied in response to a prompt. S acl2-doc-re-search Perform a regular expression search, forward from the top of the manual, for the input string. If the search succeeds, then go to that topic with the cursor put immediately after the found text, with the topic name displayed in the minibuffer. With prefix argument, consider (also for subsequent \"n\" and \"p\" commands) only descendents of the topic supplied in response to a prompt. t acl2-doc-top Go to the top topic. u acl2-doc-up Go to the parent of the current topic. w acl2-doc-where Display the topic name in the minibuffer, together with the manual name (ACL2+Books Manual or ACL2 User's Manual) SPC scroll-up Scroll up (same as Control-v) TAB acl2-doc-tab Visit the next link after the cursor on the current page, searching from the top if no link is below the cursor. Control-TAB acl2-doc-tab-back Visit the previous link before the cursor on the current page, searching from the bottom if no link is below the cursor. D Download the ``bleeding edge'' ACL2+Books Manual from the web; then restart the ACL2-Doc browser to view that manual. H acl2-doc-history Visit a buffer that displays the names of all visited topics in order, newest at the bottom. That buffer is in acl2-doc mode; thus the usual acl2-doc commands may be used. In particular, you can visit a displayed topic name by putting your cursor on it and typing . I acl2-doc-initialize Restart the ACL2-Doc browser, clearing its state. With prefix argument, toggle between the ACL2 User's Manual (the default) and the ACL2+Books Manual. For the latter, it will be necessary first to create file books/system/doc/rendered-doc-combined.lsp; see :DOC acl2-doc. Color By default, links in square brackets will be shown in blue. You can customize this behavior by setting (e.g., in your .emacs file) the Emacs variable *acl2-doc-link-color* to the desired link color, or to nil if you don't want the links to be in color. For example: (setq *acl2-doc-link-color* \"#FF0000\") ; red (setq *acl2-doc-link-color* \"Green\") ; green (setq *acl2-doc-link-color* nil) ; no special color for links The Two Manuals ACL2-Doc can display the ACL2 User's Manual, which includes documentation for the ACL2 system but not for the [community-books]. But by default, ACL2-Doc will display the ACL2+Books Manual, which includes documentation for those books as well. To change which of these two manuals you display, just give a prefix argument to the \"I\" command, as indicated above. If you are using a git version of ACL2 and the books, between releases, then you may need to download an extra file in order to browse the ACL2+Books Manual. Most likely you will just answer y when queried about downloading the file when first using ACL2-Doc. If you want more details, see the last of the Notes below. Notes * You might find that when you attempt to follow [some-broken-link], you find yourself at the [broken-link] topic. If you are using the ACL2 User's Manual rather than the ACL2+Books Manual, the reason might be that some-broken-link is documented in a book, not in the ACL2 system. In that case, the broken-link page will show you where to find that book; but if you want to read the documentation for some-broken-link in the ACL2-Doc browser, you can do so by switching to the ACL2+Books Manual. See the I command, documented above. * Files with names ending in .acl2-doc will come up in ACL2-Doc mode. Thus, you may wish to save a file with that extension, for example bookmarks.acl2-doc, that contains your favorite bookmarks. You may wish to use the history command (H) to obtain a list of names of visited topics, in order to create an initial such file. * Many commands offer defaults, and many offer completion. The default is determined by cursor position: if the cursor is sitting on a letter of a documentation topic name, or on a space character immediately after it, then that name will be offered as the default. * Square brackets indicate documentation topic names, for example: [acl2-doc]. The square brackets are really there, for example when you are searching using \"s\", \"S\", or \"n\". However, for purposes of determining the default name (see above), the only effect of the enclosing square brackets is to extend the region in which the default is offered. For example, consider the string \"[acl2-doc]\": the default name of \"acl2-doc\" is offered if the cursor is on either square bracket. But links have some idiosyncrasies. 1. Topic names, including links `[..]' to topic names, are printed relative to the ACL2 package. Especially in the case of the ACL2+Books Manual, you may therefore see links that include package prefixes. Here, for example, is a sentence from the documentation for [gl] in the ACL2+Books Manual. We call these structures [gl::symbolic-objects]. The \"gl\" package prefix allows commands to pick up \"gl::symbolic-objects\" as the name to use as a default, so that for example, hitting will take you to that topic. But when reading the sentence, for best results you should ignore package prefixes. So for example, you would read the sentence above as follows. We call these structures symbolic-objects. 2. Topic names that originally contained spaces now have underscores in place of the spaces. So for example, the topic [cert.pl] in the ACL2+Books Manual contains a link to the topic originally named as follows. 1. Certifying Simple Books This link shows up in the ACL2-Doc browser (and in output from the :[doc] command at the terminal) as: [1._Certifying_Simple_Books]. When you see a potential link that does include whitespace, then it will not work, probably because the original markup specified English text that differs from the topic name. For example, consider the following passage from the documentation for [gl]. GL requires ACL2(h) because it makes extensive use of [hons-and-memoization]. Some optional parts of GL also require [trust tags]. The first link will take you to the topic, [hons-and-memoization]. But the second link was actually written to be a link to the documentation for [defttag]. The command will not work on that second link; unfortunately, the alternative is to use the g command and specify defttag in the minibuffer. Of course, the web-based browser avoids these idiosyncrasies (see [xdoc::save]), hence may be more appropriate for those who have no particular preference for using Emacs to browse the documentation. * Searching using the \"s\" or \"S\" command is carried out by searching top-to-bottom in a hidden Emacs buffer that contains all of the documentation. The topics are listed in the following order according to topic name: 1. All topics whose names reside in the \"ACL2\" package; 2. All topics whose names reside in the \"ACL2-PC\" package; and, for the ACL2+Books Manual, 3. All other topics, sorted by [symbol-name] and then by [symbol-package-name]. * You may be queried, regarding whether you want to browse the ACL2+Books Manual, which is preferred, or the ACL2 User's Manual, which omits documentation for the books. Both of these manuals are based on files that you will have if you are using a released version of ACL2 (after Version 6.3). But if you are using a {git version | https://github.com/acl2/acl2/}, then to use the ACL2+Books Manual you will need an extra file. You can build this file yourself, as described below but you may prefer to download it: for example, when you start ACL2-Doc, you may be given the option of downloading {a tarball for the latest ``bleeding edge'' copy | http://www.cs.utexas.edu/users/moore/acl2/manuals/current/rendered-doc-combined.lsp.gz} and extracting into directory system/doc/ of your community books directory. Indeed, the system will do all this for you if you answer y to that query. Alternatively, you can insist on a download of a ``bleeding edge'' version by using the `D' command. However, if you prefer to browse the ACL2 User's Manual (without the books), you can put the following form into your ~/.emacs file, above the form that loads the code for ACL2-Doc (see above). (defvar *acl2-doc-top-default* 'TOP) If you prefer to build rendered-doc-combined.lsp yourself, you can do so as follows. 1. Build ([hons-enabled]) ACL2: make large 2. Build the manual, optionally supplying your \"make\" command with a \"-j\" argument. If \"acl2\" invokes the ACL2 executable that you just built, then you may omit \"ACL2=acl2\" below; otherwise replace \"acl2\" by a suitable executable. cd books make all USE_QUICKLISP=1 ACL2_BOOK_CERTS=doc/top.cert ACL2=acl2 3. Build the file books/system/doc/rendered-doc-combined.lsp as follows, still standing in the books directory, perhaps modifying \"ACL2=acl2\" as discussed above. cd books make doc/top.cert USE_QUICKLISP=1 ACL2=acl2") (ACL2-HELP (ABOUT-ACL2) "The acl2-help mailing list You can email questions about ACL2 usage to the acl2-help mailing list: acl2-help@utlists.utexas.edu. If you have more general questions about ACL2, for example, about projects completed using ACL2, you may prefer the acl2 mailing list, acl2@utlists.utexas.edu, which tends to have wider distribution.") (ACL2-NUMBER-LISTP (NUMBERS LISTS ACL2-BUILT-INS) "Recognizer for a true list of numbers The predicate acl2-number-listp tests whether its argument is a true list of numbers. Function: (defun acl2-number-listp (l) (declare (xargs :guard t)) (cond ((atom l) (eq l nil)) (t (and (acl2-numberp (car l)) (acl2-number-listp (cdr l))))))") (ACL2-NUMBERP (NUMBERS ACL2-BUILT-INS) "Recognizer for numbers (acl2-numberp x) is true if and only if x is a number, i.e., a rational or complex rational number.") (ACL2-SEDAN (ACL2-TUTORIAL) "ACL2 Sedan interface Many successful ACL2 users run in an shell under Emacs; see [emacs]. However, those not familiar with Emacs may prefer to start with an Eclipse-based interface initiallly developed by Peter Dillinger and Pete Manolios called the {ACL2 Sedan | http://acl2s.ccs.neu.edu/acl2s/doc/} or ``ACL2s''. ACL2 sessions in the ACL2 Sedan can utilize non-standard extensions and enhancements, especially geared toward new users, termination reasoning, and attaching rich user interfaces. These extensions are {generally available | http://acl2s.ccs.neu.edu/acl2s/src/acl2-extensions} as certifiable ACL2 books. (Some code originating from this project has been migrated to the ACL2 community books, but only after it was quite stable.) Thanks to Peter Dillinger, Pete Manolios, Daron Vroon, and Harsh Raju Chamarthi for their work on the ACL2 Sedan and for making their books available to ACL2 users.") (ACL2-TUTORIAL (ACL2) "Tutorial introduction to ACL2 To learn about ACL2, read at least the following two links. * [Industrial Applications of ACL2] (10 minutes) to help you understand what sophisticated users can do; * [A Flying Tour] (10 minutes) to get an overview of the system and what skills the user must have. If you want to learn how to use ACL2, we recommend that you read a selection of the materials referenced below, depending on your learning style, and do suggested exercises. * [A Walking Tour] (1 hour) provides an overview of the theorem prover. * The {Try ACL2 | http://tryacl2.org} web site provides interactive lessons to get you started using ACL2. * See [introduction-to-the-theorem-prover] (10-40 hours) for instruction on how to interact with the system. Unlike the three documents above, this document expects you to think! It cites the necessary background pages on programming in ACL2 and on the logic and then instructs you in [the-method], which is how expert users use ACL2. It concludes with some challenge problems for the ACL2 beginner (including solutions) and an FAQ. Most users will spend several hours a day for several days working through this material. * The book {Computer-Aided Reasoning: An Approach | http://www.cs.utexas.edu/users/moore/publications/acl2-books/car/index.html} is worth a careful read, as you work exercises and learn [the-method]. * [Annotated ACL2 Scripts and Demos] contains relatively elementary proof scripts that have been annotated to help train the newcomer. * Many files (``books'') in the ACL2 community books (see [community-books]) are extensively annotated. * An [Alternative Introduction] document, while largely subsumed by the [Introduction to the Theorem Prover] mentioned above, still might be useful because it covers much of the tutorial material in a different way. At this point you are probably ready to use ACL2 on your own small projects. A common mistake for beginners is to browse the documentation and then try to do something that is too big! Think of a very small project and then simplify it! Note that ACL2 has a very supportive user network. See the link to ``Mailing Lists'' on the {ACL2 home page | http://www.cs.utexas.edu/users/moore/acl2}. The topics listed below are a hodge podge, developed over time. Although some of these are not mentioned above, you might find some to be useful as well. Subtopics [ACL2-as-standalone-program] Calling ACL2 from another program [ACL2-sedan] ACL2 Sedan interface [Advanced-features] Some advanced features of ACL2 [Alternative-introduction] Introduction to ACL2 [Annotated-ACL2-scripts] Examples of ACL2 scripts [Emacs] Emacs support for ACL2 [Interesting-applications] Some industrial examples of ACL2 use [Introduction-to-the-theorem-prover] How the theorem prover works -- level 0 [Nqthm-to-ACL2] ACL2 analogues of Nqthm functions and commands [Pages_Written_Especially_for_the_Tours] Pages Written Especially for the Tours [Startup] How to start using ACL2; the ACL2 [command] loop [The-method] How to find proofs [Tidbits] Some basic hints for using ACL2 [Tips] Some hints for using the ACL2 prover") (ACL2-USER (PACKAGES) "A package the ACL2 user may prefer This package imports the standard Common Lisp symbols that ACL2 supports and also a few symbols from package \"ACL2\" that are commonly used when interacting with ACL2. You may prefer to select this as your current package so as to avoid colliding with ACL2 system names. This package imports the symbols listed in *common-lisp-symbols-from-main-lisp-package*, which contains hundreds of CLTL function and macro names including those supported by ACL2 such as [cons], [car], and [cdr]. It also imports the symbols in *acl2-exports*, which contains a few symbols that are frequently used while interacting with the ACL2 system, such as [implies], [defthm], and [rewrite]. It imports nothing else. Thus, names such as [alistp], [member-equal], and [type-set], which are defined in the \"ACL2\" package are not present here. If you find yourself frequently colliding with names that are defined in \"ACL2\" you might consider selecting \"ACL2-USER\" as your current package (see [in-package]). If you select \"ACL2-USER\" as the current package, you may then simply type [member-equal] to refer to acl2-user::member-equal, which you may define as you see fit. Of course, should you desire to refer to the \"ACL2\" version of [member-equal], you will have to use the \"ACL2::\" prefix, e.g., acl2::member-equal. If, while using \"ACL2-USER\" as the current package, you find that there are symbols from \"ACL2\" that you wish we had imported into it (because they are frequently used in interaction), please bring those symbols to our attention. For example, should [union-theories] and [universal-theory] be imported? Except for stabilizing on the ``frequently used'' names from \"ACL2\", we intend never to define a symbol whose [symbol-package-name] is \"ACL2-USER\".") (ACL2P-KEY-CHECKPOINTS (PARALLEL-PROOF) "Key checkpoints in ACL2(p) This [documentation] topic relates to the experimental extension of ACL2 supporting parallel execution and proof; see [parallelism]. For printing output, the parallel version of the waterfall follows the precedent of [gag-mode]. The idea behind gag mode is to print only the subgoals most relevant to debugging a failed proof attempt. These subgoals are called 'key checkpoints' (see [set-gag-mode] for the definition of ``key'' and ``checkpoint''), and we restrict the default output mode for the parallel version of the waterfall to printing checkpoints similar to these key checkpoints. As of this writing, we are aware of exactly one discrepancy between gag mode's key checkpoints and the parallel version of the waterfall's checkpoints. This discrepancy occurs when using ``by'' hints (see [hints]). As an example, take the following form, which attempts to prove a non-theorem: (thm (equal (append x y z) (append z (append y x))) :hints ((\"Subgoal *1/2'''\" :by nil))) With waterfall parallelism enabled, Subgoal *1/2'' will be printed as a key checkpoint. This is different from using [gag-mode] while running the serial version of the waterfall, which skips printing the subgoal as a checkpoint. For those familiar with the ACL2 waterfall, we note that that the parallel version of the waterfall prints key checkpoints that are unproved in the following sense: a subgoal is a key checkpoint if it leads, in the current call of the waterfall, to a goal that is pushed for induction.") (ACL2S (POINTERS) "See [ACL2-sedan].") (ACL2_AS_AN_INTERACTIVE_THEOREM_PROVER (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "ACL2 as an Interactive Theorem Prover The ACL2 theorem prover finds proofs in the ACL2 logic. It can be automatic. But most often the user must help it. {IMAGE} The user usually guides ACL2 by suggesting that it first prove key lemmas. Lemmas are just theorems used in the proofs of other theorems.") (ACL2_AS_AN_INTERACTIVE_THEOREM_PROVER_{CONT} (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "ACL2 as an Interactive Theorem Prover (cont) [{IMAGE}] When ACL2 proves a lemma, it is converted into one or more rules and stored in a database. The theorem prover is rule-driven. By proving lemmas you can configure ACL2 to behave in certain ways when it is trying to prove formulas in a certain problem domain. The expert user can make ACL2 do amazingly ``smart'' looking things. But it would be wrong to think that ACL2 knows the mathematical content of a formula just because it has proved it. What ACL2 knows --- all ACL2 knows --- is what is encoded in its rules. There are many types of rules (see [rule-classes] [{ICON}]). Many formulas can be effectively coded as rules. But by the same token, it is possible to encode a formula as a rule that is so ineffective it cannot even prove itself! The way a formula is stored as a rule is entirely up to the user. That is, you determine how ACL2 should use each formula that it proves. The most common kind of rule is the rewrite rule. It is so common that if you don't tell ACL2 how to store a formula, it stores it as a rewrite rule. [{IMAGE}]") (ACL2_CHARACTERS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "ACL2 Characters ACL2 accepts 256 distinct characters, which are the characters obtained by applying the function [code-char] [{ICON}] to each integer from 0 to 255. Among these, Common Lisp designates certain ones as *standard-characters*, namely those of the form (code-char n) where n is from 33 to 126, together with #\\Newline and #\\Space. The actual standard characters may be viewed by evaluating the constant expression *standard-chars*. The standard character constants are written by writing a hash mark followed by a backslash (#\\) followed by the character. The function [characterp] [{ICON}] recognizes characters. For more details, See [characters] [{ICON}].") (ACL2_CONSES_OR_ORDERED_PAIRS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "ACL2 Conses or Ordered Pairs The function [cons] [{ICON}] creates an ordered pair. [Car] [{ICON}] and [cdr] [{ICON}] return the first and second components, respectively, of an ordered pair. The function [consp] [{ICON}] recognizes ordered pairs. Ordered pairs are used to represent lists and trees. See any Common Lisp documentation for a discussion of how list constants are written and for the many list processing functions available. Also, see [programming] [{ICON}] where we list all the ACL2 primitive functions. Here are some examples of list constants to suggest their syntax. '(a . b) ; a pair whose car is 'a and cdr is 'b '(a . nil) ; a pair whose car is 'a and cdr is nil '(a) ; another way to write the same thing '(a b) ; a pair whose car is 'a and cdr is '(b) '(a b c) ; a pair whose car is 'a and cdr is '(b c) ; i.e., a list of three symbols, a, b, and c. '((a . 1) (b . 2)) ; a list of two pairs It is useful to distinguish ``proper'' conses from ``improper'' ones, the former being those cons trees whose right-most branch terminates with nil. A ``true list'' (see [true-listp] [{ICON}]) is either nil or a proper cons. (A b c . 7) is an improper cons and hence not a true list.") (ACL2_IS_AN_UNTYPED_LANGUAGE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "ACL2 is an Untyped Language The example ACL2 !>(app '(a b c) 27) (A B C . 27) illustrates the fact that ACL2's logic is untyped (click [here] for a brief discussion of the typed versus untyped nature of the logic). The definition of app makes no restriction of the arguments to lists. The definition says that if the first argument satisfies [endp] [{ICON}] then return the second argument. In this example, when app has recursed three times down the cdr of its first argument, '(a b c), it reaches the final nil, which satisfies endp, and so 27 is returned. It is naturally consed into the emerging list as the function returns from successive recursive calls (since cons does not require its arguments to be lists, either). The result is an ``improper'' list, (a b c . 27). You can think of (app x y) as building a binary tree by replacing the right-most tip of the tree x with the tree y.") (ACL2_STRINGS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "ACL2 Strings Strings of ACL2 [characters] are written as sequences of characters delimited by ``double quotation marks'' (\"). To put a double quotation mark in a string (or, any other character such as backslash or newline that seems to cause problems), escape it by preceding it with a backslash (\\). The function [stringp] [{ICON}] recognizes strings and [char] [{ICON}] will fetch the nth character of a string. There are many other primitives for handling strings, such as [string<] [{ICON}] for comparing two strings lexicographically. We suggest you See [programming] [{ICON}] where we list all of the primitive ACL2 functions. Alternatively, see any Common Lisp language documentation.") (ACL2_SYMBOLS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "ACL2 Symbols Common Lisp's symbols are a data type representing words. They are frequently regarded as atomic objects in the sense that they are not frequently broken down into their constituents. Often the only important properties of symbols is that they are not numbers, characters, strings, or lists and that two symbols are not equal if they look different (!). Examples of symbols include PLUS and SMITH::ABC. All function and variable names in ACL2 are symbols. When symbols are used as constants they must be quoted, as in 'PLUS. The symbol T is commonly used as the Boolean ``true.'' The symbol NIL is commonly used both as the Boolean ``false'' and as the ``empty list.'' Despite sometimes being called the ``empty list'' NIL is a symbol not an ``empty cons.'' Unlike other symbols, T and NIL may be used as constants without quoting them. Usually, symbols are written as sequences of alphanumeric characters other than those denoting numbers. Thus, A12, +1A and 1+ are symbols but +12 is a number. Roughly speaking, when symbols are read lower case characters are converted to upper case, so we frequently do not distinguish ABC from Abc or abc. Click [here] for information about case conversion when symbols are read. However, any character can be used in a symbol, but some characters must be ``escaped'' to allow the Lisp reader to parse the sequence as a symbol. For example, |Abc| is a symbol whose first character is capitalized and whose remaining characters are in lower case. |An odd duck| is a symbol containing two #\\Space characters. See any Common Lisp documentation for the syntactic rules for symbols. Technically, a symbol is a special kind of pair consisting of a package name (which is a string) and a symbol name (which is also a string). (See [symbol-package-name] [{ICON}] and see [symbol-name] [{ICON}].) The symbol SMITH::ABC is said to be in package \"SMITH\" and to have the symbol name \"ABC\". The symbol ABC in package \"SMITH\" is generally not equal to the symbol ABC in package \"JONES\". However, it is possible to ``import'' symbols from one package into another one, but in ACL2 this can only be done when the package is created. (See [defpkg] [{ICON}].) If the [current-package] [{ICON}] is \"SMITH\" then SMITH::ABC may be more briefly written as just ABC. [Intern] [{ICON}] ``creates'' a symbol of a given name in a given package.") (ACL2_SYSTEM_ARCHITECTURE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "ACL2 System Architecture [{IMAGE}] {IMAGE} The user interacts with the theorem prover by giving it definitions, theorems and advice. Most often the advice is about how to store each proved theorem as a rule. Sometimes the advice is about how to prove a specific theorem. The database consists of all the rules ACL2 ``knows.'' It is possible to include in the database all of the rules in some certified file of other events. Such certified files are called [books] [{ICON}]. Interesting proofs are usually built on top of many books, some of which are written especially for that problem domain and others of which are about oft-used domains, like arithmetic or list processing. ACL2's distribution includes many books written by users. See the ``books'' link under the Lemma Libraries and Utilities [{ICON}] link of the ACL2 home page. [{IMAGE}]") (ACONS (ALISTS ACL2-BUILT-INS) "Constructor for association lists (Acons key datum alist) equals the result of consing the pair (cons key datum) to the front of the association list alist. (Acons key datum alist) has a [guard] of (alistp alist). Acons is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun acons (key datum alist) (declare (xargs :guard (alistp alist))) (cons (cons key datum) alist))") (ACTIVE-RUNEP (THEORIES) "Check that a [rune] exists and is [enable]d Example: (active-runep '(:rewrite left-to-right)) General Form: (active-runep rune) where rune has the shape of a [rune]. This macro expands to an expression using the variables ens and state, and returns non-nil when the given rune exists and is [enable]d (according to the given ``enabled structure,'' ens, and the current logical [world] of the given [state]). See [theory-invariant] for how this macro can be of use.") (ADD-BINOP (MACROS) "Associate a function name with a macro name The form (add-binop macro macro-fn) is an abbreviation for the form (add-macro-fn macro macro-fn t). See [add-macro-fn].") (ADD-CUSTOM-KEYWORD-HINT (EVENTS) "Add a new custom keyword hint Examples: (add-custom-keyword-hint :my-hint (my-hint-fn val ...)) (add-custom-keyword-hint :my-hint (my-hint-fn val ...) :checker (my-hint-checker-fn val ...)) General Form: (add-custom-keyword-hint :key term1 :checker term2) where :key is a [keywordp] not among the primitive keyword hints listed in *hint-keywords*, the :checker argument is optional, and term1 and (if supplied) term2 are terms with certain free-variable and signature restrictions described below. Henceforth, :key is treated as a custom keyword hint, e.g., the user can employ :key in hints to [defthm], such as: (defthm name ... :hints ((\"Subgoal *1/1'\" ... :key val ...))). Custom keyword hints are complicated. To use them you must understand [state], multiple values (e.g., [mv] and [mv-let]), ACL2's notion of error triples (see [programming-with-state]), how to generate ``soft'' errors with [er], how to use [fmt]-strings to control output, how to use computed hints (see [computed-hints]) and some aspects of ACL2's internal event processing. Furthermore, it is possible to implement a custom keyword hint that can make an event non-reproducible! So we recommend that these hints be developed by ACL2 experts. Basically the custom keyword feature allows the implementors and other experts to extend the hint facility without modifying the ACL2 sources. Term1 is called the ``generator'' term and term2 is called the ``checker'' term of the custom keyword hint :key. Together they specify the semantics of the new custom keyword hint :key. Roughly speaking, when a custom keyword hint is supplied by the user, as in (defthm name ... :hints ((\"Subgoal *1/1'\" ... :my-hint val ...))). the checker term is evaluated on val to check that val is of the expected shape. Provided val passes the check, the generator term is used to compute a standard hint. Like computed hints, the generator of a custom keyword hint is allowed to inspect the actual clause on which it is being fired. Indeed, it is allowed to inspect the entire list of hints (standard and custom) supplied for that clause. Thus, in the most general case, a custom keyword hint is just a very special kind of computed hint. The generator, term1, must have no free variables other than: (val keyword-alist id clause world stable-under-simplificationp hist pspv ctx state). Moreover, either term1 must evaluate to a single non-[stobj] value, or else it must be single-threaded in state and have the standard error-triple output signature, (mv * * state). The restrictions on the checker, term2, are that it be single-threaded in state, have the standard error-triple output signature, (mv * * state), and have no free variables other than: (val world ctx state). For examples, see the community books directory books/hints/, in particular basic-tests.lisp. To delete a previously added custom keyword hint, see [remove-custom-keyword-hint]. The community book hints/merge-hint.lisp can be useful in writing custom keyword hints. See the examples near the of the file. Note: This is an event! It does not print the usual event summary but nevertheless changes the ACL2 logical [world] and is so recorded.") (ADD-DEFAULT-HINTS (DEFAULT-HINTS) "Add to the default hints Examples: (add-default-hints '((computed-hint-1 clause) (computed-hint-2 clause stable-under-simplificationp))) (add-default-hints '((computed-hint-3 id clause world)) :at-end t) Note: This is an event! It does not print the usual event summary but nevertheless changes the ACL2 logical [world] and is so recorded. It is [local] to the book or [encapsulate] form in which it occurs (see [add-default-hints!] for a corresponding non-[local] event). General Forms: (add-default-hints lst) (add-default-hints lst :at-end flg) where lst is a list. Generally speaking, the elements of lst should be suitable for use as [computed-hints]. This event is completely analogous to [set-default-hints], the difference being that add-default-hints appends the indicated hints to the front of the list of default hints, so that they are tried first --- or, if flg is supplied and evaluates to other than nil, at the end of the list, so that they are tried last --- rather than replacing the default hints with the indicated hints. Each new hint is thus considered after each existing hints when both are applied to the same goal. Also See [set-default-hints], see [remove-default-hints], and see [default-hints]. Finally, note that the effects of set-default-hints, [add-default-hints], and [remove-default-hints] are [local] to the book in which they appear. Thus, users who include a book with such forms will not have their default hints affected by such forms. In order to export the effect of setting the default hints, use [set-default-hints!], [add-default-hints!], or [remove-default-hints!]. For a related feature, which however is only for advanced system builders, see [override-hints].") (ADD-DEFAULT-HINTS! (DEFAULT-HINTS) "Add to the default hints non-[local]ly Please see [add-default-hints], which is the same as add-default-hints! except that the latter is not [local] to the [encapsulate] or the book in which it occurs. Probably [add-default-hints] is to be preferred unless you have a good reason for wanting to export the effect of this event outside the enclosing [encapsulate] or book.") (ADD-DIVE-INTO-MACRO (DIVE-INTO-MACROS-TABLE) "Associate [proof-checker] diving function with macro name Examples: (add-dive-into-macro cat expand-address-cat) This feature is used so that the [proof-checker]'s DV command and numeric diving commands (e.g., 3) will dive properly into subterms. Please see [dive-into-macros-table].") (ADD-INCLUDE-BOOK-DIR (BOOKS-REFERENCE) "Link keyword for :dir argument of [ld] and [include-book] Example Forms: ; For (include-book \"foo\" :dir :smith), prepend \"/u/smith/\" to \"foo\". (add-include-book-dir :smith \"/u/smith/\") ; For (include-book \"bar\" :dir :util), prepend absolute directory pathname ; corresponding to the relative pathname, \"utilities/\". (add-include-book-dir :util \"utilities\") Note: This is an event! It does not print the usual event summary but nevertheless changes the ACL2 logical [world] and is so recorded. It is [local] to the book or [encapsulate] form in which it occurs. See [add-include-book-dir!] for a corresponding non-[local] event. General Form: (add-include-book-dir kwd dir) where kwd is a [keywordp] and dir is a relative or absolute [pathname] for a directory, optionally using the syntax (:system . filename) described in [full-book-name]. If the final '/' is missing for the resulting directory, ACL2 will add it for you. The effect of this event is to modify the meaning of the :dir keyword argument of [include-book] or [ld] as indicated by the examples above, that is, by associating the indicated directory with the indicated keyword for purposes of the :dir argument. By the ``indicated directory'' we mean, in the case that the pathname is a relative pathname, the directory relative to the current connected book directory; see [cbd]. See [delete-include-book-dir] for how to undo this effect. For a keyword already associated with a directory string by a previous invocation of add-include-book-dir or [add-include-book-dir!], it is illegal to associate a different directory string until removing the existing association; see [delete-include-book-dir] (and see [delete-include-book-dir!] if the existing association was made by [add-include-book-dir!]. If however the new directory string is identical with the existing one, which was already assigned by add-include-book-dir, then the new call of add-include-book-dir will be redundant (see [redundant-events]). The keyword :system can never be redefined. It will always point to the absolute pathname of the system books directory, which by default is immediately under the directory where the ACL2 executable was originally built (see [include-book], in particular the discussion there of ``books directory''). This macro generates a [table] event that updates the table include-book-dir!-table, which associates keywords with absolute pathnames. However, as with [add-include-book-dir], direct table updates are disallowed; you must use add-include-book-dir! to add to the table and [delete-include-book-dir!] to remove from the table. It is illegal to call add-include-book-dir! in a [local] context. (If you are tempted to do that, consider using [add-include-book-dir] instead.) To understand this restriction, imagine a book that contains the following sequence of [events]. (add-include-book-dir! :my-dir \"path/to/BAD/dir\") (local (delete-include-book-dir! :my-dir)) (local (add-include-book-dir! :my-dir \"path/to/GOOD/dir\")) (include-book \"foo\" :dir :my-dir) (defthm f-def (equal (f x) x)) During the first (proof) pass of [certify-book], the book path/to/GOOD/dir/foo.lisp will be included. But on the second pass, the book path/to/BAD/dir/foo.lisp will be included. Now imagine that the ``good'' version contains the event (defun f (x) x) but the ``bad'' version instead contains the event (defun f (x) (not x)). Then we can easily prove nil from the theorem f-def! Although it is likely that checksums will catch this error at [include-book] time, we prefer not to rely on checksums for soundness.") (ADD-INCLUDE-BOOK-DIR! (BOOKS-REFERENCE) "Non-[local]ly link keyword for :dir argument of [ld] and [include-book] Please see [add-include-book-dir], which has completely analogous syntax and semantics, except that add-include-book-dir! is not [local] to the [encapsulate] or the book in which it occurs. Probably [add-include-book-dir] is to be preferred unless you have a good reason for wanting to export the effect of this event outside the enclosing [encapsulate] or book. Note: This is an event! It does not print the usual event summary but nevertheless changes the ACL2 logical [world] and is so recorded. This macro is essentially a [table] event that updates the table include-book-dir!-table, which associates keywords with absolute pathnames. However, as with [add-include-book-dir], direct table updates are disallowed; you must use add-include-book-dir! to add to the table and [delete-include-book-dir!] to remove from the table. It is illegal to call add-include-book-dir! in a [local] context. (If you are tempted to do that, consider using [add-include-book-dir] instead.) To understand this restriction, imagine a book that contains the following sequence of [events]. (add-include-book-dir! :my-dir \"path/to/BAD/dir\") (local (delete-include-book-dir! :my-dir)) (local (add-include-book-dir! :my-dir \"path/to/GOOD/dir\")) (include-book \"foo\" :dir :my-dir) (defthm f-def (equal (f x) x)) During the first (proof) pass of [certify-book], the book path/to/GOOD/dir/foo.lisp will be included. But on the second pass, the book path/to/BAD/dir/foo.lisp will be included. Now imagine that the ``good'' version contains the event (defun f (x) x) but the ``bad'' version instead contains the event (defun f (x) (not x)). Then we can easily prove nil from the theorem f-def! Although it is likely that checksums will catch this error at [include-book] time, we prefer not to rely on checksums for soundness.") (ADD-INVISIBLE-FNS (LOOP-STOPPER) "Make some unary functions invisible to the [loop-stopper] algorithm Examples: (add-invisible-fns binary-+ unary-- foo) (add-invisible-fns + unary-- foo) Each of the [events] above makes unary functions [unary--] and foo ``invisible'' for the purposes of applying permutative :[rewrite] rules to [binary-+] trees. Thus, arg and (unary-- arg) will be given the same weight and will be permuted so as to be adjacent. General Form: (add-invisible-fns top-fn unary-fn1 ... unary-fnk) where top-fn is a function symbol and the unary-fni are unary function symbols, or more generally, these are all macro aliases for function symbols (see [macro-aliases-table]). For more information see [invisible-fns-table]. Also see [set-invisible-fns-table], which explains how to set the entire table in a single event, and see [remove-invisible-fns].") (ADD-LD-KEYWORD-ALIAS (POINTERS) "See [ld-keyword-aliases].") (ADD-LD-KEYWORD-ALIAS! (POINTERS) "See [ld-keyword-aliases].") (ADD-MACRO-ALIAS (MACROS) "Associate a function name with a macro name Example: (add-macro-alias append binary-append) This example associates the function symbol [binary-append] with the macro name [append]. As a result, the name [append] may be used as a runic designator (see [theories]) by the various theory functions. See [macro-aliases-table] for more details. Also see [add-macro-fn] for an extension of this utility that also affects printing. General Form: (add-macro-alias macro-name function-name) This is a convenient way to add an entry to [macro-aliases-table]. See [macro-aliases-table] and also see [remove-macro-alias].") (ADD-MACRO-FN (MACROS) "Associate a function name with a macro name Examples: (add-macro-fn append binary-append) (add-macro-fn append binary-append t) These examples each associate the function symbol [binary-append] with the macro name [append]. As a result, theory functions will understand that append refers to binary-append --- see [add-macro-alias] --- and moreover, proof output will be printed using append rather than binary-append. In the first case, (append x (append y z)) is printed rather than (append x y z). In the second case, right-associated arguments are printed flat: (append x y z). Such right-association is considered only for binary function symbols; otherwise the optional third argument is ignored. General Forms: (add-macro-fn macro-name function-name) (add-macro-fn macro-name function-name nil) ; same as above (add-macro-fn macro-name function-name t) This is a convenient way to add an entry to [macro-aliases-table] and at the same time extend the [untrans-table]. As suggested by the example above, calls of a function in this table will be printed as corresponding calls of macros, with right-associated arguments printed flat in the case of a binary function symbol if the optional third argument is t. In that case, for a binary function symbol fn associated with macro name mac, then a call (fn arg1 (fn arg2 (... (fn argk arg)))) will be displayed to the user as though the ``term'' were (mac arg1 arg2 ... argk arg). For a call (f a1 ... ak) of a function symbol that is not binary, or the optional argument is not supplied as t, then the effect is simply to replace f by the corresponding macro symbol. See [add-macro-alias], which is invoked on the first two arguments. Also see [remove-macro-alias], see [untrans-table], and see [remove-macro-fn].") (ADD-MATCH-FREE-OVERRIDE (FREE-VARIABLES) "Set :match-free value to :once or :all in existing rules Example Forms: (add-match-free-override :once t) ; Try only the first binding of free variables when relieving hypotheses ; of any rule of class :rewrite, :linear, or :forward-chaining. (add-match-free-override :all (:rewrite foo) (:rewrite bar)) ; For rewrite rules foo and bar, try all bindings of free variables when ; relieving hypotheses. (add-match-free-override :clear) ; Restore :match-free to what was originally stored for each rule (either ; :all or :once). As described elsewhere (see [free-variables]), a [rewrite], [linear], or [forward-chaining] rule may have free variables in its hypotheses, and ACL2 can be directed either to try all bindings (``:all'') or just the first (``:once'') when relieving a hypothesis, as a basis for relieving subsequent hypotheses. This direction is generally provided by specifying either :match-free :once or :match-free :all in the :[rule-classes] of the rule, or by using the most recent [set-match-free-default] event. Also see [rule-classes]. However, if a proof is going slowly, you may want to modify the behavior of some such rules so that they use only the first match for free variables in a hypothesis when relieving subsequent hypotheses, rather than backtracking and trying additional matches as necessary. (But note: add-match-free-override is not relevant for [type-prescription] rules.) The event (add-match-free-override :once t) has that effect. Or at the other extreme, perhaps you want to specify all rules as :all rules except for a some specific exceptions. Then you can execute (add-match-free-override :all t) followed by, say, (add-match-free-override :once (:rewrite foo) (:linear bar)). General Forms: (add-match-free-override :clear) (add-match-free-override flg t) (add-match-free-override flg rune1 rune2 ... runek) where flg is :once or :all and the runei are [rune]s. If :clear is specified then all rules will have the :all/:once behavior from when they were first stored. The second general form causes all [rewrite] [linear], and [forward-chaining] rules to have the behavior specified by flg (:all or :once). Finally, the last of these, where runes are specified, is additive in the sense that only the indicated rules are affected; all others keep the behavior they had just before this event was executed (possible because of earlier add-match-free-override events). At the conclusion of this event, ACL2 prints out the list of all :[linear], :[rewrite], and :[forward-chaining] runes whose rules contain free variables in hypotheses that are to be bound :once, except that if there are no overrides (value :clear was used), then :clear is printed. This event only affects rules that exist at the time it is executed. Future rules are not affected by the override. Note: This is an event! It does not print the usual event summary but nevertheless changes the ACL2 logical [world] and is so recorded. It uses the [ACL2-defaults-table], and hence its effect is [local] to the book or [encapsulate] form in which it occurs. Remarks Lists of the :[rewrite], :[linear], and :[forward-chaining] [rune]s whose behavior was originally :once or :all are returned by the following forms, respectively. (free-var-runes :once (w state)) (free-var-runes :all (w state)) The form (match-free-override (w state)) evaluates to a pair, whose [car] is a number used by ACL2 to determine whether a [rune] is sufficiently old to be affected by the override, and whose [cdr] is the list of [rune]s whose behavior is specified as :once by add-match-free-override; except, if no runes have been overridden, then the keyword :clear is returned.") (ADD-NTH-ALIAS (NTH-ALIASES-TABLE) "Associate one symbol with another for printing of [nth]/[update-nth] terms Example: (add-nth-alias st0 st) This example associates the symbol st0 with the symbol st for purposes of printing certain terms of the form (nth n st0) and (update-nth n val st0). General Form: (add-nth-alias alias-name name) This is a convenient way to add an entry to [nth-aliases-table]. See [nth-aliases-table] and also see [remove-nth-alias].") (ADD-OVERRIDE-HINTS (OVERRIDE-HINTS) "Add to the [override-hints] See [override-hints] for a discussion of override-hints. Here we describe how to extend the list of override-hints. Note that the effects of add-override-hints [events] are [local] to the [books] or encapsulate [events] in which they reside; see [add-override-hints!] to avoid that restriction. Also see [set-override-hints] to set a new list of override-hints to it, ignoring the present list rather than adding to it. General Forms: (add-override-hints form) (add-override-hints form :at-end t) (add-override-hints form :at-end nil) ; default for :at-end where form evaluates to a list of computed hint forms. The effect of this event is to extend the current list of [override-hints] by appending the result of that evaluation. The default is to append the evaluation result to the front of the current list of override-hints, but if :at-end t is specified, then the evaluation result is appended to the end of the current list.") (ADD-OVERRIDE-HINTS! (OVERRIDE-HINTS) "Add non-[local]ly to the [override-hints] Add-override-hints! is the same as [add-override-hints], except that the former is not [local] to [books] or [encapsulate] [events] in which it occurs. See [add-override-hints]; also see [set-override-hints].") (ADD-RAW-ARITY (SET-RAW-MODE) "Add arity information for raw mode Technical note: This macro is a no-op, and is not necessary, when ACL2 is built with #-acl2-mv-as-values. Users of raw mode (see [set-raw-mode]) can use arbitrary raw Lisp functions that are not known inside the usual ACL2 loop. In such cases, ACL2 may not know how to display a multiple value returned by ACL2's [mv] macro. The following example should make this clear. ACL2 P>(defun foo (x y) (mv y x)) FOO ACL2 P>(foo 3 4) Note: Unable to compute number of values returned by this evaluation because function FOO is not known in the ACL2 logical world. Presumably it was defined in raw Lisp or in raw mode. Returning the first (perhaps only) value for calls of FOO. 4 ACL2 P>(add-raw-arity foo 2) RAW-ARITY-ALIST ACL2 P>(foo 3 4) (4 3) ACL2 P> The first argument of add-raw-arity should be a symbol, representing the name of a function, macro, or special form, and the second argument should either be a non-negative integer (denoting the number of values returned by ACL2) or else the symbol :LAST, meaning that the number of values returned by the call is the number of values returned by the last argument. The current arity assignments can be seen by evaluating (@ raw-arity-alist). See [remove-raw-arity] for how to undo a call of add-raw-arity.") (ADD-TO-SET (LISTS SYMBOLS ACL2-BUILT-INS) "Add a symbol to a list General Forms: (add-to-set x lst) (add-to-set x lst :test 'eql) ; same as above (eql as equality test) (add-to-set x lst :test 'eq) ; same, but eq is equality test (add-to-set x lst :test 'equal) ; same, but equal is equality test For a symbol x and an object lst, (add-to-set-eq x lst) is the result of [cons]ing x on to the front of lst, unless x is already a [member] of lst, in which case the result is lst. The optional keyword, :TEST, has no effect logically, but provides the test (default [eql]) used for comparing x with successive elements of lst. The [guard] for a call of add-to-set depends on the test. In all cases, the second argument must satisfy [true-listp]. If the test is [eql], then either the first argument must be suitable for [eql] (see [eqlablep]) or the second argument must satisfy [eqlable-listp]. If the test is [eq], then either the first argument must be a symbol or the second argument must satisfy [symbol-listp]. See [equality-variants] for a discussion of the relation between add-to-set and its variants: (add-to-set-eq x lst) is equivalent to (add-to-set x lst :test 'eq); (add-to-set-equal x lst) is equivalent to (add-to-set x lst :test 'equal). In particular, reasoning about any of these primitives reduces to reasoning about the function add-to-set-equal.") (ADD-TO-SET-EQ (POINTERS) "See [add-to-set].") (ADD-TO-SET-EQL (POINTERS) "See [add-to-set].") (ADD-TO-SET-EQUAL (POINTERS) "See [add-to-set].") (ADVANCED-FEATURES (ACL2-TUTORIAL) "Some advanced features of ACL2 Maybe you've been using ACL2 for awhile, and you wonder if there are lesser-known features that you might find useful. Then this topic is for you. We present below a ``laundry list'' of some such features, with brief descriptions and links to [documentation] topics. Although the list below is long, it is not intended to be complete, and indeed some topics have been deliberately excluded. Some have fallen out of use, perhaps for good reason, such as [obdd]. Others are already likely to be discovered when needed, such as [getenv$] and perhaps [double-rewrite]. Some topics are referenced by documentation for others in the list, such as [mbt], which is referenced by [mbe]. Some utilities such as [pstack] and [verbose-pstack] seem too low-level to be worthy of inclusion below. For an extensive introduction to using the prover, which may include some aspects new to you, see [introduction-to-the-theorem-prover]. A shorter topic contains highlights for efficient prover usage: see [tips]. Also see [ACL2-sedan] for an extension of ACL2 (written by others), ACL2s, that includes an Eclipse-based interface, more powerful and automatic termination reasoning, and other features. We now move on to the list. Top-level commands and utilities: * See [a!] and see [p!] to abort or pop. * See [ACL2-customization] for initial commands to run at startup. * See [keyword-commands] for how keyword commands are processed. * See [ld] for many ways to control the top-level loop. * See [compilation] for a discussion of set-compiler-enabled and other compiler-related utilities. * For useful reader macros `#!', `#.', and `#u', see [sharp-bang-reader], see [sharp-dot-reader], and see [sharp-u-reader]. * To save and use an ACL2 executable, see [ACL2-as-standalone-program] and see [save-exec]. * For utilities related to timing, see [time$], see [with-prover-time-limit], see [with-prover-step-limit], and see [set-prover-step-limit]. * To query and manage the database, see [history] (which discusses many useful utilities, such as :[pbt] and :[pl]), and see [dead-events]. * See [add-include-book-dir] for linking keyword for :dir argument of [ld] and [include-book]. * See [rebuild] for a fast way to load a file without waiting for proofs. * For parallel certification, see [books-certification] for use of the -j option of `make'; also see [provisional-certification]. Some relatively less common events * See [reset-prehistory] to reset the prehistory. * See [assert-event] to assert that a given form returns a non-nil value. * See [defattach] to execute constrained functions using corresponding attached functions. * See [defun-sk] to define a function whose body has an outermost quantifier. * See [defchoose] to define a Skolem (witnessing) function. * For efficiency consider using defconst-fast; see [defconst]. * See [set-verify-guards-eagerness] to specify when [guard] verification is tried by default. Output and its control (see [io] for additional information) * See [with-output] to suppress or turn on specified output for an event. * See [evisc-table] for support for abbreviated output. * See [nth-aliases-table] for a table used to associate names for [nth]/[update-nth] printing. * See [output-to-file] to redirect output to a file. * See [print-control] to control ACL2 printing. * See [set-evisc-tuple] to control suppression of details when printing. * See [set-inhibit-output-lst] to control output by type. * See [set-iprint] to allow abbreviated output to be read back in. * See [set-print-base-radix] (also [set-print-base] and [set-print-radix]) to control the radix in which numbers are printed. * See [set-print-case] to control whether symbols are printed in upper case or in lower case. On proving termination for definitions: * See [ordinals] for a discussion of ordinals in ACL2. * See [ruler-extenders] for a control on ACL2's termination and induction analyses. * See [set-well-founded-relation] to set the default well-founded relation for termination analysis. * See [ACL2-sedan] for a related tool that provides extra automation for termination proofs. Proof debugging and output control: * See [accumulated-persistence] to get statistics on which runes are being tried. * See [add-macro-fn] and see [add-macro-alias] to associate a function name with a macro name. * See [break-rewrite] for how to monitor rewrite rules. * See [dmr] for dynamic monitoring of rewriting and other prover activity. * See [forward-chaining-reports] to see reports about the forward chaining process. * See [guard-debug] and [measure-debug] to generate markers to indicate sources of [guard] and measure proof obligations. * See [proof-checker] for support for low-level interaction. * See [redo-flat] for redo on failure of a [progn], [encapsulate], or [certify-book]. * See [set-gag-mode] and see [pso] to abbreviate or restore proof output. * See [set-inhibit-output-lst], see [set-inhibit-warnings], and see [set-inhibited-summary-types] to inhibit various types of output. * See [set-raw-proof-format] to make proof output display lists of [rune]s. * See [skip-proofs] to skip proofs for a given form. Program debugging: * See [break$] to cause an immediate Lisp break. * See [break-on-error] to break when encountering a hard or soft error caused by ACL2. * See [disassemble$] to disassemble a function. * See [print-gv] to print a form whose evaluation caused a guard violation. * See [profile] to turn on profiling for one function. * See [trace$] and see [open-trace-file] to [trace] function evaluations, possibly sending trace output to a file. * See [wet] to evaluate a form and print a subsequent error trace. Programming and evaluation idioms, support, utilities (also see [programming] for more utilities, e.g., [random$]). * See [arrays] and See [defstobj] for introductions to ACL2 arrays and single-threaded objects (stobjs), respectively, each of which provides efficient destructive operations in an applicative setting. Also see [with-local-stobj] for a way to create local stobjs. * See [assert$] to cause a hard error if the given test is false. * See [canonical-pathname] to obtain the true absolute filename, with soft links resolved. * See [case-match] for a utility providing pattern matching and destructuring. * See [defpun] to define a tail-recursive function symbol. * See [ec-call] to execute a call in the ACL2 logic instead of raw Lisp. * See [er] to print an error message and ``cause an error''. * See [flet] to provide local binding of function symbols. * See [gc$] to invoke the garbage collector. * See [mbe] to attach code for execution. * See [mv-list] to convert a multiple-valued result to a single-valued list. * See [mv?] to return one or more values. * For non-executable code, see [defun-nx] and see [non-exec]. * See [prog2$] and see [progn$] to execute two or more forms and return the value of the last one. * See [programming-with-state] for how to program using the von Neumannesque ACL2 [state] object. * See [top-level] to evaluate a top-level form as a function body. * See [with-guard-checking] to suppress or enable guard-checking for a form. * For ways to fake access to the state see [wormhole], see [with-local-state], see [cw], see [cw!], see [printing-to-strings], see [observation-cw], and (dangerous!) see [with-live-state]. Connecting with the underlying host Lisp, and doing other evil: * See [defttag] to introduce a trust tag (ttag). * See [defmacro-last] to define a macro that returns its last argument, but with side effects. * See [progn!] to evaluate forms that are not necessarily [events]. * See [return-last] to return the last argument, perhaps with side effects. * See [set-raw-mode] to enter or exit ``raw mode,'' a raw Lisp environment. * See [sys-call] and [sys-call+] to make a system call to the host operating system. Macros and related utilities: * See [defabbrev] for a convenient form of macro definition for simple expansions. * See [macro-args] for the formals list of a macro definition (see [defmacro]). * See [make-event] for a sort of extension of [defmacro] that allows access to the [state], by evaluating (expanding) a given form and then evaluate the result of that expansion. * See [trans], see [trans!], and see [trans1] to print the macroexpansion of a form. Additional capabilities: * See [hons-and-memoization] for a discussion of the [hons-enabled] features providing hash cons, function memoization, and applicative hash tables. In particular, see [memoize] for efficient function memoization and see [profile] for profiling. * See [real] for ACL2(r), which supports the real numbers. * See [parallelism] for ACL2(p), which supports parallel evaluation and proof. Database control and query: * See [disabledp] to determine whether a given name or rune is disabled. * For redefinition support see [redef], see [redef!], see [redef+], see [redef-], and see [redefined-names]. * See [table] for user-managed tables. * See [verify-guards-formula] to view a guard proof obligation without doing the proof. Prover control * For congruence-based reasoning see [defcong], see [congruence], see [equivalence], see [defequiv], and see [defrefinement]. * For meta rules and clause processors see [meta], see [defevaluator], see [clause-processor], see [define-trusted-clause-processor] (for connecting with external tools, such as SAT solvers), and See [extended-metafunctions] (for [state] and context-sensitive metafunctions). * For theory control, see [theories] for detailed information, but in particular see [deftheory], see [theory-functions], see [in-arithmetic-theory] (and see [non-linear-arithmetic]), and see [theory-invariant]. * See [hints] for a complete list of prover hints, including some of the more obscure ones such as :restrict, :[clause-processor], :nonlinearp, :backchain-limit-rw, :reorder, and :backtrack. Also see [hints-and-the-waterfall] for an explanation of how hints interact with the ACL2 proof process. For other topics related to hints, see [override-hints], see [add-custom-keyword-hint], see [default-hints], and see [computed-hints] and [using-computed-hints]. * See [bind-free] to bind [free-variables] of a [rewrite] or [linear] rule. * See [case-split] for a utility like [force] that immediately splits the top-level goal on the indicated hypothesis. * See [case-split-limitations] for a way to the number of cases produced at once * See [default-backchain-limit] to specify the backchain limit for a rule. * See [force] for an identity function used to force a hypothesis. * See [otf-flg] for a way to push more than one initial subgoal for induction. * See [rule-classes] to add various kinds of rules to the database, including more unusual sorts such as :[built-in-clause] rules and :[induction] rules. * See [set-backchain-limit] to set the backchain-limit used by the type-set and rewriting mechanisms. * See [set-body] to set an alternate definition body for :expand [hints]. * See [set-rewrite-stack-limit] to set the [rewrite] stack depth used by the rewriter. * See [syntaxp] to attach a heuristic filter on a :[rewrite], :[meta], or :[linear] rule. Subtopics [Program-wrapper] Avoiding expensive guard checks using [program]-mode functions") (ALISTP (ALISTS ACL2-BUILT-INS) "Recognizer for association lists (alistp x) is true if and only if x is a list of [cons] pairs. (alistp x) has a [guard] of t. Function: (defun alistp (l) (declare (xargs :guard t)) (cond ((atom l) (eq l nil)) (t (and (consp (car l)) (alistp (cdr l))))))") (ALISTS (PROGRAMMING) "Operations on association lists, which bind keys to values. Subtopics [Acons] Constructor for association lists [Alistp] Recognizer for association lists [Assoc] Look up key in association list [Assoc-string-equal] Look up key, a string, in association list [Character-alistp] Recognizer for association lists with characters as keys [Delete-assoc] Remove the first pair from an association list for a given key [Eqlable-alistp] Recognizer for a true list of pairs whose [car]s are suitable for [eql] [Fast-alists] Alists with hidden hash tables for faster execution [Pairlis] See [pairlis$] [Pairlis$] Zipper together two lists [Put-assoc] Modify an association list by associating a value with a key [R-eqlable-alistp] Recognizer for a true list of pairs whose [cdr]s are suitable for [eql] [R-symbol-alistp] Recognizer for association lists with symbols as values [Rassoc] Look up value in association list [Standard-string-alistp] Recognizer for association lists with standard strings as keys [Strip-cars] Collect up all first components of pairs in a list [Strip-cdrs] Collect up all second components of pairs in a list [Sublis] Substitute an alist into a tree [Symbol-alistp] Recognizer for association lists with symbols as keys") (ALLOCATE-FIXNUM-RANGE (NUMBERS ACL2-BUILT-INS) "Set aside fixnums in GCL (Allocate-fixnum-range fixnum-lo fixnum-hi) causes Gnu Common Lisp (GCL) to create a persistent table for the integers between fixnum-lo and fixnum-hi (both bounds inclusive). This table is referenced first when any integer is boxed and the existing box in the table is used if the integer is in bounds. This can speed up GCL considerably by avoiding wasteful fixnum boxing. Here, fixnum-lo and fixnum-hi should be fixnums. On 32-bit machines it would be good for them to be of type (signed-byte 30), with fixnum-lo <= fixnum-hi. When this function is executed in a Lisp implementation other than GCL, it has no side effect. This function always returns nil.") (ALPHA-CHAR-P (CHARACTERS ACL2-BUILT-INS) "Recognizer for alphabetic characters (Alpha-char-p x) is true for a standard character x if and only if x is alphabetic, i.e., one of the [characters] #\\a, #\\b, ..., #\\z, #\\A, #\\B, ..., #\\Z. The [guard] for alpha-char-p requires its argument to be a standard character (see [standard-char-p]). Alpha-char-p is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun alpha-char-p (x) (declare (xargs :guard (and (characterp x) (standard-char-p x)))) (and (member x '(#\\a #\\b #\\c #\\d #\\e #\\f #\\g #\\h #\\i #\\j #\\k #\\l #\\m #\\n #\\o #\\p #\\q #\\r #\\s #\\t #\\u #\\v #\\w #\\x #\\y #\\z #\\A #\\B #\\C #\\D #\\E #\\F #\\G #\\H #\\I #\\J #\\K #\\L #\\M #\\N #\\O #\\P #\\Q #\\R #\\S #\\T #\\U #\\V #\\W #\\X #\\Y #\\Z)) t))") (ALPHORDER (<< ACL2-BUILT-INS) "Total order on atoms Alphorder is a non-strict total order, a ``less than or equal,'' on atoms. By ``non-strict total order'' we mean a function that always returns t or nil and satisfies the following properties. * Antisymmetry: XrY & YrX -> X=Y * Transitivity: XrY & YrZ -> XrZ * Trichotomy: XrY v YrX Also see [lexorder], which extends alphorder to all objects. (Alphorder x y) has a guard of (and (atom x) (atom y)). Within a single type: rationals are compared arithmetically, complex rationals are compared lexicographically, characters are compared via their char-codes, and strings and symbols are compared with alphabetic ordering. Across types, rationals come before complexes, complexes come before characters, characters before strings, and strings before symbols. We also allow for ``bad atoms,'' i.e., atoms that are not legal Lisp objects but make sense in the ACL2 logic; these come at the end, after symbols. Function: (defun alphorder (x y) (declare (xargs :guard (and (atom x) (atom y)))) (cond ((real/rationalp x) (cond ((real/rationalp y) (<= x y)) (t t))) ((real/rationalp y) nil) ((complex/complex-rationalp x) (cond ((complex/complex-rationalp y) (or (< (realpart x) (realpart y)) (and (= (realpart x) (realpart y)) (<= (imagpart x) (imagpart y))))) (t t))) ((complex/complex-rationalp y) nil) ((characterp x) (cond ((characterp y) (<= (char-code x) (char-code y))) (t t))) ((characterp y) nil) ((stringp x) (cond ((stringp y) (and (string<= x y) t)) (t t))) ((stringp y) nil) (t (cond ((symbolp x) (cond ((symbolp y) (not (symbol-< y x))) (t t))) ((symbolp y) nil) (t (bad-atom<= x y))))))") (ALTERNATIVE-INTRODUCTION (ACL2-TUTORIAL) "Introduction to ACL2 This section contains introductory material on ACL2 including what ACL2 is, how to get started using the system, how to read the output, and other introductory topics. It was written almost entirely by Bill Young of Computational Logic, Inc. You might also find CLI Technical Report 101 helpful, especially if you are familiar with Nqthm. If you would like more familiarity with Nqthm, we suggest CLI Technical Report 100. OVERVIEW ACL2 is an automated reasoning system developed (for the first 9 years) at Computational Logic, Inc. and (from January, 1997) at the University of Texas at Austin. It is the successor to the Nqthm (or Boyer-Moore) logic and proof system and its Pc-Nqthm interactive enhancement. The acronym ACL2 actually stands for ``A Computational Logic for Applicative Common Lisp''. This title suggests several distinct but related aspects of ACL2. We assume that readers of the ACL2 [documentation] have at least a very slight familiarity with some Lisp-like language. We will address the issue of prerequisites further, in ``ABOUT THIS TUTORIAL'' below. As a logic, ACL2 is a formal system with rigorously defined syntax and semantics. In mathematical parlance, the ACL2 logic is a first-order logic of total recursive functions providing mathematical induction on the ordinals up to epsilon-0 and two extension principles: one for recursive definition and one for constrained introduction of new function symbols, here called encapsulation. The syntax of ACL2 is that of Common Lisp; ACL2 specifications are ``also'' Common Lisp programs in a way that we will make clear later. In less formal language, the ACL2 logic is an integrated collection of rules for defining (or axiomatizing) recursive functions, stating properties of those functions, and rigorously establishing those properties. Each of these activities is mechanically supported. As a specification language, ACL2 supports modeling of systems of various kinds. An ACL2 function can equally be used to express purely formal relationships among mathematical entities, to describe algorithms, or to capture the intended behavior of digital systems. For digital systems, an ACL2 specification is a mathematical model that is intended to formalize relevant aspects of system behavior. Just as physics allows us to model the behavior of continuous physical systems, ACL2 allows us to model digital systems, including many with physical realizations such as computer hardware. As early as the 1930's Church, Kleene, Turing and others established that recursive functions provide an expressive formalism for modeling digital computation. Digital computation should be understood in a broad sense, covering a wide variety of activities including almost any systematic or algorithmic activity, or activity that can be reasonably approximated in that way. This ranges from the behavior of a digital circuit to the behavior of a programming language compiler to the behavior of a controller for a physical system (as long as the system can be adequately modeled discretely). All of these have been modeled using ACL2 or its predecessor Nqthm. ACL2 is a computational logic in at least three distinct senses. First, the theory of recursive functions is often considered the mathematics of computation. Church conjectured that any ``effective computation'' can be modeled as a recursive function. Thus, ACL2 provides an expressive language for modeling digital systems. Second, many ACL2 specifications are executable. In fact, recursive functions written in ACL2 are Common Lisp functions that can be submitted to any compliant Common Lisp compiler and executed (in an environment where suitable ACL2-specific macros and functions are defined). Third, ACL2 is computational in the sense that calculation is heavily integrated into the reasoning process. Thus, an expression with explicit constant values but no free variables can be simplified by calculation rather than by complex logical manipulations. ACL2 is a powerful, automated theorem prover or proof checker. This means that a competent user can utilize the ACL2 system to discover proofs of theorems stated in the ACL2 logic or to check previously discovered proofs. The basic deductive steps in an ACL2-checked proof are often quite large, due to the sophisticated combination of decision procedures, conditional rewriting, mathematical and structural induction, propositional simplification, and complex heuristics to orchestrate the interactions of these capabilities. Unlike some automated proof systems, ACL2 does not produce a formal proof. However, we believe that if ACL2 certifies the ``theoremhood'' of a given conjecture, then such a formal proof exists and, therefore, the theorem is valid. The ultimate result of an ACL2 proof session is a collection of ``[events],'' possibly grouped into ``[books],'' that can be replayed in ACL2. Therefore, a proof can be independently validated by any ACL2 user. ACL2 may be used in purely automated mode in the shallow sense that conjectures are submitted to the prover and the user does not interact with the proof attempt (except possibly to stop it) until the proof succeeds or fails. However, any non-trivial proof attempt is actually interactive, since successful proof ``[events]'' influence the subsequent behavior of the prover. For example, proving a lemma may introduce a rule that subsequently is used automatically by the prover. Thus, any realistic proof attempt, even in ``automatic'' mode, is really an interactive dialogue with the prover to craft a sequence of [events] building an appropriate theory and proof rules leading up to the proof of the desired result. Also, ACL2 supports annotating a theorem with ``[hints]'' designed to guide the proof attempt. By supplying appropriate [hints], the user can suggest proof strategies that the prover would not discover automatically. There is a ``[proof-tree]'' facility (see [proof-tree]) that allows the user to [monitor] the progress and structure of a proof attempt in real-time. Exploring failed proof attempts is actually where heavy-duty ACL2 users spend most of their time. ACL2 can also be used in a more explicitly interactive mode. The ``[proof-checker]'' subsystem of ACL2 allows exploration of a proof on a fairly low level including expanding calls of selected function symbols, invoking specific [rewrite] rules, and selectively navigating around the proof. This facility can be used to gain sufficient insight into the proof to construct an automatic version, or to generate a detailed interactive-style proof that can be replayed in batch mode. Because ACL2 is all of these things --- computational logic, specification language, [programming] system, and theorem prover --- it is more than the sum of its parts. The careful integration of these diverse aspects has produced a versatile automated reasoning system suitable for building highly reliable digital systems. In the remainder of this tutorial, we will illustrate some simple uses of this automated reasoning system. ABOUT THIS TUTORIAL ACL2 is a complex system with a vast array of features, bells and whistles. However, it is possible to perform productive work with the system using only a small portion of the available functionality. The goals of this tutorial are to: familiarize the new user with the most basic features of and modes of interaction with ACL2; familiarize her with the form of output of the system; and work through a graduated series of examples. The more knowledge the user brings to this system, the easier it will be to become proficient. On one extreme: the ideal user of ACL2 is an expert Common Lisp programmer, has deep understanding of automated reasoning, and is intimately familiar with the earlier Nqthm system. Such ideal users are unlikely to need this tutorial. However, without some background knowledge, the beginning user is likely to become extremely confused and frustrated by this system. We suggest that a new user of ACL2 should: (a) have a little familiarity with Lisp, including basic Lisp programming and prefix notation (a Lisp reference manual such as Guy Steele's ``Common Lisp: The Language'' is also helpful); (b) be convinced of the utility of formal modeling; and (c) be willing to gain familiarity with basic automated theorem proving topics such as rewriting and algebraic simplification. We will not assume any deep familiarity with Nqthm (the so-called ``Boyer-Moore Theorem Prover''), though the book ``A Computational Logic Handbook'' by Boyer and Moore (Academic Press, 1988) is an extremely useful reference for many of the topics required to become a competent ACL2 user. We'll refer to it as ACLH below. As we said in the introduction, ACL2 has various facets. For example, it can be used as a Common Lisp [programming] system to construct application programs. In fact, the ACL2 system itself is a large Common Lisp program constructed almost entirely within ACL2. Another use of ACL2 is as a specification and modeling tool. That is the aspect we will concentrate on in the remainder of this tutorial. GETTING STARTED This section is an abridged version of what's available elsewhere; feel free to see [startup] for more details. How you start ACL2 will be system dependent, but you'll probably type something like ``acl2'' at your operating system prompt. Consult your system administrator for details. When you start up ACL2, you'll probably find yourself inside the ACL2 [command] loop, as indicated by the following [prompt]. ACL2 !> If not, you should type (LP). See [lp], which has a lot more information about the ACL2 [command] loop. There are two ``modes'' for using ACL2, :[logic] and :[program]. When you begin ACL2, you will ordinarily be in the :[logic] mode. This means that any new function defined is not only executable but also is axiomatically defined in the ACL2 logic. (See [defun-mode] and see [default-defun-mode].) Roughly speaking, :[program] mode is available for using ACL2 as a [programming] language without some of the logical burdens necessary for formal reasoning. In this tutorial we will assume that we always remain in :[logic] mode and that our purpose is to write formal models of digital systems and to reason about them. Now, within the ACL2 [command] loop you can carry out various kinds of activities, including the folllowing. (We'll see examples later of many of these.) define new functions (see [defun]); execute functions on concrete data; pose and attempt to prove conjectures about previously defined functions (see [defthm]); query the ACL2 ``[world]'' or database (e.g., see [pe]); and numerous other things. In addition, there is extensive on-line [documentation], of which this tutorial introduction is a part. INTERACTING WITH ACL2 The standard means of interacting with ACL2 is to submit a sequence of forms for processing by the ACL2 system. These forms are checked for syntactic and semantic acceptability and appropriately processed by the system. These forms can be typed directly at the ACL2 [prompt]. However, most successful ACL2 users prefer to do their work using the Emacs text editor, maintaining an Emacs ``working'' buffer in which forms are edited. Those forms are then copied to the ACL2 interaction buffer, which is often the \"*shell*\" buffer. In some cases, processing succeeds and makes some change to the ACL2 ``logical [world],'' which affects the processing of subsequent forms. How can this processing fail? For example, a proposed theorem will be rejected unless all function symbols mentioned have been previously defined. Also the ability of ACL2 to discover the proof of a theorem may depend on the user previously having proved other theorems. Thus, the order in which forms are submitted to ACL2 is quite important. Maintaining forms in an appropriate order in your working buffer will be helpful for re-playing the proof later. One of the most common [events] in constructing a model is introducing new functions. New functions are usually introduced using the [defun] form; we'll encounter some exceptions later. Proposed function definitions are checked to make sure that they are syntactically and semantically acceptable (e.g., that all mentioned functions have been previously defined) and, for recursive functions, that their recursive calls terminate. A recursive function definition is guaranteed to terminate if there is some some ``measure'' of the arguments and a ``well-founded'' ordering such that the arguments to the function get smaller in each recursive call. See [well-founded-relation]. For example, suppose that we need a function that will append two lists together. (We already have one in the ACL2 [append] function; but suppose perversely that we decide to define our own.) Suppose we submit the following definition (you should do so as well and study the system output): (defun my-app (x y) (if (atom x) y (cons (car x) (my-app x y)))) The system responds with the following message: ACL2 Error in ( DEFUN MY-APP ...): No :MEASURE was supplied with the definition of MY-APP. Our heuristics for guessing one have not made any suggestions. No argument of the function is tested along every branch and occurs as a proper subterm at the same argument position in every recursive call. You must specify a :MEASURE. See :DOC defun. This means that the system could not find an expression involving the formal parameters x and y that decreases under some well-founded order in every recursive call (there is only one such call). It should be clear that there is no such measure in this case because the only recursive call doesn't change the arguments at all. The definition is obviously flawed; if it were accepted and executed it would loop forever. Notice that a definition that is rejected is not stored in the system database; there is no need to take any action to have it ``thrown away.'' Let's try again with the correct definition. The interaction now looks like (we're also putting in the ACL2 [prompt]; you don't type that): ACL2 !>(defun my-app (x y) (if (atom x) y (cons (car x) (my-app (cdr x) y)))) The admission of MY-APP is trivial, using the relation O< (which is known to be well-founded on the domain recognized by O-P) and the measure (ACL2-COUNT X). We observe that the type of MY-APP is described by the theorem (OR (CONSP (MY-APP X Y)) (EQUAL (MY-APP X Y) Y)). We used primitive type reasoning. Summary Form: ( DEFUN MY-APP ...) Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL)) Warnings: None Time: 0.07 seconds (prove: 0.00, print: 0.00, other: 0.07) MY-APP Notice that this time the function definition was accepted. We didn't have to supply a measure explicitly; the system inferred one from the form of the definition. On complex functions it may be necessary to supply a measure explicitly. (See [xargs].) The system output provides several pieces of information. The revised definition is acceptable. The system realized that there is a particular measure (namely, (acl2-count x)) and a well-founded relation (o<) under which the arguments of my-app get smaller in recursion. Actually, the theorem prover proved several theorems to admit my-app. The main one was that when (atom x) is false the acl2-count of (cdr x) is less than (in the o< sense) the acl2-count of x. [Acl2-count] is the most commonly used measure of the ``size`` of an ACL2 object. [o<] is the ordering relation on ordinals less than epsilon-0. On the natural numbers it is just ordinary ``<''. The observation printed about ``the type of MY-APP'' means that calls of the function my-app will always return a value that is either a [cons] pair or is equal to the second parameter. The summary provides information about which previously introduced definitions and lemmas were used in this proof, about some notable things to watch out for (the Warnings), and about how long this event took to process. Usually, it's not important to read this information. However, it is a good habit to scan it briefly to see if the type information is surprising to you or if there are Warnings. We'll see an example of them later. After a function is accepted, it is stored in the database and available for use in other function definitions or lemmas. To see the definition of any function use the :[pe] command (see [pe]). For example, ACL2 !>:pe my-app L 73:x(DEFUN MY-APP (X Y) (IF (ATOM X) Y (CONS (CAR X) (MY-APP (CDR X) Y)))) This displays the definition along with some other relevant information. In this case, we know that this definition was processed in :[logic] mode (the ``L'') and was the 73rd [command] processed in the current session. We can also try out our newly defined function on some sample data. To do that, just submit a form to be evaluated to ACL2. For example, ACL2 !>(my-app '(0 1 2) '(3 4 5)) (0 1 2 3 4 5) ACL2 !>(my-app nil nil) NIL ACL2 !> Now suppose we want to prove something about the function just introduced. We conjecture, for example, that the length of the [append] of two lists is the sum of their lengths. We can formulate this conjecture in the form of the following ACL2 [defthm] form. (defthm my-app-length (equal (len (my-app x y)) (+ (len x) (len y)))) First of all, how did we know about the functions len and [+], etc.? The answer to that is somewhat unsatisfying --- we know them from our past experience in using Common Lisp and ACL2. It's hard to know that a function such as len exists without first knowing some Common Lisp. If we'd guessed that the appropriate function was called [length] (say, from our knowledge of Lisp) and tried :pe length, we would have seen that [length] is defined in terms of len, and we could have explored from there. Luckily, you can write a lot of ACL2 functions without knowing too many of the primitive functions. Secondly, why don't we need some ``type'' hypotheses? Does it make sense to append things that are not lists? Well, yes. ACL2 and Lisp are both quite weakly typed. For example, inspection of the definition of my-app shows that if x is not a [cons] pair, then (my-app x y) always returns y, no matter what y is. Thirdly, would it matter if we rewrote the lemma with the equality reversed, as follows? (defthm my-app-length2 (equal (+ (len x) (len y)) (len (my-app x y)))). The two are logically equivalent, but...yes, it would make a big difference. Recall our remark that a lemma is not only a ``fact'' to be proved; it also is used by the system to prove other later lemmas. The current lemma would be stored as a [rewrite] rule. (See [rule-classes].) For a [rewrite] rule, a conclusion of the form (EQUAL LHS RHS) means to replace instances of the LHS by the appropriate instance of the RHS. Presumably, it's better to [rewrite] (len (my-app x y)) to (+ (len x) (len y)) than the other way around. The reason is that the system ``knows'' more about [+] than it does about the new function symbol my-app. So let's see if we can prove this lemma. Submitting our preferred [defthm] to ACL2 (do it!), we get the following interaction: -------------------------------------------------- ACL2 !>(defthm my-app-length (equal (len (my-app x y)) (+ (len x) (len y)))) Name the formula above *1. Perhaps we can prove *1 by induction. Three induction schemes are suggested by this conjecture. These merge into two derived induction schemes. However, one of these is flawed and so we are left with one viable candidate. We will induct according to a scheme suggested by (LEN X), but modified to accommodate (MY-APP X Y). If we let (:P X Y) denote *1 above then the induction scheme we'll use is (AND (IMPLIES (NOT (CONSP X)) (:P X Y)) (IMPLIES (AND (CONSP X) (:P (CDR X) Y)) (:P X Y))). This induction is justified by the same argument used to admit LEN, namely, the measure (ACL2-COUNT X) is decreasing according to the relation O< (which is known to be well-founded on the domain recognized by O-P). When applied to the goal at hand the above induction scheme produces the following two nontautological subgoals. Subgoal *1/2 (IMPLIES (NOT (CONSP X)) (EQUAL (LEN (MY-APP X Y)) (+ (LEN X) (LEN Y)))). But simplification reduces this to T, using the :definitions of FIX, LEN and MY-APP, the :type-prescription rule LEN, the :rewrite rule UNICITY-OF-0 and primitive type reasoning. Subgoal *1/1 (IMPLIES (AND (CONSP X) (EQUAL (LEN (MY-APP (CDR X) Y)) (+ (LEN (CDR X)) (LEN Y)))) (EQUAL (LEN (MY-APP X Y)) (+ (LEN X) (LEN Y)))). This simplifies, using the :definitions of LEN and MY-APP, primitive type reasoning and the :rewrite rules COMMUTATIVITY-OF-+ and CDR-CONS, to Subgoal *1/1' (IMPLIES (AND (CONSP X) (EQUAL (LEN (MY-APP (CDR X) Y)) (+ (LEN Y) (LEN (CDR X))))) (EQUAL (+ 1 (LEN (MY-APP (CDR X) Y))) (+ (LEN Y) 1 (LEN (CDR X))))). But simplification reduces this to T, using linear arithmetic, primitive type reasoning and the :type-prescription rule LEN. That completes the proof of *1. Q.E.D. Summary Form: ( DEFTHM MY-APP-LENGTH ...) Rules: ((:REWRITE UNICITY-OF-0) (:DEFINITION FIX) (:REWRITE COMMUTATIVITY-OF-+) (:DEFINITION LEN) (:REWRITE CDR-CONS) (:DEFINITION MY-APP) (:TYPE-PRESCRIPTION LEN) (:FAKE-RUNE-FOR-TYPE-SET NIL) (:FAKE-RUNE-FOR-LINEAR NIL)) Warnings: None Time: 0.30 seconds (prove: 0.13, print: 0.05, other: 0.12) MY-APP-LENGTH -------------------------------------------------- Wow, it worked! In brief, the system first tried to [rewrite] and simplify as much as possible. Nothing changed; we know that because it said ``Name the formula above *1.'' Whenever the system decides to name a formula in this way, we know that it has run out of techniques to use other than proof by induction. The induction performed by ACL2 is structural or ``Noetherian'' induction. You don't need to know much about that except that it is induction based on the structure of some object. The heuristics infer the structure of the object from the way the object is recursively decomposed by the functions used in the conjecture. The heuristics of ACL2 are reasonably good at selecting an induction scheme in simple cases. It is possible to override the heuristic choice by providing an :induction hint (see [hints]). In the case of the theorem above, the system inducts on the structure of x as suggested by the decomposition of x in both (my-app x y) and (len x). In the base case, we assume that x is not a [consp]. In the inductive case, we assume that it is a [consp] and assume that the conjecture holds for (cdr x). There is a close connection between the analysis that goes on when a function like my-app is accepted and when we try to prove something inductively about it. That connection is spelled out well in Boyer and Moore's book ``A Computational Logic,'' if you'd like to look it up. But it's pretty intuitive. We accepted my-app because the ``size'' of the first argument x decreases in the recursive call. That tells us that when we need to prove something inductively about my-app, it's a good idea to try an induction on the size of the first argument. Of course, when you have a theorem involving several functions, it may be necessary to concoct a more complicated [induction] schema, taking several of them into account. That's what's meant by ``merging'' the induction schemas. The proof involves two cases: the base case, and the inductive case. You'll notice that the subgoal numbers go down rather than up, so you always know how many subgoals are left to process. The base case (Subgoal *1/2) is handled by opening up the function definitions, simplifying, doing a little rewriting, and performing some reasoning based on the types of the arguments. You'll often encounter references to system defined lemmas (like unicity-of-0). You can always look at those with :[pe]; but, in general, assume that there's a lot of simplification power under the hood that's not too important to understand fully. The inductive case (Subgoal *1/1) is also dispatched pretty easily. Here we assume the conjecture true for the [cdr] of the list and try to prove it for the entire list. Notice that the prover does some simplification and then prints out an updated version of the goal (Subgoal *1/1'). Examining these gives you a pretty good idea of what's going on in the proof. Sometimes one goal is split into a number of subgoals, as happened with the induction above. Sometimes after some initial processing the prover decides it needs to prove a subgoal by induction; this subgoal is given a name and pushed onto a stack of goals. Some steps, like generalization (see ACLH), are not necessarily validity preserving; that is, the system may adopt a false subgoal while trying to prove a true one. (Note that this is ok in the sense that it is not ``unsound.'' The system will fail in its attempt to establish the false subgoal and the main proof attempt will fail.) As you gain facility with using the prover, you'll get pretty good at recognizing what to look for when reading a proof script. The prover's [proof-tree] utility helps with monitoring an ongoing proof and jumping to designated locations in the proof (see [proof-tree]). See [tips] for a number of useful pointers on using the theorem prover effectively. When the prover has successfully proved all subgoals, the proof is finished. As with a [defun], a summary of the proof is printed. This was an extremely simple proof, needing no additional guidance. More realistic examples typically require the user to look carefully at the failed proof log to find ways to influence the prover to do better on its next attempt. This means either: proving some rules that will then be available to the prover, changing the global state in ways that will affect the proof, or providing some [hints] locally that will influence the prover's behavior. Proving this lemma (my-app-length) is an example of the first. Since this is a [rewrite] rule, whenever in a later proof an instance of the form (LEN (MY-APP X Y)) is encountered, it will be rewritten to the corresponding instance of (+ (LEN X) (LEN Y)). Disabling the rule by executing the [command] (in-theory (disable my-app-length)), is an example of a global change to the behavior of the prover since this [rewrite] will not be performed subsequently (unless the rule is again [enable]d). Finally, we can add a (local) [disable] ``hint'' to a [defthm], meaning to [disable] the lemma only in the proof of one or more subgoals. For example: (defthm my-app-length-commutativity (equal (len (my-app x y)) (len (my-app y x))) :hints ((\"Goal\" :in-theory (disable my-app-length)))) In this case, the hint supplied is a bad idea since the proof is much harder with the hint than without it. Try it both ways. By the way, to undo the previous event use :u (see [u]). To undo back to some earlier event use :ubt (see [ubt]). To view the current event use :pe :here. To list several [events] use :pbt (see [pbt]). Notice the form of the hint in the previous example (see [hints]). It specifies a goal to which the hint applies. \"Goal\" refers to the top-level goal of the theorem. Subgoals are given unique names as they are generated. It may be useful to suggest that a function symbol be [disable]d only for Subgoal 1.3.9, say, and a different function [enable]d only on Subgoal 5.2.8. Overuse of such [hints] often suggests a poor global proof strategy. We now recommend that you visit [documentation] on additional examples. See [annotated-ACL2-scripts].") (ANALYZING_COMMON_LISP_MODELS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Analyzing Common Lisp Models To analyze a model you must be able to reason about the operations and relations involved. Perhaps, for example, some aspect of the model depends upon the fact that the concatenation operation is associative. In any Common Lisp you can confirm that (app '(A B) (app '(C D) '(E F))) and (app (app '(A B) '(C D)) '(E F))) both evaluate to the same thing, (A B C D E F). But what distinguishes ACL2 (the logic) from applicative Common Lisp (the language) is that in ACL2 you can prove that the concatenation function app is associative when its arguments are true-lists, whereas in Common Lisp all you can do is test that proposition. That is, in ACL2 it makes sense to say that the following formula is a ``theorem.'' Theorem Associativity of App (implies (and (true-listp a) (true-listp b)) (equal (app (app a b) c) (app a (app b c)))) Theorems about the properties of models are proved by symbolically manipulating the operations and relations involved. If the concatenation of sequences is involved in your model, then you may well need the theorem above in order to that your model has some particular property.") (AND (BASICS ACL2-BUILT-INS) "Conjunction And is the macro for conjunctions. And takes any number of arguments. And returns nil if one of the arguments is nil, but otherwise returns the last argument. If there are no arguments, and returns t. And is a Common Lisp macro. See any Common Lisp documentation for more information. Macro: (defmacro and (&rest args) (and-macro args)) Function: (defun and-macro (lst) (declare (xargs :guard t)) (if (consp lst) (if (consp (cdr lst)) (list 'if (car lst) (and-macro (cdr lst)) nil) (car lst)) t))") (ANNOTATED-ACL2-SCRIPTS (ACL2-TUTORIAL) "Examples of ACL2 scripts Beginning users may find these annotated scripts useful. We suggest that you read these in the following order: [Tutorial1-Towers-of-Hanoi] [Tutorial2-Eights-Problem] [Tutorial3-Phonebook-Example] [Tutorial4-Defun-Sk-Example] [Tutorial5-Miscellaneous-Examples] You can also find useful demos in the [community-books] directory, books/demos/, and its subdirectories. The web page {Brief ACL2 Tutorial | http://www.cs.utexas.edu/users/moore/publications/tutorial/rev3.html} contains a script that illustrates how it feels to use The Method to prove an unusual list reverse function correct. The screen shots of ACL2's proof output are outdated -- in the version shown, ACL2 does not print Key Checkpoints, but the concept of key checkpoint is clear in the discussion and the behavior of the user. See {Polishing Proofs Tutorial | http://www.cs.utexas.edu/users/moore/acl2/contrib/POLISHING-PROOFS-TUTORIAL.html} for a tutorial on becoming successful at approaching a formalization and proof problem in ACL2. That tutorial, written by Shilpi Goel and Sandip Ray, has two parts: it illustrates how to guide the theorem prover to a successful proof, and it shows how to clean up the proof in order to facilitate maintenance and extension of the resulting book (see [books]). The {ACL2 Demo Given at TPHOLs 2008 | http://www.cs.utexas.edu/users/moore/publications/tutorial/kaufmann-TPHOLs08/index.html} by Matt Kaufmann includes scripts and a gzipped tar file containing the entire contents of the demos. The {sort equivalence demo | http://www.cs.utexas.edu/users/moore/publications/tutorial/sort-equivalence} is a collection of scripts illustrating both high-level strategy and lower-level tactics dealing with the functional equivalence of various list sorting algorithms. Start with the README on that directory. There is also a {gzipped tar file | http://www.cs.utexas.edu/users/moore/publications/tutorial/sort-equivalence.tgz} with all of these scripts. When you feel you have read enough examples, you might want to try the following very simple example on your own. (See [solution-to-simple-example] for a solution, after you work on this example.) First define the notion of the ``fringe'' of a tree, where we identify trees simply as [cons] structures, with [atom]s at the leaves. For example: ACL2 !>(fringe '((a . b) c . d)) (A B C D) Next, define the notion of a ``leaf'' of a tree, i.e., a predicate leaf-p that is true of an atom if and only if that atom appears at the tip of the tree. Define this notion without referencing the function fringe. Finally, prove the following theorem, whose proof may well be automatic (i.e., not require any lemmas). (defthm leaf-p-iff-member-fringe (iff (leaf-p atm x) (member-equal atm (fringe x)))) Subtopics [Solution-to-simple-example] Solution to a simple example [Tutorial1-towers-of-hanoi] The Towers of Hanoi Example [Tutorial2-eights-problem] The Eights Problem Example [Tutorial3-phonebook-example] A Phonebook Specification [Tutorial4-defun-sk-example] Example of quantified notions [Tutorial5-miscellaneous-examples] Miscellaneous ACL2 examples") (AN_EXAMPLE_COMMON_LISP_FUNCTION_DEFINITION (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "An Example Common Lisp Function Definition [{IMAGE}] Consider the binary trees x and y below. {IMAGE} In Lisp, x is written as the list '(A B) or, equivalently, as '(A B . NIL). Similarly, y may be written '(C D E). Suppose we wish to replace the right-most tip of x by the entire tree y. This is denoted (app x y), where app stands for ``append''. {IMAGE} We can define app with: (defun app (x y) ; Concatenate x and y. (declare (type (satisfies true-listp) x)); We expect x to end in NIL. (cond ((endp x) y) ; If x is empty, return y. (t (cons (car x) ; Else, copy first node (app (cdr x) y))))) ; and recur into next. If you defined this function in some Common Lisp, then to run app on the x and y above you could then type (app '(A B) '(C D E)) and Common Lisp will print the result (A B C D E). [{IMAGE}]") (AN_EXAMPLE_OF_ACL2_IN_USE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "An Example of ACL2 in Use [{IMAGE}] To introduce you to ACL2 we will consider the app function discussed in the [Common Lisp] page, except we will omit for the moment the declare form, which in ACL2 is called a guard. Guards are arbitrary ACL2 terms that express the ``intended domain'' of functions. In that sense, guards are akin to type signatures. However, Common Lisp and ACL2 are untyped programming languages: while the language supports several different data types and the types of objects can be determined by predicates at runtime, any type of object may be passed to any function. Thus, guards are ``extra-logical.'' Recognizing both the practical and intellectual value of knowing that your functions are applied to the kinds of objects you intend, ACL2 imposes guards on Common Lisp and provides a means of proving that functions are used as intended. But the story is necessarily complicated and we do not recommend it to the new user. Get used to the fact that any ACL2 function may be applied to any objects and program accordingly. Read about guards later. Here is the definition again (defun app (x y) (cond ((endp x) y) (t (cons (car x) (app (cdr x) y))))) The next few stops along the Walking Tour will show you * how to use the ACL2 documentation, * what happens when the above definition is submitted to ACL2, * what happens when you evaluate calls of app, * what one simple theorem about app looks like, * how ACL2 proves the theorem, and * how that theorem can be used in another proof. Along the way we will talk about the definitional principle, types, the ACL2 read-eval-print loop, and how the theorem prover works. When we complete this part of the tour we will return briefly to the notion of guards and revisit several of the topics above in that context. [{IMAGE}]") (APPEND (LISTS ACL2-BUILT-INS) "[concatenate] zero or more lists Append, which takes zero or more arguments, expects all the arguments except perhaps the last to be true (null-terminated) lists. It returns the result of concatenating all the elements of all the given lists into a single list. Actually, in ACL2 append is a macro that expands into calls of the binary function [binary-append] if there are at least two arguments; if there is just one argument then the expansion is that argument; and finally, (append) expands to nil. Append is a Common Lisp function. See any Common Lisp documentation for more information. See [append-without-guard] for a version of append that has a guard of t. Macro: (defmacro append (&rest rst) (cond ((null rst) nil) ((null (cdr rst)) (car rst)) (t (xxxjoin 'binary-append rst)))) Function: (defun binary-append (x y) (declare (xargs :guard (true-listp x))) (cond ((endp x) y) (t (cons (car x) (binary-append (cdr x) y))))) Subtopics [Binary-append] [concatenate] two lists") (APROPOS (POINTERS) "See [finding-documentation].") (ARCHITECTURE-OF-THE-PROVER (INTRODUCTION-TO-THE-THEOREM-PROVER) "A simple overview of how the prover works Six built-in proof techniques are used by ACL2 to decompose the goal formula into subgoals. * simplification --- decision procedures and rewriting with previously proved rules, but actually including a host of other techniques under your control. Simplification is the only proof technique that can reduce a formula to 0 subgoals (i.e., prove it) rather than just transform it to other formulas. The predominant activity in most proofs is simplification. There are many ways you can affect what the simplifier does to your formulas. Good users spend most of their time thinking about how to control the simplifier. * destructor elimination --- getting rid of ``destructor terms'' like (CAR X) and (CDR X) by replacing a variable, e.g., X, by a ``constructor'' term, e.g., (CONS A B). But you can tell ACL2 about new destructor/constructor combinations. * fertilization --- using an equivalence hypothesis by substituting one side for the other in the goal. When under induction, ACL2 may decide to restrict the substitution as follows, using its so-called cross-fertilization heuristic: substitute only into one side of the conclusion, thus using an inductive hypothesis in preparation for possible generalization in advance of another induction. Note that cross-fertilization is used only when generalization is enabled: with the hint :do-not '(generalize), only full fertilization is applied. * generalization --- replacing a term by a new variable and restricting the new variable to have some of the properties of the term. You can control the restrictions imposed on the new variable. This is a heuristic that prepares the goal for another induction. * elimination of irrelevance --- throwing away unnecessary hypotheses. This is a heuristic that prepares the goal for another induction. * induction --- selecting an induction scheme to prove a formula. Inductions are ``suggested'' by the recursive functions appearing in the formula. But you can control what inductions are suggested by terms. But you can add additional techniques, called clause processors. The various techniques are tried in turn, with simplification first and induction last. Each technique reports one of three outcomes: it found nothing to change (i.e., the technique doesn't apply to that subgoal), it decided to abort the proof attempt (typically because there is reason to believe the proof is failing), or it decomposed the goal into k subgoals. The last outcome has a special case: if k is 0 then the technique proved the goal. Whenever k is non-0, the process starts over again with simplification on each of the k subgoals. However, it saves up all the subgoals for which induction is the only proof technique left to try. That way you see how it performs on every base case and induction step of one induction before it launches into another induction. It runs until you or one of the proof techniques aborts the proof attempt or until all subgoals have been proved. Note that if simplification produces a subgoal, that subgoal is re-simplified. This process continues until the subgoal cannot be simplified further. Only then is the next proof technique is tried. Such suboals are said to be stable under simplification. While this is happening, the prover prints an English narrative describing the process. Basically, after each goal is printed, the system prints an English paragraph that names the next applicable proof technique, gives a brief description of what that technique does to the subgoal, and says how many new subgoals are produced. Then each subgoal is dealt with in turn. If the proof is successful, you could read this log as a proof of the conjecture. But output from successful proofs is generally never read because it is not important to The Method described in [introduction-to-the-theorem-prover]. The output of an unsuccessful proof attempt concludes with some key checkpoints which usually bear looking at. For more information about how ACL2 orchestrates its proof techniques, see [hints-and-the-waterfall].") (AREF1 (ARRAYS ACL2-BUILT-INS) "Access the elements of a 1-dimensional array Example Form: (aref1 'delta1 a (+ i k)) General Form: (aref1 name alist index) where name is a symbol, alist is a 1-dimensional array and index is a legal index into alist. This function returns the value associated with index in alist, or else the default value of the array. See [arrays] for details. This function executes in virtually constant time if alist is in fact the ``semantic value'' associated with name (see [arrays]). When it is not, aref1 must do a linear search through alist. In that case the correct answer is returned but a slow array comment is printed to the comment window. See [slow-array-warning]. Function: (defun aref1 (name l n) (declare (xargs :guard (and (array1p name l) (integerp n) (>= n 0) (< n (car (dimensions name l)))))) (let ((x (and (not (eq n :header)) (assoc n l)))) (cond ((null x) (default name l)) (t (cdr x)))))") (AREF2 (ARRAYS ACL2-BUILT-INS) "Access the elements of a 2-dimensional array Example Form: (aref2 'delta1 a i j) General Form: (aref2 name alist i j) where name is a symbol, alist is a 2-dimensional array and i and j are legal indices into alist. This function returns the value associated with (i . j) in alist, or else the default value of the array. See [arrays] for details. This function executes in virtually constant time if alist is in fact the ``semantic value'' associated with name (see [arrays]). When it is not, aref2 must do a linear search through alist. In that case the correct answer is returned but a slow array comment is printed to the comment window. See [slow-array-warning]. Function: (defun aref2 (name l i j) (declare (xargs :guard (and (array2p name l) (integerp i) (>= i 0) (< i (car (dimensions name l))) (integerp j) (>= j 0) (< j (cadr (dimensions name l)))))) (let ((x (assoc2 i j l))) (cond ((null x) (default name l)) (t (cdr x)))))") (ARGS (DOCUMENTATION) "args, [guard], type, [constraint], etc., of a function symbol Example: :args assoc-eq Args takes one argument, a symbol which must be the name of a function or macro, and prints out the formal parameters, the [guard] expression, the output [signature], the deduced type, the [constraint] (if any), and whether [documentation] about the symbol is available via :[doc].") (ARRAY1P (ARRAYS ACL2-BUILT-INS) "Recognize a 1-dimensional array Example Form: (array1p 'delta1 a) General Form: (array1p name alist) where name and alist are arbitrary objects. This function returns t if alist is a 1-dimensional ACL2 array. Otherwise it returns nil. The function operates in constant time if alist is the semantic value of name. See [arrays]. Function: (defun array1p (name l) (declare (xargs :guard t)) (and (symbolp name) (alistp l) (let ((header-keyword-list (cdr (assoc-eq :header l)))) (and (keyword-value-listp header-keyword-list) (let ((dimensions (cadr (assoc-keyword :dimensions header-keyword-list))) (maximum-length (cadr (assoc-keyword :maximum-length header-keyword-list)))) (and (true-listp dimensions) (equal (length dimensions) 1) (integerp (car dimensions)) (integerp maximum-length) (< 0 (car dimensions)) (< (car dimensions) maximum-length) (<= maximum-length *maximum-positive-32-bit-integer*) (bounded-integer-alistp l (car dimensions))))))))") (ARRAY2P (ARRAYS ACL2-BUILT-INS) "Recognize a 2-dimensional array Example Form: (array2p 'delta1 a) General Form: (array2p name alist) where name and alist are arbitrary objects. This function returns t if alist is a 2-dimensional ACL2 array. Otherwise it returns nil. The function operates in constant time if alist is the semantic value of name. See [arrays]. Function: (defun array2p (name l) (declare (xargs :guard t)) (and (symbolp name) (alistp l) (let ((header-keyword-list (cdr (assoc-eq :header l)))) (and (keyword-value-listp header-keyword-list) (let ((dimensions (cadr (assoc-keyword :dimensions header-keyword-list))) (maximum-length (cadr (assoc-keyword :maximum-length header-keyword-list)))) (and (true-listp dimensions) (equal (length dimensions) 2) (let ((d1 (car dimensions)) (d2 (cadr dimensions))) (and (integerp d1) (integerp d2) (integerp maximum-length) (< 0 d1) (< 0 d2) (< (* d1 d2) maximum-length) (<= maximum-length *maximum-positive-32-bit-integer*) (bounded-integer-alistp2 l d1 d2)))))))))") (ARRAYS (PROGRAMMING) "ACL2 arrays and operations on them Below we begin a detailed presentation of ACL2 arrays. ACL2's single-threaded objects (see [stobj]) provide a similar functionality that is generally more efficient when there are updates (writes), but is also more restrictive. See [arrays-example] for a brief introduction illustrating the use of ACL2 arrays. ACL2 provides relatively efficient 1- and 2-dimensional arrays. Arrays are awkward to provide efficiently in an applicative language because the programmer rightly expects to be able to ``modify'' an array object with the effect of changing the behavior of the element accessing function on that object. This, of course, does not make any sense in an applicative setting. The element accessing function is, after all, a function, and its behavior on a given object is immutable. To ``modify'' an array object in an applicative setting we must actually produce a new array object. Arranging for this to be done efficiently is a challenge to the implementors of the language. In addition, the programmer accustomed to the von Neumann view of arrays must learn how to use immutable applicative arrays efficiently. In this note we explain 1-dimensional arrays. In particular, we explain briefly how to create, access, and ``modify'' them, how they are implemented, and how to program with them. 2-dimensional arrays are dealt with by analogy. The Logical Description of ACL2 Arrays An ACL2 1-dimensional array is an object that associates arbitrary objects with certain integers, called ``indices.'' Every array has a dimension, dim, which is a positive integer. The indices of an array are the consecutive integers from 0 through dim-1. To obtain the object associated with the index i in an array a, one uses (aref1 name a i). Name is a symbol that is irrelevant to the semantics of [aref1] but affects the speed with which it computes. We will talk more about array ``names'' later. To produce a new array object that is like a but which associates val with index i, one uses (aset1 name a i val). An ACL2 1-dimensional array is actually an alist. There is no special ACL2 function for creating arrays; they are generally built with the standard list processing functions [list] and [cons]. However, there is a special ACL2 function, called [compress1], for speeding up access to the elements of such an alist. We discuss [compress1] later. One element of the alist must be the ``header'' of the array. The [header] of a 1-dimensional array with dimension dim is of the form: (:HEADER :DIMENSIONS (dim) :MAXIMUM-LENGTH max :DEFAULT obj ; optional :NAME name ; optional :ORDER order ; optional values are < (the default), >, or :none/nil ). Obj may be any object and is called the ``default value'' of the array. [Max] must be an integer greater than dim. Name must be a symbol. The :[default] and :name entries are optional; if :[default] is omitted, the default value is nil. The function [header], when given a name and a 1- or 2-dimensional array, returns the [header] of the array. The functions [dimensions], [maximum-length], and [default] are similar and return the corresponding fields of the [header] of the array. The role of the :[dimensions] field is obvious: it specifies the legal indices into the array. The roles played by the :[maximum-length] and :[default] fields are described below. Aside from the [header], the other elements of the alist must each be of the form (i . val), where i is an integer and 0 <= i < dim, and val is an arbitrary object. The :order field of the header is ignored for 2-dimensional arrays. For 1-dimensional arrays, it specifies the order of keys (i, above) when the array is compressed as with [compress1], as described below. An :order of :none or nil specifies no reordering of the alist by [compress1], and an order of > specifies reordering by [compress1] so that keys are in descending order. Otherwise, the alist is reordered by [compress1] so that keys are in ascending order. (Aref1 name a i) is [guard]ed so that name must be a symbol, a must be an array and i must be an index into a. The value of (aref1 name a i) is either (cdr (assoc i a)) or else is the default value of a, depending on whether there is a pair in a whose [car] is i. Note that name is irrelevant to the value of an [aref1] expression. You might :pe aref1 to see how simple the definition is. (Aset1 name a i val) is [guard]ed analogously to the [aref1] expression. The value of the [aset1] expression is essentially (cons (cons i val) a). Again, name is irrelevant. Note (aset1 name a i val) is an array, a', with the property that (aref1 name a' i) is val and, except for index i, all other indices into a' produce the same value as in a. Note also that if a is viewed as an alist (which it is) the pair ``binding'' i to its old value is in a' but ``covered up'' by the new pair. Thus, the length of an array grows by one when [aset1] is done. Because [aset1] covers old values with new ones, an array produced by a sequence of [aset1] calls may have many irrelevant pairs in it. The function [compress1] can remove these irrelevant pairs. Thus, (compress1 name a) returns an array that is equivalent (vis-a-vis [aref1]) to a but which may be shorter. For technical reasons, the alist returned by [compress1] may also list the pairs in a different order than listed in a. To prevent arrays from growing excessively long due to repeated [aset1] operations, [aset1] actually calls [compress1] on the new alist whenever the length of the new alist exceeds the :[maximum-length] entry, [max], in the [header] of the array. See the definition of [aset1] (for example by using :[pe]). This is primarily just a mechanism for freeing up [cons] space consumed while doing [aset1] operations. Note however that this [compress1] call is replaced by a hard error if the header specifies an :order of :none or nil. This completes the logical description of 1-dimensional arrays. 2-dimensional arrays are analogous. The :[dimensions] entry of the [header] of a 2-dimensional array should be (dim1 dim2). A pair of indices, i and j, is legal iff 0 <= i < dim1 and 0 <= j < dim2. The :[maximum-length] must be greater than dim1*dim2. [Aref2], [aset2], and [compress2] are like their counterparts but take an additional index argument. Finally, the pairs in a 2-dimensional array are of the form ((i . j) . val). The Implementation of ACL2 Arrays Very informally speaking, the function [compress1] ``creates'' an ACL2 array that provides fast access, while the function [aref1] ``maintains'' fast access. We now describe this informal idea more carefully. [Aref1] is essentially [assoc]. If [aref1] were implemented naively the time taken to access an array element would be linear in the dimension of the array and the number of ``assignments'' to it (the number of [aset1] calls done to create the array from the initial alist). This is intolerable; arrays are ``supposed'' to provide constant-time access and change. The apparently irrelevant names associated with ACL2 arrays allow us to provide constant-time access and change when arrays are used in ``conventional'' ways. The implementation of arrays makes it clear what we mean by ``conventional.'' Recall that array names are symbols. Behind the scenes, ACL2 associates two objects with each ACL2 array name. The first object is called the ``semantic value'' of the name and is an alist. The second object is called the ``raw lisp array'' and is a Common Lisp array. When (compress1 name alist) builds a new alist, a', it sets the semantic value of name to that new alist. Furthermore, it creates a Common Lisp array and writes into it all of the index/value pairs of a', initializing unassigned indices with the default value. This array becomes the raw lisp array of name. [Compress1] then returns a', the semantic value, as its result, as required by the definition of [compress1]. When (aref1 name a i) is invoked, [aref1] first determines whether the semantic value of name is a (i.e., is [eq] to the alist a). If so, [aref1] can determine the ith element of a by invoking Common Lisp's aref function on the raw lisp array associated with name. Note that no linear search of the alist a is required; the operation is done in constant time and involves retrieval of two global variables, an [eq] test and jump, and a raw lisp array access. In fact, an ACL2 array access of this sort is about 5 times slower than a C array access. On the other hand, if name has no semantic value or if it is different from a, then [aref1] determines the answer by linear search of a as suggested by the assoc-like definition of [aref1]. Thus, [aref1] always returns the axiomatically specified result. It returns in constant time if the array being accessed is the current semantic value of the name used. The ramifications of this are discussed after we deal with [aset1]. When (aset1 name a i val) is invoked, [aset1] does two [cons]es to create the new array. Call that array a'. It will be returned as the answer. (In this discussion we ignore the case in which [aset1] does a [compress1].) However, before returning, [aset1] determines if name's semantic value is a. If so, it makes the new semantic value of name be a' and it smashes the raw lisp array of name with val at index i, before returning a' as the result. Thus, after doing an [aset1] and obtaining a new semantic value a', all [aref1]s on that new array will be fast. Any [aref1]s on the old semantic value, a, will be slow. To understand the performance implications of this design, consider the chronological sequence in which ACL2 (Common Lisp) evaluates expressions: basically inner-most first, left-to-right, call-by-value. An array use, such as (aref1 name a i), is ``fast'' (constant-time) if the alist supplied, a, is the value returned by the most recently executed [compress1] or [aset1] on the name supplied. In the functional expression of ``conventional'' array processing, all uses of an array are fast. The :name field of the [header] of an array is completely irrelevant. Our convention is to store in that field the symbol we mean to use as the name of the raw lisp array. But no ACL2 function inspects :name and its primary value is that it allows the user, by inspecting the semantic value of the array --- the alist --- to recall the name of the raw array that probably holds that value. We say ``probably'' since there is no enforcement that the alist was compressed under the name in the [header] or that all asets used that name. Such enforcement would be inefficient. Some Programming Examples In the following examples we will use ACL2 ``global variables'' to hold several arrays. See [@], and see [assign]. Let the [state] global variable a be the 1-dimensional compressed array of dimension 5 constructed below. ACL2 !>(assign a (compress1 'demo '((:header :dimensions (5) :maximum-length 15 :default uninitialized :name demo) (0 . zero)))) Then (aref1 'demo (@ a) 0) is zero and (aref1 'demo (@ a) 1) is uninitialized. Now execute ACL2 !>(assign b (aset1 'demo (@ a) 1 'one)) Then (aref1 'demo (@ b) 0) is zero and (aref1 'demo (@ b) 1) is one. All of the [aref1]s done so far have been ``fast.'' Note that we now have two array objects, one in the global variable a and one in the global variable b. B was obtained by assigning to a. That assignment does not affect the alist a because this is an applicative language. Thus, (aref1 'demo (@ a) 1) must still be uninitialized. And if you execute that expression in ACL2 you will see that indeed it is. However, a rather ugly comment is printed, namely that this array access is ``slow.'' The reason it is slow is that the raw lisp array associated with the name demo is the array we are calling b. To access the elements of a, [aref1] must now do a linear search. Any reference to a as an array is now ``unconventional;'' in a conventional language like Ada or Common Lisp it would simply be impossible to refer to the value of the array before the assignment that produced our b. Now let us define a function that counts how many times a given object, x, occurs in an array. For simplicity, we will pass in the name and highest index of the array: ACL2 !>(defun cnt (name a i x) (declare (xargs :guard (and (array1p name a) (integerp i) (>= i -1) (< i (car (dimensions name a)))) :mode :logic :measure (nfix (+ 1 i)))) (cond ((zp (1+ i)) 0) ; return 0 if i is at most -1 ((equal x (aref1 name a i)) (1+ (cnt name a (1- i) x))) (t (cnt name a (1- i) x)))) To determine how many times zero appears in (@ b) we can execute: ACL2 !>(cnt 'demo (@ b) 4 'zero) The answer is 1. How many times does uninitialized appear in (@ b)? ACL2 !>(cnt 'demo (@ b) 4 'uninitialized) The answer is 3, because positions 2, 3 and 4 of the array contain that default value. Now imagine that we want to assign 'two to index 2 and then count how many times the 2nd element of the array occurs in the array. This specification is actually ambiguous. In assigning to b we produce a new array, which we might call c. Do we mean to count the occurrences in c of the 2nd element of b or the 2nd element of c? That is, do we count the occurrences of uninitialized or the occurrences of two? If we mean the former the correct answer is 2 (positions 3 and 4 are uninitialized in c); if we mean the latter, the correct answer is 1 (there is only one occurrence of two in c). Below are ACL2 renderings of the two meanings, which we call [former] and [latter]. (Warning: Our description of these examples, and of an example [fast former] that follows, assumes that only one of these three examples is actually executed; for example, they are not executed in sequence. See ``A Word of Warning'' below for more about this issue.) (cnt 'demo (aset1 'demo (@ b) 2 'two) 4 (aref1 'demo (@ b) 2)) ; [former] (let ((c (aset1 'demo (@ b) 2 'two))) ; [latter] (cnt 'demo c 4 (aref1 'demo c 2))) Note that in [former] we create c in the second argument of the call to cnt (although we do not give it a name) and then refer to b in the fourth argument. This is unconventional because the second reference to b in [former] is no longer the semantic value of demo. While ACL2 computes the correct answer, namely 2, the execution of the [aref1] expression in [former] is done slowly. A conventional rendering with the same meaning is (let ((x (aref1 'demo (@ b) 2))) ; [fast former] (cnt 'demo (aset1 'demo (@ b) 2 'two) 4 x)) which fetches the 2nd element of b before creating c by assignment. It is important to understand that [former] and [fast former] mean exactly the same thing: both count the number of occurrences of uninitialized in c. Both are legal ACL2 and both compute the same answer, 2. Indeed, we can symbolically transform [fast former] into [former] merely by substituting the binding of x for x in the body of the [let]. But [fast former] can be evaluated faster than [former] because all of the references to demo use the then-current semantic value of demo, which is b in the first line and c throughout the execution of the cnt in the second line. [Fast former] is the preferred form, both because of its execution speed and its clarity. If you were writing in a conventional language you would have to write something like [fast former] because there is no way to refer to the 2nd element of the old value of b after smashing b unless it had been saved first. We turn now to [latter]. It is both clear and efficient. It creates c by assignment to b and then it fetches the 2nd element of c, two, and proceeds to count the number of occurrences in c. The answer is 1. [Latter] is a good example of typical ACL2 array manipulation: after the assignment to b that creates c, c is used throughout. It takes a while to get used to this because most of us have grown accustomed to the peculiar semantics of arrays in conventional languages. For example, in raw lisp we might have written something like the following, treating b as a ``global variable'': (cnt 'demo (aset 'demo b 2 'two) 4 (aref 'demo b 2)) which sort of resembles [former] but actually has the semantics of [latter] because the b from which aref fetches the 2nd element is not the same b used in the aset! The array b is destroyed by the aset and b henceforth refers to the array produced by the aset, as written more clearly in [latter]. A Word of Warning: Users must exercise care when experimenting with [former], [latter] and [fast former]. Suppose you have just created b with the assignment shown above, ACL2 !>(assign b (aset1 'demo (@ a) 1 'one)) If you then evaluate [former] in ACL2 it will complain that the [aref1] is slow and compute the answer, as discussed. Then suppose you evaluate [latter] in ACL2. From our discussion you might expect it to execute fast --- i.e., issue no complaint. But in fact you will find that it complains repeatedly. The problem is that the evaluation of [former] changed the semantic value of demo so that it is no longer b. To try the experiment correctly you must make b be the semantic value of demo again before the next example is evaluated. One way to do that is to execute ACL2 !>(assign b (compress1 'demo (@ b))) before each expression. Because of issues like this it is often hard to experiment with ACL2 arrays at the top-level. We find it easier to write functions that use arrays correctly and efficiently than to so use them interactively. This last assignment also illustrates a very common use of [compress1]. While it was introduced as a means of removing irrelevant pairs from an array built up by repeated assignments, it is actually most useful as a way of insuring fast access to the elements of an array. Many array processing tasks can be divided into two parts. During the first part the array is built. During the second part the array is used extensively but not modified. If your [programming] task can be so divided, it might be appropriate to construct the array entirely with list processing, thereby saving the cost of maintaining the semantic value of the name while few references are being made. Once the alist has stabilized, it might be worthwhile to treat it as an array by calling [compress1], thereby gaining constant time access to it. ACL2's theorem prover uses this technique in connection with its implementation of the notion of whether a [rune] is [disable]d or not. Associated with every [rune] is a unique integer index, called its ``nume.'' When each rule is stored, the corresponding nume is stored as a component of the rule. [Theories] are lists of [rune]s and membership in the ``current theory'' indicates that the corresponding rule is [enable]d. But these lists are very long and membership is a linear-time operation. So just before a proof begins we map the list of [rune]s in the current theory into an alist that pairs the corresponding numes with t. Then we compress this alist into an array. Thus, given a rule we can obtain its nume (because it is a component) and then determine in constant time whether it is [enable]d. The array is never modified during the proof, i.e., [aset1] is never used in this example. From the logical perspective this code looks quite odd: we have replaced a linear-time membership test with an apparently linear-time [assoc] after going to the trouble of mapping from a list of [rune]s to an alist of numes. But because the alist of numes is an array, the ``apparently linear-time [assoc]'' is more apparent than real; the operation is constant-time. Subtopics [Aref1] Access the elements of a 1-dimensional array [Aref2] Access the elements of a 2-dimensional array [Array1p] Recognize a 1-dimensional array [Array2p] Recognize a 2-dimensional array [Arrays-example] An example illustrating ACL2 arrays [Aset1] Set the elements of a 1-dimensional array [Aset2] Set the elements of a 2-dimensional array [Compress1] Remove irrelevant pairs from a 1-dimensional array [Compress2] Remove irrelevant pairs from a 2-dimensional array [Default] Return the :default from the [header] of a 1- or 2-dimensional array [Dimensions] Return the :dimensions from the [header] of a 1- or 2-dimensional array [Flush-compress] Flush the under-the-hood array for the given name [Header] Return the header of a 1- or 2-dimensional array [Maximum-length] Return the :maximum-length from the [header] of an array [Slow-array-warning] A warning or error issued when [arrays] are used inefficiently") (ARRAYS-EXAMPLE (ARRAYS) "An example illustrating ACL2 arrays The example below illustrates the use of ACL2 arrays. It is not, of course, a substitute for the detailed explanations provided elsewhere (see [arrays], including subtopics). ACL2 !>(defun defarray (name size initial-element) (compress1 name (cons (list :HEADER :DIMENSIONS (list size) :MAXIMUM-LENGTH (1+ size) :DEFAULT initial-element :NAME name) nil))) Since DEFARRAY is non-recursive, its admission is trivial. We observe that the type of DEFARRAY is described by the theorem (AND (CONSP (DEFARRAY NAME SIZE INITIAL-ELEMENT)) (TRUE-LISTP (DEFARRAY NAME SIZE INITIAL-ELEMENT))). We used the :type-prescription rule COMPRESS1. Summary Form: ( DEFUN DEFARRAY ...) Rules: ((:TYPE-PRESCRIPTION COMPRESS1)) Warnings: None Time: 0.02 seconds (prove: 0.00, print: 0.02, other: 0.00) DEFARRAY ACL2 !>(assign my-ar (defarray 'a1 5 17)) ((:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1)) ACL2 !>(aref1 'a1 (@ my-ar) 3) 17 ACL2 !>(aref1 'a1 (@ my-ar) 8) ACL2 Error in TOP-LEVEL: The guard for the function symbol AREF1, which is (AND (ARRAY1P NAME L) (INTEGERP N) (>= N 0) (< N (CAR (DIMENSIONS NAME L)))), is violated by the arguments in the call (AREF1 'A1 '(#) 8). ACL2 !>(assign my-ar (aset1 'a1 (@ my-ar) 3 'xxx)) ((3 . XXX) (:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1)) ACL2 !>(aref1 'a1 (@ my-ar) 3) XXX ACL2 !>(aset1 'a1 (@ my-ar) 3 'yyy) ; BAD: (@ my-ar) now points to ; an old copy of the array! ((3 . YYY) (3 . XXX) (:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 6 :DEFAULT 17 :NAME A1)) ACL2 !>(aref1 'a1 (@ my-ar) 3) ; Because of \"BAD\" above, the array ; access is done using assoc rather ; than Lisp aref, hence is slower; ; but the answer is still correct, ; reflecting the value in (@ my-ar), ; which was not changed above. ********************************************************** Slow Array Access! A call of AREF1 on an array named A1 is being executed slowly. See :DOC slow-array-warning ********************************************************** XXX ACL2 !>") (ASET1 (ARRAYS ACL2-BUILT-INS) "Set the elements of a 1-dimensional array Example Form: (aset1 'delta1 a (+ i k) 27) General Form: (aset1 name alist index val) where name is a symbol, alist is a 1-dimensional array named name, index is a legal index into alist, and val is an arbitrary object. See [arrays] for details. Roughly speaking this function ``modifies'' alist so that the value associated with index is val. More precisely, it returns a new array, alist', of the same name and dimension as alist that, under [aref1], is everywhere equal to alist except at index where the result is val. That is, (aref1 name alist' i) is (aref1 name alist i) for all legal indices i except index, where (aref1 name alist' i) is val. In order to ``modify'' alist, aset1 [cons]es a new pair onto the front. If the length of the resulting alist exceeds the :[maximum-length] entry in the array [header], aset1 compresses the array as with [compress1]. It is generally expected that the ``semantic value'' of name will be alist (see [arrays]). This function operates in virtually constant time whether this condition is true or not (unless the [compress1] operation is required). But the value returned by this function cannot be used efficiently by subsequent aset1 operations unless alist is the semantic value of name when aset1 is executed. Thus, if the condition is not true, aset1 prints a slow array warning to the comment window. See [slow-array-warning]. Function: (defun aset1 (name l n val) (declare (xargs :guard (and (array1p name l) (integerp n) (>= n 0) (< n (car (dimensions name l)))))) (let ((l (cons (cons n val) l))) (cond ((> (length l) (maximum-length name l)) (compress1 name l)) (t l))))") (ASET2 (ARRAYS ACL2-BUILT-INS) "Set the elements of a 2-dimensional array Example Form: (aset2 'delta1 a i j 27) General Form: (aset2 name alist i j val) where name is a symbol, alist is a 2-dimensional array named name, i and j are legal indices into alist, and val is an arbitrary object. See [arrays] for details. Roughly speaking this function ``modifies'' alist so that the value associated with (i . j) is val. More precisely, it returns a new array, alist', of the same name and dimension as alist that, under [aref2], is everywhere equal to alist except at (i . j) where the result is val. That is, (aref2 name alist' x y) is (aref2 name alist x y) for all legal indices x y except i and j where (aref2 name alist' i j) is val. In order to ``modify'' alist, aset2 [cons]es a new pair onto the front. If the length of the resulting alist exceeds the :[maximum-length] entry in the array [header], aset2 compresses the array as with [compress2]. It is generally expected that the ``semantic value'' of name will be alist (see [arrays]). This function operates in virtually constant time whether this condition is true or not (unless the [compress2] operation is required). But the value returned by this function cannot be used efficiently by subsequent aset2 operations unless alist is the semantic value of name when aset2 is executed. Thus, if the condition is not true, aset2 prints a slow array warning to the comment window. See [slow-array-warning]. Function: (defun aset2 (name l i j val) (declare (xargs :guard (and (array2p name l) (integerp i) (>= i 0) (< i (car (dimensions name l))) (integerp j) (>= j 0) (< j (cadr (dimensions name l)))))) (let ((l (cons (cons (cons i j) val) l))) (cond ((> (length l) (maximum-length name l)) (compress2 name l)) (t l))))") (ASH (NUMBERS ACL2-BUILT-INS) "Arithmetic shift operation (ash i c) is the result of taking the two's complement representation of the integer i and shifting it by c bits: shifting left and padding with c 0 bits if c is positive, shifting right and dropping (abs c) bits if c is negative, and simply returning i if c is 0. The [guard] for ash requires that its arguments are integers. Ash is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun ash (i c) (declare (xargs :guard (and (integerp i) (integerp c)))) (floor (* (ifix i) (expt 2 c)) 1))") (ASSERT$ (ERRORS ACL2-BUILT-INS) "Cause a hard error if the given test is false General Form: (assert$ test form) where test returns a single value and form is arbitrary. Semantically, this call of assert$ is equivalent to form. However, it causes a hard error if the value of test is nil. That hard error invokes the function [illegal], which has a [guard] that is equal to nil; so if you use assert$ in code for which you verify guards, then a proof obligation will be that the occurrence of test is never nil. For a related utility, see [assert*]. Both assert$ and assert* create a [guard] proof obligation (when used in a definition made in [logic]-mode). However, assert$ checks the assertion at runtime, while assert* does not.") (ASSERT* (ERRORS ACL2-BUILT-INS) "Create a [guard] proof obligation that given test holds General Form: (assert* test form) where test returns a single value and form is arbitrary. Semantically, this call of assert$ is equivalent to form. However, a [guard] proof obligation is created that test holds, when used in a definition made in [logic]-mode). For a related utility, see [assert$]. Both assert$ and assert* create a [guard] proof obligation (when used in a definition made in [logic]-mode). However, assert$ checks the assertion at runtime, while assert* does not. Macro: (defmacro assert* (test form) (cons 'and (cons (cons 'mbt* (cons test 'nil)) (cons form 'nil))))") (ASSERT-EVENT (EVENTS) "Assert that a given form returns a non-nil value Examples: (assert-event (equal (+ 3 4) 7)) (assert-event (equal (+ 3 4) 7) :msg (msg \"Error: ~x0\" 'equal-check)) (assert-event (equal (+ 3 4) 7) :on-skip-proofs t) General Forms: (assert-event form) (assert-event form :on-skip-proofs t) Assert-event takes a ground form, i.e., one with no free variables; [stobj]s are allowed but only a single non-[stobj] value can be returned. The form is then evaluated and if the result is nil, then a so-called hard error (see [er]) results. This evaluation is however not done if proofs are being skipped, as during [include-book] (also see [skip-proofs] and see [ld-skip-proofsp]), unless :on-skip-proofs t is supplied. Normally, if an assert-event call fails then a generic failure message is printed, showing the offending form. However, if keyword argument :msg is supplied, then the failure message is printed as with [fmt] argument ~@0; see [fmt]. In particular, :msg is typically a string or a call (msg str arg-0 arg-1 ... arg-k), where str is a string and each arg-i is the value to be associated with #\\i upon formatted printing (as with [fmt]) of the string str. This form may be put into a book to be certified (see [books]), because assert-event is a macro whose calls expand to calls of value-triple (see [embedded-event-form]). When certifying a book, guard-checking is off, as though (set-guard-checking nil) has been evaluated; see [set-guard-checking]. That, together with a ``safe mode,'' guarantees that assert-event forms are evaluated in the logic without guard violations while certifying a book.") (ASSIGN (PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "Assign to a global variable in [state] Examples: (assign x (expt 2 10)) (assign a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B)) General Form: (assign symbol term) where symbol is any symbol (with certain enforced exclusions to avoid overwriting ACL2 system ``globals'') and term is any ACL2 term that could be evaluated at the top-level. Assign evaluates the term, stores the result as the value of the given symbol in the global-table of [state], and returns the result. (Note: the actual implementation of the storage of this value is much more efficient than this discussion of the logic might suggest.) Assign is a macro that effectively expands to the more complicated but understandable: (pprogn (f-put-global 'symbol term state) (mv nil (f-get-global 'symbol state) state)). The macro f-put-global is closely related to [assign]: (assign var val) macroexpands to (f-put-global 'var val state). The macro [@] gives convenient access to the value of such globals. The :[ubt] operation has no effect on the global-table of [state]. Thus, you may use these globals to hang onto useful data structures even though you may undo back past where you computed and saved them.") (ASSOC (ALISTS ACL2-BUILT-INS) "Look up key in association list General Forms: (assoc x alist) (assoc x alist :test 'eql) ; same as above (eql as equality test) (assoc x alist :test 'eq) ; same, but eq is equality test (assoc x alist :test 'equal) ; same, but equal is equality test (Assoc x alist) is the first member of alist whose [car] is x, or nil if no such member exists. The optional keyword, :TEST, has no effect logically, but provides the test (default [eql]) used for comparing x with the [car]s of successive elements of alist. The [guard] for a call of assoc depends on the test. In all cases, the second argument must satisfy [alistp]. If the test is [eql], then either the first argument must be suitable for [eql] (see [eqlablep]) or the second argument must satisfy [eqlable-alistp]. If the test is [eq], then either the first argument must be a symbol or the second argument must satisfy [symbol-alistp]. See [equality-variants] for a discussion of the relation between assoc and its variants: (assoc-eq x alist) is equivalent to (assoc x alist :test 'eq); (assoc-equal x alist) is equivalent to (assoc x alist :test 'equal). In particular, reasoning about any of these primitives reduces to reasoning about the function assoc-equal. Assoc is defined by Common Lisp. See any Common Lisp documentation for more information. Function: (defun assoc-equal (x alist) (declare (xargs :guard (alistp alist))) (cond ((endp alist) nil) ((equal x (car (car alist))) (car alist)) (t (assoc-equal x (cdr alist)))))") (ASSOC-EQ (POINTERS) "See [assoc].") (ASSOC-EQUAL (POINTERS) "See [assoc].") (ASSOC-KEYWORD (KEYWORD-VALUE-LISTP ACL2-BUILT-INS) "Look up key in a [keyword-value-listp] If l is a list of even length of the form (k1 a1 k2 a2 ... kn an), where each ki is a keyword, then (assoc-keyword key l) is the first tail of l starting with key if key is some ki, and is nil otherwise. The [guard] for (assoc-keyword key l) is (keyword-value-listp l). Function: (defun assoc-keyword (key l) (declare (xargs :guard (keyword-value-listp l))) (cond ((endp l) nil) ((eq key (car l)) l) (t (assoc-keyword key (cddr l)))))") (ASSOC-STRING-EQUAL (ALISTS ACL2-BUILT-INS) "Look up key, a string, in association list (Assoc-string-equal x alist) is similar to [assoc-equal]. However, for string x and alist alist, the comparison of x with successive keys in alist is done using [string-equal] rather than [equal]. The [guard] for assoc-string-equal requires that x is a string and alist is an alist. Function: (defun assoc-string-equal (str alist) (declare (xargs :guard (and (stringp str) (standard-char-listp (coerce str 'list)) (standard-string-alistp alist)))) (cond ((endp alist) nil) ((string-equal str (car (car alist))) (car alist)) (t (assoc-string-equal str (cdr alist)))))") (ATOM (CONSES ACL2-BUILT-INS) "Recognizer for atoms (atom x) is true if and only if x is an atom, i.e., not a [cons] pair. Atom has a [guard] of t, and is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun atom (x) (declare (xargs :guard t)) (not (consp x))) Subtopics [Atom-listp] Recognizer for a true list of [atom]s [Good-atom-listp] Recognizer for a true list of ``good'' [atom]s") (ATOM-LISTP (ATOM LISTS ACL2-BUILT-INS) "Recognizer for a true list of [atom]s The predicate atom-listp tests whether its argument is a [true-listp] of [atom]s, i.e., of non-conses. Also see [good-atom-listp]. Function: (defun atom-listp (lst) (declare (xargs :guard t)) (cond ((atom lst) (eq lst nil)) (t (and (atom (car lst)) (atom-listp (cdr lst))))))") (A_FLYING_TOUR_OF_ACL2 (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "A Flying Tour of ACL2 [{IMAGE}] On this tour you will learn a little about what ACL2 is for rather than how ACL2 works. At the top and bottom bottom of the ``page'' there are ``flying tour'' icons. Click on either icon to go to the next page of the tour. The tour visits the following topics sequentially. But on your first reading, don't navigate through the tour by clicking on these links; they are shown as live links only so that later you can determine what you've visited. Instead, just use the flying tour icons. The Flight Plan * [This Documentation] * [What is ACL2?] * [Mathematical Logic] * [Mechanical Theorem Proving] * [Mathematical Models in General] * [Mathematical Models of Computing Machines] [Formalizing Models] [Running Models] [Symbolic Execution of Models] [Proving Theorems about Models] * Requirements of ACL2 [The User's Skills] [Training] [Host System] On your first reading, don't explore other links you see in the tour. Some of them lead to the Walking Tour, which you can take coherently when you finish this tour. Others lead into the extensive hyptertext documentation and you are liable to get lost there unless you're trying to answer a specific question. We intend the tour to take about 10 minutes of your time. [{IMAGE}]") (A_SKETCH_OF_HOW_THE_REWRITER_WORKS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "A Sketch of How the Rewriter Works Below we show the first target term, extracted from the current conjecture. Below it we show the associativity rule. {IMAGE} The variables of the rewrite rule are instantiated so that the left-hand side of the rule matches the target: variable term from target a x1 b x2 c (app x3 x4) Then the target is replaced by the instantiated right-hand side of the rule. Sometimes rules have hypotheses. To make a long story short, if the rule has hypotheses, then after matching the left-hand side, the rewriter instantiates the hypotheses and rewrites them recursively. This is called backchaining. If they all rewrite to true, then the target is replaced as above. We discuss the rewriter in more detail in the extended introduction to how to use the theorem prover, see [introduction-to-the-theorem-prover], which we will recommend you work through after you have finished the two tours.") (A_TINY_WARNING_SIGN (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "A Tiny Warning Sign {IMAGE} This warning sign, which usually appears as ``{ICON}'', indicates that the link it marks takes you into ACL2's online documentation. The documentation is a vast graph of documented topics intended to help the user of ACL2 rather than the potential user. If you are exploring ACL2's home page to learn about the system, perhaps you should go back rather than follow the link marked with this sign. But you are welcome to explore the online documentation as well. Good luck.") (A_TRIVIAL_PROOF (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "A Trivial Proof {IMAGE}") (A_TYPICAL_STATE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "A Typical State [{IMAGE}] {IMAGE} Observe that the states in typical models talk about booleans integers vectors records caches bits symbols arrays stacks files characters strings sequences tables directories These objects are discrete rather than continuous; furthermore they are built incrementally or inductively by repeatedly using primitive operations to put together smaller pieces. The functions we need to manipulate these objects do things like concatenate, reverse, sort, search, count, etc. [{IMAGE}]") (A_WALKING_TOUR_OF_ACL2 (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "A Walking Tour of ACL2 [{IMAGE}] On this tour you will learn a little more about the ACL2 logic, the theorem prover, and the user interface. This time we will stick with really simple things, such as the associativity of list concatenation. We assume you have taken the Flying Tour but that you did not necessarily follow all the ``off-tour'' links because we encouraged you not to. With the Walking Tour we encourage you to visit off-tour links --- provided they are not marked with the tiny warning sign ([{ICON}]). But they are ``branches'' in the tour that lead to ``dead ends.'' When you reach a dead end, remember to use your browser's Back Button to return to the Walking Tour to continue. When you get to the end of the tour we'll give you a chance to repeat quickly both the Flying and the Walking Tours to visit any off-tour links still of interest. [{IMAGE}]") (BACKCHAIN-LIMIT (REWRITE META LINEAR TYPE-PRESCRIPTION) "Limiting the effort expended on relieving hypotheses Before ACL2 can apply a rule with hypotheses, it must establish that the hypotheses are true. (We ignore the relaxing of this requirement afforded by [case-split]s and [force]d hypotheses.) ACL2 typically establishes each hypothesis by backchaining --- instantiating the hypothesis and then rewriting it recursively. Here we describe how ACL2 allows the user to limit backchaining. At the end, below, we describe the function [backchain-limit]. Each hypothesis of a [rewrite], [meta], [linear], or [type-prescription] rule is assigned a backchain-limit when the rule is stored. By default, this limit is nil, denoting infinity (no limit). However, the value used for the default may be set to a non-negative integer (or to nil) by the user; see [set-default-backchain-limit]. The default is overridden when a :backchain-limit-lst is supplied explicitly with the rule; see [rule-classes]. The number of recursive applications of backchaining starting with the hypothesis of a rule is limited to the backchain-limit associated with that hypothesis. Moreover, the user may set global backchain-limits that limit the total backchaining depth. See [set-backchain-limit]. One limit is for the use of [rewrite], [meta], and [linear] rules, while the other limit is for so-called ``[type-set] reasoning'', which uses rules of class [type-prescription] rules. The two limits operate independently. Below, we discuss the first kind of backchain limits, i.e., for other than [type-prescription] rules, except as otherwise indicated; but the mechanism for those rules is similar. Below we lay out the precise sense in which a global backchain-limit interacts with the backchain-limits of individual rules in order to limit backchaining. But first we note that when further backchaining is disallowed, ACL2 can still prove a hypothesis in a given context by using that contextual information. In fact, [type-set] reasoning may be used (except that a weaker version of it is used in the second case above, i.e., where we are already doing type-set reasoning). Thus, the relieving of hypotheses may be limited to the use of contextual information (without backchaining, i.e., without recursively rewriting hypotheses) by executing :set-backchain-limit 0. Recall that there are two sorts of backchain limits: those applied to hypotheses of individual rules, as assigned by their :[rule-classes] or else taken from the default (see [set-default-backchain-limit]); and the global limit, initially nil (no limit) but settable with :[set-backchain-limit]. Here is how these two types of limits interact to limit backchaining, i.e., recursive rewriting of hypotheses. ACL2 maintains a current backchain limit, which is the limit on the depth of recursive calls to the rewriter, as well as a current backchain depth, which is initially 0 and is incremented each time ACL2 backchains (and is decremented when a backchain completes). When ACL2 begins to rewrite a literal (crudely, one of the ``top-level'' terms of the goal currently being worked on), it sets the current backchain-limit to the global value, which is initially nil but can be set using :[set-backchain-limit]. When ACL2 is preparing to relieve a hypothesis by backchaining (hence, after it has already tried type-set reasoning), it first makes sure that the current backchain limit is greater than the current backchain depth. If not, then it refuses to relieve that hypothesis. Otherwise, it increments the current backchain depth and calculates a new current backchain-limit by taking the minimum of two values: the existing current backchain-limit, and the sum of the current backchain depth and the backchain-limit associated with the hypothesis. Thus, ACL2 only modifies the current backchain-limit if it is necessary to decrease that limit in order to respect the backchain limit associated with the hypothesis. We illustrate with the following examples. ; We stub out some functions so that we can reason about them. (defstub p0 (x) t) (defstub p1 (x) t) (defstub p2 (x) t) (defstub p3 (x) t) ; Initially, the default-backchain-limit is nil, or infinite. (defaxiom p2-implies-p1-limitless (implies (p2 x) (p1 x))) ; The following rule will have a backchain-limit of 0. (defaxiom p1-implies-p0-limit-0 (implies (p1 x) (p0 x)) :rule-classes ((:rewrite :backchain-limit-lst 0))) ; We have (p2 x) ==> (p1 x) ==> (p0 x). We wish to establish that ; (p2 x) ==> (p0 x). Normally, this would be no problem, but here ; we fail because ACL2 cannot establish (p0 x) by type-set reasoning ; alone. (thm (implies (p2 x) (p0 x))) ; We set the default-backchain-limit (for rewriting) to 1. :set-default-backchain-limit 1 ; The following is more powerful than p1-implies-p0-limit-0 ; because it can use rewrite rules to establish (p1 x). (defaxiom p1-implies-p0-limit-1 (implies (p1 x) (p0 x))) ; This theorem will succeed: (thm (implies (p2 x) (p0 x))) ; We return the default-backchain-limit to its initial value. :set-default-backchain-limit nil ; Here is our last axiom. (defaxiom p3-implies-p2-limitless (implies (p3 x) (p2 x))) ; We now have (p3 x) ==> (p2 x) ==> (p1 x) ==> (p0 x). However the ; rule p1-implies-p0-limit-1 has a backchain-limit of 1; hence we ; are not allowed to backchain far enough back to use ; p3-implies-p2-limitless. We therefore lose. (defthm will-fail (implies (p3 x) (p0 x))) Finally, we remark that to see the current global backchain-limits, issue the following commands. (backchain-limit wrld :ts) ; backchain limit for type-set reasoning (backchain-limit wrld :rewrite) ; backchain limit for rewriting Subtopics [Set-backchain-limit] Sets the backchain-limit used by the type-set and rewriting mechanisms [Set-default-backchain-limit] Sets the default backchain-limit used when admitting a rule") (BACKCHAIN-LIMIT-RW (POINTERS) "See [hints] for keyword :backchain-limit-rw.") (BACKCHAINING (RULE-CLASSES) "Attempting to relieve the hypotheses of a rule When the theorem prover attempts to apply a rule (e.g., a [rewrite] rule), it must relieve (prove) the hypotheses of that rule. In the ACL2 community, this process of relieving hypotheses is called backchaining. There is no such thing as a backchaining or backward-chaining rule class (see [rule-classes]) in ACL2.") (BACKTRACK (POINTERS) "See [hints] for keyword :backtrack.") (BASICS (PROGRAMMING) "Basic control structures for [programming] like [if] and [cond], binding operators like [let] and [flet], multiple-value constructs like [mv], and so forth. Subtopics [ACL2-count] A commonly used measure for justifying recursion [And] Conjunction [Booleanp] Recognizer for booleans [Case] Conditional based on if-then-else using [eql] [Case-match] Pattern matching or destructuring [Cond] Conditional based on if-then-else [Equal] True equality [Flet] Local binding of function symbols [Good-bye] Quit entirely out of Lisp [Identity] The identity function [If] If-then-else function [Iff] Logical ``if and only if'' [Implies] Logical implication [Let] Binding of lexically scoped (local) variables [Let*] Binding of lexically scoped (local) variables [Mv] Returning a multiple value [Not] Logical negation [Null] Recognizer for the empty list [Or] Disjunction [Progn$] Execute a sequence of forms and return the value of the last one [Quote] Create a constant [Return-last] Return the last argument, perhaps with side effects [Xor] Logical ``exclusive or''") (BDD (ACL2) "Ordered binary decision diagrams with rewriting Ordered binary decision diagrams (OBDDs, often simply called BDDs) are a technique, originally published by Randy Bryant, for the efficient simplification of Boolean expressions. In ACL2 we combine this technique with rewriting to handle arbitrary ACL2 terms that can represent not only Boolean values, but non-Boolean values as well. In particular, we provide a setting for deciding equality of bit vectors (lists of Boolean values). An introduction to BDDs for the automated reasoning community may be found in ``Introduction to the OBDD Algorithm for the ATP Community'' by J Moore, Journal of Automated Reasoning (1994), pp. 33-45. (This paper also appears as Technical Report #84 from Computational Logic, Inc.) Further information about BDDs in ACL2 can be found in the subtopics of this [documentation] section. In particular, see [bdd-introduction] for a good starting place that provides a number of examples. See [hints] for a description of :bdd hints. For quick reference, here is an example; but only the :vars part of the hint is required, as explained in the documentation for [hints]. The values shown are the defaults. (:vars nil :bdd-constructors (cons) :prove t :literal :all) We suggest that you next visit the documentation topic [bdd-introduction]. Subtopics [Bdd-algorithm] Summary of the BDD algorithm in ACL2 [Bdd-introduction] Examples illustrating the use of BDDs in ACL2 [If*] For conditional rewriting with BDDs [Obdd] Ordered binary decision diagrams with rewriting [Show-bdd] Inspect failed BDD proof attempts") (BDD-ALGORITHM (BDD) "Summary of the BDD algorithm in ACL2 The BDD algorithm in ACL2 uses a combination of manipulation of IF terms and unconditional rewriting. In this discussion we begin with some relevant mathematical theory. This is followed by a description of how ACL2 does BDDs, including concluding discussions of soundness, completeness, and efficiency. We recommend that you read the other documentation about BDDs in ACL2 before reading the rather technical material that follows. See [bdd]. Here is an outline of our presentation. Readers who want a user perspective, without undue mathematical theory, may wish to skip to Part (B), referring to Part (A) only on occasion if necessary. (A) Mathematical Considerations (A1) BDD term order (A2) BDD-constructors and BDD terms, and their connection with aborting the BDD algorithm (A3) Canonical BDD terms (A4) A theorem stating the equivalence of provable and syntactic equality for canonical BDD terms (B) Algorithmic Considerations (B1) BDD rules (rules used by the rewriting portion of the ACL2 BDD algorithm) (B2) Terms ``known to be Boolean'' (B3) An ``IF-lifting'' operation used by the algorithm, as well as an iterative version of that operation (B4) The ACL2 BDD algorithm (B5) Soundness and Completeness of the ACL2 BDD algorithm (B6) Efficiency considerations (A) Mathematical Considerations (A1) BDD term order Our BDD algorithm creates a total ``BDD term order'' on ACL2 terms, on the fly. We use this order in our discussions below of IF-lifting and of canonical BDD terms, and in the algorithm's use of commutativity. The particular order is unimportant, except that we guarantee (for purposes of commutative functions) that constants are smaller in this order than non-constants. (A2) BDD-constructors (assumed to be '(cons)) and BDD terms We take as given a list of function symbols that we call the ``BDD-constructors.'' By default, the only BDD-constructor is [cons], although it is legal to specify any list of function symbols as the BDD-constructors, either by using the [ACL2-defaults-table] (see [ACL2-defaults-table]) or by supplying a :BDD-CONSTRUCTORS hint (see [hints]). Warning: this capability is largely untested and may produce undesirable results. Henceforth, except when explicitly stated to the contrary, we assume that BDD-constructors is '(cons). Roughly speaking, a [bdd] term is the sort of [term] produced by our BDD algorithm, namely a tree with all [cons] nodes lying above all non-CONS nodes. More formally, a [term] is said to be a [bdd] term if it contains no subterm of either of the following forms, where f is not CONS. (f ... (CONS ...) ...) (f ... 'x ...) ; where (consp x) = t We will see that whenever the BDD algorithm attempts to create a [term] that is not a [bdd] term, it aborts instead. Thus, whenever the algorithm completes without aborting, it creates a [bdd] term. (A3) Canonical BDD terms We can strengthen the notion of ``BDD term'' to a notion of ``canonical BDD term'' by imposing the following additional requirements, for every subterm of the form (IF x y z): (a) x is a variable, and it precedes (in the BDD term order) every variable occurring in y or z; (b) y and z are syntactically distinct; and, (c) it is not the case that y is t and z is nil. We claim that it follows easily from our description of the BDD algorithm that every term it creates is a canonical BDD term, assuming that the variables occurring in all such terms are treated by the algorithm as being Boolean (see (B2) below) and that the terms contain no function symbols other than IF and CONS. Thus, under those assumptions the following theorem shows that the BDD algorithm never creates distinct terms that are provably equal, a property that is useful for completeness and efficiency (as we explain in (B5) and (B6) below). (A4) Provably equal canonical BDD terms are identical We believe that the following theorem and proof are routine extensions of a standard result and proof to terms that allow calls of CONS. Theorem. Suppose that t1 and t2 are canonical BDD terms that contain no function symbols other than IF and CONS. Also suppose that (EQUAL t1 t2) is a theorem. Then t1 and t2 are syntactically identical. Proof of theorem: By induction on the total number of symbols occurring in these two terms. First suppose that at least one term is a variable; without loss of generality let it be t1. We must prove that t2 is syntactically the same as t1. Now it is clearly consistent that (EQUAL t1 t2) is false if t2 is a call of CONS (to see this, simply let t1 be an value that is not a CONSP). Similarly, t2 cannot be a constant or a variable other than t1. The remaining possibility to rule out is that t2 is of the form (IF t3 t4 t5), since by assumption its function symbol must be IF or CONS and we have already handled the latter case. Since t2 is canonical, we know that t3 is a variable. Since (EQUAL t1 t2) is provable, i.e., (EQUAL t1 (if t3 t4 t5)) is provable, it follows that we may substitute either t or nil for t3 into this equality to obtain two new provable equalities. First, suppose that t1 and t3 are distinct variables. Then these substitutions show that t1 is provably equal to both t4 and t5 (since t3 does not occur in t4 or t5 by property (a) above, as t2 is canonical), and hence t4 and t5 are provably equal to each other, which implies by the inductive hypothesis that they are the same term --- and this contradicts the assumption that t2 is canonical (property (b)). Therefore t1 and t3 are the same variable, i.e., the equality displayed above is actually (EQUAL t1 (if t1 t4 t5)). Substituting t and then nil for t1 into this provable equality lets us prove (EQUAL t t4) and (EQUAL nil t5), which by the inductive hypothesis implies that t4 is (syntactically) the term t and t5 is nil. That is, t2 is (IF t1 t nil), which contradicts the assumption that t2 is canonical (property (c)). Next, suppose that at least one term is a call of IF. Our first observation is that the other term is also a call of IF. For if the other is a call of CONS, then they cannot be provably equal, because the former has no function symbols other than IF and hence is Boolean when all its variables are assigned Boolean values. Also, if the other is a constant, then both branches of the IF term are provably equal to that constant and hence these branches are syntactically identical by the inductive hypothesis, contradicting property (b). Hence, we may assume for this case that both terms are calls of IF; let us write them as follows. t0: (IF t1 t2 t3) u0: (IF u1 u2 u3) Note that t1 and u1 are variables, by property (a) of canonical BDD terms. First we claim that t1 does not strictly precede u1 in the BDD term order. For suppose t1 does strictly precede u1. Then property (a) of canonical BDD terms guarantees that t1 does not occur in u0. Hence, an argument much like one used above shows that u0 is provably equal to both t2 (substituting t for t1) and t3 (substituting nil for t1), and hence t2 and t3 are provably equal. That implies that they are identical terms, by the inductive hypothesis, which then contradicts property (b) for t0. Similarly, u1 does not strictly precede t1 in the BDD term order. Therefore, t1 and u1 are the same variable. By substituting t for this variable we see that t2 and u2 are provably equal, and hence they are equal by the inductive hypothesis. Similarly, by substituting nil for t1 (and u1) we see that t3 and u3 are provably, hence syntactically, equal. We have covered all cases in which at least one term is a variable or at least one term is a call of IF. If both terms are constants, then provable and syntactic equality are clearly equivalent. Finally, then, we may assume that one term is a call of CONS and the other is a constant or a call of CONS. The constant case is similar to the CONS case if the constant is a CONSP, so we omit it; while if the constant is not a CONSP then it is not provably equal to a call of CONS; in fact it is provably not equal! So, we are left with a final case, in which canonical BDD terms (CONS t1 t2) and (CONS u1 u2) are provably equal, and we want to show that t1 and u1 are syntactically equal as are t2 and u2. These conclusions are easy consequences of the inductive hypothesis, since the ACL2 axiom CONS-EQUAL (which you can inspect using :[pe]) shows that equality of the given terms is equivalent to the conjunction of (EQUAL t1 t2) and (EQUAL u1 u2). Q.E.D. (B) Algorithmic Considerations (B1) BDD rules A rule of class :[rewrite] (see [rule-classes]) is said to be a ``[bdd] rewrite rule'' if and only if it satisfies the following criteria. (1) The rule is [enable]d. (2) Its [equivalence] relation is [equal]. (3) It has no hypotheses. (4) Its :[loop-stopper] field is nil, i.e., it is not a permutative rule. (5) All variables occurring in the rule occur in its left-hand side (i.e., there are no ``free variables''; see [rewrite]). A rule of class :[definition] (see [rule-classes]) is said to be a ``[bdd] definition rule'' if it satisfies all the criteria above (except (4), which does not apply), and moreover the top function symbol of the left-hand side was not recursively (or mutually recursively) defined. Technical point: Note that this additional criterion is independent of whether or not the indicated function symbol actually occurs in the right-hand side of the rule. Both BDD rewrite rules and BDD definition rules are said to be ``BDD rules.'' (B2) Terms ''known to be Boolean'' We apply the BDD algorithm in the context of a top-level goal to prove, namely, the goal at which the :BDD hint is attached. As we run the BDD algorithm, we allow ourselves to say that a set of [term]s is ``known to be Boolean'' if we can verify that the goal is provable from the assumption that at least one of the terms is not Boolean. Equivalently, we allow ourselves to say that a set of terms is ``known to be Boolean'' if we can verify that the original goal is provably equivalent to the assertion that if all terms in the set are Boolean, then the goal holds. The notion ``known to be Boolean'' is conservative in the sense that there are generally sets of terms for which the above equivalent criteria hold and yet the sets of terms are not noted as as being ``known to be Boolean.'' However, ACL2 uses a number of tricks, including [type-set] reasoning and analysis of the structure of the top-level goal, to attempt to establish that a sufficiently inclusive set of terms is known to be Boolean. From a practical standpoint, the algorithm determines a set of terms known to be Boolean; we allow ourselves to say that each term in this set is ``known to be Boolean.'' The algorithm assumes that these terms are indeed Boolean, and can make use of that assumption. For example, if t1 is known to be Boolean then the algorithm simplifies (IF t1 t nil) to t1; see (iv) in the discussion immediately below. (B3) IF-lifting and the IF-lifting-for-IF loop Suppose that one has a [term] of the form (f ... (IF test x y) ...), where f is a function symbol other than CONS. Then we say that ``IF-lifting'' test ``from'' this term produces the following term, which is provably equal to the given term. (if test (f ... x ...) ; resulting true branch (f ... y ...)) ; resulting false branch Here, we replace each argument of f of the form (IF test .. ..), for the same test, in the same way. In this case we say that ``IF-lifting applies to'' the given term, ``yielding the test'' test and with the ``resulting two branches'' displayed above. Whenever we apply IF-lifting, we do so for the available test that is least in the BDD term order (see (A1) above). We consider arguments v of f that are ``known to be Boolean'' (see above) to be replaced by (IF v t nil) for the purposes of IF-lifting, i.e., before IF-lifting is applied. There is one special case, however, for IF-lifting. Suppose that the given term is of the form (IF v y z) where v is a variable and is the test to be lifted out (i.e., it is least in the BDD term order among the potential tests). Moroever, suppose that neither y nor z is of the form (IF v W1 W2) for that same v. Then IF-lifting does not apply to the given term. We may now describe the IF-lifting-for-IF loop, which applies to terms of the form (IF test tbr fbr) where the algorithm has already produced test, tbr, and fbr. First, if test is nil then we return fbr, while if test is a non-nil constant or a call of CONS then we return tbr. Otherwise, we see if IF-lifting applies. If IF-lifting does not apply, then we return (IF test tbr fbr). Otherwise, we apply IF-lifting to obtain a term of the form (IF x y z), by lifting out the appropriate test. Now we recursively apply the IF-lifting-for-IF loop to the term (IF x y z), unless any of the following special cases apply. (i) If y and z are the same term, then return y. (ii) Otherwise, if x and z are the same term, then replace z by nil before recursively applying IF-lifting-for-IF. (iii) Otherwise, if x and y are the same term and y is known to be Boolean, then replace y by t before recursively applying IF-lifting-for-IF. (iv) If z is nil and either x and y are the same term or x is ``known to be Boolean'' and y is t, then return x. NOTE: When a variable x is known to be Boolean, it is easy to see that the form (IF x t nil) is always reduced to x by this algorithm. (B4) The ACL2 BDD algorithm We are now ready to present the BDD algorithm for ACL2. It is given an ACL2 [term], x, as well as an association list va that maps variables to terms, including all variables occurring in x. We maintain the invariant that whenever a variable is mapped by va to a term, that term has already been constructed by the algorithm, except: initially va maps every variable occurring in the top-level term to itself. The algorithm proceeds as follows. We implicitly ordain that whenever the BDD algorithm attempts to create a [term] that is not a [bdd] term (as defined above in (A2)), it aborts instead. Thus, whenever the algorithm completes without aborting, it creates a [bdd] term. If x is a variable, return the result of looking it up in va. If x is a constant, return x. If x is of the form (IF test tbr fbr), then first run the algorithm on test with the given va to obtain test'. If test' is nil, then return the result fbr' of running the algorithm on fbr with the given va. If test' is a constant other than nil, or is a call of CONS, then return the result tbr' of running the algorithm on tbr with the given va. If tbr is identical to fbr, return tbr. Otherwise, return the result of applying the IF-lifting-for-IF loop (described above) to the term (IF test' tbr' fbr'). If x is of the form (IF* test tbr fbr), then compute the result exactly as though [if] were used rather than [if*], except that if test' is not a constant or a call of CONS (see paragraph above), then abort the BDD computation. Informally, the tests of [if*] terms are expected to ``resolve.'' NOTE: This description shows how [if*] can be used to implement conditional rewriting in the BDD algorithm. If x is a LAMBDA expression ((LAMBDA vars body) . args) (which often corresponds to a [let] term; see [let]), then first form an alist va' by binding each v in vars to the result of running the algorithm on the corresponding member of args, with the current alist va. Then, return the result of the algorithm on body in the alist va'. Otherwise, x is of the form (f x1 x2 ... xn), where f is a function symbol other than [if] or [if*]. In that case, let xi' be the result of running the algorithm on xi, for i from 1 to n, using the given alist va. First there are a few special cases. If f is [equal] then we return t if x1' is syntactically identical to x2' (where this test is very fast; see (B6) below); we return x1' if it is known to be Boolean and x2' is t; and similarly, we return x2' if it is known to be Boolean and x1' is t. Next, if each xi' is a constant and the :[executable-counterpart] of f is enabled, then the result is obtained by computation. Next, if f is [booleanp] and x1' is known to be Boolean, t is returned. Otherwise, we proceed as follows, first possibly swapping the arguments if they are out of (the BDD term) order and if f is known to be commutative (see below). If a BDD rewrite rule (as defined above) matches the term (f x1'... xn'), then the most recently stored such rule is applied. If there is no such match and f is a BDD-constructor, then we return (f x1'... xn'). Otherwise, if a BDD definition rule matches this term, then the most recently stored such rule (which will usually be the original definition for most users) is applied. If none of the above applies and neither does IF-lifting, then we return (f x1'... xn'). Otherwise we apply IF-lifting to (f x1'... xn') to obtain a term (IF test tbr fbr); but we aren't done yet. Rather, we run the BDD algorithm (using the same alist) on tbr and fbr to obtain terms tbr' and fbr', and we return (IF test tbr' fbr') unless tbr' is syntactically identical to fbr', in which case we return tbr'. When is it the case that, as said above, ``f is known to be commutative''? This happens when an enabled rewrite rule is of the form (EQUAL (f X Y) (f Y X)). Regarding swapping the arguments in that case: recall that we may assume very little about the BDD term order, essentially only that we swap the two arguments when the second is a constant and the first is not, for example, in (+ x 1). Other than that situation, one cannot expect to predict accurately when the arguments of commutative operators will be swapped. (B5) Soundness and Completeness of the ACL2 BDD algorithm Roughly speaking, ``soundness'' means that the BDD algorithm should give correct answers, and ``completeness'' means that it should be powerful enough to prove all true facts. Let us make the soundness claim a little more precise, and then we'll address completeness under suitable hypotheses. Claim (Soundness). If the ACL2 BDD algorithm runs to completion on an input term t0, then it produces a result that is provably equal to t0. We leave the proof of this claim to the reader. The basic idea is simply to check that each step of the algorithm preserves the meaning of the term under the bindings in the given alist. Let us start our discussion of completeness by recalling the theorem proved above in (A4). Theorem. Suppose that t1 and t2 are canonical BDD terms that contain no function symbols other than IF and CONS. Also suppose that (EQUAL t1 t2) is a theorem. Then t1 and t2 are syntactically identical. Below we show how this theorem implies the following completeness property of the ACL2 BDD algorithm. We continue to assume that CONS is the only BDD-constructor. Claim (Completeness). Suppose that t1 and t2 are provably equal terms, under the assumption that all their variables are known to be Boolean. Assume further that under this same assumption, top-level runs of the ACL2 BDD algorithm on these terms return terms that contain only the function symbols IF and CONS. Then the algorithm returns the same term for both t1 and t2, and the algorithm reduces (EQUAL t1 t2) to t. Why is this claim true? First, notice that the second part of the conclusion follows immediately from the first, by definition of the algorithm. Next, notice that the terms u1 and u2 obtained by running the algorithm on t1 and t2, respectively, are provably equal to t1 and t2, respectively, by the Soundness Claim. It follows that u1 and u2 are provably equal to each other. Since these terms contain no function symbols other than IF or CONS, by hypothesis, the Claim now follows from the Theorem above together with the following lemma. Lemma. Suppose that the result of running the ACL2 BDD algorithm on a top-level term t0 is a term u0 that contains only the function symbols IF and CONS, where all variables of t0 are known to be Boolean. Then u0 is a canonical BDD term. Proof: left to the reader. Simply follow the definition of the algorithm, with a separate argument for the IF-lifting-for-IF loop. Finally, let us remark on the assumptions of the Completeness Claim above. The assumption that all variables are known to be Boolean is often true; in fact, the system uses the forward-chaining rule boolean-listp-forward (you can see it using :[pe]) to try to establish this assumption, if your theorem has a form such as the following. (let ((x (list x0 x1 ...)) (y (list y0 y1 ...))) (implies (and (boolean-listp x) (boolean-listp y)) ...)) Moreover, the :BDD hint can be used to force the prover to abort if it cannot check that the indicated variables are known to be Boolean; see [hints]. Finally, consider the effect in practice of the assumption that the terms resulting from application of the algorithm contain calls of IF and CONS only. Typical use of BDDs in ACL2 takes place in a theory (see [theories]) in which all relevant non-recursive function symbols are enabled and all recursive function symbols possess enabled BDD rewrite rules that tell them how open up. For example, such a rule may say how to expand on a given function call's argument that has the form (CONS a x), while another may say how to expand when that argument is nil). (See for example the rules append-cons and append-nil in the documentation for [if*].) We leave it to future work to formulate a theorem that guarantees that the BDD algorithm produces terms containing calls only of IF and CONS assuming a suitably ``complete'' collection of rewrite rules. (B6) Efficiency considerations Following Bryant's algorithm, we use a graph representation of [term]s created by the BDD algorithm's computation. This representation enjoys some important properties. (Time efficiency) The test for syntactic equality of BDD terms is very fast. (Space efficiency) Equal BDD data structures are stored identically in memory. Implementation note. The representation actually uses a sort of hash table for BDD terms that is implemented as an ACL2 1-dimensional array. See [arrays]. In addition, we use a second such hash table to avoid recomputing the result of applying a function symbol to the result of running the algorithm on its arguments. We believe that these uses of hash tables are standard. They are also discussed in Moore's paper on BDDs; see [bdd] for the reference.") (BDD-INTRODUCTION (BDD) "Examples illustrating the use of BDDs in ACL2 See [bdd] for a brief introduction to BDDs in ACL2 and for pointers to other documentation on BDDs in ACL2. Here, we illustrate the use of BDDs in ACL2 by way of some examples. For a further example, see [if*]. Let us begin with a really simple example. (We will explain the :bdd hint (:vars nil) below.) ACL2 !>(thm (equal (if a b c) (if (not a) c b)) :hints ((\"Goal\" :bdd (:vars nil)))) ; Prove with BDDs [Note: A hint was supplied for our processing of the goal above. Thanks!] But simplification with BDDs (7 nodes) reduces this to T, using the :definitions EQUAL and NOT. Q.E.D. Summary Form: ( THM ...) Rules: ((:DEFINITION EQUAL) (:DEFINITION NOT)) Warnings: None Time: 0.18 seconds (prove: 0.05, print: 0.02, other: 0.12) Proof succeeded. ACL2 !> The :bdd hint (:vars nil) indicates that BDDs are to be used on the indicated goal, and that any so-called ``variable ordering'' may be used: ACL2 may use a convenient order that is far from optimal. It is beyond the scope of the present documentation to address the issue of how the user may choose good variable orderings. Someday our implementation of BDDs may be improved to include heuristically-chosen variable orderings rather than rather random ones. Here is a more interesting example. (defun v-not (x) ; Complement every element of a list of Booleans. (if (consp x) (cons (not (car x)) (v-not (cdr x))) nil)) ; Now we prove a rewrite rule that explains how to open up v-not on ; a consp. (defthm v-not-cons (equal (v-not (cons x y)) (cons (not x) (v-not y)))) ; Finally, we prove for 7-bit lists that v-not is self-inverting. (thm (let ((x (list x0 x1 x2 x3 x4 x5 x6))) (implies (boolean-listp x) (equal (v-not (v-not x)) x))) :hints ((\"Goal\" :bdd ;; Note that this time we specify a variable order. (:vars (x0 x1 x2 x3 x4 x5 x6))))) It turns out that the variable order doesn't seem to matter in this example; using several orders we found that 30 nodes were created, and the proof time was about 1/10 of a second on a (somewhat enhanced) Sparc 2. The same proof took about a minute and a half without any :bdd hint! This observation is a bit misleading perhaps, since the theorem for arbitrary x, (thm (implies (boolean-listp x) (equal (v-not (v-not x)) x))) only takes about 1.5 times as long as the :bdd proof for 7 bits, above! Nevertheless, BDDs can be very useful in reducing proof time, especially when there is no regular structure to facilitate proof by induction, or when the induction scheme is so complicated to construct that significant user effort is required to get the proof by induction to go through. Finally, consider the preceding example, with a :bdd hint of (say) (:vars nil), but with the rewrite rule v-not-cons above disabled. In that case, the proof fails, as we see below. That is because the BDD algorithm in ACL2 uses hypothesis-free :[rewrite] rules, :[executable-counterpart]s, and nonrecursive definitions, but it does not use recursive definitions. Notice that when we issue the (show-bdd) command, the system's response clearly shows that we need a rewrite rule for simplifying terms of the form (v-not (cons ...)). ACL2 !>(thm (let ((x (list x0 x1 x2 x3 x4 x5 x6))) (implies (boolean-listp x) (equal (v-not (v-not x)) x))) :hints ((\"Goal\" :bdd (:vars nil) :in-theory (disable v-not-cons)))) [Note: A hint was supplied for our processing of the goal above. Thanks!] ACL2 Error in ( THM ...): Attempted to create V-NOT node during BDD processing with an argument that is a call of a bdd-constructor, which would produce a non-BDD term (as defined in :DOC bdd-algorithm). See :DOC show-bdd. Summary Form: ( THM ...) Rules: NIL Warnings: None Time: 0.58 seconds (prove: 0.13, print: 0.00, other: 0.45) ******** FAILED ******** See :DOC failure ******** FAILED ******** ACL2 !>(show-bdd) BDD computation on Goal yielded 17 nodes. ------------------------------ BDD computation was aborted on Goal, and hence there is no falsifying assignment that can be constructed. Here is a backtrace of calls, starting with the top-level call and ending with the one that led to the abort. See :DOC show-bdd. (LET ((X (LIST X0 X1 X2 X3 X4 X5 ...))) (IMPLIES (BOOLEAN-LISTP X) (EQUAL (V-NOT (V-NOT X)) X))) alist: ((X6 X6) (X5 X5) (X4 X4) (X3 X3) (X2 X2) (X1 X1) (X0 X0)) (EQUAL (V-NOT (V-NOT X)) X) alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...))) (V-NOT (V-NOT X)) alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...))) (V-NOT X) alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...))) ACL2 !> The term that has caused the BDD algorithm to abort is thus (V-NOT X), where X has the value (LIST X0 X1 X2 X3 X4 X5 ...), i.e., (CONS X0 (LIST X1 X2 X3 X4 X5 ...)). Thus, we see the utility of introducing a rewrite rule to simplify terms of the form (V-NOT (CONS ...)). The moral of this story is that if you get an error of the sort shown above, you may find it useful to execute the command (show-bdd) and use the result as advice that suggests the left hand side of a rewrite rule. Here is another sort of failed proof. In this version we have omitted the hypothesis that the input is a bit vector. Below we use show-bdd to see what went wrong, and use the resulting information to construct a counterexample. This failed proof corresponds to a slightly modified input theorem, in which x is bound to the 4-element list (list x0 x1 x2 x3). ACL2 !>(thm (let ((x (list x0 x1 x2 x3))) (equal (v-not (v-not x)) x)) :hints ((\"Goal\" :bdd ;; This time we do not specify a variable order. (:vars nil)))) [Note: A hint was supplied for our processing of the goal above. Thanks!] ACL2 Error in ( THM ...): The :BDD hint for the current goal has successfully simplified this goal, but has failed to prove it. Consider using (SHOW-BDD) to suggest a counterexample; see :DOC show-bdd. Summary Form: ( THM ...) Rules: NIL Warnings: None Time: 0.18 seconds (prove: 0.07, print: 0.00, other: 0.12) ******** FAILED ******** See :DOC failure ******** FAILED ******** ACL2 !>(show-bdd) BDD computation on Goal yielded 73 nodes. ------------------------------ Falsifying constraints: ((X0 \"Some non-nil value\") (X1 \"Some non-nil value\") (X2 \"Some non-nil value\") (X3 \"Some non-nil value\") ((EQUAL 'T X0) T) ((EQUAL 'T X1) T) ((EQUAL 'T X2) T) ((EQUAL 'T X3) NIL)) ------------------------------ Term obtained from BDD computation on Goal: (IF X0 (IF X1 (IF X2 (IF X3 (IF # # #) (IF X3 # #)) (IF X2 'NIL (IF X3 # #))) (IF X1 'NIL (IF X2 (IF X3 # #) (IF X2 # #)))) (IF X0 'NIL (IF X1 (IF X2 (IF X3 # #) (IF X2 # #)) (IF X1 'NIL (IF X2 # #))))) ACL2 Query (:SHOW-BDD): Print the term in full? (N, Y, W or ?): n ; I've seen enough. The assignment shown above suggests ; (though not conclusively) that if we bind x3 to a non-nil ; value other than T, and bind x0, x1, and x2 to t, then we ; this may give us a counterexample. ACL2 !>(let ((x0 t) (x1 t) (x2 t) (x3 7)) (let ((x (list x0 x1 x2 x3))) ;; Let's use LIST instead of EQUAL to see how the two ;; lists differ. (list (v-not (v-not x)) x))) ((T T T T) (T T T 7)) ACL2 !> See [if*] for another example.") (BIBLIOGRAPHY (ABOUT-ACL2) "Reports about ACL2 The ACL2 home page includes a {list of notes and reports about ACL2 | http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html}.") (BINARY-* (* ACL2-BUILT-INS) "Multiplication function Completion Axiom (completion-of-*): (equal (binary-* x y) (if (acl2-numberp x) (if (acl2-numberp y) (binary-* x y) 0) 0)) [Guard] for (binary-* x y): (and (acl2-numberp x) (acl2-numberp y)) Notice that like all arithmetic functions, binary-* treats non-numeric inputs as 0. Calls of the macro [*] expand to calls of binary-*; see [*].") (BINARY-+ (+ ACL2-BUILT-INS) "Addition function Completion Axiom (completion-of-+): (equal (binary-+ x y) (if (acl2-numberp x) (if (acl2-numberp y) (binary-+ x y) x) (if (acl2-numberp y) y 0))) [Guard] for (binary-+ x y): (and (acl2-numberp x) (acl2-numberp y)) Notice that like all arithmetic functions, binary-+ treats non-numeric inputs as 0. Calls of the macro [+] expand to calls of binary-+; see [+].") (BINARY-APPEND (APPEND ACL2-BUILT-INS) "[concatenate] two lists This binary function implements [append], which is a macro in ACL2. See [append] The [guard] for binary-append requires the first argument to be a [true-listp]. Function: (defun binary-append (x y) (declare (xargs :guard (true-listp x))) (cond ((endp x) y) (t (cons (car x) (binary-append (cdr x) y)))))") (BIND-FREE (REWRITE LINEAR DEFINITION) "To bind free variables of a rewrite, definition, or linear rule Examples: (IMPLIES (AND (RATIONALP LHS) (RATIONALP RHS) (BIND-FREE (FIND-MATCH-IN-PLUS-NESTS LHS RHS) (X))) (EQUAL (EQUAL LHS RHS) (EQUAL (+ (- X) LHS) (+ (- X) RHS)))) (IMPLIES (AND (BIND-FREE (FIND-RATIONAL-MATCH-IN-TIMES-NESTS LHS RHS MFC STATE) (X)) (RATIONALP X) (CASE-SPLIT (NOT (EQUAL X 0)))) (EQUAL (< LHS RHS) (IF (< 0 X) (< (* (/ X) LHS) (* (/ X) RHS)) (< (* (/ X) RHS) (* (/ X) LHS))))) General Forms: (BIND-FREE term var-list) (BIND-FREE term t) (BIND-FREE term) A rule which uses a bind-free hypothesis has similarities to both a rule which uses a [syntaxp] hypothesis and to a :[meta] rule. Bind-free is like [syntaxp], in that it logically always returns t but may affect the application of a :[rewrite], :[definition], or :[linear] rule when it is called at the top-level of a hypothesis. It is like a :[meta] rule, in that it allows the user to perform transformations of terms under progammatic control. Note that a bind-free hypothesis does not, in general, deal with the meaning or semantics or values of the terms, but rather with their syntactic forms. Before attempting to write a rule which uses bind-free, the user should be familiar with [syntaxp] and the internal form that ACL2 uses for terms. This internal form is similar to what the user sees, but there are subtle and important differences. [Trans] can be used to view this internal form. Just as for a [syntaxp] hypothesis, there are two basic types of bind-free hypotheses. The simpler type of bind-free hypothesis may be used as the nth hypothesis in a :[rewrite], :[definition], or :[linear] rule whose :[corollary] is (implies (and hyp1 ... hypn ... hypk) (equiv lhs rhs)) provided term is a term, term contains at least one variable, and every variable occuring freely in term occurs freely in lhs or in some hypi, i (EQUAL (+ (- (EXPT A N)) 3 (EXPT A N) (FOO A C)) (+ (- (EXPT A N)) (BAR B) (EXPT A N))). Question: What is the internal form of this result? Hint: Use :[trans]. When this rule fires, it adds the negation of a common term to both sides of the equality by selecting a binding for the otherwise-free variable x, under programmatic control. Note that other mechanisms such as the binding of [free-variables] may also extend the substitution alist. Just as for a [syntaxp] test, a bind-free form signals failure by returning nil. However, while a [syntaxp] test signals success by returning true, a bind-free form signals success by returning an alist which is used to extend the current substitution alist. Because of this use of the alist, there are several restrictions on it --- in particular the alist must only bind variables, these variables must not be already bound by the substitution alist, and the variables must be bound to ACL2 terms. If term returns an alist and the alist meets these restrictions, we append the alist to the substitution alist and use the result as the new current substitution alist. This new current substitution alist is then used when we attempt to relieve the next hypothesis or, if there are no more, instantiate the right hand side of the rule. There is also a second, optional, var-list argument to a bind-free hypothesis. If provided, it must be either t or a list of variables. If it is not provided, it defaults to t. If it is a list of variables, this second argument is used to place a further restriction on the possible values of the alist to be returned by term: any variables bound in the alist must be present in the list of variables. We strongly recommend the use of this list of variables, as it allows some consistency checks to be performed at the time of the rule's admittance which are not possible otherwise. An extended bind-free hypothesis is similar to the simple type described above, but it uses two additional variables, mfc and state, which must not be bound by the left hand side or an earlier hypothesis of the rule. They must be the last two variables mentioned by term: first mfc, then state. These two variables give access to the functions mfc-xxx; see [extended-metafunctions]. As described there, mfc is bound to the so-called metafunction-context and state to ACL2's [state]. See [bind-free-examples] for examples of the use of these extended bind-free hypotheses. SECTION: Returning a list of alists. As promised above, we conclude with a discussion of the case that evaluation of the bind-free term produces a list of alists, x, rather than a single alist. In this case each member b of x is considered in turn, starting with the first and proceeding through the list. Each such b is handled exactly as discussed above, as though it were the result of evaluating the bind-free term. Thus, each b extends the current variable binding alist, and all remaining hypotheses are then relieved, as though b had been the value obtained by evaluating the bind-free term. As soon as one such b leads to successful relieving of all remaining hypotheses, the process of relieving hypotheses concludes, so no further members of x are considered. We illustrate with a simple pedagogical example. First introduce functions p1 and p2 such that a rewrite rule specifies that p2 implies p1, but with a free variable. (defstub p1 (x) t) (defstub p2 (x y) t) (defaxiom p2-implies-p1 (implies (p2 x y) (p1 x))) If we add the following axiom, then (p1 x) follows logically for all x. (defaxiom p2-instance (p2 v (cons v 4))) Unfortunately, evaluation of (thm (p1 a)) fails, because ACL2 fails to bind the free variable y in order to apply the rule p2-instance. Let's define a function that produces a list of alists, each binding the variable y. Of course, we know that only the middle one below is necessary in this simple example. In more complex examples, one might use heuristics to construct such a list of alists. (defun my-alists (x) (list (list (cons 'y (fcons-term* 'cons x ''3))) (list (cons 'y (fcons-term* 'cons x ''4))) (list (cons 'y (fcons-term* 'cons x ''5))))) The following rewrite rule uses bind-free to return a list of candidate alists binding y. (defthm p2-implies-p1-better (implies (and (bind-free (my-alists x) (y)) ; the second argument, (y), is optional (p2 x y)) (p1 x))) Now the proof succeeds for (thm (p1 a)). Why? When ACL2 applies the rewrite rule p2-implies-p1-better, it evaluates my-alists, as we can see from the following [trace], to bind y in three different alists. ACL2 !>(thm (p1 a)) 1> (ACL2_*1*_ACL2::MY-ALISTS A) <1 (ACL2_*1*_ACL2::MY-ALISTS (((Y CONS A '3)) ((Y CONS A '4)) ((Y CONS A '5)))) Q.E.D. The first alist, binding y to (cons a '3), fails to allow the hypothesis (p2 x y) to be proved. But the next binding of y, to (cons a '4), succeeds: then the current binding alist is ((x . a) (y . (cons a '4))), for which the hypothesis (p2 x y) rewrites to true using the rewrite rule p2-instance. Subtopics [Bind-free-examples] Examples pertaining to [bind-free] hypotheses") (BIND-FREE-EXAMPLES (BIND-FREE) "Examples pertaining to [bind-free] hypotheses See [bind-free] for a basic discussion of the use of bind-free to control rewriting. Note that the examples below all illustrate the common case in which a bind-free hypothesis generates a binding alist. See [bind-free], in particular the final section, for a discussion of the case that instead a list of binding alists is generated. We give examples of the use of [bind-free] hypotheses from the perspective of a user interested in reasoning about arithmetic, but it should be clear that [bind-free] can be used for many other purposes also. EXAMPLE 1: Cancel a common factor. (defun bind-divisor (a b) ; If a and b are polynomials with a common factor c, we return a ; binding for x. We could imagine writing get-factor to compute the ; gcd, or simply to return a single non-invertible factor. (let ((c (get-factor a b))) (and c (list (cons 'x c))))) (defthm cancel-factor ;; We use case-split here to ensure that, once we have selected ;; a binding for x, the rest of the hypotheses will be relieved. (implies (and (acl2-numberp a) (acl2-numberp b) (bind-free (bind-divisor a b) (x)) (case-split (not (equal x 0))) (case-split (acl2-numberp x))) (iff (equal a b) (equal (/ a x) (/ b x))))) EXAMPLE 2: Pull integer summand out of floor. Note: This example has an extended [bind-free] hypothesis, which uses the term (find-int-in-sum sum mfc state). (defun fl (x) ;; This function is defined, and used, in the IHS books. (floor x 1)) (defun int-binding (term mfc state) ;; The call to mfc-ts returns the encoded type of term. ; ;; Thus, we are asking if term is known by type reasoning to ; ;; be an integer. ; (declare (xargs :stobjs (state) :mode :program)) (if (ts-subsetp (mfc-ts term mfc state) *ts-integer*) (list (cons 'int term)) nil)) (defun find-int-in-sum (sum mfc state) (declare (xargs :stobjs (state) :mode :program)) (if (and (nvariablep sum) (not (fquotep sum)) (eq (ffn-symb sum) 'binary-+)) (or (int-binding (fargn sum 1) mfc state) (find-int-in-sum (fargn sum 2) mfc state)) (int-binding sum mfc state))) ; Some additional work is required to prove the following. So for ; purposes of illustration, we wrap skip-proofs around the defthm. (skip-proofs (defthm cancel-fl-int ;; The use of case-split is probably not needed, since we should ;; know that int is an integer by the way we selected it. But this ;; is safer. (implies (and (acl2-numberp sum) (bind-free (find-int-in-sum sum mfc state) (int)) (case-split (integerp int))) (equal (fl sum) (+ int (fl (- sum int))))) :rule-classes ((:rewrite :match-free :all))) ) ; Arithmetic libraries will have this sort of lemma. (defthm hack (equal (+ (- x) x y) (fix y))) (in-theory (disable fl)) (thm (implies (and (integerp x) (acl2-numberp y)) (equal (fl (+ x y)) (+ x (fl y))))) EXAMPLE 3: Simplify terms such as (equal (+ a (* a b)) 0) (defun factors (product) ;; We return a list of all the factors of product. We do not ;; require that product actually be a product. (if (eq (fn-symb product) 'BINARY-*) (cons (fargn product 1) (factors (fargn product 2))) (list product))) (defun make-product (factors) ;; Factors is assumed to be a list of ACL2 terms. We return an ;; ACL2 term which is the product of all the ellements of the ;; list factors. (cond ((atom factors) ''1) ((null (cdr factors)) (car factors)) ((null (cddr factors)) (list 'BINARY-* (car factors) (cadr factors))) (t (list 'BINARY-* (car factors) (make-product (cdr factors)))))) (defun quotient (common-factors sum) ;; Common-factors is a list of ACL2 terms. Sum is an ACL2 term each ;; of whose addends have common-factors as factors. We return ;; (/ sum (make-product common-factors)). (if (eq (fn-symb sum) 'BINARY-+) (let ((first (make-product (set-difference-equal (factors (fargn sum 1)) common-factors)))) (list 'BINARY-+ first (quotient common-factors (fargn sum 2)))) (make-product (set-difference-equal (factors sum) common-factors)))) (defun intersection-equal (x y) (cond ((endp x) nil) ((member-equal (car x) y) (cons (car x) (intersection-equal (cdr x) y))) (t (intersection-equal (cdr x) y)))) (defun common-factors (factors sum) ;; Factors is a list of the factors common to all of the addends ;; examined so far. On entry, factors is a list of the factors in ;; the first addend of the original sum, and sum is the rest of the ;; addends. We sweep through sum, trying to find a set of factors ;; common to all the addends of sum. (declare (xargs :measure (acl2-count sum))) (cond ((null factors) nil) ((eq (fn-symb sum) 'BINARY-+) (common-factors (intersection-equal factors (factors (fargn sum 1))) (fargn sum 2))) (t (intersection-equal factors (factors sum))))) (defun simplify-terms-such-as-a+ab-rel-0-fn (sum) ;; If we can find a set of factors common to all the addends of sum, ;; we return an alist binding common to the product of these common ;; factors and binding quotient to (/ sum common). (if (eq (fn-symb sum) 'BINARY-+) (let ((common-factors (common-factors (factors (fargn sum 1)) (fargn sum 2)))) (if common-factors (let ((common (make-product common-factors)) (quotient (quotient common-factors sum))) (list (cons 'common common) (cons 'quotient quotient))) nil)) nil)) (defthm simplify-terms-such-as-a+ab-=-0 (implies (and (bind-free (simplify-terms-such-as-a+ab-rel-0-fn sum) (common quotient)) (case-split (acl2-numberp common)) (case-split (acl2-numberp quotient)) (case-split (equal sum (* common quotient)))) (equal (equal sum 0) (or (equal common 0) (equal quotient 0))))) (thm (equal (equal (+ u (* u v)) 0) (or (equal u 0) (equal v -1))))") (BOOK-COMPILED-FILE (BOOKS-REFERENCE) "Creating and loading of compiled and expansion files for [books] An effect of [compilation] is to speed up the execution of the functions defined in a book. Compilation can also remove tail recursion, thus avoiding stack overflows. The presence of compiled code for the functions in the book should not otherwise affect the performance of ACL2. See [guard] for a discussion; also See [compilation]. By default, the [certify-book] command compiles the book that it certifies. see [certify-book] for how to control this behavior. By default, the [include-book] command loads the compiled file for the book. The details of how this loading works are subtle, and do not need to be understood by most users. The ACL2 source code contains an ``Essay on Hash Table Support for Compilation'' that explains such details for those interested. All that users should generally need to know about this is that the compiled file is always the result of compiling a so-called ``expansion file'', which contains certain additional code besides the book itself. The relevance to users of the expansion file is that it can be loaded if the compiled file is missing (except when :load-compiled-file t is specified by the [include-book] form), and its existence is required in order for [include-book] to create a book's compiled file, as described below. Most users can skip the remainder of this documentation topic, which addresses the uncommon activity of using [include-book] to compile books. Include-book can be made to compile a book by supplying its keyword argument :load-compiled-file the value :comp. However, a compiled file can only be produced if there is already an expansion file that is at least as recent as the book's [certificate]. Such a file, whose name happens to be the result of concatenating the string \"@expansion.lsp\" to the book name (without the \".lisp\" suffix), is created by [certify-book] when state global variable 'save-expansion-file has a non-nil value. That will be the case if ACL2 started up when environment variable ACL2_SAVE_EXPANSION was t (or any value that is not the empty string and whose [string-upcase] is not \"NIL\"), until the time (if any) that 'save-expansion-file is assigned a different value by the user. In most respects, the :comp setting is treated exactly the same as :warn; but after all events in the book are processed, the expansion file is compiled if a compiled file was not loaded, after which the resulting compiled file is loaded. One can thus, for example, compile books for several different host Lisps --- useful when installing ACL2 executables at the same site that are built on different host Lisps. A convenient way to do this in an environment that provides Gnu `make' is to certify the community books using the shell command ``make regression'' in the acl2-sources/ directory, after setting environment variable ACL2_SAVE_EXPANSION to t, and then moving to the books directory and executing the appropriate `make' commands to compile the books (targets fasl, o, and so on, according to the compiled file extension for the host Lisp). We conclude by saying more about the :load-compiled-file argument of [include-book]. We assume that [state] global 'compiler-enabled has a non-nil value; otherwise :load-compiled-file is always treated as nil. We do not consider raw mode below (see [set-raw-mode]), which presents a special case: ACL2 will attempt to load the book itself whenever it would otherwise load the expansion or compiled file, but cannot (either because the :load-compiled-file argument is nil, or for each of the expansion and compiled files, either it does not exist or it is out of date with respect to the .cert file). The :load-compiled-file argument is not recursive: calls of include-book that are inside the book supplied to include-book use their own :load-compiled-file arguments. However, those subsidiary include-book calls can nevertheless be sensitive to the :load-compiled-file arguments of enclosing include-book calls, as follows. If :load-compiled-file has value t, then every subsidiary include-book is required to load a compiled file. Moreover, if a book's compiled file or expansion file is loaded in raw Lisp, then an attempt will be made to load the compiled file or expansion file for any [include-book] form encountered during that load. If that attempt fails, then that load immediately aborts, as does its parent load, and so on up the chain. If, when going up the chain, an [include-book] is aborted for which keyword argument :load-compiled-file has value t, then an error occurs. When loading a book's compiled file or expansion file, FILE, it is possible to encounter an [include-book] form for a book that has no suitable compiled file or expansion file. In that case, the load of FILE is aborted at that point. Similarly, the load of FILE is aborted in the case that this include-book form has a suitable compiled file or expansion file whose load is itself aborted. Thus, whenever any include-book aborts, so do all of its parent include-books, up the chain. Such an abort causes an error when the include-book form specifies a :load-compiled-file value of t.") (BOOK-CONTENTS (BOOKS-TOUR) "Restrictions on the forms inside [books] Example Book: ; This book defines my app function and the theorem that it is ; associative. One irrelevant help lemma is proved first but ; it is local and so not seen by include-book. I depend on the ; inferior book \"weird-list-primitives\" from which I get ; definitions of hd and tl. (in-package \"MY-PKG\") (include-book \"weird-list-primitives\") (defun app (x y) (if (consp x) (cons (hd x) (app (tl x) y)) y)) (local (defthm help-lemma (implies (true-listp x) (equal (app x nil) x)))) (defthm app-is-associative (equal (app (app a b) c) (app a (app b c)))) The first form in a book must be (in-package \"pkg\") where \"pkg\" is some package name known to ACL2 whenever the book is certified. The rest of the forms in a book are embedded event forms, i.e., [defun]s, [defthm]s, etc., some of which may be marked [local]. See [embedded-event-form]. The usual Common Lisp commenting conventions are provided. Note that since a book consists of embedded event forms, we can talk about the ``[local]'' and ``non-local'' [events] of a book. Because [in-package] is not an embedded event form, the only [in-package] in a book is the initial one. Because [defpkg] is not an embedded event form, a book can never contain a [defpkg] form. Because [include-book] is an embedded event form, [books] may contain references to other [books]. This makes [books] structured objects. When the forms in a book are read from the file, they are read with [current-package] set to the package named in the [in-package] form at the top of the file. The effect of this is that all symbols are [intern]ed in that package, except those whose packages are given explicitly with the ``::'' notation. For example, if a book begins with (in-package \"ACL2-X\") and then contains the form (defun fn (x) (acl2::list 'car x)) then [defun], fn, x, and [car] are all [intern]ed in the \"ACL2-X\" package. I.e., it is as though the following form were read instead: (acl2-x::defun acl2-x::fn (acl2-x::x) (acl2::list 'acl2-x::car acl2-x::x)). Of course, acl2-x::defun would be the same symbol as acl2::defun if the \"ACL2-X\" package imported acl2::defun. If each book has its own unique package name and all the names defined within the book are in that package, then name clashes between [books] are completely avoided. This permits the construction of useful logical [world]s by the successive inclusion of many [books]. Although it is often too much trouble to manage several packages, their judicious use is a way to minimize name clashes. Often, a better way is to use local; see [local]. How does [include-book] know the definitions of the packages used in a book, since [defpkg]s cannot be among the forms? More generally, how do we know that the forms in a book will be admissible in the host logical [world] of an [include-book]? See [certificate] for answers to these questions.") (BOOK-EXAMPLE (BOOKS-TOUR) "How to create, certify, and use a simple book Suppose you have developed a sequence of admissible [events] which you want to turn into a book. We call this ``publishing'' the book. This note explains how to do that. A key idea of [books] is that they are ``incremental'' in the sense that when you include a book in a host logical [world], the [world] is incrementally extended by the results established in that book. This is allowed only if every name defined by the incoming book is either new or is already identically defined. See [redundant-events]. This is exactly the same problem faced by a programmer who wishes to provide a utility to other people: how can he make sure he doesn't create name conflicts? The solution, in Common Lisp, is also the same: use packages. While [books] and packages have a very tenuous formal connection (every book must start with an [in-package]), the creation of a book is intimately concerned with the package issue. Having motivated what would otherwise appear as an unnecessary fascination with packages below, we now proceed with a description of how to publish a book. Just to be concrete, let's suppose you have already gotten ACL2 to accept the following sequence of [command]s, starting in the ACL2 initial [state]. (defpkg \"ACL2-MY-BOOK\" (union-eq *common-lisp-symbols-from-main-lisp-package* *acl2-exports*)) (in-package \"ACL2-MY-BOOK\") (defun app (x y) (if (consp x) (cons (car x) (app (cdr x) y)) y)) (defun rev (x) (if (consp x) (app (rev (cdr x)) (list (car x))) nil)) (defthm rev-app-hack (equal (rev (app a (list x))) (cons x (rev a)))) (defthm rev-rev (implies (acl2::true-listp x) (equal (rev (rev x)) x))) Observe that the first form above defines a package (which imports the symbols defined in CLTL such as [if] and [cons] and the symbols used to [command] ACL2 such as [defun] and [defthm]). The second form selects that package as the current one. All subsequent forms are read into that package. The remaining forms are just event forms: [defun]s and [defthm]s in this case. Typically you would have created a file with Emacs containing these forms and you will have submitted each of them interactively to ACL2 to confirm that they are all admissible. That interactive verification should start in ACL2's initial [world] --- although you might, of course, start your sequence of [events] with some [include-book]s to build a more elaborate [world]. The first step towards publishing a book containing the results above is to create a file that starts with the [in-package] and then contains the rest of the forms. Let's call that file \"my-book.lisp\". The name is unimportant, except it must end with \".lisp\". If there are [events] that you do not wish to be available to the user of the book --- e.g., lemmas you proved on your way toward proving the main ones --- you may so mark them by enclosing them in [local] forms. See [local]. Let us suppose you wish to hide rev-app-hack above. You may also add standard Lisp comments to the file. The final content of \"my-book.lisp\" might be: ; This book contains my app and rev functions and the theorem ; that rev is its own inverse. (in-package \"ACL2-MY-BOOK\") (defun app (x y) (if (consp x) (cons (car x) (app (cdr x) y)) y)) (defun rev (x) (if (consp x) (app (rev (cdr x)) (list (car x))) nil)) ; The following hack is not exported. (local (defthm rev-app-hack (equal (rev (app a (list x))) (cons x (rev a))))) (defthm rev-rev (implies (acl2::true-listp x) (equal (rev (rev x)) x))) The file shown above is the book. By the time this note is done you will have seen how to certify that the book is correct, how to compile it, and how to use it in other host [world]s. Observe that the [defpkg] is not in the book. It cannot be: Common Lisp compilers disagree on how to treat new package definitions appearing in files to be compiled. Since a book is just a source file typed by the user, ACL2 provides a mechanism for checking that the [events] are all admissible and then marking the file as checked. This is called certification. To certify \"my-book.lisp\" you should first get into ACL2 with an initial [world]. Then, define the package needed by the book, by typing the following [defpkg] to the ACL2 [prompt]: ACL2 !>(defpkg \"ACL2-MY-BOOK\" (union-eq *common-lisp-symbols-from-main-lisp-package* *acl2-exports*)) Then execute the [command]: ACL2 !>(certify-book \"my-book\" 1 t) ; the `t' is in fact the default Observe that you do not type the \".lisp\" part of the file name. For purposes of [books], the book's name is \"my-book\" and by the time all is said and done, there will be several extensions in addition to the \".lisp\" extension associated with it. The 1 tells [certify-book] that you acknowledge that there is one command in this ``certification [world]'' (namely the [defpkg]). To use the book, any prospective host [world] must be extended by the addition of whatever [command]s occurred before certification. It would be a pity to certify a book in a [world] containing junk because that junk will become the ``[portcullis]'' guarding entrance to the book. The t above tells [certify-book] that you wish to compile \"my-book.lisp\" also (but see [compilation] for an exception). [Certify-book] makes many checks but by far the most important and time-consuming one is that it ``proves'' every event in the file. When [certify-book] is done it will have created two new files. The first will be called \"my-book.cert\" and contains the ``[certificate]'' attesting to the admissibility of the [events] in \"my-book.lisp\". The [certificate] contains the [defpkg] and any other forms necessary to construct the certification [world]. It also contains various check sums used to help you keep track of which version of \"my-book.lisp\" was certified. The second file that may be created by [certify-book] is the compiled version of \"my-book.lisp\" and will have a name that is assigned by the host compiler (e.g., \"my-book.o\" in GCL, \"my-book.fasl\" in SBCL). [Certify-book] will also load this object file. When [certify-book] is done, you may throw away the logical [world] it created, for example by executing the [command] :u. To use the book later in any ACL2 session, just execute the event (include-book \"my-book\"). This will do the necessary [defpkg], load the non-[local] [events] in \"my-book.lisp\" and then may load the compiled code for the non-local functions defined in that file. Checks are made to ensure that the [certificate] file exists and describes the version of \"my-book.lisp\" that is read. The compiled code is loaded if and only if it exists and has a later write date than the source file (but see [compilation] for an exception). Since [include-book] is itself an event, you may put such forms into other [books]. Thus it is possible for the inclusion of a single book to lead to the inclusion of many others. The check sum information maintained in [certificate]s helps deal with the version control problem of the referenced [books]. I.e., if this version of \"my-book\" is used during the certification of \"your-book\", then the [certificate] for \"your-book\" includes the check sum of this version of \"my-book\". If a later (include-book \"your-book\") finds a version of \"my-book\" with a different check sum, an error is signalled. But check sums are not perfect and the insecurity of the host file system prevents ACL2 from guaranteeing the logical soundness of an [include-book] event, even for a book that appears to have a valid [certificate] (they can be forged, after all). (See [certificate] for further discussion.) This concludes the example of how to create, certify and use a book. If you wish, you could now review the [documentation] for book-related topics (see [books]) and browse through them. They'll probably make sense in this context. Alternatively, you could continue the ``guided tour'' through the rest of the [documentation] of [books]. See [book-name], following the pointer given at the conclusion.") (BOOK-MAKEFILES (POINTERS) "See [books-certification].") (BOOK-NAME (BOOKS-TOUR) "Conventions associated with book names Examples: \"list-processing\" \"/usr/home/smith/my-arith\" Book names are string constants that can be elaborated into file names. We elaborate book names by concatenating the ``connected book directory'' (see [cbd]) string on the left and some ``extension,'' such as \".lisp\", on the right. However, the connected book directory is not added if the book name itself already represents an absolute file name. Furthermore, [include-book] and [certify-book] temporarily reset the connected book directory to be the directory of the book being processed. This allows [include-book] forms to use file names without explicit mention of the enclosing book's directory. This in turn allows [books] (together with those that they include, using [include-book]) to be moved between directories while maintaining their certification and utility. You may wish to read elsewhere for details of ACL2 file name conventions (see [pathname]), for a discussion of the filename that is the result of the elaboration described here (see [full-book-name]), and for details of the concept of the connected book directory (see [cbd]). For details of how [include-book] (see [include-book]) and [certify-book] (see [certify-book]) use these concepts, see below. Often a book name is simply the familiar name of the file. (See [full-book-name] for discussion of the notions of ``directory string,'' ``familiar name,'' and ``extension''. These concepts are not on the guided tour through [books] and you should read them separately.) However, it is permitted for book names to include a directory or part of a directory name. Book names never include the extension, since ACL2 must routinely tack several different extensions onto the name during [include-book]. For example, [include-book] uses the \".lisp\", \".cert\" and possibly the \".o\" or \".lbin\" extensions of the book name. Book names are elaborated into full file names by [include-book] and [certify-book]. This elaboration is sensitive to the ``connected book directory.'' The connected book directory is an absolute filename string (see [pathname]) that is part of the ACL2 [state]. (You may wish to see [cbd] and to see [set-cbd] --- note that these are not on the guided tour). If a book name is an absolute filename string, ACL2 elaborates it simply by appending the desired extension to the right. If a book name is a relative filename string, ACL2 appends the connected book directory on the left and the desired extension on the right. Note that it is possible that the book name includes some partial specification of the directory. For example, if the connected book directory is \"/usr/home/smith/\" then the book name \"project/task-1/arith\" is a book name that will be elaborated to \"/usr/home/smith/project/task-1/arith.lisp\". Observe that while the [events] in this \"arith\" book are being processed the connected book directory will temporarily be set to \"/usr/home/smith/project/task-1/\". Thus, if the book requires other [books], e.g., (include-book \"naturals\") then it is not necessary to specify the directory on which they reside provided that directory is the same as the superior book. This inheritance of the connected book directory and its use to elaborate the names of inferior [books] makes it possible to move [books] and their inferiors to new directories, provided they maintain the same relative relationship. It is even possible to move with ease whole collections of [books] to different filesystems that use a different operating system than the one under which the original certification was performed. The \".cert\" extension of a book, if it exists, is presumed to contain the most recent [certificate] for the book. See [certificate] (or, if you are on the guided tour, wait until the tour gets there). See [book-contents] to continue the guided tour.") (BOOKDATA (BOOKS) "An optional tool for writing out small files with meta-data about the books that are being certified. ACL2 provides a primitive capability for writing out a file of data associated with a book. This information might be useful, for example, in building a database that allows you to search for name conflicts. See [community-books] directory books/tools/book-conflicts/ for an application of this capability by Dave Greve. If you use this capability and have ideas for enhancing it, please feel free to send them to the ACL2 developers. If the book has the name BK, then the output file is named BK__bookdata.out. That file is generated in the same directory as BK, by certifying BK when [state] global 'write-bookdata has a non-nil value, for example as follows. (assign write-bookdata t) (certify-book \"BK\" ...) The resulting file will contain a single form of the following shape, although not necessarily in the following order, according to the description that follows below. (\"...BK.lisp\" :PKGS pkgs-val :BOOKS book-val :PORT-BOOKS port-book-val :CONSTS consts-val :PORT-CONSTS port-consts-val :FNS fns-val :PORT-FNS port-fns-val :LABELS labels-val :PORT-LABELS port-labels-val :MACROS macros-val :PORT-MACROS port-macros-val :STOBJS stobjs-val :PORT-STOBJS port-stobjs-val :THEORIES theories-val :PORT-THEORIES port-theories-val :THMS thms-val :PORT-THMS port-thms-val ) The first entry in the form will always be the full book name (see [full-book-name]) of the certified book, BK. Subsequent values in the form are based on [events] introduced by including BK. For various values of xxx as described below, port-xxx-val is a list of values corresponding to [events] introduced in the certification [world] for BK (see [portcullis]), and xxx-val is a list of values corresponding to [events] introduced non-[local]ly by BK. These lists include only ``top-level'' events, not those that are introduced by a book included either in BK or its certification world. pkgs-val is a list of names of packages introduced in the certification world (at the top level, not in an included book). Note that no packages are introduced in a book itself, so no distinction is made between pkgs-val and port-pkgs-val. Both port-book-val and book-val are lists of full book names (see [full-book-name]) of included books. The values associated with the other keywords are, themselves, association lists (see [alistp]) such that each key is a package name, which is associated with a list of [symbol-name]s for symbols in that package that are introduced for that keyword. For example, fns-val may be the alist ((\"ACL2\" \"F1\" \"F2\") (\"MY-PKG\" \"G1\" \"G2\")) if the function symbols introduced in the book are F1 and F2 in the \"ACL2\" package, as well as G1 and G2 in the \"MY-PKG\" package. We next explain what kinds of symbols are introduced for each keyword :xxx. Each such symbol would be associated with either the keyword :port-xxx or the keyword :xxx depending respectively on whether the symbol is introduced at the top level of the certification world for BK or BK itself. :CONSTS constant symbol introduced by defconst :FNS function symbol: introduced by defun, defuns, or defchoose; or constrained (by an [encapsulate] event) :LABELS symbol introduced by deflabel :MACROS macro name introduced by defmacro :STOBJS stobj name introduced by defstobj or defabsstobj :THEORIES theory name introduced by deftheory :THMS theorem name, which may be introduced by defthm or a macro call expanding to a call of defthm, such as see [defequiv] or defaxiom; but may be introduced by [defpkg], for example, with name \"MYPKG-PACKAGE\" if the package name is \"MYPKG\" Our hope is that people in the ACL2 community will generate and use this data to improve the ACL2 [community-books]. Here is an example illustrating how to generate bookdata files for those books as a byproduct of a regression run. Below, we write {DIR} as an abbreviation for the ACL2 sources directory, and assume that this command is run from that directory. Of course, you may wish to use make options like -j 8 and make variable settings like ACL2={DIR}/my-saved_acl2; see [books-certification] for details. make regression-fresh \\ ACL2_CUSTOMIZATION={DIR}/acl2-customization-files/bookdata.lisp") (BOOKS (ACL2 NOTE1) "Books are files of ACL2 [events]---they are the main way to split up large ACL2 developments into separate modules. This [documentation] topic is about ACL2 {source code | https://en.wikipedia.org/wiki/Source_code} files. However, there are also {traditional, paper books | http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books} published about ACL2 and its applications. You will almost surely want to organize your own ACL2 work into books. They facilitate reuse, allow you to reload proofs more quickly, allow you to rebuild parts of your proof in parallel, and so forth. You will also want to be aware of the many community books, which provide useful tools and lemmas to build upon. See [community-books] for more information, including how to contribute. Introduction A book is a file of ACL2 forms. Books are prepared entirely by the user of the system, i.e., they are source files not object files. Some of the forms in a book are marked [local] and the others are considered ``non-local.'' [Include-book] lets you load a book into any ACL2 [world]. A successful include-book extends the logic of the host [world] by adding just the non-local [events] in the book. Ordinarily, you might include a variety of books to load all of their definitions and rules. Successful book inclusion is consistency preserving, provided that the book itself is consistent, as discussed later. However, [include-book] assumes the [events] in a book are valid, so if you include a book that contains an inconsistency (e.g., an inadmissible definition) then the resulting theory is inconsistent! [Certify-book] lets you certify a book to guarantee that its successful inclusion is consistency preserving. During certification, both the [local] and non-local forms are processed. This lets you mark as [local] any [events] you need for certification, but that you want to hide from users of the book---e.g., the hacks, crocks, and kludges on the way to a good set of [rewrite] rules. Certification can also [compile] a book to speed up the execution of the functions defined within it. The desire to compile books is largely responsible for the restrictions we put on the forms allowed in books. Extensive [documentation] is available on the various aspects of books. We recommend that you read it all before using books. It has been written so as to make sense when read in a certain linear sequence, called the ``guided tour'', though in general you may browse through it randomly. If you are on the guided tour, you should next read [book-example]. Subtopics [Bookdata] An optional tool for writing out small files with meta-data about the books that are being certified. [Books-reference] Reference guide for ACL2 functionality related to books, e.g., [include-book], [certify-book], [cbd], etc. [Books-tour] The guided tour of concepts related to ACL2 [books]. [Community-books] Libraries of ACL2 [books] developed by the ACL2 community. [Uncertified-books] Invalid [certificate]s and uncertified [books]") (BOOKS-CERTIFICATION (COMMUNITY-BOOKS) "Instructions for certifying the ACL2 [community-books]. Starting in ACL2 6.4 we recommend using the new Community Books make system to certify the books. If you encounter problems using the new system (described below) or need some feature that is no longer available, please see [books-certification-alt] for alternate instructions. We have not changed how make regression works from the acl2-sources directory. Prerequisites We assume that you have already downloaded and installed ACL2 as per the {ACL2 installation instructions | http://www.cs.utexas.edu/users/moore/acl2/v7-1/HTML/installation/installation.html} on the ACL2 home page. We assume you know the path to your ACL2 executable. Typically this is a script named saved_acl2 in your acl2-sources directory. We assume the ACL2 [community-books] are installed in the books/ subdirectory of your ACL2 distribution, as is the case when you have followed the ACL2 installation instructions above. The instructions below are suitable for ACL2 and all of its experimental extensions, e.g., ACL2(p) and ACL2(r), as well as the ``classic'' variants (see [hons-enabled], ACL2(cp) and ACL2(cr). A Basic Build In previous versions of ACL2, building the Community Books could take several hours. Starting in ACL2 6.4, the default build has been made much faster by excluding many books by default. The new default make target, called basic, now certifies only the following, widely used books: * arithmetic * arithmetic-3 * arithmetic-5 * [ihs] * misc * tools * [std] * [xdoc] * data-structures To certify these books, you should be able to run make as follows. The -j 2 part of this command is suitable for a computer with two cores. If you have, e.g., a quad-core computer, you should probably use -j 4 instead, and so on. $ cd /path/to/acl2-sources/books $ make ACL2=/path/to/acl2-sources/saved_acl2 -j 2 basic If you configure your PATH so that you can launch ACL2 by typing acl2, then you may omit the ACL2=... part. Certifying Additional Books We expect that most ACL2 users will want to certify at least the basic books described above. But what if you also need other books? One option is to do a full build (see below). But it is usually much faster to simply tell make to build the books you actually want to use. There are make targets corresponding to most directory names. For instance, to build the books under coi and rtl and cgen, you can run: $ cd /path/to/acl2-sources/books $ make ACL2=/path/to/acl2-sources/saved_acl2 coi rtl cgen -j 2 For finer grained control, you can name individual books. This works particularly well for libraries that have top books. For instance, if you want the rtl/rel9 library, you could run: $ cd /path/to/acl2-sources/books $ make ACL2=/path/to/acl2-sources/saved_acl2 rtl/rel9/lib/top.cert -j 2 Books that Require ACL2 Extensions Some books require experimental extensions to ACL2, such as ACL2(p) (see [parallelism]) or ACL2(r) (see [real]) or their classic variants, ACL2(cp) or ACL2(cr). Other books require certain additional software. The build system will automatically determine which kind of ACL2 you are running (e.g., ACL2(c), ACL2(p), ACL2(r)) and, based on this, may prevent incompatible books from being certified. The output of make should explain which books are being excluded and why. These kinds of book requirements are controlled by special [cert_param] comments. Books that Require Quicklisp Some books, especially [interfacing-tools] like [oslib] and the ACL2 [bridge], require certain Common Lisp libraries. These libraries are now bundled with ACL2 via [quicklisp], so you should not need to download anything extra to use them. However, since these libraries are not portable across all Lisps that can run ACL2, you must explicitly enable Quicklisp by setting USE_QUICKLISP=1 in your make command if you want to use them. For instance: make ACL2=... USE_QUICKLISP=1 doc/top.cert -j 4 Using Quicklisp should definitely work for CCL and SBCL. We have not tested it with other Lisps, but there is some chance it will work with Lisps such as Allegro, Lispworks, and CMUCL. It will almost certainly not work for GCL. Books that Require Additional Software Some other books based on [satlink] and [gl] require a SAT solver, typically Glucose, to be installed; see [satlink::sat-solver-options] for installation options. The build system should automatically determine if Glucose is installed on your system, and will avoid trying to certify these books unless Glucose is present. Building the manual See [Building_the_ACL2+Books_Manual]. A Full Build Building all of the books can take hours and is usually unnecessary. That said, it is easy to do: just run make all, e.g., $ cd /path/to/acl2-sources/books $ make ACL2=/path/to/acl2-sources/saved_acl2 -j 2 all This actually still skips a few books that are very slow. If you really need to certify absolutely everything, you can run make everything, but this will likely add hours to your build! Cleaning Up If you want to delete generated files, you can run make clean to remove certificates, compiled files, and build logs. If you just want to remove the files in a particular subdirectory (and its subdirectories), you can go into that directory and then run the build/clean.pl script. This will delete, starting from your current directory, recursively, all certificates, logs, compiled files, etc. Note that make clean doesn't remove some files, e.g., [xdoc] manuals. To remove everything, try make moreclean. Debugging Failed Certifications If a book fails to certify, you may want to try certifying it in an interactive session. The most reliable way to do this is to replicate the environment and commands that the build system used. This information can be found at the top of the [bookname].cert.out file. For instance: ;; foo.cert.out -*- Mode: auto-revert -*- ... Environment variables: ACL2_CUSTOMIZATION=NONE ;; <-- first configure your ACL2_SYSTEM_BOOKS=/path/to/acl2/books ;; environment to match ACL2=/path/to/saved_acl2 ;; these settings ... Temp lisp file: (acl2::value :q) ;; <--- then submit these commands to (acl2::in-package \"ACL2\") ;; $ACL2 to debug the failure ... ;; interactively --- End temp lisp file --- Some other notes/tips: * Make sure the ACL2 image you run is the same as the one listed as ACL2 in those environment variables! * You may wish to set the environment variables for only the duration of your ACL2 session by using the \"env\" command. * You may wish to edit some of the commands for better debugging purposes; e.g. you may modify the [set-inhibit-output-lst] command, or insert a [set-debugger-enable] command, etc. * If you don't want your session to exit after a successful certification, replace the last form (er-progn (time$ (certify-book ... with just the (time$ (certify-book ...)) part. Further Resources The build system is largely based on [cert.pl]. There is considerable documentation about cert.pl, and we highly recommend using it to manage your own ACL2 projects. The main build script is books/GNUmakefile. There are many comments at the start of this file, and you can also inspect it to see what targets are available. Please feel absolutely free to contact the [ACL2-help] mailing list with any questions about building the community books. Subtopics [Books-certification-alt] Alternate instructions for certifying the [community-books], from the perspective of the acl2-sources directory. [Books-certification-classic] Classic ACL2 `make'-based certification of [books] [Provisional-certification] Certify a book in stages for improved book-level parallelism") (BOOKS-CERTIFICATION-ALT (BOOKS-CERTIFICATION) "Alternate instructions for certifying the [community-books], from the perspective of the acl2-sources directory. WARNING: Parts of this documentation are probably obsolete, but parts are still relevant. See [books-certification] as the primary source of information on how to certify the [community-books]. For background on the ACL2 community books, see [community-books]. Here we explain how to certify those books, or some of those books, with ACL2. We thank Bishop Brock, Jared Davis, and Sol Swords for their substantial contributions to this methodology. See books/GNUmakefile, in the community books, for more about ``Credits and History'', and for additional technical details not covered in this topic. For more information about installing ACL2, see the {ACL2 installation instructions | http://www.cs.utexas.edu/users/moore/acl2/v7-1/HTML/installation/installation.html}. For information about so-called ``classic ACL2 `make'-based certification'', which provides support for certifying directories of books but may disappear in a future ACL2 release, see [books-certification-classic]. The Basics We make the following assumptions. * Gnu `make' is available on your system via the `make' command (rather than some other flavor of `make'). (Execute `make --version to verify this.) * You have built or obtained an ACL2 executable. * The ACL2 [community-books] are installed in the books/ subdirectory of your ACL2 distribution, as is the case when you have followed the standard installation instructions. Note: All commands shown below are issued in the top-level (ACL2 sources) directory of your ACL2 distribution. By default the ACL2 executable is file saved_acl2 in your ACL2 sources directory, and you can issue the following command to the shell in order to do a ``regression run'' that certifies all of the community books using that executable. make regression Better yet, save a log file in case there are problems, for example as follows. (make regression) >& make-regression.log or perhaps better yet: (time nice make regression) >& make-regression.log For the sake of brevity, below we'll skip mentioning any of `time', `nice', or `>& make-regression.log'. But saving a log file, in particular, is useful in case you encounter problems to report. If you fetched the community books using git, then you will have a directory books/workshops/ that is not necessary for certifying the other books. If you want to skip certification of the books under books/workshops/, use target `certify-books' instead of target `regression', for example as follows. (time nice make certify-books) >& make-certify-books.log Whether you use target `regression' or target `certify-books', then for each book foo.lisp whose certification is attempted, a file foo.cert.out in the same directory will contain the output from the book's certification attempt. A regression run may take a few hours, but if you have a multiprocessing computer, you can speed it up by certifying some books in parallel, by providing a value for `make' option -j. For example, if you have 8 hardware threads then you might want to issue the following command. make regression -j 8 Specifying the ACL2 Executable If your ACL2 executable is not file saved_acl2 in the ACL2 sources directory (or saved_acl2c for ACL2(c); also see [hons-enabled]), then you will need to specify that executable. You can do that by setting variable ACL2, either as an environment variable or, as displayed below, as a `make' variable. Either way, you will need to avoid relative pathnames. For example, the first two forms below are legal, but the third is not, assuming that my-acl2 is on your PATH in a Unix-like environment (e.g., linux or MacOS) and that my-saved_acl2 is just a pathname relative to your ACL2 sources directory, which is not on your path. make regression -j 8 ACL2=my-acl2 make regression -j 8 ACL2=/u/smith/bin/acl2 # The following only works if my-saved_acl2 is on your path (see above). make regression -j 8 ACL2=my-saved_acl2 Cleaning You can delete files generated by book certification (including .cert files, .out files, compiled files, and more) by issuing the following command (again, in your ACL2 sources directory). make clean-books If you want to cause such deletion and then do a regression, simply replace the `regression' or `certify-books' target by `regression-fresh' or `certify-books-fresh', respectively, for example as follows. follows. make -j 4 regression-fresh make -j 4 certify-books-fresh If however you only want to clean up generated files residing under a given directory (or its subdirectories, and recursively), you can issue the following command while standing in that directory, where DIR is a pathname of your books directory. DIR/clean.pl For example, to clean up generated files under books/arithmetic, you could do the following. cd books/arithmetic ../clean.pl cd - # to return to the ACL2 sources directory, if you wish to do so Restricting to Specific Directories and Books You can specify which books you want certified by using any or all of the variables EXCLUDED_PREFIXES, ACL2_BOOK_CERTS, or ACL2_BOOK_DIRS. First, the set of desired .cert files is restricted to those that do not start with any string that is one of the words in the value of EXCLUDED_PREFIXES. Then ACL2_BOOK_CERTS and ACL2_BOOK_DIRS, if supplied, specify which books should be certified, as illustrated by the following example. make -j 8 regression-fresh \\ ACL2_BOOK_DIRS=\"symbolic paco\" \\ ACL2_BOOK_CERTS=\" \\ workshops/2006/cowles-gamboa-euclid/Euclid/ed6a.cert \\ workshops/2006/cowles-gamboa-euclid/Euclid/ed4bb.cert \\ \" Then all book in directories symbolic and paco will be certified, as will the books workshops/2006/cowles-gamboa-euclid/Euclid/ed6a.lisp and workshops/2006/cowles-gamboa-euclid/Euclid/ed4bb.lisp. Note that all pathnames should be relative to your community books directory; in particular, they should not be absolute pathnames. Also notice the .cert extension used in files supplied for ACL2_BOOK_CERTS. Alternatively, you may wish to invoke books/cert.pl while standing in a directory under which you want to certify books. This will certify not only those books, but all supporting books --- even those not under the current directory --- that do not have up-to-date .cert files. The following is a simple command to invoke that will certify all books in the current directory, where if the books/ directory is not on your path, you will need to provide a suitable filename, e.g. ../../cert.pl or ~/acl2/books/cert.pl. cert.pl -j 4 *.lisp Here is a more complex command, which illustrates a way to certify books in subdirectories (as well as the current directory), the use of provisional certification (see [provisional-certification]), and `make'-level parallelism (in this case specifying four parallel processes). ACL2_PCERT=t cert.pl -j 4 `find . -name '*.lisp'` Note that with this approach, unlike classic ACL2 `make'-based certification (see [books-certification-classic], out-of-date .cert files that are not under the current directory will also be built. For documentation of cert.pl invoke: cert.pl -h See the top of cert.pl for authorship and copyright information. Finally, we give a brief summary of how to use so-called ``classic ACL2 `make'-based certification'' for community books; see [books-certification-classic] for details. Note that support for this approach might be eliminated in a future ACL2 release. We welcome comments from the ACL2 community about whether or not that would be a good thing to do. See the discussion above about ACL2_BOOK_DIRS for the ``modern'' way to accomplish the same thing. Many community book directories have a Makefile. If you modify books only in such a directory, you can recertify by standing in that directory and issuing a `make' command. This command can optionally specify an ACL2 executable as well as parallelism, for example as follows, where the first line (make clean) is optional. make clean (time nice make -j 8 ACL2=my-acl2) ACL2 Customization Files By default, your acl2-customization file (see [ACL2-customization]) is ignored by all flavors of ``make regression''. However, you can specify the use of an acl2-customization file by setting the value of environment variable ACL2_CUSTOMIZATION to the empty string, indicating a default such file, or to the desired absolute pathname. For example: make regression ACL2_CUSTOMIZATION='' make regression ACL2_CUSTOMIZATION='~/acl2-customization.lisp' Regressions for Variants of ACL2 The discussion above also pertain pertain to using ACL2(p) (see [parallel]) or ACL2(r) (see [real]), in which case the default is saved_acl2p or saved_acl2r respectively, rather than saved_acl2 (alternatively, saved_acl2cp or saved_acl2cr, respectively, if the executable is not [hons-enabled]). However, we recommend that you use ACL2, not ACL2(p), for your regression. Then you can use ACL2(p) for your own proof developments. However, if you want to use ACL2(p) or (ACL2(cp), which adds parallelism to classic ACL2) for your regression, see [waterfall-parallelism-for-book-certification]. Provisional Certification To use provisional certification (see [provisional-certification]), supply ACL2_PCERT=t with your `make' command. Here is an example. time nice make regression -j 4 ACL2_BOOK_DIRS=deduction ACL2_PCERT=t Miscellany Other control of the certification process may be found by perusing community books file books/make_cert. In particular, the INHIBIT variable may be set to a call of [set-inhibit-output-lst], for example as follows to obtain the output one would get by default in an (interactive) ACL2 session. time nice make regression -j 4 ACL2_BOOK_DIRS=arithmetic \\ INHIBIT='(set-inhibit-output-lst proof-tree)' Troubleshooting If you run into problems, you can get help by joining the acl2-help email list (follow the link from the ACL2 home page) and sending a message to that list. Also consider trying another version of GNU `make'; for example, we have found that versions 3.81 and 3.82 sometimes cause errors on Linux where version 3.80 does not. Note however that Version 3.80 does not print certain informational messages that are printed by later versions.") (BOOKS-CERTIFICATION-CLASSIC (BOOKS-CERTIFICATION) "Classic ACL2 `make'-based certification of [books] This [documentation] topic explains an approach to certifying directories of books, which we call ``classic ACL2 `make'-based certification''. Warning: The capability described in this section might be replaced at any time by a capability based on corresponding support for community books (see [books-certification]). If you think that would be a hardship, please contact the ACL2 implementors. This topic discusses a way to certify a directory of books other than the ACL2 community books. See [books-certification] for how to certify the set of ACL2 community [books]. There is also a section in that [documentation] topic, ``Restricting to Specific Directories and Books'', that provides an alternative to classic ACL2 `make'-based certification (as discussed in the present topic) for certifying specified sets of books. We assume here a familiarity with Unix/Linux `make'. We also assume that you are using GNU `make' rather than some other flavor of `make'. And finally, we assume, as is typically the case by following the standard installation instructions, that you install the ACL2 community books in the books/ subdirectory of your ACL2 distribution. We will refer below to that directory as BOOKS. In summary: to use `make' to certify [books] under a given directory, you may create a simple Makefile in that directory (as explained below) so that when you stand in that directory, you can submit the command, `make', to certify those books. If you have a multi-processor machine or the like, then you can use the `-j flag `make'-level parallelism by specifying the number of concurrent processes. For example: make -j 4 For each book foo.lisp, a file foo.out in the same directory as foo.lisp will contain the output from the corresponding certification attempt. If you have previously executed such a command, then you might first want to delete [certificate] files and other generated files by executing the following command. make clean Note that when you run `make', then by default, the first error will cause the process to stop. You can use make -i to force `make' to ignore errors, thus continuing past them. Or, use make -k to keep going, but skipping certification for any book that includes another whose certification has failed. By default, your acl2-customization file (see [ACL2-customization]) is ignored by such `make' commands. However, you can specify the use of an acl2-customization file by setting the value of environment variable ACL2_CUSTOMIZATION to the empty string, indicating a default such file, or to the desired absolute pathname. For example: make ACL2_CUSTOMIZATION='' make ACL2_CUSTOMIZATION='~/acl2-customization.lisp' We now discuss how to create makefiles to support `make' commands as discussed above. First we give five steps for creating a Makefile to support certification of a directory of books, without subdirectories. For examples of such Makefiles you can look in community book directories (which, however, might disappear in future versions of ACL2). 1. Include the file Makefile-generic from the books/ subdirectory of your ACL2 sources directory, but first perhaps define the variable `ACL2'. Consider the following example. ACL2 ?= /Users/john_doe/acl2/acl2-sources/saved_acl2 include /Users/john_doe/acl2/acl2-sources/books/Makefile-generic In this example, you can omit the first line, because the default ACL2 executable is file saved_acl2 in the directory immediately above the directory of the specified Makefile-generic file. Indeed, that is the common case. Note the use of ?= instead of = or :=, so that ACL2 can instead be defined by the environment or provided on the command line as part of the `make' command. 2. (Optional; usually skipped.) Set the INHIBIT variable if you want to see more than the summary output. For example, if you want to see the same output as you would normally see at the terminal, put this line in your Makefile after the `include' lines. INHIBIT = (assign inhibit-output-lst (list (quote proof-tree))) For other values to use for INHIBIT, see [set-inhibit-output-lst] and see the original setting of INHIBIT in books/Makefile-generic. 3. Specify the books to be certified. Normally, every file with extension .lisp will be a book that you want to certify, in which case you can skip this step. Otherwise, put a line in your Makefile after the ones above that specifies the books to be certified. The following example, from an old version of community books file books/finite-set-theory/osets/Makefile, should make this clear. BOOKS = computed-hints fast instance map membership outer primitives \\ quantify set-order sets sort But better yet, use the extension .lsp for any Lisp or ACL2 files that are not to be certified, so that the definition of BOOKS can be omitted. 4. Create .acl2 files for books that are to be certified in other than the initial ACL2 world (see [portcullis]). For example, if you look in community books file books/arithmetic/equalities.acl2 you will see [defpkg] forms followed by a [certify-book] command, because it was determined that [defpkg] forms were necessary in the certification world in order to certify the equalities book. In general, for each .lisp whose certification requires a non-initial certification world, you will need a corresponding .acl2 file that ends with the appropriate [certify-book] command. You also have the option of creating a file cert.acl2 that has a special role. When file .lisp is certified, if there is no file .acl2 but there is a file cert.acl2, then cert.acl2 will be used as .acl2 would have been used, as described in the preceding paragraph, except that the appropriate [certify-book] command will be generated automatically. Thus, no certify-book command should occur in cert.acl2. It is actually allowed to put raw lisp forms in a .acl2 file (presumably preceded by :q or (value :q) and followed by (lp)). But this is not recommended; we make no guarantees about certification performed any time after raw Lisp has been entered in the ACL2 session. 5. Generally, the next step is to include the following line after the `include' of Makefile-generic (see the first step above). -include Makefile-deps This will cause `make' to create and then include a file Makefile-deps that contains ``dependency'' lines needed by `make'. If those dependencies are somehow flawed, it may be because you have [include-book] forms that are not truly including books, for example in multi-line comments (#|..|#). These will be ignored if preceded by a semicolon (;), or if you add a line break after ``include-book.'' But instead of adding the `-include' line above, you can create dependency lines yourself by running the command make dependencies and pasting the result into the end of your Makefile, and editing as you see fit. This concludes the basic instructions for creating a Makefile in a directory including books. Here are some other capabilities offered by community books file books/Makefile-subdirs. Not included below is a discussion of how to increase parallelism by avoiding the need to certify included books before certifying a given book; see [provisional-certification]. Subdirectory Support There is support for using `make' to certify books in subdirectories. Consider the following example. DIRS = pass1 bind-free floor-mod include ../Makefile-subdirs This indicates that we are to run `make' in subdirectories pass1/, bind-free/, and floor-mod/ of the current directory. You can combine this subdirectory support with the support already discussed for certifying books in the top-level directory. Here is an example, which as of this writing is in community books file books/arithmetic-3/Makefile contains the following lines. arith-top: top all all: top DIRS = pass1 bind-free floor-mod include ../Makefile-subdirs include ../Makefile-generic -include Makefile-deps The `top' target is defined in ../Makefile-subdirs to call `make' in each subdirectory specified in DIRS. We have set the default target in the example above to a new name, arith-top, that makes that top target before making the `all' target which, in turn, is the default target in any Makefile-generic, and is responsible for certifying books in the current directory as discussed in the five steps displayed above. Use Makefile-psubdirs instead of Makefile-subdirs if certification of a book in a subdirectory never depends on certification of a book in a different subdirectory, because then the -j option of `make' can allow subdirectories to be processed in parallel. Cleaning Up We note that there is a clean target. Thus, make clean will remove generated files including .cert, .out files, and compiled files. System Books An environment variable ACL2_SYSTEM_BOOKS is generally set automatically, so you can probably skip reading the following paragraph unless your attempt to certify books fails to locate those books properly. The environment variable ACL2_SYSTEM_BOOKS can be set to the top-level directory of the ACL2 community books. A Unix-style pathname, typically ending in books/ or books, is permissible. In most cases, your ACL2 executable is a small script in which you can set this environment variable just above the line on which the actual ACL2 image is invoked, for example: export ACL2_SYSTEM_BOOKS ACL2_SYSTEM_BOOKS=/home/acl2/v3-2/acl2-sources/books However, you can also set ACL2_SYSTEM_BOOKS as a `make' variable, by setting it in your Makefile before the first target definition, e.g.: ACL2_SYSTEM_BOOKS ?= /home/acl2/v3-2/acl2-sources/books Compilation Support The file books/Makefile-generic provides support for compiling books that are already certified (but see [compilation] for an exception). For example, suppose that you have certified books using GCL as the host Lisp, resulting in compiled files with the .o extension. Now suppose you would like to compile the books for Allegro Common Lisp, whose compiled files have the .fasl extension. The following command will work if you have included books/Makefile-generic in your Makefile. make fasl In general, the compiled file extension for a Lisp supported by ACL2 will be a target name for building compiled files for all your books (after certifying the books, if not already up-to-date on certification). If you run into problems, you can get help by joining the acl2-help email list (follow the link from the ACL2 home page) and sending a message to that list. Also consider trying another version of GNU `make'; for example, we have found that versions 3.81 and 3.82 sometimes cause errors on Linux where version 3.80 does not.") (BOOKS-REFERENCE (BOOKS) "Reference guide for ACL2 functionality related to books, e.g., [include-book], [certify-book], [cbd], etc. Subtopics [Add-include-book-dir] Link keyword for :dir argument of [ld] and [include-book] [Add-include-book-dir!] Non-[local]ly link keyword for :dir argument of [ld] and [include-book] [Book-compiled-file] Creating and loading of compiled and expansion files for [books] [Cbd] Connected book directory string [Certify-book] How to produce a [certificate] for a book [Delete-include-book-dir] Unlink keyword for :dir argument of [ld] and [include-book] [Delete-include-book-dir!] Non-[local]ly unlink keyword for :dir argument of [ld] and [include-book] [Full-book-name] Book naming conventions assumed by ACL2 [Include-book] Load the [events] in a file [Pathname] Introduction to filename conventions in ACL2 [Set-cbd] To set the connected book directory [Set-write-ACL2x] Cause [certify-book] to write out a .acl2x file") (BOOKS-TOUR (BOOKS) "The guided tour of concepts related to ACL2 [books]. The tour begins with [book-example]. Subtopics [Book-contents] Restrictions on the forms inside [books] [Book-example] How to create, certify, and use a simple book [Book-name] Conventions associated with book names [Certificate] How a book is known to be admissible and where its [defpkg]s reside [Certify-book] How to produce a [certificate] for a book [Include-book] Load the [events] in a file [Keep] How we know if [include-book] read the correct files [Portcullis] The gate guarding the entrance to a certified book") (BOOLE$ (NUMBERS ACL2-BUILT-INS) "Perform a bit-wise logical operation on 2 two's complement integers When integers x and y are viewed in their two's complement representation, (boole$ op x y) returns the result of applying the bit-wise logical operation specified by op. The following table is adapted from documentation for the analogous Common Lisp function {boole | http://www.lispworks.com/documentation/HyperSpec/Body/f_boole.htm} in the {Common Lisp Hyperspec | http://www.lispworks.com/documentation/HyperSpec/}. Note that the values of op for boole$ are ACL2 constants, rather than corresponding values of op for the Common Lisp function boole. op result ----------- --------- *boole-1* x *boole-2* y *boole-andc1* and complement of x with y *boole-andc2* and x with complement of y *boole-and* and *boole-c1* complement of x *boole-c2* complement of y *boole-clr* the constant 0 (all zero bits) *boole-eqv* equivalence (exclusive nor) *boole-ior* inclusive or *boole-nand* not-and *boole-nor* not-or *boole-orc1* or complement of x with y *boole-orc2* or x with complement of y *boole-set* the constant -1 (all one bits) *boole-xor* exclusive or The guard of boole$ specifies that op is the value of one of the constants above and that x and y are integers. See any Common Lisp documentation for analogous information about Common Lisp function boole. Function: (defun boole$ (op i1 i2) (declare (type (integer 0 15) op) (type integer i1 i2)) (cond ((eql op *boole-1*) i1) ((eql op *boole-2*) i2) ((eql op *boole-and*) (logand i1 i2)) ((eql op *boole-andc1*) (logandc1 i1 i2)) ((eql op *boole-andc2*) (logandc2 i1 i2)) ((eql op *boole-c1*) (lognot i1)) ((eql op *boole-c2*) (lognot i2)) ((eql op *boole-clr*) 0) ((eql op *boole-eqv*) (logeqv i1 i2)) ((eql op *boole-ior*) (logior i1 i2)) ((eql op *boole-nand*) (lognand i1 i2)) ((eql op *boole-nor*) (lognor i1 i2)) ((eql op *boole-orc1*) (logorc1 i1 i2)) ((eql op *boole-orc2*) (logorc2 i1 i2)) ((eql op *boole-set*) 1) ((eql op *boole-xor*) (logxor i1 i2)) (t 0)))") (BOOLEAN-LISTP (BOOLEANP LISTS ACL2-BUILT-INS) "Recognizer for a true list of booleans The predicate boolean-listp tests whether its argument is a [true-listp] of objects each or which satisfyies [booleanp], i.e., is t or nil. Function: (defun boolean-listp (lst) (declare (xargs :guard t)) (cond ((atom lst) (eq lst nil)) (t (and (or (eq (car lst) t) (eq (car lst) nil)) (boolean-listp (cdr lst))))))") (BOOLEANP (BASICS ACL2-BUILT-INS) "Recognizer for booleans (Booleanp x) is t if x is t or nil, and is nil otherwise. See [generalized-booleans] for a discussion of a potential soundness problem for ACL2 related to the question: Which Common Lisp functions are known to return Boolean values? Function: (defun booleanp (x) (declare (xargs :guard t)) (if (eq x t) t (eq x nil))) Subtopics [Boolean-listp] Recognizer for a true list of booleans") (BOUNDERS (TAU-SYSTEM) "Intervals, bounder functions, and bounder correctness Bounder Forms 1 and 2: (implies (and (tau-intervalp i1) ... (or (equal (tau-interval-dom i1) 'dom1-1) ...) ... (in-tau-intervalp x1 i1) ...) (and (tau-intervalp (bounder-fn i1 ...)) (in-tau-intervalp target (bounder-fn i1 ...)))) where target is either (fn x1 ... y1 ...) or (mv-nth 'n (fn x1 ... y1 ...)), depending on whether we are in the Form 1 or Form 2 case, respectively. However, the shape above is meant just as a reminder. Details are given below. This topic first explains the basic shape of Bounder Form 1. Then it illustrates Bounder Form 2. Finally, it deals briefly with proving bounder correctness theorems. The community book tau-bounders/elementary-bounders contains bounders for various elementary functions including [+], [*], [/], [floor], [mod], [logand], [lognot], [logior], [logorc1], [logeqv], [logxor], and [ash]. You might look at or include this book to see more example theorems, to see how proofs of such theorems are managed, and to experiment with their effects on proving theorems involving arithmetic over finite or half-finite intervals. A bounder correctness theorem establishes that bounder-fn is a ``bounder'' for the function fn. That means that when trying to compute a tau for a call of fn (or, in the case of Form 2, for the nth component of the multiple-value vector returned by a call of fn) the tau system can call bounder-fn on the intervals containing certain arguments of fn. Let us start with an example. Let fn be the addition function, + (actually, [binary-+]). Consider the target term (+ x y) and contemplate the question: if you know intervals containing x and y, say intx and inty respectively, what is an interval containing their sum? The answer is pretty easy to state in English: the domain of the answer interval is the less restrictive of the domains of intx and inty. The lower bound of the answer interval is the sum of the lower bounds of intx and inty, and the lower relation is the stronger of the lower relations of intx and inty. Analogous comments define the upper bound and relation of the answer interval. So for example, if x is an INTEGERP such that 0 <= x <= 10 and y is a RATIONALP such that 0 < y <= 20, then (+ x y) is a RATIONALP such that 0 < (+ x y) <= 30. Defining this precisely is more tedious than describing it in English because one must make precise the notions of ``less restrictive'' domains, ``weaker'' relations, and the possibility that either or both of the bounds could be ``infinite.'' But we can easily imagine defining the function bounder-for-+ that returns the answer interval described, given intx and inty. Then the following Bounder Form 1 formula establishes the correctness of bounder-for-+ and allows the tau system to use it to produce bounds in the tau computed for +-expressions: (implies (and (tau-intervalp intx) (tau-intervalp inty) (in-tau-intervalp x intx) (in-tau-intervalp y inty)) (and (tau-intervalp (bounder-for-+ intx inty)) (in-tau-intervalp (+ x y) (bounder-for-+ intx inty)))) For example, suppose we have a formula with the following hypotheses (and (integerp a) (<= 0 a) (<= a 10) (rationalp b) (< 0 b) (<= b 20)) and suppose the tau system encounters the term (+ a b). When the term is enountered, the tau for a would include an INTEGERP interval such that 0 <= a <= 10 and the tau for b would include a RATIONALP interval such that 0 < b <= 20. In its most primitive configuration, the tau system would only know that the tau for (+ a b) includes the recognizer RATIONALP (and all that it is known to imply). But after the bounder theorem above is proved and available as a :tau-system rule the tau system would infer that (+ a b) was in the RATIONALP interval such that 0 < (+ a b) <= 30. Thus, by defining bounder functions and proving them correct the user can give the tau system the ability to compute the bounds on function calls as a function of the known bounds on their actuals. It is sometimes useful to restrict the domains of the intervals to be considered. For example, in bounding *-expressions it is simplifying to restrict one's attention to intervals over the integers or rationals (and thus exclude the complex rationals so one need not think about the getting negative bounds by multiplying two ``positive'' complex rationals or how to ``round up'' from complex bounds to the rationals required by our intervals). If we were to define bounder-for-* so that it works correctly to bound *-expressions, but only for integer or rational arguments, its correctness theorem would be: (implies (and (tau-intervalp intx) ; (a) (tau-intervalp inty) (or (equal (tau-interval-dom intx) 'INTEGERP) ; (b) (equal (tau-interval-dom intx) 'RATIONALP)) (or (equal (tau-interval-dom inty) 'INTEGERP) (equal (tau-interval-dom inty) 'RATIONALP)) (in-tau-intervalp x intx) ; (c) (in-tau-intervalp y inty)) (and (tau-intervalp (bounder-for-* intx inty)) ; (d) (in-tau-intervalp (* x y) ; (e) (bounder-for-* intx inty)))) In this case, bounder-for-* would be applied to the intervals for x and y only if those intervals were over the integers or the rationals. The above theorem for bounder-for-* begins to suggest the general form of a bounder theorem and we will use it to explain the general form. The hypotheses of a bounder theorem must be a conjunction and the conjuncts must be partitionable into three parts, (a), (b), and (c). The conclusion, must be a conjunction, must contain at least two conjuncts, (d) and (e), and is allowed to contain others that are simply ignored for purposes of bounders. (See the note below about why we allow but ignore additional conjuncts in the conclusion.) Part (a) introduces some distinct ``interval variables,'' here called ``ivars,'' that are known to denote intervals; for the example above, the ivars are intx and inty. Each hypothesis in part (a) is of the form (TAU-INTERVALP ivar). Part (b) allows us to restrict the domains of some of the intervals. Each hypothesis in part (b) must be a disjunction and each of the disjuncts must be of the form (EQUAL (TAU-INTERVAL-DOM ivar) 'dom), where ivar is one of the interval variables and dom is one of INTEGERP, RATIONALP, ACL2-NUMBERP, or NIL. It is not necessary to restrict every interval variable. Indeed, part (b) may be empty, as in the theorem for bounder-for-+ above. Part (c) consists of a set of (IN-TAU-INTERVALP avar ivar) hypotheses where each avar is a variable and no two hypotheses in part (c) use the same avar or ivar. We call the set of all such avar the ``actual variables'' or ``avars.'' The avars and ivars must be distinct. Part (c) sets up a correspondence between the avars and the ivars, each avar is in an interval denoted by one ivar. Part (d) introduces the name of the bounder function, here bounder-for-*, and the order of its ivar arguments. We see that bounder-for-* takes two arguments and they correspond, in order, to the intervals containing x and y. Part (d) also establishes that the bounder function always returns an interval under hypotheses (a), (b), and (c). Note that it is sometimes useful to return the ``universal interval'' (one that contains everything) if you don't want to compute a better interval for some case; see [tau-intervalp] or [in-tau-intervalp]. Part (e) introduces the name of the function being bounded, here *, and the order of its arguments. It establishes that the function being bounded really is bounded by the interval computed by the bounder function. In general, the function being bounded may take additional arguments. It is possible that the function being bounded takes some arguments that do not affect the bounds of its output. Thus, parts (c) and (e) together establish a mapping between the actuals of a call of the function being bounded and the intervals to be supplied to the bounder. The parts identified above may be presented in any order and the literals constituting those parts may be mingled. Thus, for example, here is another version of the theorem above that generates the same bounding information for the tau system. In this version, the hypotheses and conclusions are rearranged, bounder-for-* takes its arguments in the opposite order, and the theorem includes an additional conclusion. (implies (and (tau-intervalp intx) ; (a) (or (equal (tau-interval-dom intx) 'INTEGERP) ; (b) (equal (tau-interval-dom intx) 'RATIONALP)) (in-tau-intervalp x intx) ; (c) (tau-intervalp inty) ; (a) (or (equal (tau-interval-dom inty) 'INTEGERP) ; (b) (equal (tau-interval-dom inty) 'RATIONALP)) (in-tau-intervalp y inty)) (and (in-tau-intervalp (* x y) ; (e) (bounder-for-* inty intx)) (tau-intervalp (bounder-for-* inty intx)) ; (d))) (or (equal (tau-interval-dom (bounder-for-* inty intx)) 'INTEGERP) (equal (tau-interval-dom (bounder-for-* inty intx)) 'RATIONALP)) Note on why bounder forms allow additional conjuncts in the conclusion: It is often the case that one creates bounders by composing other bounders. To prove compositional bounds correct one must often prove more than the mere correctness of the components. For example, one might need to prove that the domain of the new bounding interval is INTEGERP or otherwise restricted. We allow such ``unnecessary'' conclusions simply to save the user the burden of stating multiple theorems. An Illustration of Bounder Form 2: Suppose (quad i) is defined so that truncates the integer i to the largest multiple of 4 weakly below i and, additionally, returns the remainder. For example, (quad 26) returns (mv 24 2). Then here are bounders for each of its return values: (defun quad-bounds-0 (i) (cond ((and (tau-interval-lo i) (<= 0 (tau-interval-lo i))) (make-tau-interval 'integerp nil 0 nil (tau-interval-hi i))) (t (make-tau-interval nil nil nil nil nil)))) (defun quad-bounds-1 (i) (cond ((and (tau-interval-lo i) (<= 0 (tau-interval-lo i))) (make-tau-interval 'integerp nil 0 nil 3)) (t (make-tau-interval nil nil nil nil nil)))) Note that the bounders assume i is an INTEGERP and return the universal interval when i is not a natural. As noted in the discussion below about how to prove bounder correctness theorems, proving these bounders correct will require an arithmetic book, e.g., (include-book \"arithmetic-5/top\" :dir :system) Here then are two bounder correctness theorems of Form 2: (defthm quad-bounds-0-correct (implies (and (tau-intervalp i) (equal (tau-interval-dom i) 'INTEGERP) (in-tau-intervalp x i)) (and (tau-intervalp (quad-bounds-0 i)) (in-tau-intervalp (mv-nth 0 (quad x)) (quad-bounds-0 i)))) :rule-classes :tau-system) (defthm quad-bounds-1-correct (implies (and (tau-intervalp i) (equal (tau-interval-dom i) 'INTEGERP) (in-tau-intervalp x i)) (and (tau-intervalp (quad-bounds-1 i)) (in-tau-intervalp (mv-nth 1 (quad x)) (quad-bounds-1 i)))) :rule-classes :tau-system) As noted above, if these bounders are to be used in constructing other bounders, we might include (in the first theorem) an additional concluding conjunct, such as (equal (tau-interval-dom (quad-bounds-0 i)) 'INTEGERP) so that we can keep quad-bounds-0 disabled to allow us to use quad-bounds-0-correct as a :rewrite or other rule and still relieve hypotheses about the domain of the interval it produces. These hypotheses would arise if some other verified bounder was called on the produced interval. In addition, as noted below, we might replace the :rule-classes above with :rule-classes ((:rewrite) (:forward-chaining :trigger-terms ((quad-bounds-0 i)))) Since the theorem is being stored as some kind of rule and since it satisfies the Bounder Form 2 shape, it will additionally be stored as a :tau-system rule. Note on proving bounder theorems: Proving bounder theorems is just like proving any other arithmetic theorem and you will need whatever libraries are appropriate for the problem domain you are working in. Do not expect the tau system to be of much use in proving bounder theorems. A typical bounder theorem might require you to prove a subgoal like (< (fn x y) (g (tau-interval-hi int1) int2)). But tau deals with inequalities relating terms to constants, e.g., (< ... 16). A bounder theorem is a sort of ``metatheorem'' about how to construct bounded intervals from other bounded intervals. So when you undertake to define a bounder and prove it correct, go into the project with your eyes open! But bounder functions can be broadly divided into two classes, those defined in terms of arithmetic on the interval bounds and those defined in terms of other bounders. For example, given that (LOGXOR x y) = (LOGNOT (LOGEQV x y)) an interval for bounding LOGXOR can be constructed by composing the constructions of intervals for LOGEQV and LOGNOT. So some bounder correctness proofs will involve direct manipulation of arithmetic inequalities and others might involve appeal to the correctness of other bounders, depending on how the new bounder is defined. Regardless of which style of bounder we are dealing with, we have found it useful to prove the basic theorems relating the tau interval accessors to [make-tau-interval], e.g., (equal (tau-interval-dom (make-tau-interval dom lo-rel lo hi-rel hi)) dom) and then disable those functions to avoid seeing excessive cars and cdrs. When dealing with bounders defined in the direct, arithmetic style, we tend to keep [tau-intervalp] and [in-tau-intervalp] enabled so they unfold and expose the algebra. When dealing with bounders defined compositionally in terms of other verified bounders, we tend to keep [tau-intervalp] and [in-tau-intervalp] disabled so we can rely on the previously proved bounder theorems as rewrite and forward chaining rules. Note that this last remark means that when you prove bounder correctness theorems you should include corollaries that are useful :rewrite and possibly :forward-chaining rules if you anticipate using that bounder in more complex ones. We tend to trigger the forward chaining with the bounder expression itself, rather than one of the hypotheses. For example in the rule above for bounder-for-* we would include (:forward-chaining :trigger-terms ((tau-bounder-expt2 int2))) and let the in-tau-intervalp hypotheses select the free variables x and y.") (BREAK$ (ERRORS ACL2-BUILT-INS) "Cause an immediate Lisp break ACL2 users are generally advised to avoid breaking into raw Lisp. Advanced users may, on occasion, see the need to do so. Evaluating (break$) will have that effect. (Exception: break$ is disabled after evaluation of (set-debugger-enable :never); see [set-debugger-enable].) Break$ returns nil. Function: (defun break$ nil (declare (xargs :guard t)) nil)") (BREAK-LEMMA (BREAK-REWRITE) "A quick introduction to breaking rewrite rules in ACL2 Example: :brr t ; if you haven't done that yet :monitor (:rewrite lemma12) t ; to install a break point on the ; rule named (:rewrite lemma12) ACL2 does not support Nqthm's break-lemma but supports a very similar and more powerful break facility. Suppose some proof is failing; apparently some particular rule is not being used and you wish to learn why. Then you need the ACL2 [break-rewrite] facility. See [break-rewrite] and all of its associated :[doc] topics for details. The following basic steps are required. (1) To enable the ``break rewrite'' feature, you must first execute ACL2 !>:brr t at the top-level of ACL2. Equivalently, evaluate (brr t). [Break-rewrite] stays enabled until you disable it with (brr nil). When [break-rewrite] is enabled the ACL2 rewriter will run slower than normal but you will be able to [monitor] the attempts to apply specified rules. (2) Decide what [rune]s (see [rune]) you wish to [monitor]. For example, you might want to know why (:rewrite lemma12 . 2) is not being used in the attempted proof. That, by the way, is the name of the second rewrite rule generated from the event named lemma12. The command ACL2 !>:monitor (:rewrite lemma12 . 2) t will install an ``unconditional'' break point on that rule. The ``t'' at the end of the command means it is unconditional, i.e., a break will occur every time the rule is tried. ACL2 supports conditional breaks also, in which case the t is replaced by an expression that evaluates to non-nil when you wish for a break to occur. See [monitor]. The above keyword command is, of course, equivalent to ACL2 !>(monitor '(:rewrite lemma12 . 2) t) which you may also type. You may install breaks on as many rules as you wish. You must use [monitor] on each rule. You may also change the break condition on a rule with [monitor]. Use [unmonitor] (see [unmonitor]) to remove a rule from the list of [monitor]ed rules. (3) Then try the proof again. When a [monitor]ed rule is tried by the rewriter you will enter an interactive break, called [break-rewrite]. See [break-rewrite] for a detailed description. Very simply, [break-rewrite] lets you inspect the context of the attempted application both before and after the attempt. When [break-rewrite] is entered it will print out the ``target'' term being rewritten. If you type :go [break-rewrite] will try the rule and then exit, telling you (a) whether the rule was applied, (b) if so, how the target was rewritten, and (c) if not, why the rule failed. There are many other commands. See [brr-commands]. (4) When you have finished using the [break-rewrite] feature you should disable it to speed up the rewriter. You can disable it with ACL2 !>:brr nil The list of [monitor]ed rules and their break conditions persists but is ignored. If you enable [break-rewrite] later, the list of [monitor]ed rules will be displayed and will be used again by rewrite. You should disable the [break-rewrite] feature whenever you are not intending to use it, even if the list of [monitor]ed rules is empty, because the rewriter is slowed down as long as [break-rewrite] is enabled. If you get a stack overflow, see [cw-gstack].") (BREAK-ON-ERROR (TRACE ACL2-BUILT-INS) "Break when encountering a hard or soft error caused by ACL2 General forms: (break-on-error t) ; installs a trace causing a continuable error (break) ; when an error is invoked by ACL2. (break-on-error) ; same as above (break-on-error :all) ; same as above, but even when inside the prover (break-on-error nil) ; uninstall any above trace (Break-on-error) generates a suitable trace of error functions. Evaluate (trace$) after (break-on-error) if you want to see the specific trace forms (which you can modify and then submit directly to trace$, if you wish). This [trace] should cause entry to the Lisp debugger whenever ACL2 calls its error routines, except for certain errors when inside the theorem prover, and also at those times if option :all is supplied. NOTE: For technical reasons, you may see some error messages more than once. Finally, note that you are welcome to define your own version of break-on-error by modifying a copy of the source definition (search for ``(defmacro break-on-error'' in ACL2 source file other-events.lisp). Please feel free to send your version of break-on-error to the ACL2 implementors, for possible inclusion into ACL2. Break-on-error is implmented using ACL2 [trace$]. See [trace!] if you want an explanation of the ``TTAG NOTE'' that is printed. The argument, if supplied, is evaluated and must evaluate to t, nil, or :all. Also see [set-debugger-enable] for how to get raw-Lisp backtrace information when an error occurs as a result of break-on-error, or even of a raw Lisp error, by calling set-debugger-enable with argument :bt, :bt-break, or :break-bt. Note that for ACL2 errors (as opposed to raw Lisp errors), i.e. errors affected by break-on-error, all three of those keyword values are treated equivalently (and, all are ignored for non-ANSI GCL; see [set-debugger-enable]).") (BREAK-REWRITE (DEBUGGING) "The read-eval-print loop entered to [monitor] rules ACL2 allows the user to [monitor] the application of [rewrite], [definition], and [linear] rules. When [monitor]ed rules are about to be tried by the rewriter, an interactive break occurs and the user is allowed to watch and, in a limited sense, control the attempt to apply the rule. This interactive loop, which is technically just a call of the standard top-level ACL2 read-eval-print loop, [ld], on a ``[wormhole] [state]'' (see [wormhole]), is called ``break-rewrite.'' While in break-rewrite, certain keyword commands are available for accessing information about the context in which the lemma is being tried. These keywords are called break-rewrite ``commands.'' Also see [dmr] (Dynamically Monitor Rewrites) for a related utility, which allows you to watch progress of the rewriter in real time. To abort from inside break-rewrite at any time, execute For further information, see the related :[doc] topics listed below. As explained in the documentation for [monitor], it is possible to cause the ACL2 rewriter to [monitor] the attempted application of selected rules. When such a rule is about to be tried, the rewriter evaluates its break condition and if the result is non-nil, break-rewrite is entered. Break-rewrite permits the user to inspect the current [state] by evaluating break-rewrite commands. Type :help in break-rewrite to see what the break-rewrite commands are. However, break-rewrite is actually just a call of the general ACL2 read-eval-print loop, [ld], on a certain [state] and the break-rewrite commands are simply aliases provided by ld-keyword-aliases [table] (see [ld-keyword-aliases]). See [ld] for details about this read-eval-print loop. Thus, with a few exceptions, anything you can do at the ACL2 top-level can be done within break-rewrite. For example, you can evaluate arbitrary expressions, use the keyword command hack, access [documentation], print [events], and even define functions and prove theorems. However, the ``certain [state]'' upon which [ld] was called is a ``[wormhole] [state]'' (see [wormhole]) because break-rewrite is not allowed to have any effect upon the behavior of rewrite. What this means, very roughly but understandably, is that break-rewrite operates on a copy of the [state] being used by rewrite and when break-rewrite exits the [wormhole] closes and the [state] ``produced'' by break-rewrite disappears. Thus, break-rewrite lets you query the state of the rewriter and even do experiments involving proofs, etc., but these experiments have no effect on the ongoing proof attempt. In particular: Note that the output from break-rewrite is sometimes abbreviated by default, such as for the term causing the break. This can be controlled by setting the :term evisc-tuple; see [set-evisc-tuple]. (Another option: use iprinting. See [set-iprint].) But as noted above, if you use set-evisc-tuple from inside the break-rewrite [wormhole], its effect will disappear when you exit the break. So you might want to issue a set-evisc-tuple command from the top level, outside break-rewrite. When you first enter break-rewrite a simple herald is printed such as: (3 Breaking (:rewrite lemma12) on (delta a (+ 1 j)): The integer after the open parenthesis indicates the depth of nested break-rewrite calls. In this discussion we use 3 consistently for this integer. Unless you abort or somehow enter unbalanced parentheses into the script, the entire session at a given depth will be enclosed in balanced parentheses, making it easy to skip over them in Emacs. You then will see the break-rewrite [prompt]: 3 ACL2 !> The leading integer is, again, the depth. Because breaks often occur recursively it is convenient always to know the level with which you are interacting. You may type arbitrary commands as in the top-level ACL2 loop. For example, you might type: 3 ACL2 !>:help or 3 ACL2 !>:pe lemma12 More likely, upon entering break-rewrite you will determine the context of the attempted application. Here are some useful commands: 3 ACL2 >:target ; the term being rewritten 3 ACL2 >:unify-subst ; the unifying substitution 3 ACL2 >:path ; the stack of goals pursued by the rewriter ; starting at the top-level clause being simplified ; and ending with the current application At this point in the interaction the system has not yet tried to apply the [monitor]ed rule. That is, it has not tried to establish the hypotheses, considered the heuristic cost of backchaining, rewritten the right-hand side of the conclusion, etc. When you are ready for it to try the rule you can type one of several different ``proceed'' commands. The basic proceed commands are :ok, :go, and :eval. :ok exits break-rewrite without further interaction. When break-rewrite exits it prints ``3)'', closing the parenthesis that opened the level 3 interaction. :go exits break-rewrite without further interaction, but prints out the result of the application attempt, i.e., whether the application succeeded, if so, what the :target term was rewritten to, and if not why the rule was not applicable. :eval causes break-rewrite to attempt to apply the rule but interaction at this level of break-rewrite resumes when the attempt is complete. When control returns to this level of break-rewrite a message indicating the result of the application attempt (just as in :go) is printed, followed by the [prompt] for additional user input. Generally speaking, :ok and :go are used when the break in question is routine or uninteresting and :eval is used when the break is one that the user anticipates is causing trouble. For example, if you are trying to determine why a lemma isn't being applied to a given term and the :target of the current break-rewrite is the term in question, you would usually :eval the rule and if break-rewrite reports that the rule failed then you are in a position to determine why, for example by carefully inspecting the :[type-alist] of governing assumptions or why some hypothesis of the rule could not be established. It is often the case that when you are in break-rewrite you wish to change the set of [monitor]ed [rune]s. This can be done by using :[monitor] and :[unmonitor] as noted above. For example, you might want to [monitor] a certain rule, say hyp-reliever, just when it is being used while attempting to apply another rule, say main-lemma. Typically then you would [monitor] main-lemma at the ACL2 top-level, start the proof-attempt, and then in the break-rewrite in which main-lemma is about to be tried, you would install a [monitor] on hyp-reliever. If during the ensuing :eval hyp-reliever is broken you will know it is being used under the attempt to apply main-lemma. However, once hyp-reliever is being [monitor]ed it will be [monitor]ed even after main-lemma has been tried. That is, if you let the proof attempt proceed then you may see many other breaks on hyp-reliever, breaks that are not ``under'' the attempt to apply main-lemma. One way to prevent this is to :eval the application of main-lemma and then :[unmonitor] hyp-reliever before exiting. But this case arises so often that ACL2 supports several additional ``flavors'' of proceed commands. :Ok!, :go!, and :eval! are just like their counterparts (:ok, :go, and :eval, respectively), except that while processing the rule that is currently broken no [rune]s are [monitor]ed. When consideration of the current rule is complete, the set of [monitor]ed [rune]s is restored to its original setting. :Ok$, :go$, and :eval$ are similar but take an additional argument which must be a list of [rune]s. An example usage of :eval$ is 3 ACL2 !>:eval$ ((:rewrite hyp-reliever)) These three commands temporarily install unconditional breaks on the [rune]s listed, proceed with the consideration of the currently broken rule, and then restore the set of [monitor]ed rules to its original setting. Thus, there are nine ways to proceed from the initial entry into break-rewrite although we often speak as though there are two, :ok and :eval, and leave the others implicit. We group :go with :ok because in all their flavors they exit break-rewrite without further interaction (at the current level). All the flavors of :eval require further interaction after the rule has been tried. To abort a proof attempt and return to the top-level of ACL2 you may at any time type (a!) followed by a carriage return. If you are not in a raw Lisp break, you may type :a! instead. The utility p! is completely analogous to a! except that it pops up only one [ld] level. If you have just entered the break-rewrite loop, this will pop you out of that loop, back to the proof. See [a!] and see [p!]. We now address ourselves to the post-:eval interaction with break-rewrite. As noted, that interaction begins with break-rewrite's report on the results of applying the rule: whether it worked and either what it produced or why it failed. This information is also printed by certain keyword commands available after :eval, namely :wonp, :rewritten-rhs or (for [linear] rules) :poly-list, and :failure-reason. In addition, by using [brr@] you can obtain this information in the form of ACL2 data objects. This allows the development of more sophisticated ``break conditions''; see [monitor] for examples. In this connection we point out the macro form (ok-if term). See [ok-if]. This command exits break-rewrite if term evaluates to non-nil and otherwise does not exit. Thus it is possible to define macros that provide other kinds of exits from break-rewrite. The only way to exit break-rewrite after :eval is :ok (or, equivalently, the use of [ok-if]). ACL2 users who wish to know more about break-rewrite so that they can develop more convenient ways to [monitor] rules are encouraged to speak to J Moore. The rest of this [documentation] discusses a few implementation details of break-rewrite and may not be interesting to the typical user. There is no ACL2 function named break-rewrite. It is an illusion created by appropriate calls to two functions named brkpt1 and brkpt2. As previously noted, break-rewrite is [ld] operating on a [wormhole] [state]. One might therefore wonder how break-rewrite can apply a rule and then communicate the results back to the rewriter running in the external [state]. The answer is that it cannot. Nothing can be communicated through a [wormhole]. In fact, brkpt1 and brkpt2 are each calls of [ld] running on [wormhole] [state]s. Brkpt1 implements the pre-:eval break-rewrite and brkpt2 implements the post-:eval break-rewrite. The rewriter actually calls brkpt1 before attempting to apply a rule and calls brkpt2 afterwards. In both cases, the rewriter passes into the [wormhole] the relevant information about the current context. Logically brkpt1 and brkpt2 are no-ops and [rewrite] ignores the nil they return. But while control is in them, the execution of [rewrite] is suspended and cannot proceed until the break-rewrite interactions complete. This design causes a certain anomoly that might be troubling. Suppose that inside break-rewrite before :evaling a rule (i.e., in the brkpt1 [wormhole] [state]) you define some function, foo. Suppose then you :eval the rule and eventually control returns to break-rewrite (i.e., to brkpt2 on a [wormhole] [state] with the results of the application in it). You will discover that foo is no longer defined! That is because the [wormhole] [state] created during your pre-:eval interaction is lost when we exit the [wormhole] to resume the proof attempt. The post-:eval [wormhole] [state] is in fact identical to the initial pre-:eval [state] (except for the results of the application) because [rewrite] did not change the external [state] and both [wormhole] [state]s are copies of it. A similar issue occurs with the use of [trace] utilities: all effects of calling [trace$] and [untrace$] are erased when you proceed from a break in the break-rewrite loop. There is a lot more to know about break-rewrite, most of which is fairly easy to learn from looking at the code, since it is all expressed in ACL2. Feel free to ask questions of J Moore. Subtopics [Break-lemma] A quick introduction to breaking rewrite rules in ACL2 [Brr] To enable or disable the breaking of rewrite rules [Brr-commands] [Break-Rewrite] Commands [Brr@] To access context sensitive information within [break-rewrite] [Cw-gstack] Debug a rewriting loop or stack overflow [Dmr] Dynamically monitor rewrites and other prover activity [Monitor] To monitor the attempted application of a rule name [Monitored-runes] Print the [monitor]ed [rune]s and their break conditions [Ok-if] Conditional exit from break-rewrite [Unmonitor] To stop monitoring a rule name [Why-brr] An explanation of why ACL2 has an explicit [brr] mode") (BREAKS (ERRORS) "Common Lisp breaks Example: Broken at PROVE. Type :H for Help. >>:Q ACL2 !> You may interrupt the system by typing various control character sequences. The precise sequences are determined by the host Lisp and operating system environment. For example, in GCL and Allegro Common Lisp, a console interrupt is caused by typing ``ctrl-c''. If, however, the GCL or Allegro is running in an Emacs shell buffer, one must type ``ctrl-c ctrl-c''. If a break occurs, for example because of a bug in ACL2 or a user interrupt, the break will run a Common Lisp read-eval-print loop, not an ACL2 read-eval-print loop. This may not be obvious if the [prompt]s in the two loops are similar. Because you are typing to a Common Lisp evaluator, you must be careful. It is possible to damage your ACL2 state in irreparable ways by executing non-ACL2 Common Lisp. It is even possible to disrupt and render inaccurate the interrupted evaluation of a simple ACL2 expression. For ACL2 built on most host Common Lisps, you will see the string [RAW LISP] in the [prompt] at a break, to emphasize that one is inside a break and hence should quit from the break. For some host Common Lisps, the top-level prompt also contains the string [RAW LISP]. See [prompt] for how to control printing of that string. The most reliable way to return to the ACL2 top level is by executing the following command: ([abort!]). Appropriate cleanup will then be done, which should leave you in an appropriate state. However, you may be able to quit from the break in the normal Lisp manner (as with :q in GCL or CCL, :reset in Allegro CL, and q in CMU CL). If this attempt to quit is successful, it will return you to the innermost ACL2 read-eval-print loop, with appropriate cleanup performed first. Note that if you are within a [brr] environment when the break occurs, quitting from the break will only return you to that environment, not to the top of ACL2's read-eval-print loop.") (BROKEN-LINK (DOCUMENTATION) "Placeholder for link to documentation that resides in the community books You may have attempted to access information about the ACL2 [community-books] while looking at the ACL2 User's Manual, which contains [documentation] only about the ACL2 system, and does not include documentation from the [community-books]. Please point your browser at the {ACL2+Books Manual | http://www.cs.utexas.edu/users/moore/acl2/v7-1/combined-manual/index.html} (or if browsing in [ACL2-Doc], switch to that manual with meta-0 I) to access the desired topic. If you want information about the book where your missing topic is defined, see [broken-link-table]. Subtopics [Broken-link-table] Map [documentation] topics to the community books that define them") (BROKEN-LINK-TABLE (BROKEN-LINK) "Map [documentation] topics to the community books that define them The table below maps topics to book locations that reside only in the ACL2+Books combined manual, not the ACL2 User's Manual. For example, the entry (note-7-1-books \"[books]/doc/relnotes.lisp\") signifies that the topic NOTE-7-1-BOOKS is documented in the community book doc/relnotes.lisp. ((|2. Pre Certify-Book Commands| \"[books]/build/doc.lisp\") (<< \"[books]/misc/total-order.lisp\") (append-without-guard \"[books]/std/lists/flatten.lisp\") (oslib::argv \"[books]/oslib/argv-logic.lisp\") (arith-equivs \"[books]/centaur/misc/arith-equiv-defs.lisp\") (arithmetic \"[books]/doc/top.lisp\") (arithmetic-1 \"[books]/arithmetic/top.lisp\") (arithmetic/natp-posp \"[books]/arithmetic/natp-posp.lisp\") (b* \"[books]/std/util/bstar.lisp\") (bridge \"[books]/centaur/bridge/top.lisp\") (|Building the ACL2+Books Manual| \"[books]/doc/top.lisp\") (cert.pl \"[books]/build/doc.lisp\") (cert_param \"[books]/build/doc.lisp\") (std::defaggregate \"[books]/std/util/defaggregate.lisp\") (defconsts \"[books]/std/util/defconsts.lisp\") (defdata \"[books]/acl2s/defdata/top.lisp\") (define \"[books]/std/util/define.lisp\") (fty::defprod \"[books]/centaur/fty/deftypes.lisp\") (getopt-demo::demo2 \"[books]/centaur/getopt/demo2.lisp\") (do-not-hint \"[books]/tools/do-not.lisp\") (fty::fty \"[books]/centaur/fty/fixtype.lisp\") (getopt \"[books]/centaur/getopt/top.lisp\") (gl \"[books]/centaur/gl/doc.lisp\") (hacker \"[books]/hacking/hacking-xdoc.lisp\") (ihs \"[books]/ihs/ihs-doc-topic.lisp\") (include-raw \"[books]/tools/include-raw.lisp\") (make-flag \"[books]/tools/flag.lisp\") (str::natstr \"[books]/std/strings/decimal.lisp\") (non-parallel-book \"[books]/std/system/non-parallel-book.lisp\") (note-6-4-books \"[books]/doc/relnotes.lisp\") (note-6-5-books \"[books]/doc/relnotes.lisp\") (note-7-0-books \"[books]/doc/relnotes.lisp\") (note-7-1-books \"[books]/doc/relnotes.lisp\") (str::numbers \"[books]/std/strings/top.lisp\") (oslib \"[books]/oslib/top-logic.lisp\") (patbind-the \"[books]/std/util/bstar.lisp\") (str::pretty \"[books]/std/strings/pretty.lisp\") (str::pretty-printing \"[books]/std/strings/pretty.lisp\") (quicklisp \"[books]/centaur/quicklisp/top.lisp\") (satlink::sat-solver-options \"[books]/centaur/satlink/top.lisp\") (satlink \"[books]/centaur/satlink/top.lisp\") (xdoc::save \"[books]/xdoc/topics.lisp\") (set-max-mem \"[books]/centaur/misc/memory-mgmt-logic.lisp\") (spacewalk \"[books]/centaur/misc/spacewalk.lisp\") (std \"[books]/std/top.lisp\") (std/io \"[books]/std/io/top.lisp\") (std/strings \"[books]/std/strings/top.lisp\") (std/util \"[books]/std/util/top.lisp\") (std::strict-list-recognizers \"[books]/std/util/deflist-base.lisp\") (subseq-list \"[books]/std/lists/subseq.lisp\") (unsound-read \"[books]/std/io/unsound-read.lisp\") (untranslate-patterns \"[books]/misc/untranslate-patterns.lisp\") (with-raw-mode \"[books]/hacking/hacking-xdoc.lisp\") (with-redef-allowed \"[books]/hacking/hacking-xdoc.lisp\") (working-with-packages \"[books]/doc/practices.lisp\") (xdoc \"[books]/xdoc/topics.lisp\"))") (BRR (BREAK-REWRITE) "To enable or disable the breaking of rewrite rules Example: :brr t ; enable :brr nil ; disable General Form: (brr flg) where flg evaluates to t or nil. This function modifies [state] so that the attempted application of certain rewrite rules are ``broken.'' ``Brr'' stands for ``break-rewrite'' and can be thought of as a mode with two settings. The normal mode is ``disabled.'' For a more thorough introduction to the break rewrite system see [break-rewrite]. When brr mode is ``enabled'' the ACL2 rewriter monitors the attempts to apply certain rules and advises the user of those attempts by entering an interactive wormhole break. From within this break the user can watch selected application attempts. The user can also interact with the system during brr breaks via [brr-commands]. The rules monitored are selected by using the [monitor] and [unmonitor] commands. It is possible to break a rune ``conditionally'' in the sense that an interactive break will occur only if a specified predicate is true of the environment at the time of the attempted application. See [monitor] and see [unmonitor]. Even if a non-empty set of rules has been selected, no breaks will occur unless brr mode is enabled. Thus, the first time in a session that you wish to monitor a rewrite rule, use :brr t to enable brr mode. Thereafter you may select runes to be monitored with [monitor] and [unmonitor] with the effect that whenever monitored rules are tried (and their break conditions are met) an interactive break will occur. Be advised that when brr mode is enabled the rewriter is somewhat slower than normal. Furthermore, that sluggishness persists even if no runes are monitored. You may regain normal performance --- regardless of what runes are monitored --- by disabling brr mode with :brr nil. Why isn't brr mode disabled automatically when no runes are monitored? More generally, why does ACL2 have brr mode at all? Why not just test whether there are monitored runes? If you care about the answers, see [why-brr]. BRR Mode and Console Interrupts: If the system is operating in brr mode and you break into raw Lisp (as by causing a console interrupt or happening upon a signalled Lisp error; see [breaks]), you can return to the ACL2 top-level, outside any brr environment, by executing ([abort!]). Otherwise, the normal way to quit from such a break (for example :q in GCL, :reset in Allegro CL, and q in CMU CL) will return to the innermost ACL2 read-eval-print loop, which may or may not be the top-level of your ACL2 session! In particular, if the break happens to occur while ACL2 is within the brr environment (in which it is preparing to read [brr-commands]), the abort will merely return to that brr environment. Upon exiting that environment, normal theorem proving is continued (and the brr environment may be entered again in response to subsequent monitored rule applications). Before returning to the brr environment, ACL2 ``cleans up'' from the interrupted brr processing. However, it is not possible (given the current implementation) to clean up perfectly. This may have two side-effects. First, the system may occasionally print the self-explanatory ``Cryptic BRR Message 1'' (or 2), informing you that the system has attempted to recover from an aborted brr environment. Second, it is possible that subsequent brr behavior in that proof will be erroneous because the cleanup was done incorrectly. The moral is that you should not trust what you learn from brr if you have interrupted and aborted brr processing during the proof. These issues do not affect the behavior or soundness of the theorem prover.") (BRR-COMMANDS (BREAK-REWRITE) "[Break-Rewrite] Commands :a! abort to ACL2 top-level :p! pop one level (exits a top-level break-rewrite loop) :target term being rewritten :unify-subst substitution making :lhs equal :target :hyps hypotheses of the rule :hyp i ith hypothesis of the rule :lhs left-hand side of rule's conclusion :rhs right-hand side of rule's conclusion :type-alist type assumptions governing :target :initial-ttree ttree before :eval (see [ttree]) :ancestors negations of backchaining hypotheses being pursued :wonp indicates whether application succeeded (after :eval) :rewritten-rhs rewritten :rhs (after :eval) of a rewrite rule :poly-list list of polynomials (after :eval) of a linear rule, where the leading term of each is enclosed in an extra set of parentheses :final-ttree ttree after :eval (see [ttree]) :failure-reason reason rule failed (after :eval) :path rewriter's path from top clause to :target :frame i ith frame in :path :top top-most frame in :path :btm bottom-most frame in :path :ok exit break :go exit break, printing result :eval try rule and re-enter break afterwards :ok! :ok but no recursive breaks :go! :go but no recursive breaks :eval! :eval but no recursive breaks :ok$ runes :ok with runes monitored during recursion :go$ runes :go with runes monitored during recursion :eval$ runes :eval with runes monitored during recursion :help this message :standard-help :help message from ACL2 top-level [Break-rewrite] is just a call of the standard ACL2 read-eval-print loop, [ld], on a ``[wormhole]'' [state]. Thus, you may execute most commands you might normally execute at the top-level of ACL2. However, all [state] changes you cause from within [break-rewrite] are lost when you exit or :eval the rule. You cannot modify [stobj]s from within the break. See [break-rewrite] for more details and see [ld] for general information about the standard ACL2 read-eval-print loop. Also see [brr@] for a utility that can return a value for many of the keywords above, instead of merely printing to the screen. Note that if you are breaking on a [monitor]ed [linear] rule, several of the commands listed above do not apply: :lhs, :rhs, :initial-ttree, and :final-ttree. Moreover, :rewritten-rhs also does not apply, but instead, :poly-list shows the result of applying the linear lemma as a list of polynomials, implicitly conjoined. The leading term of each polynomial is enclosed in an extra set of parentheses.") (BRR@ (BREAK-REWRITE) "To access context sensitive information within [break-rewrite] Example: (brr@ :target) ; the term being rewritten (brr@ :unify-subst) ; the unifying substitution General Form: (brr@ :symbol) where :symbol is one of the keywords displayed below. This utility may be most useful for system hackers; see [brr-commands] for queries that are more at a user level. In particular, keywords marked below with * probably require an implementor's knowledge of the system to use effectively. They are supported but not well documented. More is said on this topic following the table. :symbol (brr@ :symbol) ------- --------------------- :target the term to be rewritten. This term is an instantiation of the left-hand side of the conclusion of the rewrite-rule being broken. This term is in translated form! Thus, if you are expecting (equal x nil) -- and your expectation is almost right -- you will see (equal x 'nil); similarly, instead of (cadr a) you will see (car (cdr a)). In translated forms, all constants are quoted (even nil, t, strings and numbers) and all macros are expanded. :unify-subst the substitution that, when applied to :target, produces the left-hand side of the rule being broken. This substitution is an alist pairing variable symbols to translated (!) terms. :wonp t or nil indicating whether the rune was successfully applied. (brr@ :wonp) returns nil if evaluated before :EVALing the rule. :rewritten-rhs the result of successfully applying the rewrite rule or else nil if (brr@ :wonp) is nil. The result of successfully applying the rule is always a translated (!) term and is never nil. :poly-list the result of successfully applying the linear rule or else nil if (brr@ :wonp) is nil. This result represents the list of polynomials produced by the rule application. The leading term of each polynomial is enclosed in an extra set of parentheses. :failure-reason some non-nil lisp object indicating why the rule was not applied or else nil. Before the rule is :EVALed, (brr@ :failure-reason) is nil. After :EVALing the rule, (brr@ :failure-reason) is nil if (brr@ :wonp) is t. Rather than document the various non-nil objects returned as the failure reason, we encourage you simply to evaluate (brr@ :failure-reason) in the contexts of interest. Alternatively, study the ACL2 function tilde-@- failure-reason-phrase. :lemma * the rewrite rule being broken. For example, (access rewrite-rule (brr@ :lemma) :lhs) will return the left-hand side of the conclusion of the rule. :type-alist * a display of the type-alist governing :target. Elements on the displayed list are of the form (term type), where term is a term and type describes information about term assumed to hold in the current context. (See also the documentation for type-alist.) The type-alist may be used to determine the current assumptions, e.g., whether A is a CONSP. :ancestors * a stack of frames indicating the backchain history of the current context. The theorem prover is in the process of trying to establish each hypothesis in this stack. Thus, the negation of each hypothesis can be assumed false. Each frame also records the rules on behalf of which this backchaining is being done and the weight (function symbol count) of the hypothesis. All three items are involved in the heuristic for preventing infinite backchaining. Exception: Some frames are ``binding hypotheses'' (equal var term) or (equiv var (double-rewrite term)) that bind variable var to the result of rewriting term. The ACL2 source code has a definition (defrec ancestor ...) that may provide some relevant insight. :initial-ttree * the initial and (after :EVAL) final tag trees, :final-ttree respectively. (Tag trees are low-level data structures that store lemmas used and other information, as documented in topic TTREE.) :gstack * the current goal stack. The gstack is maintained by rewrite and is the data structure printed as the current ``path.'' Thus, any information derivable from the :path brr command is derivable from gstack. For example, from gstack one might determine that the current term is the second hypothesis of a certain rewrite rule. In general brr@-expressions are used in break conditions, the expressions that determine whether interactive breaks occur when [monitor]ed [rune]s are applied. See [monitor]. For example, you might want to break only those attempts in which one particular term is being rewritten or only those attempts in which the binding for the variable a is known to be a [consp]. Such conditions can be expressed using ACL2 system functions and the information provided by brr@. Unfortunately, digging some of this information out of the internal data structures may be awkward or may, at least, require intimate knowledge of the system functions. But since conditional expressions may employ arbitrary functions and macros, we anticipate that a set of convenient primitives will gradually evolve within the ACL2 community. It is to encourage this evolution that brr@ provides access to the *'d data.") (BUILDING-ACL2 (ABOUT-ACL2) "How to build an ACL2 executable To build an ACL2 executable, submit the following command while standing in the main ACL2 directory, where invokes your Lisp executable (default: ccl). make LISP= You should find \"Initialization SUCCEEDED.\" near the end the of the log. Note: There may be ACL2 warnings, for example: \"ACL2 Warning [Skip-proofs] in....\". These may be safely ignored. Note that you will want to certify [books] in order to take full advantage of ACL2. See [books-certification]. See also [hons-enabled].") (BUILT-IN-CLAUSE (RULE-CLASSES) "To build a clause into the simplifier See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. Example: (defthm acl2-count-abl (and (implies (and (true-listp x) (not (equal x nil))) (< (acl2-count (abl x)) (acl2-count x))) (implies (and (true-listp x) (not (equal nil x))) (< (acl2-count (abl x)) (acl2-count x)))) :rule-classes :built-in-clause) A :built-in-clause rule can be built from any formula other than propositional tautologies. Roughly speaking, the system uses the list of built-in clauses as the first method of proof when attacking a new goal. Any goal that is subsumed by a built in clause is proved ``silently.'' ACL2 maintains a set of ``built-in'' clauses that are used to short-circuit certain theorem proving tasks. We discuss this at length below. When a theorem is given the rule class :built-in-clause ACL2 flattens the [implies] and [and] structure of the :[corollary] formula so as to obtain a set of formulas whose conjunction is equivalent to the given corollary. It then converts each of these to clausal form and adds each clause to the set of built-in clauses. The example above (regardless of the definition of abl) will build in two clauses, {(not (true-listp x)) (equal x nil) (< (acl2-count (abl x)) (acl2-count x))} and {(not (true-listp x)) (equal nil x) (< (acl2-count (abl x)) (acl2-count x))}. We now give more background. Recall that a clause is a set of terms, implicitly representing the disjunction of the terms. Clause c1 is ``subsumed'' by clause c2 if some instance of c2 is a subset c1. For example, let c1 be {(not (consp l)) (equal a (car l)) (< (acl2-count (cdr l)) (acl2-count l))}. Then c1 is subsumed by c2, shown below, {(not (consp x)) ; second term omitted here (< (acl2-count (cdr x)) (acl2-count x))} because we can instantiate x in c2 with l to obtain a subset of c1. Observe that c1 is the clausal form of (implies (and (consp l) (not (equal a (car l)))) (< (acl2-count (cdr l)) (acl2-count l))), c2 is the clausal form of (implies (consp l) (< (acl2-count (cdr l)) (acl2-count l))) and the subsumption property just means that c1 follows trivially from c2 by instantiation. The set of built-in clauses is just a set of known theorems in clausal form. Any formula that is subsumed by a built-in clause is thus a theorem. If the set of built-in theorems is reasonably small, this little theorem prover is fast. ACL2 uses the ``built-in clause check'' in four places: (1) at the top of the iteration in the prover -- thus if a built-in clause is generated as a subgoal it will be recognized when that goal is considered, (2) within the simplifier so that no built-in clause is ever generated by simplification, (3) as a filter on the clauses generated to prove the termination of recursively [defun]'d functions and (4) as a filter on the clauses generated to verify the guards of a function. The latter two uses are the ones that most often motivate an extension to the set of built-in clauses. Frequently a given formalization problem requires the definition of many functions which require virtually identical termination and/or guard proofs. These proofs can be short-circuited by extending the set of built-in clauses to contain the most general forms of the clauses generated by the definitional schemes in use. The attentive user might have noticed that there are some recursive schemes, e.g., recursion by [cdr] after testing [consp], that ACL2 just seems to ``know'' are ok, while for others it generates measure clauses to prove. Actually, it always generates measure clauses but then filters out any that pass the built-in clause check. When ACL2 is initialized, the clause justifying [cdr] recursion after a [consp] test is added to the set of built-in clauses. (That clause is c2 above.) Note that only a subsumption check is made; no rewriting or simplification is done. Thus, if we want the system to ``know'' that [cdr] recursion is ok after a negative [atom] test (which, by the definition of [atom], is the same as a [consp] test), we have to build in a second clause. The subsumption algorithm does not ``know'' about commutative functions. Thus, for predictability, we have built in commuted versions of each clause involving commutative functions. For example, we build in both {(not (integerp x)) (< 0 x) (= x 0) (< (acl2-count (+ -1 x)) (acl2-count x))} and the commuted version {(not (integerp x)) (< 0 x) (= 0 x) (< (acl2-count (+ -1 x)) (acl2-count x))} so that the user need not worry whether to write (= x 0) or (= 0 x) in definitions. :built-in-clause rules added by the user can be enabled and disabled.") (BUTLAST (LISTS ACL2-BUILT-INS) "All but a final segment of a list (Butlast l n) is the list obtained by removing the last n elements from the true list l. The following is a theorem (though it takes some effort, including lemmas, to get ACL2 to prove it). (implies (and (integerp n) (<= 0 n) (true-listp l)) (equal (length (butlast l n)) (if (< n (length l)) (- (length l) n) 0))) For related functions, see [take] and see [nthcdr]. The [guard] for (butlast l n) requires that n is a nonnegative integer and lst is a true list. Butlast is a Common Lisp function. See any Common Lisp documentation for more information. Note: In Common Lisp the second argument of butlast is optional, but in ACL2 it is required. Function: (defun butlast (lst n) (declare (xargs :guard (and (true-listp lst) (integerp n) (<= 0 n)))) (let ((lng (len lst)) (n (nfix n))) (if (<= lng n) nil (take (- lng n) lst))))") (BY (POINTERS) "See [hints] for keyword :by.") (CAAAAR (CONSES ACL2-BUILT-INS) "[car] of the [caaar] See any Common Lisp documentation for details.") (CAAADR (CONSES ACL2-BUILT-INS) "[car] of the [caadr] See any Common Lisp documentation for details.") (CAAAR (CONSES ACL2-BUILT-INS) "[car] of the [caar] See any Common Lisp documentation for details.") (CAADAR (CONSES ACL2-BUILT-INS) "[car] of the [cadar] See any Common Lisp documentation for details.") (CAADDR (CONSES ACL2-BUILT-INS) "[car] of the [caddr] See any Common Lisp documentation for details.") (CAADR (CONSES ACL2-BUILT-INS) "[car] of the [cadr] See any Common Lisp documentation for details.") (CAAR (CONSES ACL2-BUILT-INS) "[car] of the [car] See any Common Lisp documentation for details.") (CADAAR (CONSES ACL2-BUILT-INS) "[car] of the [cdaar] See any Common Lisp documentation for details.") (CADADR (CONSES ACL2-BUILT-INS) "[car] of the [cdadr] See any Common Lisp documentation for details.") (CADAR (CONSES ACL2-BUILT-INS) "[car] of the [cdar] See any Common Lisp documentation for details.") (CADDAR (CONSES ACL2-BUILT-INS) "[car] of the [cddar] See any Common Lisp documentation for details.") (CADDDR (CONSES ACL2-BUILT-INS) "[car] of the [cdddr] See any Common Lisp documentation for details.") (CADDR (CONSES ACL2-BUILT-INS) "[car] of the [cddr] See any Common Lisp documentation for details.") (CADR (CONSES ACL2-BUILT-INS) "[car] of the [cdr] See any Common Lisp documentation for details.") (CALLING-LD-IN-BAD-CONTEXTS (LD) "Errors caused by calling [ld] in inappropriate contexts The macro [ld] was designed to be called directly in the top-level ACL2 loop, although there may be a few occasions for calling it from functions. ACL2 cannot cope with invocations of [ld] during the process of loading a compiled file for a book, so this is an error. To see how that can happen, consider the following book, where file const.lsp contains the single form (defconst *foo* '(a b)). (in-package \"ACL2\") (defttag t) (progn! (ld \"const.lsp\")) An attempt to certify this book will cause an error, but that particular error can be avoided, as discussed below. If the book is certified, however, with production of a corresponding compiled file (which is the default behavior for [certify-book]), then any subsequent call of [include-book] that loads this compiled file will cause an error. Again, this error is necessary because of how ACL2 is designed; specifically, this [ld] call would interfere with tracking of constant definitions when loading the compiled file for the book. Because including such a book (with a compiled file) causes an error, then as a courtesy to the user, ACL2 arranges that the certification will fail (thus avoiding a surprise later when trying to include the book). The error in that case will look as follows. ACL2 Error in LD: It is illegal to call LD in this context. See DOC calling-ld-in-bad-contexts. If you really think it is OK to avoid this error, you can get around it by setting [state] global variable ld-okp to t: (assign ld-okp t). You can then certify the book in the example above, but you will still not be able to include it with a compiled file.") (CANONICAL-PATHNAME (PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "The true absolute filename, with soft links resolved For the name fname of a file, the form (Canonical-pathname fname nil state) evaluates to a Unix-style absolute filename representing the same file as fname, but generally without any use of soft links in the name. (Below, we explain the qualifier ``generally''.) If however the file indicated by fname does not exist, (canonical-pathname fname nil state) is nil. Thus, canonical-pathname can be used as one would use the raw Lisp function probe-file. The specification of (Canonical-pathname fname dir-p state) when dir-p is not nil is simlar, except that if the specified file exists but is not a directory, then the result is nil. The function canonical-pathname has a guard of t, though the second argument must be the ACL2 [state]. This function is introduced with the following properties. (defthm canonical-pathname-is-idempotent (equal (canonical-pathname (canonical-pathname x dir-p state) dir-p state) (canonical-pathname x dir-p state))) (defthm canonical-pathname-type (or (equal (canonical-pathname x dir-p state) nil) (stringp (canonical-pathname x dir-p state))) :rule-classes :type-prescription) We use the qualifier ``generally'', above, because there is no guarantee that the filename will be canonical without soft links, though we expect this to be true in practice. ACL2 attempts to compute the desired result and then checks that the input and result have the same Common Lisp ``truename''. This check is expected to succeed, but if it fails then the input string is returned unchanged, and to be conservative, the value returned is nil in this case if dir-p is true.") (CAR (CONSES ACL2-BUILT-INS) "Returns the first element of a non-empty list, else nil Completion Axiom (completion-of-car): (equal (car x) (cond ((consp x) (car x)) (t nil))) [Guard]: (or (consp x) (equal x nil)) Notice that in the ACL2 logic, car returns nil for every [atom].") (CASE (BASICS ACL2-BUILT-INS) "Conditional based on if-then-else using [eql] Example Form: (case typ ((:character foo) (open file-name :direction :output)) (bar (open-for-bar file-name)) (otherwise (my-error \"Illegal.\"))) is the same as (cond ((member typ '(:character foo)) (open file-name :direction :output)) ((eql typ 'bar) (open-for-bar file-name)) (t (my-error \"Illegal.\"))) which in turn is the same as (if (member typ '(:character foo)) (open file-name :direction :output) (if (eql typ 'bar) (open-for-bar file-name) (my-error \"Illegal.\"))) Notice the quotations that appear in the example above: '(:character foo) and 'bar. Indeed, a case expression expands to a [cond] expression in which each tested form is quoted, and [eql] is used as the test. General Forms: (case expr (x1 val-1) ... (xk val-k) (otherwise val-k+1)) (case expr (x1 val-1) ... (xk val-k) (t val-k+1)) (case expr (x1 val-1) ... (xk val-k)) where each xi is either [eqlablep] or a true list of [eqlablep] objects. The final otherwise or t case is optional. Case is defined in Common Lisp. See any Common Lisp documentation for more information.") (CASE-MATCH (BASICS ACL2-BUILT-INS) "Pattern matching or destructuring General Form: (case-match x (pat1 dcl1 body1) ... (patk dclk bodyk)) where x is a variable symbol, the pati are structural patterns as described below, the dcli are optional [declare] forms and the bodyi are terms. Return the value(s) of the bodyi corresponding to the first pati matching x, or nil if none matches. Pattern Language: With the few special exceptions described below, matching requires that the [cons] structure of x be isomorphic to that of the pattern, down to the [atom]s in the pattern. Non-symbol [atom]s in the pattern match only themselves. Symbols in the pattern denote variables which match anything and which are bound by a successful match to the corresponding substructure of x. Variables that occur more than once must match the same ([equal]) structure in every occurrence. Exceptions: & Matches anything and is not bound. Repeated occurrences of & in a pattern may match different structures. nil, t, *sym* These symbols cannot be bound and match only their global values. !sym where sym is a symbol that is already bound in the context of the case-match, matches only the current binding of sym. 'obj Matches only itself. Some examples are shown below. Below we show some sample patterns and examples of things they match and do not match. pattern matches non-matches (x y y) (ABC 3 3) (ABC 3 4) ; 3 is not 4 (fn x . rst) (P (A I) B C) (ABC) ; NIL is not (x . rst) (J (A I)) ; rst matches nil ('fn (g x) 3) (FN (H 4) 3) (GN (G X) 3) ; 'fn matches only itself (& t & !x) ((A) T (B) (C)) ; provided x is '(C) Consider the two binary trees that contain three leaves. They might be described as (x . (y . z)) and ((x . y) . z), where x, y, and z are atomic. Suppose we wished to recognize those trees. The following case-match would do: (case-match tree ((x . (y . z)) (and (atom x) (atom y) (atom z))) (((x . y) . z) (and (atom x) (atom y) (atom z)))) Suppose we wished to recognize such trees where all three tips are identical. Suppose further we wish to return the tip if the tree is one of those recognized ones and to return the number 7 otherwise. (case-match tree ((x . (x . x)) (if (atom x) x 7)) (((x . x) . x) (if (atom x) x 7)) (& 7)) Note that case-match returns nil if no pati matches. Thus if we must return 7 in that case, we have to add as the final pattern the &, which always matches anything.") (CASE-SPLIT (REWRITE LINEAR TYPE-PRESCRIPTION DEFINITION META FORWARD-CHAINING) "Like force but immediately splits the top-level goal on the hypothesis Case-split is an variant of [force], which has similar special treatment in hypotheses of rules for the same [rule-classes] as for force (see [force]). This treatment takes place for rule classes :[rewrite], :[linear], :[type-prescription], :[definition], :[meta] (actually in that case, the result of evaluating the hypothesis metafunction call), and :[forward-chaining]. When a hypothesis of a conditional rule (of one of the classes listed above) has the form (case-split hyp) it is logically equivalent to hyp. However it affects the application of the rule generated as follows: if ACL2 attempts to apply the rule but cannot establish that the required instance of hyp holds in the current context, it considers the hypothesis true anyhow, but (assuming all hypotheses are seen to be true and the rule is applied) creates a subgoal in which that instance of hyp is assumed false. (There are exceptions, noted below.) For example, given the rule (defthm p1->p2 (implies (case-split (p1 x)) (p2 x))) then an attempt to prove (implies (p3 x) (p2 (car x))) can give rise to a single subgoal: (IMPLIES (AND (NOT (P1 (CAR X))) (P3 X)) (P2 (CAR X))). Unlike [force], case-split does not delay the ``false case'' to a forcing round but tackles it more or less immediately. The special ``split'' treatment of case-split can be disabled by disabling forcing: see [force] for a discussion of disabling forcing, and also see [disable-forcing]. Finally, we should mention that the rewriter is never willing to split when there is an [if] term present in the goal being simplified. Since [and] terms and [or] terms are merely abbreviations for [if] terms, they also prevent splitting. Note that [if] terms are ultimately eliminated using the ordinary flow of the proof (but see [set-case-split-limitations]), so case-split will ultimately function as intended. When in the proof checker, case-split behaves like force. Function: (defun case-split (x) (declare (xargs :guard t)) x)") (CASE-SPLIT-LIMITATIONS (MISCELLANEOUS) "A list of two ``numbers'' limiting the number of cases produced at once Examples: ACL2 !>(case-split-limitations (w state)) (500 100) With the setting above, clausify will not try subsumption/replacement if more than 500 clauses are involved. Furthermore, the simplifier, as it sweeps over a clause, will inhibit further case splits when it has accumulated 100 subgoals. This inhibition is implemented by continuing to rewrite subsequent literals but not splitting out their cases. This can produce literals containing IFs. See [set-case-split-limitations] for a more general discussion.") (CASES (POINTERS) "See [hints] for keyword :cases.") (CBD (BOOKS-REFERENCE PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "Connected book directory string Example: ACL2 !>:cbd \"/usr/home/smith/\" The connected book directory is a nonempty string that specifies a directory as an absolute pathname. (See [pathname] for a discussion of file naming conventions.) When [include-book] is given a relative book name it elaborates it into a full book name, essentially by appending the connected book directory string to the left and \".lisp\" to the right. (For details, see [book-name] and also see [full-book-name].) Furthermore, [include-book] temporarily sets the connected book directory to the directory string of the resulting full book name so that references to inferior [books] in the same directory may omit the directory. See [set-cbd] for how to set the connected book directory string. General Form: (cbd) This is a macro that expands into a term involving the single free variable [state]. It returns the connected book directory string. The connected book directory (henceforth called the ``cbd'') is used by [include-book] to elaborate the supplied book name into a full book name (see [full-book-name]). For example, if the cbd is \"/usr/home/smith/\" then the elaboration of the [book-name] \"project/task-1/arith\" (to the \".lisp\" extension) is \"/usr/home/smith/project/task-1/arith.lisp\". That [full-book-name] is what [include-book] opens to read the source text for the book. The cbd may be changed using [set-cbd] (see [set-cbd]). Furthermore, during the processing of the [events] in a book, [include-book] sets the cbd to be the directory string of the [full-book-name] of the book. Thus, if the cbd is \"/usr/home/smith/\" then during the processing of [events] by (include-book \"project/task-1/arith\") the cbd will be set to \"/usr/home/smith/project/task-1/\". Note that if \"arith\" recursively includes a sub-book, say \"naturals\", that resides on the same directory, the [include-book] event for it may omit the specification of that directory. For example, \"arith\" might contain the event (include-book \"naturals\"). In general, suppose we have a superior book and several inferior [books] which are included by [events] in the superior book. Any inferior book residing on the same directory as the superior book may be referenced in the superior without specification of the directory. We call this a ``relative'' as opposed to ``absolute'' naming. The use of relative naming is preferred because it permits [books] (and their accompanying inferiors) to be moved between directories while maintaining their [certificate]s and utility. Certified [books] that reference inferiors by absolute file names are unusable (and rendered uncertified) if the inferiors are moved to new directories. Technical Note and a Challenge to Users: After elaborating the book name to a full book name, [include-book] opens a channel to the file to process the [events] in it. In some host Common Lisps, the actual file opened depends upon a notion of ``connected directory'' similar to our connected book directory. Our intention in always elaborating book names into absolute filename strings (see [pathname] for terminology) is to circumvent the sensitivity to the connected directory. But we may have insufficient control over this since the ultimate file naming conventions are determined by the host operating system rather than Common Lisp (though, we do check that the operating system ``appears'' to be one that we ``know'' about). Here is a question, which we'll pose assuming that we have an operating system that calls itself ``Unix.'' Suppose we have a file name, filename, that begins with a slash, e.g., \"/usr/home/smith/...\". Consider two successive invocations of CLTL's (open filename :direction :input) separated only by a change to the operating system's notion of connected directory. Must these two invocations produce streams to the same file? A candidate string might be something like \"/usr/home/smith/*/usr/local/src/foo.lisp\" which includes some operating system-specific special character to mean ``here insert the connected directory'' or, more generally, ``here make the name dependent on some non-ACL2 aspect of the host's state.'' If such ``tricky'' name strings beginning with a slash exist, then we have failed to isolate ACL2 adequately from the operating system's file naming conventions. Once upon a time, ACL2 did not insist that the cbd begin with a slash and that allowed the string \"foo.lisp\" to be tricky because if one were connected to \"/usr/home/smith/\" then with the empty cbd \"foo.lisp\" is a full book name that names the same file as \"/usr/home/smith/foo.lisp\". If the actual file one reads is determined by the operating system's state then it is possible for ACL2 to have two distinct ``full book names'' for the same file, the ``real'' name and the ``tricky'' name. This can cause ACL2 to include the same book twice, not recognizing the second one as redundant.") (CCL-UPDATES (HONS-AND-MEMOIZATION) "Updating Clozure Common Lisp (CCL) Those who use ACL2 built on CCL, especially those who make compute-intensive use of ACL2's [hons-enabled] features, are advised to to stay plugged into the ``trunk'' or ``bleeding edge'' of CCL development. This is very easy to do by typing a few commands to a shell, for example standing above the target directory as follows, provided one has svn working. For linux: rm -rf ccl svn co http://svn.clozure.com/publicsvn/openmcl/trunk/linuxx8664/ccl For an x86 Macintosh running the Darwin OS: svn co http://svn.clozure.com/publicsvn/openmcl/trunk/darwinx8664/ccl To keep up to date, you may find it sufficient to do: cd ccl svn update Whether obtaining a fresh CCL or just updating, finally issue these commands. ./lx86cl64 (rebuild-ccl :full t) (quit) ./lx86cl64 (rebuild-ccl :full t) (quit)") (CDAAAR (CONSES ACL2-BUILT-INS) "[cdr] of the [caaar] See any Common Lisp documentation for details.") (CDAADR (CONSES ACL2-BUILT-INS) "[cdr] of the [caadr] See any Common Lisp documentation for details.") (CDAAR (CONSES ACL2-BUILT-INS) "[cdr] of the [caar] See any Common Lisp documentation for details.") (CDADAR (CONSES ACL2-BUILT-INS) "[cdr] of the [cadar] See any Common Lisp documentation for details.") (CDADDR (CONSES ACL2-BUILT-INS) "[cdr] of the [caddr] See any Common Lisp documentation for details.") (CDADR (CONSES ACL2-BUILT-INS) "[cdr] of the [cadr] See any Common Lisp documentation for details.") (CDAR (CONSES ACL2-BUILT-INS) "[cdr] of the [car] See any Common Lisp documentation for details.") (CDDAAR (CONSES ACL2-BUILT-INS) "[cdr] of the [cdaar] See any Common Lisp documentation for details.") (CDDADR (CONSES ACL2-BUILT-INS) "[cdr] of the [cdadr] See any Common Lisp documentation for details.") (CDDAR (CONSES ACL2-BUILT-INS) "[cdr] of the [cdar] See any Common Lisp documentation for details.") (CDDDAR (CONSES ACL2-BUILT-INS) "[cdr] of the [cddar] See any Common Lisp documentation for details.") (CDDDDR (CONSES ACL2-BUILT-INS) "[cdr] of the [cdddr] See any Common Lisp documentation for details.") (CDDDR (CONSES ACL2-BUILT-INS) "[cdr] of the [cddr] See any Common Lisp documentation for details.") (CDDR (CONSES ACL2-BUILT-INS) "[cdr] of the [cdr] See any Common Lisp documentation for details.") (CDR (CONSES ACL2-BUILT-INS) "Returns the second element of a [cons] pair, else nil Completion Axiom (completion-of-cdr): (equal (cdr x) (cond ((consp x) (cdr x)) (t nil))) [Guard]: (or (consp x) (equal x nil)) Notice that in the ACL2 logic, cdr returns nil for every [atom].") (CEILING (NUMBERS ACL2-BUILT-INS) "Division returning an integer by truncating toward positive infinity Example Forms: ACL2 !>(ceiling 14 3) 5 ACL2 !>(ceiling -14 3) -4 ACL2 !>(ceiling 14 -3) -4 ACL2 !>(ceiling -14 -3) 5 ACL2 !>(ceiling -15 -3) 5 (Ceiling i j) is the result of taking the quotient of i and j and returning the smallest integer that is at least as great as that quotient. For example, the quotient of -14 by 3 is -4 2/3, and the smallest integer at least that great is -4. The [guard] for (ceiling i j) requires that i and j are rational ([real], in ACL2(r)) numbers and j is non-zero. Ceiling is a Common Lisp function. See any Common Lisp documentation for more information. However, note that unlike Common Lisp, the ACL2 ceiling function returns only a single value, Function: (defun ceiling (i j) (declare (xargs :guard (and (real/rationalp i) (real/rationalp j) (not (eql j 0))))) (let* ((q (* i (/ j))) (n (numerator q)) (d (denominator q))) (cond ((= d 1) n) ((>= n 0) (+ (nonnegative-integer-quotient n d) 1)) (t (- (nonnegative-integer-quotient (- n) d))))))") (CERTIFICATE (BOOKS-TOUR) "How a book is known to be admissible and where its [defpkg]s reside A book, say \"arith\", is said to have a ``certificate'' if there is a file named \"arith.cert\". Certificates are created by the function [certify-book] and inspected by [include-book]. Check sums are used to help ensure that certificates are legitimate and that the corresponding book has not been modified since certification. But because the file system is insecure and check sums are not perfect it is possible for the inclusion of a book to cause inconsistency even though the book carries an impeccable certificate. The certificate includes the version number of the certifying ACL2. A book is considered uncertified if it is included in an ACL2 with a different [version] number. The presence of a ``valid'' certificate file for a book attests to two things: all of the [events] of the book are admissible in a certain extension of the initial ACL2 logic, and the non-[local] [events] of the book are independent of the [local] ones (see [local-incompatibility]). In addition, the certificate contains the [command]s used to construct the [world] in which certification occurred. Among those [command]s, of course, are the [defpkg]s defining the packages used in the book. When a book is included into a host [world], that [world] is first extended by the [command]s listed in the certificate for the book. Unless that causes an error due to name conflicts, the extension ensures that all the packages used by the book are identically defined in the host [world]. Security: Because the host file system is insecure, there is no way ACL2 can guarantee that the contents of a book remain the same as when its certificate was written. That is, between the time a book is certified and the time it is used, it may be modified. Furthermore, certificates can be counterfeited. Check sums (see [check-sum]) are used to help detect such problems. But check sums provide imperfect security: two different files can have the same check sum. Therefore, from the strictly logical point of view, one must consider even the inclusion of certified [books] as placing a burden on the user: The non-erroneous inclusion of a certified book is consistency preserving provided (a) the objects read by [include-book] from the certificate were the objects written there by a [certify-book] and (b) the forms read by [include-book] from the book itself are the forms read by the corresponding [certify-book]. We say that a given execution of [include-book] is ``certified'' if a certificate file for the book is present and well-formed and the check sum information contained within it supports the conclusion that the [events] read by the [include-book] are the ones checked by [certify-book]. When an uncertified [include-book] occurs, warnings are printed or errors are caused. But even if no warning is printed, you must accept burdens (a) and (b) if you use [books]. These burdens are easier to live with if you protect your [books] so that other users cannot write to them, you abstain from running concurrent ACL2 jobs, and you abstain from counterfeiting certificates. But even on a single user uniprocessor, you can shoot yourself in the foot by using the ACL2 [io] primitives to fabricate an inconsistent book and the corresponding certificate. Note that part (a) of the burden described above implies, in particular, that there are no guarantees when a certificate is copied. When [books] are renamed (as by copying them), it is recommended that their certificates be removed and the [books] be recertified. The expectation is that recertification will go through without a hitch if relative [pathname]s are used. See [pathname], which is not on the guided tour. Certificates essentially contain two parts, a [portcullis] and a [keep]. There is a third part, an expansion-alist, in order to record expansions if [make-event] has been used, but the user need not be concerned with that level of detail. See [portcullis] to continue the guided tour through [books]. Subtopics [Check-sum] Assigning ``often unique'' integers to files and objects") (CERTIFY-BOOK (BOOKS-REFERENCE BOOKS-TOUR) "How to produce a [certificate] for a book Examples: (certify-book \"my-arith\") ; certify in a world with 0 commands (certify-book \"my-arith\" 3) ; ... in a world with 3 commands (certify-book \"my-arith\" ?) ; ... in a world without checking the ; number of commands (certify-book \"my-arith\" 0 nil) ; ... without compilation (certify-book \"my-arith\" 0 t) ; ... with compilation (default) (certify-book \"my-arith\" 0 t :ttags (foo)) ; ... allowing trust tag (ttag) foo (certify-book \"my-arith\" 0 t :ttags :all) ; ... allowing all trust tags (ttags) (certify-book \"my-arith\" t) ; ... from world of old certificate (certify-book \"my-arith\" 0 nil :acl2x t) ; ... writing or reading a .acl2x file General Form: (certify-book book-name k ; [default 0] compile-flg ; [default t] :defaxioms-okp t/nil ; [default nil] :skip-proofs-okp t/nil ; [default nil] :ttags ttags ; [default nil] :acl2x t/nil ; [default nil] :ttagsx ttags ; [default nil] :pcert pcert ; [default nil] :write-port t/nil ; [default t unless pcert is non-nil] ) where book-name is a book name (see [book-name]), k is used to indicate your approval of the ``certification [world],'' and compile-flg can control whether the book is to be compiled. The defaults for compile-flg, skip-proofs-okp, acl2x, write-port, and pcert can be affected by environment variables. All of these arguments are described in detail below, except for :pcert. (We assume below that the value of :pcert is nil (and environment variable ACL2_PCERT_ARG is unset or the empty string). For a discussion of this argument, see [provisional-certification].) Certification occurs in some logical [world], called the ``certification [world].'' That [world] must contain the [defpkg]s needed to read and execute the forms in the book. The [command]s necessary to recreate that [world] from the ACL2 initial [world] are called the ``[portcullis] commands,'' and will be copied into the [certificate] created for the book. Those [command]s will be re-executed whenever the book is included, to ensure that the appropriate packages (and all other names used in the certification [world]) are correctly defined. Note that Step 1 of certify-book will fail if a package mentioned in the book is not defined before attempting the certification, i.e., defined by a portcullis command in the certification world. For example, suppose that your book contains the symbol FOO::X, but the package \"FOO\" is not currently defined. Then an error message will likely complain either about a missing package \"FOO\", or about a symbol FOO::X that is ``not in any of the packages known to ACL2.'' A solution is to define the package \"FOO\", perhaps directly using [defpkg] or by including a book that defines this package, before attempting the certification. The certified book will be more often usable if the certification [world] is kept to a minimal extension of the ACL2 initial [world] (for example, to prevent name clashes with functions defined in other books). Thus, before you call certify-book for the first time on a book, you may wish to get into the initial ACL2 [world] (e.g., with :ubt 1 or just starting a new version of ACL2), [defpkg] the desired packages, and then invoke certify-book. The k argument to certify-book must be either a nonnegative integer or else one of the symbols t or ? in any package. If k is an integer, then it must be the number of [command]s that have been executed after the initial ACL2 [world] to create the [world] in which certify-book was called. One way to obtain this number is by doing :pbt :start to see all the [command]s back to the first one. If k is t (or any symbol whose [symbol-name] is \"T\"), it means that certify-book should use the same [world] used in the last certification of this book. K may have such a value only if you call certify-book in the initial ACL2 [world] and there is a [certificate] on file for the book being certified. (Of course, the [certificate] is probably invalid.) In this case, certify-book reads the old [certificate] to obtain the [portcullis] [command]s and executes them to recreate the certification [world]. Finally, k may be ? (or any symbol whose [symbol-name] is \"?\"), in which case there is no check made on the certification world. That is, if k is such a value then no action related to the preceding two paragraphs is performed, which can be a nice convenience but at the cost of eliminating a potentially valuable check that the certification [world] may be as expected. We next describe the meaning of compile-flg and how it defaults. If explicit compilation has been suppressed by (set-compiler-enabled nil state), then compile-flg is coerced to nil; see [compilation]. Otherwise compile-flg may be given the value of t (or :all, which is equivalent to t except during provisional certification; see [provisional-certification]), indicating that the book is to be compiled, or else nil. (Note that compilation initially creates a compiled file with a temporary file name, and then moves that temporary file to the final compiled file name obtained by adding a suitable extension to the book name. Thus, a compiled file will appear atomically in its intended location.) Finally, suppose that compile-flg is not supplied (or is :default). If environment variable ACL2_COMPILE_FLG is defined and not the empty string, then its value should be T, NIL, or ALL after converting to upper case, in which case compile-flg is considered to have value t, nil, or :all (respectively). Otherwise compile-flg defaults to t. Note that the value :all is equivalent to t except for during the Convert procedure of provisional certification; see [provisional-certification]. Two keyword arguments, :defaxioms-okp and :skip-proofs-okp, determine how the system handles the inclusion of [defaxiom] events and [skip-proofs] events, respectively, in the book. The value t allows such events, but prints a warning message. The value nil causes an error if such an event is found. Nil is the default unless keyword argument :acl2x t is provided and state global 'write-acl2x is a cons (see [set-write-ACL2x]), in which case the default is t. The keyword argument :ttags may normally be omitted. A few constructs, used for example if you are building your own system based on ACL2, may require it. See [defttag] for an explanation of this argument. When book B is certified with value t (the default, unless the value used for pcert is non-nil) for keyword argument :write-port, a file B.port is written by certification process. This file contains all of the [portcullis] [command]s for B, i.e., all user commands present in the ACL2 logical [world] at the time certify-book is called. if B.lisp later becomes uncertified, say because [events] from that file or an included book have been edited, then (include-book \"B\") will consult B.port to evaluate forms in that file before evaluating the events in B.lisp. On the other hand, B.port is ignored when including B if B is certified. If you use [guard]s, please note certify-book is executed as though (set-guard-checking nil) has been evaluated; see [set-guard-checking]. If you want guards checked, consider using ld instead, or in addition; see [ld]. For a general discussion of books, see [books]. Certify-book is akin to what we have historically called a ``proveall'': all the forms in the book are ``proved'' to guarantee their admissibility. More precisely, certify-book (1) reads the forms in the book, confirming that the appropriate packages are defined in the certification [world]; (2) does the full admissibility checks on each form (proving termination of recursive functions, proving theorems, etc.), checking as it goes that each form is an embedded event form (see [embedded-event-form]); (3) may roll back the [world] (how far? ~-[] see below) and perform an [include-book] to check for [local] incompatibilities (see [local-incompatibility]); (4) writes a [certificate] recording not only that the book was certified but also recording the [command]s necessary to recreate the certification [world] (so the appropriate packages can be defined when the book is included in other [world]s) and the check sums of all the [books] involved (see [certificate]); (5) compiles the book if so directed (and then loads the object file in that case). The result of executing a certify-book [command] is the creation of a single new event, which is actually an [include-book] event. If you don't want its included [events] in your present [world], simply execute :[ubt] :here afterwards. Technical Remark. Step 3 above mentions rolling the logical [world] back to check for local incompatibilies. For efficiency, this retraction to an initial segment of the the world is skipped if a local event is not encountered as described below; otherwise, the world is rolled back to the point just before the first such event was admitted. For this purpose, a relevant local event is one at the top level of the book or under a sequences of [progn] calls in the book. Here, we include forms generated by [make-event]. But this category does not include local [events] within an [encapsulate] event, since those are ignored in the final processing of the encapsulate event. We also do not consider local events within an [include-book] event. End of Technical Remark. A utility is provided to assist in debugging failures of certify-book; see [redo-flat].) Certify-book requires that the default [defun-mode] (see [default-defun-mode]) be :[logic] when certification is attempted. If the mode is not :[logic], an error is signalled. An error will occur if certify-book has to deal with any uncertified book other than the one on which it was called. For example, if the book being certified includes another book, that sub-book must already have been certified; that is, that sub-book must have a valid [certificate] file. If you have a certified book that has remained unchanged for some time you might well not remember the appropriate [defpkg]s for it, though they are stored in the [certificate] file and (by default) also in the .port file. If you begin to change the book, don't throw away its [certificate] file just because it has become invalid! It is an important historical document until the book is re-certified. More important, don't throw away the .port file, as it will provide the [portcullis] commands when including the book as an uncertified book; see [include-book]. When certify-book is directed to produce a compiled file, it calls the Common Lisp function compile-file on the original source file. This creates a compiled file with an extension known to ACL2, e.g., if the book is named \"my-book\" then the source file is \"my-book.lisp\" and the compiled file under GCL will be \"my-book.o\" while under SBCL it will be \"my-book.fasl\". The compiled file is then loaded. When [include-book] is used later on \"my-book\" it will automatically load the compiled file, provided the compiled file has a later write date than the source file. The only effect of such [compilation] and loading is that the functions defined in the book execute faster. See [guard] for a discussion of the issues, and if you want more details about [books] and compilation, see [book-compiled-file]. When certify-book is directed not to produce a compiled file, it will delete any existing compiled file for the book, so as not to mislead [include-book] into loading the now outdated compiled file. Otherwise, certify-book will create a temporary ``expansion file'' to compile, obtained by appending the string \"@expansion.lsp\" to the end of the book name. Remark: Users may ignore that file, which is automatically deleted unless [state] global variable 'save-expansion-file has been set, presumably by a system developer, to a non-nil value; see [book-compiled-file] for more information about hit issue, including the role of environment variable ACL2_SAVE_EXPANSION. After execution of a certify-book form, the value of [ACL2-defaults-table] is restored to what it was immediately before that certify-book form was executed. See [ACL2-defaults-table]. Those who use the relatively advanced features of trust tags (see [defttag]) and [make-event] may wish to know how to create a [certificate] file that avoids dependence on trust tags that are used only during [make-event] expansion. For this, including documentation of the :acl2x and :ttagsx keyword arguments for certify-book, see [set-write-ACL2x]. This completes the tour through the [documentation] of [books]. Subtopics [Certify-book!] A variant of [certify-book]") (CERTIFY-BOOK! (CERTIFY-BOOK) "A variant of [certify-book] Examples: (certify-book! \"my-arith\" 3) ;Certify in a world with 3 ; commands, starting in a world ; with at least 3 commands. (certify-book! \"my-arith\") ;Certify in the initial world. General Form: (certify-book! book-name k compile-flg) where book-name is a book name (see [book-name]), k is a nonnegative integer used to indicate the ``certification [world],'' and compile-flg indicates whether you wish to compile the (functions in the) book. This [command] is identical to [certify-book], except that the second argument k may not be t in certify-book! and if k exceeds the current [command] number, then an appropriate [ubt!] will be executed first. See [certify-book] and see [ubt!].") (CERTIFYING-BOOKS (POINTERS) "See [books-certification].") (CHANGE (DEFREC ACL2-BUILT-INS) "Mutator macro for [defrec] structures. The change macro is built into ACL2, and allows you to \"modify\" instances of structures that have been introduced with [defrec]. Of course, since ACL2 is applicative, the original structure is not actually changed---instead, a new structure is constructed, copying some fields from the original structure and installing new values for other fields. For instance, suppose we first use [make] to create an employee structure, e.g.,: (defconst *jimmy* (make employee :name \"Jimmy\" :salary 0 :position \"Unpaid Intern\") Then we can use change to mutate this structure, e.g.,: (change employee *jimmy* :salary 300000 :position \"Vice President\") Produces a new employee structure where the name is still \"Jimmy\", but where the salary and position have been updated to 300000 and \"Vice President\", respectively. See [defrec] for more information.") (CHAR (CHARACTERS ACL2-BUILT-INS) "The [nth] element (zero-based) of a string (Char s n) is the nth element of s, zero-based. If n is greater than or equal to the length of s, then char returns nil. (Char s n) has a [guard] that n is a non-negative integer and s is a [stringp]. Char is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun char (s n) (declare (xargs :guard (and (stringp s) (integerp n) (>= n 0) (< n (length s))))) (nth n (coerce s 'list)))") (CHAR-CODE (CHARACTERS NUMBERS ACL2-BUILT-INS) "The numeric code for a given character Completion Axiom (completion-of-char-code): (equal (char-code x) (if (characterp x) (char-code x) 0)) [Guard] for (char-code x): (characterp x) This function maps all non-characters to 0.") (CHAR-DOWNCASE (CHARACTERS ACL2-BUILT-INS) "Turn upper-case [characters] into lower-case [characters] (Char-downcase x) is equal to #\\a when x is #\\A, #\\b when x is #\\B, ..., and #\\z when x is #\\Z, and is x for any other character. The [guard] for char-downcase requires its argument to be a standard character (see [standard-char-p]). Char-downcase is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun char-downcase (x) (declare (xargs :guard (and (characterp x) (standard-char-p x)))) (let ((pair (assoc x '((#\\A . #\\a) (#\\B . #\\b) (#\\C . #\\c) (#\\D . #\\d) (#\\E . #\\e) (#\\F . #\\f) (#\\G . #\\g) (#\\H . #\\h) (#\\I . #\\i) (#\\J . #\\j) (#\\K . #\\k) (#\\L . #\\l) (#\\M . #\\m) (#\\N . #\\n) (#\\O . #\\o) (#\\P . #\\p) (#\\Q . #\\q) (#\\R . #\\r) (#\\S . #\\s) (#\\T . #\\t) (#\\U . #\\u) (#\\V . #\\v) (#\\W . #\\w) (#\\X . #\\x) (#\\Y . #\\y) (#\\Z . #\\z))))) (cond (pair (cdr pair)) ((characterp x) x) (t (code-char 0)))))") (CHAR-EQUAL (CHARACTERS ACL2-BUILT-INS) "Character equality without regard to case For [characters] x and y, (char-equal x y) is true if and only if x and y are the same except perhaps for their case. The [guard] on char-equal requires that its arguments are both standard [characters] (see [standard-char-p]). Char-equal is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun char-equal (x y) (declare (xargs :guard (and (characterp x) (standard-char-p x) (characterp y) (standard-char-p y)))) (eql (char-downcase x) (char-downcase y)))") (CHAR-UPCASE (CHARACTERS ACL2-BUILT-INS) "Turn lower-case [characters] into upper-case [characters] (Char-upcase x) is equal to #\\A when x is #\\a, #\\B when x is #\\b, ..., and #\\Z when x is #\\z, and is x for any other character. The [guard] for char-upcase requires its argument to be a standard character (see [standard-char-p]). Char-upcase is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun char-upcase (x) (declare (xargs :guard (and (characterp x) (standard-char-p x)))) (let ((pair (assoc x '((#\\a . #\\A) (#\\b . #\\B) (#\\c . #\\C) (#\\d . #\\D) (#\\e . #\\E) (#\\f . #\\F) (#\\g . #\\G) (#\\h . #\\H) (#\\i . #\\I) (#\\j . #\\J) (#\\k . #\\K) (#\\l . #\\L) (#\\m . #\\M) (#\\n . #\\N) (#\\o . #\\O) (#\\p . #\\P) (#\\q . #\\Q) (#\\r . #\\R) (#\\s . #\\S) (#\\t . #\\T) (#\\u . #\\U) (#\\v . #\\V) (#\\w . #\\W) (#\\x . #\\X) (#\\y . #\\Y) (#\\z . #\\Z))))) (cond (pair (cdr pair)) ((characterp x) x) (t (code-char 0)))))") (CHAR< (CHARACTERS ACL2-BUILT-INS) "Less-than test for [characters] (char< x y) is true if and only if the character code of x is less than that of y. See [char-code]. The [guard] for char< specifies that its arguments are [characters]. Char< is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun char< (x y) (declare (xargs :guard (and (characterp x) (characterp y)))) (< (char-code x) (char-code y)))") (CHAR<= (CHARACTERS ACL2-BUILT-INS) "Less-than-or-equal test for [characters] (char<= x y) is true if and only if the character code of x is less than or equal to that of y. See [char-code]. The [guard] for char<= specifies that its arguments are [characters]. Char<= is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun char<= (x y) (declare (xargs :guard (and (characterp x) (characterp y)))) (<= (char-code x) (char-code y)))") (CHAR> (CHARACTERS ACL2-BUILT-INS) "Greater-than test for [characters] (char> x y) is true if and only if the character code of x is greater than that of y. See [char-code]. The [guard] for char> specifies that its arguments are [characters]. Char> is a Common Lisp function. See any Common Lisp documentation for more information. Function: > (defun char> (x y) (declare (xargs :guard (and (characterp x) (characterp y)))) (> (char-code x) (char-code y)))") (CHAR>= (CHARACTERS ACL2-BUILT-INS) "Greater-than-or-equal test for [characters] (char>= x y) is true if and only if the character code of x is greater than or equal to that of y. See [char-code]. The [guard] for char>= specifies that its arguments are [characters]. Char>= is a Common Lisp function. See any Common Lisp documentation for more information. Function: => (defun char>= (x y) (declare (xargs :guard (and (characterp x) (characterp y)))) (>= (char-code x) (char-code y)))") (CHARACTER-ALISTP (CHARACTERS ALISTS ACL2-BUILT-INS) "Recognizer for association lists with characters as keys (Character-alistp x) is true if and only if x is a list of pairs of the form (cons key val) where key is a [characterp]. Function: (defun character-alistp (x) (declare (xargs :guard t)) (cond ((atom x) (eq x nil)) (t (and (consp (car x)) (characterp (car (car x))) (character-alistp (cdr x))))))") (CHARACTER-ENCODING (IO) "How bytes are parsed into characters When the Common Lisp reader comes across bytes in a file or at the terminal, they are parsed into characters. The simplest case is when each byte that is read is a standard character (see [standard-char-p]). It is actually quite common that each byte that is read corresponds to a single character. The parsing of bytes into characters is based on a character encoding, that is, a mapping that associates one or more bytes with each legal character. In order to help guarantee the portability of files (including [books]), ACL2 installs a common character encoding for reading files, often known as iso-8859-1 or latin-1. For some host Lisps this character encoding is also used for reading from the terminal; but, sadly, this may not hold for all host Lisps, and may not even be possible for some of them. The use of the above encoding could in principle cause problems if one's editor produces files using an encoding other than iso-8859-1, at least if one uses non-standard characters. In particular, the default Emacs buffer encoding may be utf-8. If your file has non-standard characters, then in Emacs you can evaluate the form (setq save-buffer-coding-system 'iso-8859-1) before saving the buffer into a file. This will happen automatically for users who load distributed file emacs/emacs-acl2.el into their Emacs sessions. For an example of character encodings in action, see the community book books/misc/character-encoding-test.lisp.") (CHARACTER-LISTP (CHARACTERS LISTS ACL2-BUILT-INS) "Recognizer for a true list of characters The predicate character-listp tests whether its argument is a true list of [characters]. Function: (defun character-listp (l) (declare (xargs :guard t)) (cond ((atom l) (equal l nil)) (t (and (characterp (car l)) (character-listp (cdr l))))))") (CHARACTERP (CHARACTERS ACL2-BUILT-INS) "Recognizer for [characters] (characterp x) is true if and only if x is a character.") (CHARACTERS (PROGRAMMING) "Characters in ACL2 and operations on them ACL2 accepts 256 distinct characters, which are the characters obtained by applying the function [code-char] to each integer from 0 to 255. Among these, Common Lisp designates certain ones as standard characters, namely those of the form (code-char n) where n is from 33 to 126, together with #\\Newline and #\\Space. The actual standard characters may be viewed by evaluating the [defconst] *standard-chars*. To be more precise, Common Lisp does not specify the precise relationship between [code-char] and the standard characters. However, we check that the underlying Common Lisp implementation uses a particular relationship that extends the usual ASCII coding of characters. We also check that Space, Tab, Newline, Page, and Rubout correspond to characters with respective [char-code]s 32, 9, 10, 12, and 127. [Code-char] has an inverse, [char-code]. Thus, when [char-code] is applied to an ACL2 character, c, it returns a number n between 0 and 255 inclusive such that (code-char n) = c. The preceding paragraph implies that there is only one ACL2 character with a given character code. CLTL allows for ``attributes'' for characters, which could allow distinct characters with the same code, but ACL2 does not allow this. The Character Reader ACL2 supports the `#\\' notation for characters provided by Common Lisp, with some restrictions. First of all, for every character c, the notation #\\c may be used to denote the character object c. That is, the user may type in this notation and ACL2 will read it as denoting the character object c. In this case, the character immediately following c must be one of the following ``terminating characters'': a Tab, a Newline, a Page character, a space, or one of the characters: \" ' ( ) ; ` , Other than the notation above, ACL2 accepts alternate notation for five characters. #\\Space #\\Tab #\\Newline #\\Page #\\Rubout Again, in each of these cases the next character must be from among the set of ``terminating characters'' described in the single-character case. Our implementation is consistent with IS0-8859, even though we don't provide #\\ syntax for entering characters other than that described above. Finally, we note that it is our intention that any object printed by ACL2's top-level-loop may be read back into ACL2. Please notify the implementors if you find a counterexample to this claim. Subtopics [Alpha-char-p] Recognizer for alphabetic characters [Char] The [nth] element (zero-based) of a string [Char-code] The numeric code for a given character [Char-downcase] Turn upper-case [characters] into lower-case [characters] [Char-equal] Character equality without regard to case [Char-upcase] Turn lower-case [characters] into upper-case [characters] [Char<] Less-than test for [characters] [Char<=] Less-than-or-equal test for [characters] [Char>] Greater-than test for [characters] [Char>=] Greater-than-or-equal test for [characters] [Character-alistp] Recognizer for association lists with characters as keys [Character-listp] Recognizer for a true list of characters [Characterp] Recognizer for [characters] [Code-char] The character corresponding to a given numeric code [Coerce] Coerce a character list to a string and a string to a list [Digit-char-p] The number, if any, corresponding to a given character [Digit-to-char] Map a digit to a character [Explode-atom] Convert any [atom] into a [character-listp] that contains its printed representation, rendering numbers in your choice of print base. [Explode-nonnegative-integer] The list of [characters] in the radix-r form of a number [Lower-case-p] Recognizer for lower case characters [Make-character-list] [coerce] to a list of characters [Standard-char-listp] Recognizer for a true list of standard characters [Standard-char-p] Recognizer for standard characters [Upper-case-p] Recognizer for upper case characters") (CHECK-SUM (CERTIFICATE) "Assigning ``often unique'' integers to files and objects A ``check sum'' is an integer in some fixed range computed from the printed representation of an object, e.g., the sum, modulo 2**32, of the ascii codes of all the [characters] in the printed representation. Ideally, you would like the check sum of an object to be uniquely associated with that object, like a fingerprint. It could then be used as a convenient way to recognize the object in the future: you could remember the check sum (which is relatively small) and when an object is presented to you and alleged to be the special one you could compute its check sum and see if indeed it was. Alas, there are many more objects than check sums (after all, each check sum is an object, and then there's t). So you try to design a check sum algorithm that maps similar looking objects far apart, in the hopes that corruptions and counterfeits --- which appear to be similar to the object --- have different check sums. Nevertheless, the best you can do is a many-to-one map. If an object with a different check sum is presented, you can be positive it is not the special object. But if an object with the same check sum is presented, you have no grounds for positive identification. The basic check sum algorithm in ACL2 is called check-sum-obj, which computes the check sum of an ACL2 object. Roughly speaking, we scan the print representation of the object and, for each character encountered, we multiply the ascii code of the character times its position in the stream (modulo a certain prime) and then add (modulo a certain prime) that into the running sum. This is inaccurate in many senses (for example, we don't always use the ascii code and we see numbers as though they were printed in base 127) but indicates the basic idea. ACL2 uses check sums to increase security in the [books] mechanism; see [certificate].") (CHECKPOINT-FORCED-GOALS (PROOF-TREE) "Cause forcing goals to be checkpointed in proof trees Example forms: (checkpoint-forced-goals t) (checkpoint-forced-goals nil) Also see [proof-tree]. By default, goals are not marked as checkpoints by a proof tree display (as described elsewhere; see [proof-tree]) merely because they [force] some hypotheses, thus possibly contributing to a forcing round. However, some users may want such behavior, which will occur once the command (checkpoint-forced-goals t) has been executed. To return to the default behavior, use the command (checkpoint-forced-goals nil).") (CLAUSE-IDENTIFIER (GOAL-SPEC) "The internal form of a [goal-spec] To each goal-spec, str, there corresponds a clause-identifier produced by (parse-clause-id str). For example, (parse-clause-id \"[2]Subgoal *4.5.6/7.8.9'''\") returns ((2 4 5 6) (7 8 9) . 3). The function string-for-tilde-@-clause-id-phrase inverts parse-clause-id in the sense that given a clause identifier it returns the corresponding goal-spec. As noted in the documentation for [goal-spec], each clause printed in the theorem prover's proof attempt is identified by a name. When these names are represented as strings they are called ``goal specs.'' Such strings are used to specify where in the proof attempt a given hint is to be applied. The function parse-clause-id converts goal-specs into clause identifiers, which are cons-trees containing natural numbers. Examples of goal-specs and their corresponding clause identifiers are shown below. parse-clause-id --> \"Goal\" ((0) NIL . 0) \"Subgoal 3.2.1'\" ((0) (3 2 1) . 1) \"[2]Subgoal *4.5.6/7.8.9'''\" ((2 4 5 6) (7 8 9) . 3) <-- string-for-tilde-@-clause-id-phrase The caar of a clause id specifies the forcing round, the cdar specifies the goal being proved by induction, the cadr specifies the particular subgoal, and the cddr is the number of primes in that subgoal. Internally, the system maintains clause ids, not goal-specs. The system prints clause ids in the form shown by goal-specs. When a goal-spec is used in a hint, it is parsed (before the proof attempt begins) into a clause id. During the proof attempt, the system watches for the clause id and uses the corresponding hint when the id arises. (Because of the expense of creating and garbage collecting a lot of strings, this design is more efficient than the alternative.)") (CLAUSE-PROCESSOR (RULE-CLASSES) "Make or apply a :clause-processor rule (goal-level simplifier) See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. We will introduce clause-processor rules by way of the following example. But note that the clause-processor utility is more general than this example may suggest; for example, the second argument of evl0 in the hypothesis need not be the same as its second argument in the conclusion. ; Example (which we'll return to, below): (defthm correctness-of-note-fact-clause-processor (implies (and (pseudo-term-listp cl) (alistp a) (evl0 (conjoin-clauses (note-fact-clause-processor cl term)) a)) (evl0 (disjoin cl) a)) :rule-classes :clause-processor) We begin this documentation with an introduction, focusing on the example above, and then conclude with a detailed general discussion of clause-processor rules. You might find it most useful simply to look at the examples in community books directory books/clause-processors/; see file Readme.lsp in that directory. Also see [define-trusted-clause-processor] for documentation of an analogous utility that does not require the clause-processor to be proved correct. But please read the present documentation before reading about that utility. Both utilities designate functions as ``clause-processors''. Such functions must be executable --- hence not constrained by virtue of being introduced in the [signature] of an [encapsulate] --- and must respect [stobj] and output arity restrictions. For example, something like (car (mv ...)) is illegal; also see [signature]. INTRODUCTION A :clause-processor rule installs a simplifier at the level of goals, where a goal is represented as a clause: a list of [term]s that is implicitly viewed as a disjunction (the application of [or]). For example, if ACL2 prints a goal in the form (implies (and p q) r), then the clause might be the one-element list containing the internal representation of this term --- (implies (if p q 'nil) r) --- but more likely, the corresponding clause is ((not p) (not q) r). Note that the members of a clause are translated terms; see [term]. For example, they do not contain calls of the macro AND, and constants are quoted. The result of running a clause-processor must be a list of legal clauses; see [meta] for a discussion of translated terms, and for related discussion about ``forbidden'' function symbols, [set-skip-meta-termp-checks]. Note that clause-processor simplifiers are similar to metafunctions, and similar efficiency considerations apply. See [meta], in particular the discussion on how to ``make a metafunction maximally efficient.'' Unlike rules of class :[meta], rules of class :clause-processor must be applied by explicit :clause-processor [hints]; they are not applied automatically (unless by way of computed hints; see [computed-hints]). But :clause-processor rules can be useful in situations for which it is more convenient to code a simplifier that manipulates the entire goal clause rather than individual subterms of terms in the clause. We begin with a simple illustrative example: a clause-processor that assumes an alleged fact (named term in the example) and creates a separate goal to prove that fact. We can extend the hypotheses of the current goal (named cl in the example) with a term by adding the negation of that term to the clause (disjunctive) representation of that goal. So the following returns a list of two clauses: the result of adding term as a hypothesis to the input clause, as just described, and a second clause consisting only of that term. This list of two clauses can be viewed as the conjunction of the first clause and the second clause (where again, each clause is viewed as a disjunction). (defun note-fact-clause-processor (cl term) (declare (xargs :guard t)) ; optional, for better efficiency (list (cons (list 'not term) cl) (list term))) As with :[meta] rules, we need to introduce a suitable evaluator; see [defevaluator] if you want details. Since we expect to reason about the function [not], because of its role in note-fact-clause-processor as defined above, we include NOT in the set of functions known to this evaluator. We also include IF, as is often a good idea. (defevaluator evl0 evl0-list ((not x) (if x y z))) ACL2 can now prove the following theorem automatically. (This is the example displayed at the outset of this [documentation] topic.) Of course, :clause-processor rules about clause-processor functions less trivial than note-fact-clause-processor may require lemmas to be proved first! The function disjoin takes a clause and returns its disjunction (the result of applying [or] to its members), and conjoin-clauses applies disjoin to every element of a given list of clauses and then conjoins (applies AND) to the corresponding list of resulting terms. (defthm correctness-of-note-fact-clause-processor (implies (and (pseudo-term-listp cl) (alistp a) (evl0 (conjoin-clauses (note-fact-clause-processor cl term)) a)) (evl0 (disjoin cl) a)) :rule-classes :clause-processor) Now let us submit a silly but illustrative example theorem to ACL2, to show how a corresponding :clause-processor hint is applied. The hint says to apply the clause-processor function, note-fact-clause-processor, to the current goal clause and a ``user hint'' as the second argument of that function, in this case (equal a a). Thus, a specific variable, clause, is always bound to the current goal clause for the evaluation of the :clause-processor hint, to produce a list of clauses. Since two subgoals are created below, we know that this list contained two clauses. Indeed, these are the clauses returned when note-fact-clause-processor is applied to two arguments: the current clause, which is the one-element list ((equal (car (cons x y)) x)), and the user hint, (equal a a). ACL2 !>(thm (equal (car (cons x y)) x) :hints ((\"Goal\" :clause-processor (note-fact-clause-processor clause '(equal a a))))) [Note: A hint was supplied for our processing of the goal above. Thanks!] We now apply the verified :CLAUSE-PROCESSOR function NOTE-FACT-CLAUSE- PROCESSOR to produce two new subgoals. Subgoal 2 (IMPLIES (EQUAL A A) (EQUAL (CAR (CONS X Y)) X)). But we reduce the conjecture to T, by the :executable-counterpart of IF and the simple :rewrite rule CAR-CONS. Subgoal 1 (EQUAL A A). But we reduce the conjecture to T, by primitive type reasoning. Q.E.D. Summary Form: ( THM ...) Rules: ((:EXECUTABLE-COUNTERPART IF) (:EXECUTABLE-COUNTERPART NOT) (:FAKE-RUNE-FOR-TYPE-SET NIL) (:REWRITE CAR-CONS)) Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) Proof succeeded. ACL2 !> That concludes our introduction to clause-processor rules and hints. We turn now to detailed documentation. DETAILED DOCUMENTATION The [signature] of a clause-processor function, CL-PROC, must have one of the following forms. Here, each st_i is a [stobj] (possibly state) while the other parameters and results are not stobjs (see [stobj]). Note that there need not be input stobjs in [3] --- i.e., k can be 0 --- and even if there are, there need not be output stobjs. [1] ((CL-PROC cl) => cl-list) [2] ((CL-PROC cl hint) => cl-list) [3] ((CL-PROC cl hint st_1 ... st_k) => (mv erp cl-list st_i1 ... st_in)) In [3], we think of the first component of the result as an error flag. Indeed, a proof will instantly abort if that error flag is not nil. We next discuss the legal forms of :clause-processor rules, followed below by a discussion of :clause-processor [hints]. In the discussion below, we use lower-case names to represent specific symbols, for example implies, and we use upper-case names to represent more arbitrary pieces of syntax (which we will describe), for example, CL. If a :[rule-classes] specification includes :clause-processor, then the corresponding term must have the following form. (Additional ``meta-extract'' hypotheses, not shown or discussed below, may be included as desired in order to use facts from the logical [world] to help prove the rule; see [meta-extract] for explanation of this advanced feature.) ; General Form (omitting possible meta-extract hypotheses) (implies (and (pseudo-term-listp CL) (alistp A) (EVL (conjoin-clauses ) B)) (EVL (disjoin CL) A)) Here EVL is a known evaluator; CL and A are distinct non-stobj variables; and is an expression representing the clauses returned by the clause-processor function CL-PROC, whose form depends on the [signature] of that function, as follows. Typically B is A, but it can be any term (useful when generalization is occurring; see the example ``Test generalizing alist'' in community book books/clause-processors/basic-examples.lisp). For cases [1] and [2] above, is of the form (CL-PROC CL) or (CL-PROC CL HINT), respectively, where in the latter case HINT is a non-stobj variable distinct from the variables CL and A. For case [3], is of the form (clauses-result (CL-PROC CL HINT st_1 ... st_k)) where the st_i are the specific stobj names mentioned in [3]. Logically, clauses-result returns the [cadr] if the [car] is NIL, and otherwise (for the error case) returns a list containing the empty (false) clause. So in the non-error case, clauses-result picks out the second result, denoted cl-list in [3] above, and in the error case the implication above trivially holds. In the above theorem, we are asked to prove (EVL (disjoin CL) A) assuming that the conjunction of all clauses produced by the clause processor evaluates to a non-nil value under some alist B. In fact, we can choose B so as to allow us to assume evaluations of the generated clauses over many different alists. This technique is discussed in the community book books/clause-processors/multi-env-trick.lisp, which introduces some macros that may be helpful in accomplishing proofs of this type. The clause-processor function, CL, must have a guard that ACL2 can trivially prove from the hypotheses that the first argument of CL is known to be a pseudo-term-listp and any [stobj] arguments are assumed to satisfy their stobj predicates. Next we specify the legal forms for :clause-processor [hints]. These depend on the signature as described in [1] through [3] above. Below, as above, CL-PROC is the clause-processor function, and references to ``clause'' refer to that exact variable (not, for example, to cl). In each of the three cases, the forms shown for that case are equivalent; in particular, the :function syntax is simply a convenience for the final form in each case. Signature [1], ((cl-proc cl) => cl-list): :clause-processor CL-PROC :clause-processor (:function CL-PROC) :clause-processor (CL-PROC clause) or any term macroexpanding to (CL-PROC clause). Signature [2], ((cl-proc cl hint) => cl-list): :clause-processor (:function CL-PROC :hint HINT) :clause-processor (CL-PROC clause HINT) or any term macroexpanding to (CL-PROC clause HINT), where HINT is any term with at most CLAUSE free. Signature [3], ((CL-PROC cl hint ...) => (mv erp cl-list ...)) :clause-processor (:function CL-PROC :hint HINT) :clause-processor (CL-PROC clause HINT st_1 ... st_k) or any term macroexpanding to (CL-PROC clause HINT st_1 ... st_k), where HINT is any term with at most CLAUSE free. A :clause-processor hint causes the proof to abort if the result returned by evaluating the suitable CL-PROC call, as above, is not a list of clauses, i.e., a list of (translated) [term] lists. The proof also aborts if in case [3] the first (erp) value returned is not nil, in which case erp is used for printing an error message as follows: if it is a string, then that string is printed; but if it is a non-empty true list whose first element is a string, then it is printed as though by (fmt ~@0 (list (cons #\\0 erp)) ...) (see [fmt]). Otherwise, a non-nil erp value causes a generic error message to be printed. If there is no error as above, but the CL-PROC call returns clause list whose single element is equal to the input clause, then the hint is ignored since we are left with the goal with which we started. In that case, the other prover processes are then applied as usual. You can see all current :clause-processor rules by issuing the following command: (print-clause-processor-rules). The following paper discusses ACL2 clause-processors at a high level suitable for a non-ACL2 audience: M. Kaufmann, J S. Moore, S. Ray, and E. Reeber, ``Integrating External Deduction Tools with ACL2.'' Journal of Applied Logic (Special Issue: Empirically Successful Computerized Reasoning), Volume 7, Issue 1, March 2009, pp. 3--25. Also published online (DOI 10.1016/j.jal.2007.07.002). Preliminary version in: Proceedings of the 6th International Workshop on the Implementation of Logics (IWIL 2006) (C. Benzmueller, B. Fischer, and G. Sutcliffe, editors), {CEUR Workshop Proceedings Vol. 212 | http://ceur-ws.org/Vol-212/}, Phnom Penh, Cambodia, pp. 7-26, November 2006. Subtopics [Set-skip-meta-termp-checks] Skip output checks for [meta] functions and [clause-processor]s [Set-skip-meta-termp-checks!] Skip output checks non-[local]ly for [meta] functions and [clause-processor]s") (CLEAR-HASH-TABLES (MEMOIZE) "Deprecated feature Deprecated. Calls [clear-memoize-tables] and then [hons-clear] or [hons-wash], whichever makes sense for the underlying Common Lisp.") (CLEAR-MEMOIZE-STATISTICS (MEMOIZE) "Clears all profiling info displayed by ([memoize-summary]) Logically, this function just returns nil. It clears all profiling info displayed by ([memoize-summary]) Function: (defun clear-memoize-statistics nil (declare (xargs :guard t)) nil)") (CLEAR-MEMOIZE-TABLE (MEMOIZE) "Forget values remembered for the given function This function returns its argument, fn, unchanged. The values memoized for fn are forgotten. Function: (defun clear-memoize-table (fn) (declare (xargs :guard t)) fn)") (CLEAR-MEMOIZE-TABLES (MEMOIZE) "Forget values remembered for all the memoized functions Clear-memoize-tables is a logical no-op. All memoized values are forgotten. It returns nil, invoking [clear-memoize-table] for each memoized function. Function: (defun clear-memoize-tables nil (declare (xargs :guard t)) nil)") (CLOSE-INPUT-CHANNEL (POINTERS) "See [io].") (CLOSE-OUTPUT-CHANNEL (POINTERS) "See [io].") (CLOSE-TRACE-FILE (TRACE) "Stop redirecting trace output to a file General Form: (close-trace-file) ; trace output is no longer redirected to a file Output from [trace$] normally goes to the screen, or more precisely, [standard-co]. It can be redirected to a file; see [open-trace-file]. Use close-trace-file to redirect trace output to [standard-co].") (CODE-CHAR (CHARACTERS NUMBERS ACL2-BUILT-INS) "The character corresponding to a given numeric code Completion Axiom (completion-of-code-char): (equal (code-char x) (if (and (integerp x) (>= x 0) (< x 256)) (code-char x) (code-char 0))) [Guard] for (code-char x): (and (integerp x) (>= x 0) (< x 256)) ACL2 supports 8-bit [characters]. Inputs not between 0 and 255 are treated as 0.") (COERCE (STRINGS CHARACTERS ACL2-BUILT-INS) "Coerce a character list to a string and a string to a list Completion Axiom (completion-of-coerce): (equal (coerce x y) (cond ((equal y 'list) (if (stringp x) (coerce x 'list) nil)) (t (coerce (make-character-list x) 'string)))) [Guard] for (coerce x y): (if (equal y 'list) (stringp x) (if (equal y 'string) (character-listp x) nil)) Also see community book books/misc/fast-coerce.lisp, contributed by Jared Davis, for a version of coerce that may be faster for Common Lisp implementations other than CCL 1.3 or later, if the second argument is 'list (for coercing a string to a list). Logical Note The function coerce can be viewed as the constructor for strings. As discussed in Section 7 of \"{A Precise Description of the ACL2 Logic | http://www.cs.utexas.edu/users/moore/publications/km97a.pdf}\" (Matt Kaufmann and J Moore, April, 1998), a string may be built by coercing its list of characters: for example, \"abc\" is (coerce '(#\\a #\\b #\\c) 'string). More precisely, \"abc\" is an abbreviation for (coerce '(#\\a #\\b #\\c) 'string), where even more pedantically, '(#\\a #\\b #\\c) is an abbreviation for (cons '#\\a (cons '#\\b (cons '#\\c 'nil))).") (COMMAND (HISTORY) "Forms you type at the top-level, but... ...the word ``command'' usually refers to a top-level form whose evaluation produces a new logical [world]. Typical commands are: (defun foo (x) (cons x x)) (defthm consp-foo (consp (foo x))) (defrec pair (hd . tl) nil) The first two forms are examples of commands that are in fact primitive [events]. See [events]. Defrec, on the other hand, is a macro that expands into a [progn] of several primitive [events]. In general, a [world] extending command generates one or more [events]. Both [events] and commands leave landmarks on the [world] that enable us to determine how the given [world] was created from the previous one. Most of your interactions will occur at the command level, i.e., you type commands, you print previous commands, and you undo back through commands. Commands are denoted by command descriptors. See [command-descriptor].") (COMMAND-DESCRIPTOR (HISTORY) "An object describing a particular [command] typed by the user Examples: :max ; the command most recently typed by the user :x ; synonymous with :max (:x -1) ; the command before the most recent one (:x -2) ; the command before that :x-2 ; synonymous with (:x -2) 5 ; the fifth command typed by the user 1 ; the first command typed by the user 0 ; the last command of the system initialization -1 ; the next-to-last initialization command :min ; the first command of the initialization :start ; the last command of the initial ACL2 logical world fn ; the command that introduced the logical name fn (:search (defmacro foo-bar)) ; the first command encountered in a search from :max to ; 0 that either contains defmacro and foo-bar in the ; command form or contains defmacro and foo-bar in some ; event within its block. The recorded [history] of your interactions with the top-level ACL2 [command] loop is marked by the [command]s you typed that changed the logical [world]. Each such [command] generated one or more [events], since the only way for you to change the logical [world] is to execute an event function. See [command] and see [events]. We divide [history] into ``[command] blocks,'' grouping together each [world] changing [command] and its [events]. A ``[command] descriptor'' is an object that can be used to describe a particular [command] in the [history] of the ongoing session. Each [command] is assigned a unique integer called its ``[command] number'' which indicates the [command]'s position in the chronological ordering of all of the [command]s ever executed in this session (including those executed to initialize the system). We assign the number 1 to the first [command] you type to ACL2. We assign 2 to the second and so on. The non-positive integers are assigned to ``prehistoric'' [command]s, i.e., the [command]s used to initialize the ACL2 system: 0 is the last [command] of the initialization, -1 is the one before that, etc. The legal [command] descriptors are described below. We use n to denote any integer, sym to denote any logical name (see [logical-name]), and cd to denote, recursively, any [command] descriptor. command command descriptor described :max -- the most recently executed command (i.e., the one with the largest command number) :x -- synonymous with :max :x-k -- synonymous with (:x -k), if k is an integer and k>0 :min -- the earliest command (i.e., the one with the smallest command number and hence the first command of the system initialization) :start -- the last command when ACL2 starts up n -- command number n (If n is not in the range :min<=n<=:max, n is replaced by the nearest of :min and :max.) sym -- the command that introduced the logical name sym (cd n) -- the command whose number is n plus the command number of the command described by cd (:search pat cd1 cd2) In this command descriptor, pat must be either an atom or a true list of atoms and cd1 and cd2 must be command descriptors. We search the interval from cd1 through cd2 for the first command that matches pat. Note that if cd1 occurs chronologically after cd2, the search is ``backwards'' through history while if cd1 occurs chronologically before cd2, the search is ``forwards''. A backwards search will find the most recent match; a forward search will find the chronologically earliest match. A command matches pat if either the command form itself or one of the events in the block contains pat (or all of the atoms in pat if pat is a list). (:search pat) the command found by (:search pat :max 0), i.e., the most recent command matching pat that was part of the user's session, not part of the system initialization.") (COMMAND-LINE (INTERFACING-TOOLS) "Handling of command-line arguments when ACL2 is invoked You may provide command-line arguments when invoking ACL2, which are passed to the host Lisp. For more information on this topic, along with a discussion of how to save an ACL2 executable that avoids passing command-line arguments to the host Lisp, see [save-exec]. Subtopics [Save-exec] Save an executable image and a wrapper script") (COMMON-LISP (ABOUT-ACL2) "Relation to Common Lisp, including deviations from the spec ACL2 is a logic, a theorem prover, and a programming language based on Common Lisp. A connection with Common Lisp is established with guards (see [guard]). However, here we document potential deviations from Common Lisp semantics even in the presence of verified guards. Our view is that these deviations are extremely unlikely to manifest; indeed, as of this writing we are unaware of any cases in which these issues arise in practice. However, we feel obligated to acknowledge their possibility, which could result in surprises during evaluation or even proof. The Common Lisp spec allows certain predicates to return what it calls ``generalized Booleans,'' which are really arbitrary values that are to be viewed as either nil or non-nil. However, in ACL2 these functions are assumed to return nil or t. For details,see [generalized-booleans]. The execution of forms with :[program] mode functions can result in calls of functions on arguments that do not satisfy their [guard]s. In practice, this simply causes hard Lisp errors. But in principle one could imagine a damaged Lisp image that operates incorrectly. See [defun-mode-caveat]. The Common Lisp spec, specifically Section {Section 3.2.2.3 | http://www.lispworks.com/documentation/HyperSpec/Body/03_bbc.htm} of the {Common Lisp Hyperspec | http://www.lispworks.com/documentation/HyperSpec/Front}, allows for undefined results when a function is ``multiply defined'' in a compiled file. ACL2 allows redundant [defun]s in a book, and in general [books] are compiled by certify-book (but see [certify-book] and see [compilation] for how to control such compilation). Moreover, ACL2 provides a redefinition capability (see [ld-redefinition-action] and see [redef]), and the above section also allows for undefined results when a function is defined in a compiled file and then redefined, presumably (for example) because of inlining. Subtopics [Defun-mode-caveat] Potential soundness issue for functions with [defun-mode] :[program] [Escape-to-common-lisp] Escaping to Common Lisp [Generalized-booleans] Potential soundness issues related to ACL2 predicates") (COMMON_LISP (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Common Lisp [{IMAGE}] {IMAGE} The logic of ACL2 is based on Common Lisp. Common Lisp is the standard list processing programming language. It is documented in: Guy L. Steele, {Common Lisp The Language | }, Digital Press, 12 Crosby Drive, Bedford, MA 01730, 1990. ACL2 formalizes only a subset of Common Lisp. It includes such familiar Lisp functions as cons, car and cdr for creating and manipulating list structures, various arithmetic primitives such as +, *, expt and <=, and intern and symbol-name for creating and manipulating symbols. Control primitives include cond, case and if, as well as function call, including recursion. New functions are defined with defun and macros with defmacro. See [programming] [{ICON}] for a list of the Common Lisp primitives supported by ACL2. ACL2 supports five of Common Lisp's datatypes: * the precisely represented, unbounded numbers (integers, rationals, and the complex numbers with rational components, called the ``complex rationals'' here), * the characters with ASCII codes between 0 and 255 * strings of such characters * symbols (including packages) * conses ACL2 is a very small subset of full Common Lisp. ACL2 does not include the Common Lisp Object System (CLOS), higher order functions, circular structures, and other aspects of Common Lisp that are non-applicative. Roughly speaking, a language is applicative if it follows the rules of function application. For example, f(x) must be equal to f(x), which means, among other things, that the value of f must not be affected by ``global variables'' and the object x must not change over time. [{IMAGE}]") (COMMON_LISP_AS_A_MODELING_LANGUAGE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Common Lisp as a Modeling Language {IMAGE} In ACL2 we have adopted Common Lisp as the basis of our modeling language. If you have already read our brief note on Common Lisp and recall the example of app, please proceed. Otherwise click [here] for an exceedingly brief introduction to Common Lisp and then come back here. In Common Lisp it is very easy to write systems of formulas that manipulate discrete, inductively constructed data objects. In building a model you might need to formalize the notion of sequences and define such operations as concatenation, length, whether one is a permutation of the other, etc. It is easy to do this in Common Lisp. Furthermore, if you have a Common Lisp ``theory of sequences'' you can run the operations and relations you define. That is, you can execute the functions on concrete data to see what results your formulas produce. If you define the function app as shown above and then type (app '(A B) '(C D E)) in any Common Lisp, the answer will be computed and will be (A B C D E). The executable nature of Common Lisp and thus of ACL2 is very handy when producing models. But executability is not enough for a modeling language because the purpose of models is to permit analysis. Click [here] to continue.") (COMMUNITY-BOOKS (BOOKS) "Libraries of ACL2 [books] developed by the ACL2 community. ACL2 [books] are files of ACL2 [events] like definitions and theorems. The ACL2 Community Books are the canonical set of open-source books for ACL2, developed since the early 1990s by members of the ACL2 community. They include libraries for reasoning in many domains, macro libraries for more quickly writing and documenting code, interfacing tools for connecting ACL2 to other systems, productivity tools for better proof automation and debugging, and specialty libraries for areas like hardware verification. From the {github ACL2 project | https://github.com/acl2/acl2/} web site you can: * Download the Community Books; * Learn how to contribute books to the ACL2 community; and * Obtain updates between ACL2 releases. See [git-quick-start] for information about how to download the ``bleeding edge'' ACL2 system and community books. Subtopics [Books-certification] Instructions for certifying the ACL2 [community-books].") (COMP (COMPILATION EVENTS ACL2-BUILT-INS) "Compile some ACL2 functions NOTE: Comp is a no-op if explicit compilation is suppressed; see [compilation]. The documentation here assumes that this is not the case. Examples: :comp t ; compile all uncompiled ACL2 functions (comp t) ; same as above, but can be put into a book (comp :exec) ; compile all uncompiled logic (``*1*'') definitions :comp foo ; compile the defined function foo :comp (:raw foo) ; compile the raw Lisp version of the defined function foo but not the corresponding logic definition :comp (foo bar) ; compile the defined functions foo and bar :comp (foo (:raw bar)) ; compile the defined functions foo and bar, but for ; bar do not compile the corresponding logic definition General Form: :comp specifier where specifier is one of the following: t compile all user-defined ACL2 functions that are currently uncompiled (redefined built-in functions are not recompiled) :exec same as t, except that only logic versions are compiled (see below), not raw Lisp definitions :raw same as t, except that only raw Lisp definitions are compiled, not logic version (see below) (name-1 ... name-k) a non-empty list of names of functions defined by DEFUN in ACL2, except that each name-i can be of the form (:raw sym) or (:exec sym), where sym is the name of such a function name same as (name) When you define a function in ACL2, you are really causing two definitions to be made ``under the hood'' in Common Lisp: the definition is submitted explicitly to raw Lisp, but so is a corresponding ``logic definition''. If guards have not been verified, then only the logic definition will be evaluated; see [guards-and-evaluation], in particular the section titled ``Guards and evaluation V: efficiency issues''. Thus, if you are not verifying [guard]s and you want the benefit of Lisp compilation for speed and space efficiency, then you may want to place the form (comp :exec) in your [books]. Generally it is not necessary to place the form (comp t), or the form (comp :raw), in a book, because [certify-book] compiles the raw Lisp definitions anyhow, by default. But you may wish to put (comp t) or (comp fn1 fn2 ... fnk) in a book when such a form precedes expensive calls of functions, for example for proofs involving calls of functions on large constants, or to support computationally expensive macroexpansion. As suggested by the examples above, if a function specifier is of the form (:raw fn), then fn will be compiled in raw Common Lisp but its corresponding logic definition will not be compiled; and for (:exec fn), it's the other way around. The use of :comp may create various files whose names start with ``TMP*'', but it then deletes them. If you want to save these files, evaluate (assign keep-tmp-files t). Also see [set-compile-fns] for a way to compile each function as it is defined. But note that set-compile-fns is ignored during [include-book]. Note that if functions are traced (see [trace$]), then comp will first untrace the functions that are to be compiled, then will do the compile(s), and finally will re-trace the functions that it untraced (using their original trace specs). In particular, if you have traced a function and then you compile it using :comp, the resulting traced function will be compiled as well unless you specified :compile nil in your trace spec; and after you untrace the function it will definitely run compiled. We conclude with a technical remark only for those who use trust tags to write raw Lisp code. :Comp generally creates files to compile unless it is given a single function to compile. Those files contain the ACL2 definitions of all functions to compile, omitting those in the lists obtained by evaluating the forms (@ logic-fns-with-raw-code) and (@ program-fns-with-raw-code). :Comp skips compilation for functions that are already compiled, as is typically the case when you redefine functions in raw Lisp using [include-raw]. But if you define interpreted (as opposed to compiled) functions with raw Lisp code, say by using trust tags (see [defttag]) and [progn!], then you are advised to add all such symbols to one of the lists stored in the two [state] globals above: to logic-fns-with-raw-code if the function symbol is in :[logic] mode, else to program-fns-with-raw-code. Then, instead of the corresponding ACL2 definition (without raw Lisp code) being written to a file, the function symbol will be passed directly to the Lisp compile function. Note that the above two state globals are both untouchable, so you may need to deal with that before modifying them, for example as follows (also see [remove-untouchable]). (defttag t) (state-global-let* ((temp-touchable-vars t set-temp-touchable-vars)) (progn! (f-put-global 'logic-fns-with-raw-code (cons 'my-fn (@ logic-fns-with-raw-code)) state)))") (COMP-GCL (COMPILATION ACL2-BUILT-INS) "Compile some ACL2 functions leaving .c and .h files Comp-gcl is for use by experts who want to examine the results of GCL compilation, and it may only be used with ACL2 implementations built on top of GCL. It takes exactly the same arguments as [comp], and has the same basic functionality (see [comp]), but has two additional effects. First, files \"TMP.lisp\" and \"TMP1.lisp\" are always created, even when a single function is specified. Second, comp-gcl always leaves files \"TMP.c\", \"TMP.h\", \"TMP1.c\", and \"TMP1.h\" when compilation is complete.") (COMPILATION (PROGRAMMING) "Compiling ACL2 functions ACL2 has several mechanisms to speed up the evaluation of function calls by compiling functions: see [comp], see [set-compile-fns], and see [certify-book]. The intention is that compilation never changes the value returned by a function call, though it could cause the call to succeed rather than fail, for example by avoiding a stack overflow. The [state] global variable 'compiler-enabled is set automatically when the system is built, and may depend on the underlying Lisp implementation. (In order to disable the compiler at build time, which will defeat the speed-up but usually be pretty harmless when the host Lisp is CCL or SBCL, see the discussion of ACL2_COMPILER_DISABLED in distributed file GNUmakefile.) The value of 'compiler-enabled, as returned by (@ compiler-enabled), can be t, :books, or nil. If the value is nil, then [include-book] and [certify-book] coerce their arguments :load-compile-file and compile-flg arguments (respectively) to nil. Otherwise, the value is :books or t and there is no such coercion; but if the value is not t, then [comp] and [set-compile-fns] are no-ops, which is probably desirable for Lisps such as CCL and SBCL that compile on-the-fly even when the compiler is not explicitly invoked. However, you may have reason to want to change the above (default) behavior. To enable compilation by default for [certify-book] and [include-book] but not for [comp] or [set-compile-fns]: (set-compiler-enabled :books state) To enable compilation not only as above but also for [comp] and [set-compile-fns]: (set-compiler-enabled t state) To suppress compilation and loading of compiled files by [include-book] (for example, if you get a raw Lisp error such as ``Wrong FASL version''): (set-compiler-enabled nil state) Remark for users of [make-event]. If set-compiler-enabled is invoked during make-event expansion, its effect on [state] global variable 'compiler-enabled will persist after evaluation completes for that make-event form. So for example, one might use the following idiom in a book so that for all books included on behalf of a given [include-book] form, no compiled files are loaded, but (optionally) no such effect takes place for later include-book forms in that book. (make-event (pprogn (f-put-global 'saved-compiler-enabled (@ compiler-enabled) state) (set-compiler-enabled nil state) (value '(value-triple nil))) :check-expansion t) (include-book \"my-book\") ; optional (make-event (pprogn (set-compiler-enabled (@ saved-compiler-enabled) state) (value '(value-triple nil))) :check-expansion t) Upon completion of an invocation of [include-book] or [certify-book], the value of [state] global variable 'compiler-enabled is restored to the value it had immediately before that invocation. See [book-compiled-file] for more discussion about compilation and [books]. We close with a discussion of a feature that allows control over the loading of .port files in close analogy to how loading of compiled files is controlled by set-compiler-enabled, as described above. (See [uncertified-books] for a discussion of .port files.) A [state] global variable, 'port-file-enabled exists for this purpose, and it is set as follows. (set-port-file-enabled t state) ; permit loading of .port files (default) (set-port-file-enabled nil state) ; skip loading of .port files Just as described above for state global compiler-enabled, the value of 'port-file-enabled persists after [make-event] expansion and is restored after [certify-book] and [include-book]. The idiom displayed above, for avoiding loading of compiled files, can be modified or extended in the obvious way to avoid loading of .port files. Subtopics [Comp] Compile some ACL2 functions [Comp-gcl] Compile some ACL2 functions leaving .c and .h files [Disassemble$] Disassemble a function [Set-compile-fns] Have each function compiled as you go along. [Set-compiler-enabled] Disable [compilation]. [The] The is a special form that can be used to optimize the execution efficiency of [guard]-verified ACL2 definitions, or (less frequently) to carry out a low-level run-time type checks. (Advanced)") (COMPILING-ACL2P (PARALLELISM) "Compiling ACL2(p) This [documentation] topic relates to the experimental extension of ACL2 supporting parallel execution and proof; see [parallelism]. See [parallelism-tutorial] for an introduction to parallel programming in ACL2. You can build an experimental version of ACL2 that supports parallel execution in the following host Common Lisp implementations: * CCL (OpenMCL) * Lispworks 6.0 * SBCL with threads (feature :sb-thread) The command below will compile ACL2 to support parallel execution, including parallel execution during proofs. Any non-empty string may be used in place of t, and the value of LISP (shown here as ccl) is any Lisp executable on which one can build ACL2(p) (see [parallelism]). make ACL2_PAR=t LISP=ccl So for example, to make an executable image and also documentation (which will appear in subdirectories doc/EMACS and doc/HTML), using the Lisp executable ccl: make large DOC ACL2_PAR=t LISP=ccl") (COMPLEX (NUMBERS ACL2-BUILT-INS) "Create an ACL2 number Examples: (complex x 3) ; x + 3i, where i is the principal square root of -1 (complex x y) ; x + yi (complex x 0) ; same as x, for rational numbers x The function complex takes two rational number arguments and returns an ACL2 number. This number will be of type (complex rational) [as defined in the Common Lisp language], except that if the second argument is zero, then complex returns its first argument. The function [complex-rationalp] is a recognizer for complex rational numbers, i.e. for ACL2 numbers that are not rational numbers. The reader macro #C (which is the same as #c) provides a convenient way for typing in complex numbers. For explicit rational numbers x and y, #C(x y) is read to the same value as (complex x y). The functions [realpart] and [imagpart] return the real and imaginary parts (respectively) of a complex (possibly rational) number. So for example, (realpart #C(3 4)) = 3, (imagpart #C(3 4)) = 4, (realpart 3/4) = 3/4, and (imagpart 3/4) = 0. The following built-in axiom may be useful for reasoning about complex numbers. (defaxiom complex-definition (implies (and (real/rationalp x) (real/rationalp y)) (equal (complex x y) (+ x (* #c(0 1) y)))) :rule-classes nil) A completion axiom that shows what complex returns on arguments violating its [guard] (which says that both arguments are rational numbers) is the following, named completion-of-complex. (equal (complex x y) (complex (if (rationalp x) x 0) (if (rationalp y) y 0)))") (COMPLEX-RATIONALP (NUMBERS ACL2-BUILT-INS) "Recognizes complex rational numbers Examples: (complex-rationalp 3) ; nil, as 3 is rational, not complex rational (complex-rationalp #c(3 0)) ; nil, since #c(3 0) is the same as 3 (complex-rationalp t) ; nil (complex-rationalp #c(3 1)) ; t, as #c(3 1) is the complex number 3 + i See [complex] for more about complex rationals in ACL2.") (COMPLEX/COMPLEX-RATIONALP (NUMBERS ACL2-BUILT-INS) "Recognizer for complex numbers For most ACL2 users, this is a macro abbreviating complex-rationalp; see [complex-rationalp]. In ACL2(r) (see [real]), a complex number x may have irrational real and imaginary parts. This macro abbreviates the predicate complexp in ACL2(r), which holds for such x. Most ACL2 users can ignore this macro and use [complex-rationalp] instead. Some community books use complex/complex-rationalp so that they are suitable for ACL2(r) as well.") (COMPOUND-RECOGNIZER (RULE-CLASSES) "Make a rule used by the typing mechanism See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. Examples: (defthm alistp-implies-true-listp-compound-recognizer (implies (alistp x) ; When (alistp x) is assumed true, add (true-listp x)) ; the additional hypothesis that x is :rule-classes :compound-recognizer) ; of primitive type true-listp. (defthm natp-compound-recognizer ; See discussion below. (equal (natp x) (and (integerp x) (<= 0 x))) :rule-classes :compound-recognizer) Before presenting the General Forms, we start with a motivating example: the second [defthm] form above, which provides a nice example of a :compound-recognizer rule that is built into ACL2. To see how this rule might be useful, consider the following (admittedly very simple) [events]. (defun triple (x) (* 3 x)) (defthm triple-preserves-integerp (implies (integerp x) (integerp (triple x)))) (in-theory (disable triple natp)) If the above :compound-recognizer rule is disabled, then the following trivial theorem fails as shown; we explain below. (thm (implies (natp x) (integerp (triple x))) :hints ((\"Goal\" :in-theory (disable natp-compound-recognizer)))) The problem is that when ACL2 tries to rewrite the term (integerp (triple x)) using the :[rewrite] rule triple-preserves-integerp, it needs to rewrite the hypothesis (integerp x) to t, but instead what is known is (natp x). If we remove the hint, then the proof succeeds because the above :compound-recognizer rule tells ACL2 that when assuming (natp x) to be true, it should actually assume both (integerp x) and (<= 0 x) to be true. General Forms: (implies (fn x) concl) ; (1) (implies (not (fn x)) concl) ; (2) (and (implies (fn x) concl1) ; (3) (implies (not (fn x)) concl2)) (if (fn x) concl1 concl2) ; (4) (iff (fn x) concl) ; (5) (equal (fn x) concl) ; (6) where fn is a Boolean valued function of one argument, x is a variable symbol, and the system can deduce some restriction on the primitive type of x from the assumption that concl holds. The last restriction is vague but one way to understand it is to weaken it a little to ``and concl is a non-tautological conjunction or disjunction of the primitive type recognizers listed below.'' The primitive ACL2 types and a suitable primitive recognizing expression for each are listed below. type suitable primitive recognizer zero (equal x 0) negative integers (and (integerp x) (< x 0)) positive integers (and (integerp x) (> x 0)) negative ratio (and (rationalp x) (not (integerp x)) (< x 0)) positive ratio (and (rationalp x) (not (integerp x)) (> x 0)) complex rational (complex-rationalp x) nil (equal x nil) t (equal x t) other symbols (and (symbolp x) (not (equal x nil)) (not (equal x t))) proper conses (and (consp x) (true-listp x)) improper conses (and (consp x) (not (true-listp x))) strings (stringp x) characters (characterp x) Thus, a suitable concl to recognize the naturals would be (or (equal x 0) (and (integerp x) (> x 0))) but it turns out that we also permit (and (integerp x) (>= x 0)). Similarly, the true-lists could be specified by (or (equal x nil) (and (consp x) (true-listp x))) but we in fact allow (true-listp x). When time permits we will document more fully what is allowed or implement a macro that permits direct specification of the desired type in terms of the primitives. There are essentially four forms of :compound-recognizer rules, as the forms labeled (3) and (4) above are equivalent, as are those labeled (5) and (6). We explain how such rules are used by considering the individual forms. Consider form (1), (implies (fn x) concl). The effect of such a rule is that when the rewriter assumes (fn x) true, as it would while diving through (if (fn x) xxx ...) to rewrite xxx, it restricts the type of x as specified by concl. For example, if concl is the term (integerp x), then when rewriting xxx, x will be assumed to be an integer. However, when assuming (fn x) false, as necessary in (if (fn x) ... xxx), the rule permits no additional assumptions about the type of x. For example, if fn is primep, i.e., the predicate that recognizes prime numbers, then (implies (primep x) (and (integerp x) (>= x 0))) is a compound recognizer rule of the first form. When (primep x) is assumed true, the rewriter gains the additional information that x is a natural number. When (primep x) is assumed false, no additional information is gained --- since x may be a non-prime natural or may not even be a natural. Form (2) is the symmetric case, when assuming (fn x) false permits type restrictions on x but assuming (fn x) true permits no such restrictions. For example, if we defined exprp to be the recognizer for well-formed expressions for some language in which all symbols, numbers, character objects and strings were well-formed --- e.g., the well-formedness rules only put restrictions on expressions represented by [consp]s --- then the theorem (implies (not (exprp x)) (consp x)) is a rule of the second form. Assuming (exprp x) true tells us nothing about the type of x; assuming it false tells us x is a [consp]. Forms (3) and (4), which are really equivalent, address themselves to the case where one type may be deduced from (fn x) and a generally unrelated type may be deduced from its negation. If we modified the expression recognizer above so that character objects are illegal, then rules of the forms (3) and (4) are (and (implies (exprp x) (not (characterp x))) (implies (not (exprp x)) (or (consp x) (characterp x)))). (if (exprp x) (not (characterp x)) (or (consp x) (characterp x))) Finally, rules of forms (5) and (6) address the case where fn recognizes all and only the objects whose type is described. In these cases, fn is really just a new name for some ``compound recognizers.'' The classic example is (booleanp x), which is just a handy combination of two primitive types: (iff (booleanp x) (or (equal x t) (equal x nil))). Often it is best to disable fn after proving that it is a compound recognizer, since otherwise the term (fn x) will be expanded and thus disappear. Every time you prove a new compound recognizer rule about fn it overrides all previously proved compound recognizer rules about fn. Thus, if you want to establish the type implied by (fn x) and you want to establish the type implied by (not (fn x)), you must prove a compound recognizer rule of the third, fourth, fifth, or sixth forms. Proving a rule of the first form followed by one of the second only leaves the second fact in the database. Compound recognizer rules can be disabled with the effect that older rules about fn, if any, are exposed. If you prove more than one compound recognizer rule for a function, you may see a warning message to the effect that the new rule is not as ``restrictive'' as the old. That is, the new rules do not give the rewriter strictly more type information than it already had. The new rule is stored anyway, overriding the old, if enabled. You may be playing subtle games with enabling or rewriting. But two other interpretations are more likely, we think. One is that you have forgotten about an earlier rule and should merely print it out to make sure it says what you intend, and then discard your new rule. The other is that you meant to give the system more information and the system has simply been unable to extract the intended type information from the term you placed in the conclusion of the new rule. Given our lack of specificity in saying how type information is extracted from rules, you can hardly blame yourself for this problem. Sorry. If you suspect you've been burned this way, you should rephrase the new rule in terms of the primitive recognizing expressions above and see if the warning is still given. It would also be helpful to let us see your example so we can consider it as we redesign this stuff. Compound recognizer rules are similar to :[forward-chaining] rules in that the system deduces new information from the act of assuming something true or false. If a compound recognizer rule were stored as a forward chaining rule it would have essentially the same effect as described, when it has any effect at all. The important point is that :[forward-chaining] rules, because of their more general and expensive form, are used ``at the top level'' of the simplification process: we forward chain from assumptions in the goal being proved. But compound recognizer rules are built in at the bottom-most level of the simplifier, where type reasoning is done. All that said, compound recognizer rules are a rather fancy, specialized mechanism. It may be more appropriate to create :[forward-chaining] rules instead of :compound-recognizer rules.") (COMPRESS1 (ARRAYS ACL2-BUILT-INS) "Remove irrelevant pairs from a 1-dimensional array Example Form: (compress1 'delta1 a) General Form: (compress1 name alist) where name is a symbol and alist is a 1-dimensional array, generally named name. See [arrays] for details. Logically speaking, this function removes irrelevant pairs from alist, possibly shortening it. The function returns a new array, alist', with the same [header] (including name and dimension) as alist, that, under [aref1], is everywhere equal to alist. That is, (aref1 name alist' i) is (aref1 name alist i), for all legal indices i. Alist' may be shorter than alist and the non-irrelevant pairs may occur in a different order than in alist. Practically speaking, this function plays an important role in the efficient implementation of [aref1]. In addition to creating the new array, alist', compress1 makes that array the ``semantic value'' of name and allocates a raw lisp array to name. For each legal index, i, that raw lisp array contains (aref1 name alist' i) in slot i. Thus, subsequent [aref1] operations can be executed in virtually constant time provided they are given name and the alist' returned by the most recently executed compress1 or [aset1] on name. See [arrays]. In general, compress1 returns an alist whose [cdr] is an association list whose keys are nonnegative integers in ascending order. However, if the [header] specifies an :order of > then the keys will occur in descending order, and if the :order is :none or nil then the keys will not be sorted, i.e., compress1 is logically the identity function (though it still attaches an array under the hood). Note however that a [compress1] call is replaced by a hard error if the header specifies an :order of :none or nil and the array's length exceeds the [maximum-length] field of its [header]. Function: (defun compress1 (name l) (declare (xargs :guard (array1p name l))) (case (array-order (header name l)) (< (cons (header name l) (compress11 name l 0 (car (dimensions name l)) (default name l)))) (> (cons (header name l) (reverse (compress11 name l 0 (car (dimensions name l)) (default name l))))) (t (prog2$ (and (> (length l) (maximum-length name l)) (hard-error 'compress1 \"Attempted to compress a one-dimensional array named ~ ~x0 whose header specifies :ORDER ~x1 and whose ~ length, ~x2, exceeds its maximum-length, ~x3.\" (list (cons #\\0 name) (cons #\\1 nil) (cons #\\2 (length l)) (cons #\\3 (maximum-length name l))))) l))))") (COMPRESS2 (ARRAYS ACL2-BUILT-INS) "Remove irrelevant pairs from a 2-dimensional array Example Form: (compress2 'delta1 a) General Form: (compress2 name alist) where name is a symbol and alist is a 2-dimensional array, generally named name. See [arrays] for details. Logically speaking, this function removes irrelevant pairs from alist, possibly shortening it. The function returns a new array, alist', with the same [header] (including name and dimension) as alist, that, under [aref2], is everywhere equal to alist. That is, (aref2 name alist' i j) is (aref2 name alist i j), for all legal indices i and j. Alist' may be shorter than alist and the non-irrelevant pairs may occur in a different order in alist' than in alist. Practically speaking, this function plays an important role in the efficient implementation of [aref2]. In addition to creating the new array, alist', compress2 makes that array the ``semantic value'' of name and allocates a raw lisp array to name. For all legal indices, i and j, that raw lisp array contains (aref2 name alist' i j) in slot i,j. Thus, subsequent [aref2] operations can be executed in virtually constant time provided they are given name and the alist' returned by the most recently executed compress2 or [aset2] on name. See [arrays]. Function: (defun compress2 (name l) (declare (xargs :guard (array2p name l))) (cons (header name l) (compress21 name l 0 (car (dimensions name l)) (cadr (dimensions name l)) (default name l))))") (COMPUTED-HINTS (HINTS) "Computing advice to the theorem proving process General Form of :hints: (hint1 hint2 ... hintk) Each element, hinti, must be either a common hint or a computed hint. A common hint is of the form (goal-spec :key1 val1 ... :keyn valn) where goal-spec is as specified in [goal-spec] and each :keyi and vali is as specified in [hints]. Among the ``common hints'' we include both the primitive hints and user-defined custom keyword hints (see [custom-keyword-hints]). A computed hint may be a function symbol, fn, of three, four or seven arguments. Otherwise, a computed hint is a term with the following properties: (a) the only free variables allowed in the term are ID, CLAUSE, WORLD, STABLE-UNDER-SIMPLIFICATIONP, HIST, PSPV, CTX, and [state]; (b) the output signature of the term is either (MV * * STATE), which is to be treated as an error triple (see below), or is *, denoting a single non-[stobj] value; and (c) in the former case of (b) above, the term is single-threaded in [state]. If a computed hint is a function symbol fn, whose arity n is therefore three, four, or seven, then it is treated as the term resulting from applying that fn to the first n variables shown in (a) above. Notice that it must then return a single non-[stobj] value, not an error triple, since state is not one of the first seven variables shown in (a). Note: Error triples are an ACL2 idiom for implementing ``errors''; see [error-triples]. If a computation returns (mv erp val state) in a context in which ACL2 is respecting the error triple convention (see [ld-error-triples] and see [ld-error-action]), then an error is deemed to have occurred if erp is non-nil. The computation is expected to have printed an appropriate error message to [state] and further computation is aborted. On the other hand, if a computation returns an error triple in which erp is nil, then ``value'' of the computation is taken to be the second component, val, of the triple (along with the possibly modified [state]), and computation continues. For more information about programming with error triples, see [programming-with-state]. The function symbol cases are treated as abbreviations of the term (fn ID CLAUSE WORLD), (fn ID CLAUSE WORLD STABLE-UNDER-SIMPLIFICATIONP), or (fn ID CLAUSE WORLD STABLE-UNDER-SIMPLIFICATIONP HIST PSPV CTX) as appropriate for the arity of fn. (Note that this tells you which argument of fn is which.) Moreover, in these cases the value returned must be a single ordinary (non-[stobj]) value, not an error triple. In the discussion below we assume all computed hints are of the term form. Indeed, we almost assume all computed hints are of the 3 and 4 argument forms. We only comment briefly on the 7 argument form in [using-computed-hints-8]. The semantics of a computed hint term is as follows. On every subgoal, the term is evaluated in an environment in which the variables mentioned in (a) above are bound to context-sensitive values explained below. Either the computed hint signals an error, in which the proof attempt aborts, or else it returns a value, val and a new state, [state]. Any changes to those parts of [state] that affect logical soundness are undone; more specifically, the values of symbols (sometimes called ``state global variables'') in the list *protected-system-state-globals* in the global table of the state (see [state]) are restored when changed during evaluation. The value, val, of a non-erroneous computed hint calculation is either nil, which means the computed hint did not apply to the subgoal in question, or it is an alternating list of :keyi vali pairs as specified in [hints]. With one exception, those new hints are applied to the given subgoal as though the user had typed them explicitly. The exception is that the first keyword in the returned val is allowed to be :COMPUTED-HINT-REPLACEMENT. Its value should be nil, t, or a list of terms. If this keyword is not present, the default value of nil is provided. We explain :COMPUTED-HINT-REPLACEMENT below. The evaluation of a hint term is done with guard checking turned off (see [set-guard-checking]); e.g., the form (car 23) in a computed hint returns nil as per the axioms. When a non-nil value is returned, the keyword/value pairs (other than the optional :COMPUTED-HINT-REPLACEMENT) are used as the hint for the subgoal in question. Thus, your job as the programmer of computed hints is either to cause an error, typically by invoking [er], or to return a non-erroneous value triple whose value is the list of keys and values you would have typed had you supplied a common hint for the subgoal. (In particular, any theory expressions in it are evaluated with respect to the global current-theory, not whatever theory is active at the subgoal in question.) If the generated list of keywords and values is illegal, an error will be signaled and the proof attempt will be aborted. The purpose of the :COMPUTED-HINT-REPLACEMENT keyword and its value, chr, is to change the list of hints. If chr is nil, then the hint which was applied is removed from the list of hints that is passed down to the children of the subgoal in question. This is the default. If chr is t, then the hint is left in the list of hints. This means that the same hint may act on the children of the subgoal. Otherwise, chr must be a list of terms, each of which is treated as a computed hint. The hint which was applied is deleted from the list of hints and the hints in chr are added to the list of hints passed to the children of the subgoal. The ability to compute new hints and pass them down allows strange and wonderful behavior. For these purposes, the goals produced by induction and the top-level goals of forcing rounds are not considered children; all original hints are available to them. Only the first hint applicable to a goal, as specified in the user-supplied list of :hints followed by the [default-hints-table], will be applied to that goal. (For an advanced exception, see [override-hints].) It remains only to describe the bindings of the free variables. Suppose the theorem prover is working on some clause, clause, named by some [goal-spec], e.g., \"Subgoal *1/2'''\" in some logical world, world. Corresponding to the printed goal-spec is an internal data structure called a ``clause identifier'' id. See [clause-identifier]. In the case of a common hint, the hint applies if the goal-spec of the hint is the same as the goal-spec of the clause in question. In the case of a computed hint, the variable ID is bound to the clause id, the variable CLAUSE is bound to the (translated form of the) clause, and the variable WORLD is bound to the current ACL2 world. The variable STABLE-UNDER-SIMPLIFICATIONP is bound to t or nil. It is bound to t only if the clause is known to be stable under simplification. That is, the simplifier has been applied to the clause and did not change it. Such a clause is sometimes known as a ``simplification checkpoint.'' It is frequently useful to inject hints (e.g., to enable a rule or provide a :use hint) only when the goal in question has stabilized. If a hint is provided, the processing of the clause starts over with simplification. As for CTX and [state], they are provided so that you can pass them to the [er] macro to print error messages. We recommend not writing computed hints that otherwise change [state]! The remaining variables, HIST and PSPV are not documented yet. Only users familiar with the internals of ACL2 are likely to need them or understand their values. For some instruction about how to use computed hints, see [using-computed-hints].") (CONCATENATE (LISTS STRINGS ACL2-BUILT-INS) "Concatenate lists or strings together Examples: (concatenate 'string \"ab\" \"cd\" \"ef\") ; equals \"abcdef\" (concatenate 'string \"ab\") ; equals \"ab\" (concatenate 'list '(a b) '(c d) '(e f)) ; equals '(a b c d e f) (concatenate 'list) ; equals nil General Form: (concatenate result-type x1 x2 ... xn) where n >= 0 and either: result-type is '[string] and each xi is a string; or result-type is '[list] and each xi is a true list. Concatenate simply concatenates its arguments to form the result string or list. Also see [append] and see [string-append]. (The latter immediately generates a call to concatenate when applied to strings.) Note: We do *not* try to comply with the Lisp language's insistence that concatenate copies its arguments. Not only are we in an applicative setting, where this issue shouldn't matter for the logic, but also we do not actually modify the underlying lisp implementation of concatenate; we merely provide a definition for it. Concatenate is a Common Lisp function. See any Common Lisp documentation for more information. Macro: (defmacro concatenate (result-type &rest sequences) (declare (xargs :guard (or (equal result-type ''string) (equal result-type ''list)))) (cond ((equal result-type ''string) (cond ((and sequences (cdr sequences) (null (cddr sequences))) (list 'string-append (car sequences) (cadr sequences))) (t (list 'string-append-lst (cons 'list sequences))))) ((endp sequences) nil) (t (cons 'append (append sequences (list nil))))))") (COND (BASICS ACL2-BUILT-INS) "Conditional based on if-then-else Cond is the construct for IF, THEN, ELSE IF, ... The test is against nil. The argument list for cond is a list of ``clauses'', each of which is a list. In ACL2, clauses must have length 1 or 2. Cond is a Common Lisp macro. See any Common Lisp documentation for more information. Macro: (defmacro cond (&rest clauses) (declare (xargs :guard (cond-clausesp clauses))) (cond-macro clauses)) Function: (defun cond-macro (clauses) (declare (xargs :guard (cond-clausesp clauses))) (if (consp clauses) (if (and (eq (car (car clauses)) t) (eq (cdr clauses) nil)) (if (cdr (car clauses)) (car (cdr (car clauses))) (car (car clauses))) (if (cdr (car clauses)) (list 'if (car (car clauses)) (car (cdr (car clauses))) (cond-macro (cdr clauses))) (list 'or (car (car clauses)) (cond-macro (cdr clauses))))) nil))") (CONGRUENCE (RULE-CLASSES) "The relations to maintain while simplifying arguments See [rule-classes] for a general discussion of rule classes and how they are used to build rules from formulas. An example :[corollary] formula from which a :congruence rule might be built, assuming that set-equal is a known [equivalence] relation, is: Example: (defthm set-equal-implies-iff-memb-2 (implies (set-equal x y) (iff (memb e x) (memb e y))) :rule-classes :congruence) Also see [defcong] and see [equivalence]. NOTE: This topic discusses so-called ``classic'' congruence rules. A more general class of rules, so-called ``patterned'' congruence rules, is supported. We discuss only classic congruence rules below; for a discussion of patterned congruence rules, first read the present topic and then see [patterned-congruence]. General Form: (implies (equiv1 xk xk-equiv) (equiv2 (fn x1... xk ...xn) (fn x1... xk-equiv ...xn))) where equiv1 and equiv2 are known equivalence relations, fn is an n-ary function symbol other than if, and the xi and xk-equiv are all distinct variables. The effect of such a rule is to record that the equiv2-equivalence of fn-expressions can be maintained if, while rewriting the kth argument position, equiv1-equivalence is maintained. See [equivalence] for a general discussion of the issues. We say that equiv2, above, is the ``outside equivalence'' in the rule and equiv1 is the ``inside equivalence for the kth argument.'' The macro form (defcong equiv1 equiv2 (fn x1 ... x1) k) is an abbreviation for a [defthm] of rule-class :congruence that attempts to establish that equiv2 is maintained by maintaining equiv1 in fn's kth argument. The [defcong] macro automatically generates the general formula shown above. See [defcong]. The memb example above tells us that (memb e x) is propositionally equivalent to (memb e y), provided x and y are set-equal. The outside equivalence is [iff] and the inside equivalence for the second argument is set-equal. If we see a memb expression in a propositional context, e.g., as a literal of a clause or test of an [if] (but not, for example, as an argument to [cons]), we can rewrite its second argument maintaining set-equality. For example, a rule stating the commutativity of [append] (modulo set-equality) could be applied in this context. Since equality is a refinement of all equivalence relations, all equality rules are always available. See [refinement]. All known :congruence rules about a given outside equivalence and fn can be used independently. That is, consider two :congruence rules with the same outside equivalence, equiv, and about the same function fn. Suppose one says that equiv1 is the inside equivalence for the first argument and the other says equiv2 is the inside equivalence for the second argument. Then (fn a b) is equiv (fn a' b') provided a is equiv1 to a' and b is equiv2 to b'. This is an easy consequence of the transitivity of equiv. It permits you to think independently about the inside equivalences. Furthermore, it is possible that more than one inside equivalence for a given argument slot will maintain a given outside equivalence. For example, (length a) is equal to (length a') if a and a' are related either by list-equal or by [string-equal]. You may prove two (or more) :congruence rules for the same slot of a function. The result is that the system uses a new, ``generated'' equivalence relation for that slot with the result that rules of both (or all) kinds are available while rewriting. :Congruence rules can be disabled. For example, if you have two different inside equivalences for a given argument position and you find that the :[rewrite] rules for one are unexpectedly preventing the application of the desired rule, you can disable the rule that introduced the unwanted inside equivalence. Remark on Replacing IFF by EQUAL. You may encounter a warning suggesting that a congruence rule ``can be strengthened by replacing the second equivalence relation, IFF, by EQUAL.'' Suppose for example that this warning occurs when you submit the following rule: (defcong equiv1 iff (fn x y) 2) which is shorthand for the following: (defthm equiv1-implies-iff-fn-2 (implies (equiv1 y y-equiv) (iff (fn x y) (fn x y-equiv))) :rule-classes (:congruence)) The warning is telling you that ACL2 was able to deduce that fn always returns a Boolean, and hence a trivial but useful consequence is obtained by replacing [iff] by [equal] --- (defcong equiv1 equal (fn x y) 2) --- which is shorthand for the following: (defthm equiv1-implies-equal-fn-2 (implies (equiv1 y y-equiv) (equal (fn x y) (fn x y-equiv))) :rule-classes (:congruence)) If you have difficulty proving the latter directly, you can derive it from the former by giving a suitable hint, minimally as follows. (defcong equiv1 equal (fn x y) 2 :hints ((\"Goal\" :use equiv1-implies-iff-fn-2 :in-theory (union-theories '((:type-prescription fn)) (theory 'minimal-theory))))) By heeding this warning, you may avoid unnecessary [double-rewrite] warnings later. We now explain why, but see [double-rewrite] for relevant background material. For example, suppose you have proved the ``iff'' version of the congruence rule above, and later you submit the following rewrite rule. (defthm equal-list-perm (implies (equiv1 x y) (fn x y))) Since fn is known to return a Boolean, ACL2 performs an optimization that stores this rule as though it were the following. (defthm equal-list-perm (implies (equiv1 x y) (equal (fn x y) t))) Thus, if ACL2's rewriter sees a term (fn a b) in a context where the equivalence relation [iff] is not being maintained, then it cannot use rule equiv1-implies-iff-fn-2, so it rewrites argument a without the benefit of knowing that it suffices to maintain equiv1; and then it caches the result. When ACL2 subsequently attempts to relieve the hypothesis (equiv1 x y), it will rewrite x simply by returning the rewritten value of a from the result cache. This is unfortunate if a could have been rewritten more completely under maintainance of the equivalence relation equiv1 --- which is legal in the hypothesis since a is an argument of equiv1, which is an [equivalence] relation. The user who observes the warning from rule equiv1-implies-iff-fn-2, and replaces it with equiv1-implies-equal-fn-2, will avoid this unfortunate case.") (CONJUGATE (NUMBERS ACL2-BUILT-INS) "Complex number conjugate Conjugate takes an ACL2 number as an argument, and returns its complex conjugate (i.e., the result of negating its imaginary part.). Conjugate is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun conjugate (x) (declare (xargs :guard (acl2-numberp x))) (if (complex/complex-rationalp x) (complex (realpart x) (- (imagpart x))) x))") (CONS (CONSES ACL2-BUILT-INS) "Pair and list constructor (cons x y) is a pair whose first component is x and second component is y. If y is a list, then (cons x y) is a list that has an additional element x on the front.") (CONS-SUBTREES (FAST-ALISTS ACL2-BUILT-INS) "Build a fast alist whose keys are the subtrees of X (cons-subtrees x nil) builds a fast alist that associates each subtree of X with T, without duplication. Function: (defun cons-subtrees (x al) (declare (xargs :guard t)) (cond ((atom x) al) ((hons-get x al) al) (t (cons-subtrees (car x) (cons-subtrees (cdr x) (hons-acons x t al))))))") (CONSERVATIVITY-OF-DEFCHOOSE (DEFCHOOSE) "Proof of conservativity of [defchoose] This documentation topic provides underlying theory. It is of theoretical interest only; it has no relationship to the effective use of ACL2. The argument below for the conservativity of [defchoose] replaces the terse and somewhat misleading reference to a forcing argument in Appendix B of the paper by ACL2 authors Kaufmann and Moore, ``Structured Theory Development for a Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2 (2001), pp. 161-203). Our basic idea is to to take a (countable) first-order structure for ACL2, M, together with a function symbol, f, introduced by [defchoose], and find a way to expand M with an interpretation of f (without changing the universe of M) so that e0-induction continues to hold in the expansion. A remark at the end of this documentation topic shows why care is necessary. A concept called ``forcing'', originally introduced by Paul Cohen for set theory, has long since been adapted by logicians (in a simplified form) to model theory. This simplified model-theoretic forcing provides the means for making our careful expansion. The forcing argument presented below is intended to be completely self-contained for those familiar with basic first-order logic and ACL2. No background in forcing (model-theoretic or otherwise) is expected, though we do expect a rudimentary background in first-order logic and familiarity with the following. Preliminaries. We write s[p<-p0] to denote the result of extending or modifying the assignment s by binding p to p0. Now let A be a subset of the universe U of a first-order structure M. A is said to be ``first-order definable with parameters'' in M if for some formula phi, variable x, and assignment s binding the free variables of phi except perhaps for x, A = {a \\in U: M |= phi[s[x<-a]]. Note that we are writing ``\\in'' to denote set membership. Finally, we indicate the end of a proof (or of a theorem statement, when the proof is omitted) with the symbol ``-|''. We gratefully acknowledge very helpful feedback from John Cowles, who found several errors in a draft of this note and suggested the exercises. We also thank Ruben Gamboa for helpful feedback, and we thank Jim Schmerl for an observation that led us directly to this proof in the first place. We are given a consistent first-order theory T, extending the ACL2 ground-zero theory, that satisfies the e0-induction scheme. We wish to show that the extension of T by the following arbitrary defchoose event is conservative, where g is a new function symbol. (defchoose g ) Note that by ``the extension of T'' here we mean the extension of T by not only the new defchoose axiom displayed just below, but also the addition of e0-induction axioms for formulas in the language with the new defchoose function symbol, g. -> (LET = g() in ) By definition of conservativity, since proofs are finite, it clearly suffices to consider an arbitrary finite subset of T. Then by the completeness, soundness, and downward Lowenheim-Skolem theorems of first-order logic, it suffices to show that an arbitrary countable model of T can be expanded (i.e., by interpreting the new symbol g without changing the universe of the model) to a model of the corresponding defchoose axiom above, in which all e0-induction axioms hold in the language of that model. Below, we will carry out a so-called forcing construction, which allows us to expand any countable model M of T to a model M[G] that satisfies e0-induction and also satisfies the above axiom generated from the above defchoose event. The ideas in this argument are standard in model theory; no novelty is claimed here. Fix a countable model M of a theory T that satisfies e0-induction and extends the ACL2 ground-zero theory. Also fix the above defchoose axiom, where g is not in the language of T. We start by defining a partial order P as follows. Let Nb and Nf be the lengths of and , respectively. P consists of all fn in M such that the following formula is true in M. Roughly speaking, it says that fn is a finite function witnessing the above requirement for g. alistp(fn) & no-duplicatesp-equal(strip-cars(fn)) & (forall , . (member-equal(cons(,), fn) -> (length() = Nb & length() = Nf & ((exists . ) -> )))) P is ordered by subset, i.e., we say that p2 extends p1 if p1 is a subset (not necessarily proper) of p2 (more precisely, M |= subsetp-equal(p1,p2)). Remark. The original argument in Appendix B of the aforementioned paper can essentially be salvaged, as we now show. The key observation is that the particular choice of P is nearly irrelevant for the argument that follows below. In particular, we can instead define P to consist of finite one-one functions with domain contained in the set of natural numbers. More precisely, consider the following definitions. (defun function-p (fn) (declare (xargs :guard t)) (and (alistp fn) (no-duplicatesp-equal (strip-cars fn)))) (defun nat-listp (l) (declare (xargs :guard t)) (cond ((atom l) (eq l nil)) (t (and (natp (car l)) (nat-listp (cdr l)))))) (defun nat-function-p (x) (and (function-p x) (nat-listp (strip-cars x)))) and define inverse as follows. (defun inverse (fn) (declare (xargs :guard (alistp fn))) (if (endp fn) nil (cons (cons (cdar fn) (caar fn)) (inverse (cdr fn))))) Then P may instead be defined to consist of those fn for which nat-function-p(fn) & function-p(inverse(fn)). With this alternate definition of P, the argument below then goes through virtually unchanged, and we get an expansion M[G] of M in which there is a definable enumeration of the universe. The conservativity of defchoose then follows easily because the function being introduced can be defined explicitly using that enumeration (namely, always pick the least witness in the sense of the enumeration). End of Remark. Next we present the relevant forcing concepts from model theory. A dense subset of P is a subset D of P such that for every p \\in P, there is d \\in D such that d extends p. A subset G of P is generic with respect to a collection Ds of dense subsets of P, also written ``G is Ds-generic,'' if G is closed under subset (if p2 \\in G and p2 extends p1 then p1 \\in G), G is pairwise compatible (the union-equal of any two elements of G is in G), and every set in Ds has non-empty intersection with G. For p \\in P, we say that a subset D of P is dense beyond p if for all p1 extending p there exists p2 extending p1 such that p2 \\in D. This notion makes sense even for D not a subset of P if we treat elements of D not in P as nil. Proposition 1. For any partial order P and countable collection Ds of dense subsets of P, there is a Ds-generic subset of P. Proof. Let Ds = {D0,D1,D2,...}. Define a sequence such that for all i, p_i \\in Di and p_(i+1) extends p_i. Let G = {p \\in P: for some i, pi extends p}. Then G is Ds-generic. -| Note that P is first-order definable (with parameters) in M. Let Df be the set of dense subsets of P that are first-order definable (with parameters) in M. A standard argument shows there are only countably many first-order definitions with parameters in a countable model M --- for example, we can Goedel number all terms and then all formulas --- hence, Df is countable. By Proposition 1, let G be Df-generic. Notice that for any list x of length Nb in M, the set of elements f of P for which x is in the domain of f is dense and first-order definable. We may thus define a function g0 as follows: g0(x_1,...,x_Nb) = y if there is some element of G containing the pair ((x_1 ... x_Nb) . y). It is easy to see that g0 is a total function on M. Let L be the language of T and let L[g] be the union of L with a set containing a single new function symbol, g. Let M[G] be the expansion of M to L[g] obtained by interpreting g to be g0 (see also Proposition 5 below). So now we have fixed M, P, Df, G, and g0, where G is Df-generic. Proposition 2. Let Df be the set of dense subsets of P that are first-order definable (with parameters) in M. Suppose that p \\in G and D \\in Df. Then for some q \\in G extending p, q \\in D. Proof. Let D0 be the set of p' \\in D that either extend p or have no extension in D that extends p. We leave it as a straightforward exercise to show that D0 is dense, and D0 is clearly first-order definable (with parameters) in M. So by genericity of G, we may pick q \\in D0 such that q \\in G. Thus q \\in D. By definition of generic, some extension q1 of both p and q belongs to G. Pick q2 \\in D extending q1; thus q has an extension in D that extends p (namely, q2), so by definition of D0, q extends p. -| Definition of forcing. Let phi(x1,...,xk) be a first-order formula in L[g] and let p \\in P. We define a formula of L, denoted ``p ||- phi'' (``p forces phi''), by recursion on phi (in the metatheory) as follows. (Here, we view ``or'' and ``forall'' as abbreviations.) If phi is atomic, then let phi'(A) be the result of replacing, inside-out, each subterm of the form g(x_1,...,x_Nb) with the term (cdr (assoc-equal (list x_1 ... x_Nb) A)), where A is neither p nor a variable occurring in phi. Then p ||- phi is defined as follows: ``The set {A \\in P: A extends p and phi'(A)} is dense beyond p''. That is, p ||- phi is the following formula: (forall p1 \\in P extending p) (exists p2 \\in P extending p1) phi'(p2). p ||- ~phi is: (forall p' \\in P extending p) ~(p' ||- phi) p ||- phi_1 & phi_2 is: (p ||- phi_1) & (p ||- phi_2) p ||- (exists x) phi is: (exists x) (p ||- phi) We will need the following definition later. Definition. p ||-w phi (p weakly forces phi) is an abbreviation for p ||- ~~phi. The following exercises were suggested by John Cowles as a means for gaining familiarity with the definition of forcing. Exercise 1. Consider the formula (phi_1 OR phi_2) as an abbreviation for ~(~phi_1 & ~phi_2), Show that p ||- (phi_1 OR phi_2) is equivalent to the following. (forall p' \\in P extending p) (exists p'' \\in P extending p') ((p'' ||- phi_1) OR (p'' ||- phi_2)) Exercise 2. Consider the formula (forall x)phi as an abbreviation for ~(exists x)~phi, Show that p ||- (forall x)phi is equivalent to the following. (forall x) (forall p1 \\in P extending p) (exists p2 \\in P extending p1) (p2 ||- phi). Exercise 3. Prove that p ||-w phi is equivalent to the following. (forall p' \\in P extending p) (exists p'' \\in P extending p') (p'' ||- phi). Exercise 4. Let phi be a formula of L[g]. Prove: M |= (p ||- phi)[s[p<-p0]] implies M |= (p ||-w phi)[s[p<-p0]]. Exercise 5. Let phi be a formula of L[g]. Prove: M |= (p ||- ~phi)[s[p<-p0]] iff M |= (p ||-w ~phi)[s[p<-p0]]. [End of exercises.] The definition of forcing stipulates how to view ``p ||- phi(x1,...,xk)'' as a new formula theta(p,x1,...,xk). That is, ``||-'' transforms formulas, so for any first-order formula phi, ``p ||- phi'' is just another first-order formula. That observation shows that a formula such as ((p ||- phi) OR (p ||- ~phi)) is really just another first-order formula. The following proposition thus follows easily. Proposition 3. For any formula phi of L[g], {p0: M |= ((p ||- phi) OR (p ||- ~phi))[s[p<-p0]]]} is a dense subset of P, which (since it is first-order definable with parameters in M) intersects G. -| The following proposition is easily proved by a structural induction on phi, and is left to the reader. Proposition 4. Let phi be a formula of L[g]. Suppose p0 in P, p1 in P, M |= (p ||- phi)[s[p<-p0]] and p1 extends p0. Then M |= (p ||- phi)[s[p<-p1]]. -| We will also need the following. Proposition 5. The following is dense for any finite set S of Nb-tuples: {p \\in P: for some \\in S, (list x_1 ... x_Nb) \\in strip-cars(p)}. Thus, the function g0 is a total function. -| The next lemma tells us that the sentences true in M[G] are those that are forced by an element of G. Truth Lemma. Let phi be a formula in L[g], let s be an assignment to the free variables of phi, and let p be a variable not in the domain of s. Then M[G] |= phi[s] iff for some p0 \\in G, M |= (p ||- phi)[s[p<-p0]]. Proof. The proof is by induction on the structure of phi. First suppose phi is atomic. Let D* be the set of elements p0 \\in P such that every assoc-equal evaluation from the definition of forcing phi returns a pair when A is bound to p0. (Intuitively, this means that p0 is a sufficiently large approximation from any G containing p0 to make sense of phi in M[G].) We make the following claim. (*) For all p0 \\in G such that p0 \\in D*, M[G] |= phi[s] iff M |= (p ||- phi)[s[p<-p0]]. To prove the claim, fix p0 in both G and D*, and recall the function g0 constructed from G in the definition of M[G]. Suppose that t_1, ..., t_Nb are terms and g(t_1, ..., t_Nb) is a subterm of phi. Then s assigns a value in M to each of the t_i. Let a_i be the value assigned by s to t_i. Then g0(a_1, ..., a_Nb) = (cdr (assoc-equal (list a_1 ... a_Nb) p0)), as the assoc-equal is a pair (since p0 \\in D*) and has the indicated value (because p0 \\in G). It follows by the definition of formula phi' in the definition of forcing: M[G] |= phi[s] iff M |= phi'(p)[s[p<-p0]] Moreover, because p0 \\in D* it is clear that this holds if p0 is replaced by an arbitrary extension of p0. Then (*) easily follows. By Proposition 5, D* is dense, so there is some p0 in the intersection of D* and G. The forward direction of the conclusion then follows by (*). The reverse direction is clear from (*) by application of Proposition 2 to D* and Proposition 4. Next, suppose M[G] |= ~phi[x]. Then it is not the case that M[G] |= phi, so by the inductive hypothesis, there is no p0 \\in G for which M |= (p ||- phi)[s[p<-p0]]. By Proposition 3, there is p0 \\in G for which M |= (p ||- ~phi)[s[p<-p0]]. For the other direction, suppose it is not the case that M[G] |= ~phi[s]. So M[G] |= phi[s], and by the inductive hypothesis, there is p0 \\in G for which M |= (p ||- phi)[s[p<-p0]]. It follows that there is no p1 \\in G for which M |= (p ||- ~phi)[s[p<-p1]], since from such p1 we can find a common extension p2 of p0 and p1 (since G is generic), and since p2 extends p0 then by Proposition 4, M |= (p ||- phi)[s[p<-p2]], contradicting (by definition of forcing) M |= (p ||- ~phi)[s[p<-p1]] since p2 extends p1. The case (phi_1 & phi_2) follows easily from the inductive hypothesis. For the forward direction, apply Proposition 4 and the observation that by genericity, if p0 \\in G and p1 \\in G then p0 and p1 they have a common extension in G. Finally, the case (exists x) phi follows trivially from the inductive hypothesis. -| Truth Lemma Corollary. The Truth Lemma holds with ||-w replacing ||-. Proof. This is clear by applying the Truth Lemma to ~~phi. -| Here is our main theorem. Recall that all first-order theories in our ACL2 context satisfy the e0-induction scheme. Theorem. M[G] satisfies e0-induction. Proof. We consider an arbitrary instance of e0-induction in L[g], stated using a strict well-founded relation <| and a formula phi. We write phi(y) to indicate that y may be among the free variables of phi, and phi(y<-x) to denote the result of substituting x for y in phi. theta(y): (forall y) [((forall x <| y) phi(y<-x)) -> phi(y)] -> (forall y) phi(y) Our goal is to prove that theta holds in M[G]. Below, we abuse notation by leaving assignments implicit and by writing ``p ||- phi(y0)'' to signify that the formula (p ||- phi(y)) is true in M under the extension of the explicit assignment that binds y to y0. We believe that the intended meaning will be clear. Consider the following set D. D = {p \\in P: either p ||-w phi(y0) for all y0, or else for some y0, p ||- ~phi(y0) and for all y1 <| y0 p ||-w phi(y1)}. The set D is clearly first-order definable (with parameters) in M. We claim that D is a dense subset of P. For suppose p0 \\in P; we find p1 \\in D extending p0, as follows. If p0 ||-w phi(y0) for all y0, then we may take p1 to be p0. Otherwise, by definition of ||-w and ||-, there is some y0 such that for some extension p0' of p0, p0' ||- ~phi(y0). Pick a <|-minimal such y0, and correspondingly pick p1 so that p1 extends p0 and p1 ||- ~phi(y0). In order to show that p1 \\in D, it remains to show that for all y1 <| y0, p1 ||-w phi(y1), i.e., there is no q extending p1 such that q ||- ~phi(y1). This is indeed the case since otherwise q and y1 would contradict the <|-minimality of y0. Applying the genericity of G and just-proved density of D, pick p0 \\in G such that p0 \\in D. If p0 ||-w phi(y0) for all y0, then by the Truth Lemma Corollary, M[G] |= phi(y0) for all y0, and thus M[G] |= theta. Otherwise, since p0 \\in D we may choose y0 such that p0 ||- ~phi(y0) and for all y1 <| y0, p0 ||-w phi(y1). By the Truth Lemma and its corollary, since p0 \\in G we have: (1) M[G] |= ~phi(y0). (2) For all y1 <| y0, M[G] |= phi(y1). It follows that the antecedent of theta is false in M[G], as witnessed by y = y0; thus M[G] |= theta. -| Remark. We close by returning, as promised above, to the question of why so much care is necessary in constructing an expansion of M. We assume familiarity here with the notion of a ``non-standard'' natural number of M, i.e., one that is greater than the interpretation of any term that has the form (+ 1 1 1 ... 1). Here is a very simple example that illustrates the need for some care. Consider the following event, which introduces a function foo with the following property: for all x, if natp(x) then natp(foo(x)). (defchoose foo (y) (x) (implies (natp x) (natp y))) Certainly we can build a model of the above property from a model M of the ground-zero theory, by interpreting foo so that for all x for which M satisfies natp(x), foo(x) is also a natp in M. But suppose we start with a non-standard model M of the ground-zero theory, and we happen to define foo(x) to be 1 for all non-standard natural numbers x and 0 for all other x. The resulting expansion of M will not satisfy the e0-induction scheme or even the ordinary natural number induction scheme: foo(0)=0 holds in that expansion as does the implication foo(n)=0 => foo(n+1)=0 for every natural number n of M, standard or not; and yet foo(k)=0 fails for every non-standard natural number k of M.") (CONSES (PROGRAMMING) "A cons is an ordered pair. In ACL2, data structures like [lists], [alists], etc., are made up of conses. Subtopics [Atom] Recognizer for atoms [Caaaar] [car] of the [caaar] [Caaadr] [car] of the [caadr] [Caaar] [car] of the [caar] [Caadar] [car] of the [cadar] [Caaddr] [car] of the [caddr] [Caadr] [car] of the [cadr] [Caar] [car] of the [car] [Cadaar] [car] of the [cdaar] [Cadadr] [car] of the [cdadr] [Cadar] [car] of the [cdar] [Caddar] [car] of the [cddar] [Cadddr] [car] of the [cdddr] [Caddr] [car] of the [cddr] [Cadr] [car] of the [cdr] [Car] Returns the first element of a non-empty list, else nil [Cdaaar] [cdr] of the [caaar] [Cdaadr] [cdr] of the [caadr] [Cdaar] [cdr] of the [caar] [Cdadar] [cdr] of the [cadar] [Cdaddr] [cdr] of the [caddr] [Cdadr] [cdr] of the [cadr] [Cdar] [cdr] of the [car] [Cddaar] [cdr] of the [cdaar] [Cddadr] [cdr] of the [cdadr] [Cddar] [cdr] of the [cdar] [Cdddar] [cdr] of the [cddar] [Cddddr] [cdr] of the [cdddr] [Cdddr] [cdr] of the [cddr] [Cddr] [cdr] of the [cdr] [Cdr] Returns the second element of a [cons] pair, else nil [Cons] Pair and list constructor [Consp] Recognizer for [cons] pairs [Listp] Recognizer for (not necessarily proper) lists [Subst] A single substitution into a tree") (CONSP (CONSES ACL2-BUILT-INS) "Recognizer for [cons] pairs (consp x) is true if and only if x is a [cons] pair.") (CONSTRAINT (ENCAPSULATE) "Restrictions on certain functions introduced in [encapsulate] [events] Suppose that a given theorem, thm, is to be functionally instantiated using a given functional substitution, alist. (See [lemma-instance], or for an example, see [functional-instantiation-example].) What is the set of proof obligations generated? It is the set obtained by applying alist to all terms, tm, such that (a) tm mentions some function symbol in the domain of alist, and (b) either (i) tm arises from the ``constraint'' on a function symbol ancestral in thm or in some [defaxiom] or (ii) tm is the body of a [defaxiom]. Here, a function symbol is ``ancestral'' in thm if either it occurs in thm, or it occurs in the definition of some function symbol that occurs in thm, and so on. The remainder of this note explains what we mean by ``constraint'' in the words above. In a certain sense, function symbols are introduced in essentially two ways. The most common way is to use [defun] (or when there is mutual recursion, [mutual-recursion] or [defuns]). There is also a mechanism for introducing ``witness functions''; see [defchoose]. The documentation for these [events] describes the axioms they introduce, which we will call here their ``definitional axioms.'' These definitional axioms are generally the constraints on the function symbols that these axioms introduce. However, when a function symbol is introduced in the scope of an [encapsulate] event, its constraints may differ from the definitional axioms introduced for it. For example, suppose that a function's definition is [local] to the [encapsulate]; that is, suppose the function is introduced in the [signature] of the [encapsulate]. Then its constraints include, at the least, those non-[local] theorems and definitions in the [encapsulate] that mention the function symbol. Actually, it will follow from the discussion below that if the [signature] is empty for an [encapsulate], then the constraint on each of its new function symbols is exactly the definitional axiom introduced for it. Intuitively, we view such encapsulates just as we view [include-book] [events]. But the general case, where the [signature] is not empty, is more complicated. In the discussion that follows we describe in detail exactly which constraints are associated with which function symbols that are introduced in the scope of an [encapsulate] event. In order to simplify the exposition we make two cuts at it. In the first cut we present an over-simplified explanation that nevertheless captures the main ideas. In the second cut we complete our explanation by explaining how we view certain [events] as being ``lifted'' out of the [encapsulate], resulting in a possibly smaller [encapsulate], which becomes the target of the algorithm described in the first cut. At the end of this note we present an example showing why a more naive approach is unsound. Finally, before we start our ``first cut,'' we note that any information you want ``exported'' outside an [encapsulate] event must be there as an explicit definition or theorem. For example, even if a function foo has output type (mv t t) in its [signature], the system will not know (true-listp (foo x)) merely on account of this information. Thus, if you are using functions like foo (constrained [mv] functions), then you may find it useful to prove (inside the encapsulate, to be exported) a :[type-prescription] rule for the constrained function, for example, the :[type-prescription] rule (true-listp (foo x)). First cut at constraint-assigning algorithm. Quite simply, the formulas introduced in the scope of an [encapsulate] are conjoined, and each function symbol introduced by the [encapsulate] is assigned that conjunction as its constraint. Clearly this is a rather severe algorithm. Let us consider two possible optimizations in an informal manner before presenting our second cut. Consider the (rather artificial) event below. The function before1 does not refer at all, even indirectly, to the locally-introduced function sig-fn, so it is unfortunate to saddle it with constraints about sig-fn. (encapsulate (((sig-fn *) => *)) (defun before1 (x) (if (consp x) (before1 (cdr x)) x)) (local (defun sig-fn (x) (cons x x))) (defthm sig-fn-prop (consp (sig-fn x))) ) We would like to imagine moving the definition of before1 to just in front of this [encapsulate], as follows. (defun before1 (x) (if (consp x) (before1 (cdr x)) x)) (encapsulate (((sig-fn *) => *)) (local (defun sig-fn (x) (cons x x))) (defthm sig-fn-prop (consp (sig-fn x))) ) Thus, we will only assign the constraint (consp (sig-fn x)), from the theorem sig-fn-prop, to the function sig-fn, not to the function before1. More generally, suppose an event in an [encapsulate] event does not mention any function symbol in the [signature] of the [encapsulate], nor any function symbol that mentions any such function symbol, and so on. (We might say that no function symbol from the [signature] is an ``ancestor'' of any function symbol occurring in the event.) Then we imagine moving the event, so that it appears in front of the [encapsulate]. We don't actually move it, but we pretend we do when it comes time to assign constraints. Thus, such definitions only introduce definitional axioms as the constraints on the function symbols being defined. In the example above, the event sig-fn-prop introduces no constraints on function before1. Once this first optimization is performed, we have in mind a set of ``constrained functions.'' These are the functions introduced in the [encapsulate] that would remain after moving some of them in front, as indicated above. Consider the collection of all formulas introduced by the [encapsulate], except the definitional axioms, that mention these constrained functions. So for example, in the event below, no such formula mentions the function symbol after1. (encapsulate (((sig-fn *) => *)) (local (defun sig-fn (x) (cons x x))) (defthm sig-fn-prop (consp (sig-fn x))) (defun after1 (x) (sig-fn x)) ) We can see that there is really no harm in imagining that we move the definition of after1 out of the [encapsulate], to just after the [encapsulate]. Many subtle aspects of this rearrangement process have been omitted. For example, suppose the function fn uses sig-fn, the latter being a function in the signature of the encapsulation. Suppose a formula about fn is proved in the encapsulation. Then from the discussion above fn is among the constrained functions of the encapsulate: it cannot be moved before the encapsulate and it cannot be moved after the encapsulation. But why is fn constrained? The reason is that the theorem proved about fn may impose or express constraints on sig-fn. That is, the theorem proved about fn may depend upon properties of the witness used for sig-fn. Here is a simple example: (encapsulate (((sig-fn *) => *)) (local (defun sig-fn (x) (declare (ignore x)) 0)) (defun fn (lst) (if (endp lst) t (and (integerp (sig-fn (car lst))) (fn (cdr lst))))) (defthm fn-always-true (fn lst))) In this example, there are no [defthm] events that mention sig-fn explicitly. One might therefore conclude that it is completely unconstrained. But the witness we chose for it always returns an integer. The function fn uses sig-fn and we prove that fn always returns true. Of course, the proof of this theorem depends upon the properties of the witness for sig-fn, even though those properties were not explicitly ``called out'' in theorems proved about sig-fn. It would be unsound to move fn-always-true after the encapsulate. It would also be unsound to constrain sig-fn to satisfy just fn-always-true without including in the constraint the relation between sig-fn and fn. Hence both sig-fn and fn are constrained by this encapsulation and the constraint imposed on each is the same and states the relation between the two as characterized by the equation defining fn as well as the property that fn always returns true. Suppose, later, one proved a theorem about sig-fn and wished to functionally instantiate it. Then one must also functionally instantiate fn, even if it is not involved in the theorem, because it is only through fn that sig-fn inherits its constrained properties. This is a pathological example that illustrate a trap into which one may easily fall: rather than identify the key properties of the constrained function the user has foreshadowed its intended application and constrained those notions. Clearly, the user wishing to introduce the sig-fn above would be well-advised to use the following instead: (encapsulate (((sig-fn *) => *)) (local (defun sig-fn (x) (declare (ignore x)) 0)) (defthm integerp-sig-fn (integerp (sig-fn x)))) (defun fn (lst) (if (endp lst) t (and (integerp (sig-fn (car lst))) (fn (cdr lst))))) (defthm fn-always-true (fn lst))) Note that sig-fn is constrained merely to be an integer. It is the only constrained function. Now fn is introduced after the encapsulation, as a simple function that uses sig-fn. We prove that fn always returns true, but this fact does not constrain sig-fn. Future uses of sig-fn do not have to consider fn at all. Sometimes it is necessary to introduce a function such as fn within the encapsulate merely to state the key properties of the undefined function sig-fn. But that is unusual and the user should understand that both functions are being constrained. Another subtle aspect of encapsulation that has been brushed over so far has to do with exactly how functions defined within the encapsulation use the signature functions. For example, above we say ``Consider the collection of all formulas introduced by the encapsulate, except the definitional axioms, that mention these constrained functions.'' We seem to suggest that a definitional axiom which mentions a constrained function can be moved out of the encapsulation and considered part of the ``post-encapsulation'' extension of the logical [world], if the defined function is not used in any non-definitional formula proved in the encapsulation. For example, in the encapsulation above that constrained sig-fn and introduced fn within the encapsulation, fn was constrained because we proved the formula fn-always-true within the encapsulation. Had we not proved fn-always-true within the encapsulation, fn could have been moved after the encapsulation. But this suggests an unsound rule because whether such a function can be moved after the encapsulate depend on whether its admission used properties of the witnesses! In particular, we say a function is ``subversive'' if any of its governing tests or the actuals in any recursive call involve a function in which the signature functions are ancestral. See [subversive-recursions]. (Aside: The definition of fn in the first enapsulation above that defines fn, i.e., the encapsulation with fn-always-true inside, is subversive because the call of the macro [and] expands to a call of IF that governs a recursive call of fn, in this case: (defun fn (lst) (if (endp lst) t (if (integerp (sig-fn (car lst))) (fn (cdr lst)) nil))). If we switch the order of conjuncts in fn, then the definition of fn is no longer subversive, but it still ``infects'' the constraint generated for the encapsulation, hence for sig-fn, because fn-always-true blocks the definition of fn from being moved back (to after the encapsulation). If we both switch the order of conjuncts and drop fn-always-true from the encapsulation, then the definition of fn is in essence moved back to after the encapsulation, and the constraint for sig-fn no longer includes the definition of fn. End of aside.) Another aspect we have not discussed is what happens to nested encapsulations when each introduces constrained functions. We say an encapsulate event is ``trivial'' if it introduces no constrained functions, i.e., if its signatures is nil. Trivial encapsulations are just a way to wrap up a collection of events into a single event. From the foregoing discussion we see we are interested in exactly how we can ``rearrange'' the events in a non-trivial encapsulation -- moving some ``before'' the encapsulation and others ``after'' the encapsulation. We are also interested in which functions introduced by the encapsulation are ``constrained'' and what the ``constraints'' on each are. We may summarize the observations above as follows, after which we conclude with a more elaborate example. Second cut at constraint-assigning algorithm. First, we focus only on non-trivial encapsulations that neither contain nor are contained in non-trivial encapsulations. (Nested non-trivial encapsulations are not rearranged at all: do not put anything in such a nest unless you mean for it to become part of the constraints generated.) Second, in what follows we only consider the non-local events of such an encapsulate, assuming that they satisfy the restriction of using no locally defined function symbols other than the signature functions. Given such an encapsulate event, move, to just in front of it and in the same order, all definitions and theorems for which none of the signature functions is ancestral. Now collect up all formulas (theorems) introduced in the [encapsulate] other than definitional axioms. Add to this set any of those definitional equations that is either subversive or defines a function used in a formula in the set. The conjunction of the resulting set of formulas is called the ``constraint'' and the set of all the signature functions of the encapsulate together with all function symbols defined in the encapsulate and mentioned in the constraint is called the ``constrained functions.'' Assign the constraint to each of the constrained functions. Move, to just after the encapsulate, the definitions of all function symbols defined in the encapsulate that have been omitted from the constraint. Implementation note. In the implementation we do not actually move [events], but we create constraints that pretend that we did. Here is an example illustrating our constraint-assigning algorithm. It builds on the preceding examples. (encapsulate (((sig-fn *) => *)) (defun before1 (x) (if (consp x) (before1 (cdr x)) x)) (local (defun sig-fn (x) (cons x x))) (defthm sig-fn-prop (consp (sig-fn x))) (defun during (x) (if (consp x) x (cons (car (sig-fn x)) 17))) (defun before2 (x) (before1 x)) (defthm before2-prop (atom (before2 x))) (defthm during-prop (implies (and (atom x) (before2 x)) (equal (car (during x)) (car (sig-fn x))))) (defun after1 (x) (sig-fn x)) (defchoose after2 (x) (u) (and (< u x) (during x))) ) Only the functions sig-fn and during receive extra constraints. The functions before1 and before2 are viewed as moving in front of the [encapsulate], as is the theorem before2-prop. The functions after1 and after2 are viewed as being moved past the [encapsulate]. The implementation reports the following. In addition to SIG-FN, we export AFTER2, AFTER1, BEFORE2, DURING and BEFORE1. The following constraint is associated with both of the functions DURING and SIG-FN: (AND (EQUAL (DURING X) (IF (CONSP X) X (CONS (CAR (SIG-FN X)) 17))) (CONSP (SIG-FN X)) (IMPLIES (AND (ATOM X) (BEFORE2 X)) (EQUAL (CAR (DURING X)) (CAR (SIG-FN X))))) Notice that the formula (consp (during x)) is not a conjunct of the constraint. During the first pass of the encapsulate, this formula is stored as a :[type-prescription] rule deduced during the definition of the function during. However, the rule is not exported because of a rather subtle soundness issue. (If you are interested in details, see the comments in source function putprop-type-prescription-lst.) We conclude by asking (and to a certain extent, answering) the following question: Isn't there an approach to assigning constraints that avoids over-constraining more simply than our ``second cut'' above? Perhaps it seems that given an [encapsulate], we should simply assign to each locally defined function the theorems exported about that function. If we adopted that simple approach the events below would be admissible. (encapsulate (((foo *) => *)) (local (defun foo (x) x)) (defun bar (x) (foo x)) (defthm bar-prop (equal (bar x) x) :rule-classes nil)) (defthm foo-id (equal (foo x) x) :hints ((\"Goal\" :use bar-prop))) ; The following event is not admissible in ACL2. (defthm ouch! nil :rule-classes nil :hints ((\"Goal\" :use ((:functional-instance foo-id (foo (lambda (x) (cons x x)))))))) Under the simple approach we have in mind, bar is constrained to satisfy both its definition and bar-prop because bar mentions a function declared in the signature list of the encapsulation. In fact, bar is so-constrained in the ACL2 semantics of encapsulation and the first two events above (the encapsulate and the consequence that foo must be the identity function) are actually admissible. But under the simple approach to assigning constraints, foo is unconstrained because no theorem about it is exported. Under that approach, ouch! is provable because foo can be instantiated in foo-id to a function other than the identity function. It's tempting to think we can fix this by including definitions, not just theorems, in constraints. But consider the following slightly more elaborate example. The problem is that we need to include as a constraint on foo not only the definition of bar, which mentions foo explicitly, but also abc, which has foo as an ancestor. (encapsulate (((foo *) => *)) (local (defun foo (x) x)) (local (defthm foo-prop (equal (foo x) x))) (defun bar (x) (foo x)) (defun abc (x) (bar x)) (defthm abc-prop (equal (abc x) x) :rule-classes nil)) (defthm foo-id (equal (foo x) x) :hints ((\"Goal\" :use abc-prop))) ; The following event is not admissible in ACL2. (defthm ouch! nil :rule-classes nil :hints ((\"Goal\" :use ((:functional-instance foo-id (foo (lambda (x) (cons x x))) (bar (lambda (x) (cons x x))))))))") (CONVERSION (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Conversion to Uppercase When symbols are read by Common Lisp they are converted to upper case. Note carefully that this remark applies to the characters in symbols. The characters in strings are not converted upper case. To type a symbol containing lower case characters you can enclose the symbol in vertical bars, as in |AbC| or you can put a ``backslash'' before each lower case character you wish to preserve, as in A\\bC. |AbC| and A\\bC are two different ways of writing the same symbol (just like 2/4 and 1/2 are two different ways of writing the same rational and 123 and 0123 are two different ways to write the same natural number). The symbol has three characters in its name, the middle one of which is a lower case b.") (COPYRIGHT (ABOUT-ACL2) "ACL2 copyright, license, sponsorship This topic provides information about copyright, license, authorship, and sponsorship of the ACL2 system. For information about copyright and authorship of [documentation], see [documentation-copyright], which notes that there are many documentation authors. ACL2 Version 7.1 --- A Computational Logic for Applicative Common Lisp Copyright (C) 2015, Regents of the University of Texas This version of ACL2 is a descendent of ACL2 Version 1.9, Copyright (C) 1997 Computational Logic, Inc. See the documentation topic NOTE-2-0. This program is free software; you can redistribute it and/or modify it under the terms of the LICENSE file distributed with ACL2. 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 LICENSE for more details. Written by: Matt Kaufmann and J Strother Moore email: Kaufmann@cs.utexas.edu and Moore@cs.utexas.edu Department of Computer Science University of Texas at Austin Austin, TX 78712 U.S.A. Please also see [acknowledgments]. Subtopics [Documentation-copyright] Copyright and authorship of documentation") (COROLLARY (RULE-CLASSES) "The corollary formula of a [rune] See [formula]. This is a low-level system function at the present time. See [pr] and see [pr!] instead. Also see [rule-classes] for the use of the symbol :corollary in specifying a rule class.") (CORROBORATING_MODELS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Corroborating Models [{IMAGE}] After producing a model, it must be corroborated against reality. The Falling Body Model has been corroborated by a vast number of experiments in which the time and distance were measured and compared according to the formula. In general all models must be corroborated by experiment. The Falling Body Model can be derived from deeper models, namely Newton's laws of motion and the assertion that, over the limited distances concerned, graviation exerts a constant acceleration on the object. When the model in question can be derived from other models, it is the other models that are being corroborated by our experiments. Because nature is not formal, we cannot prove that our models of it are correct. All we can do is test our models against nature's behavior. Such testing often exposes restrictions on the applicability of our models. For example, the Falling Body Model is inaccurate if air resistance is significant. Thus, we learn not to use that model to predict how long it takes a feather to fall from a 200 foot tower in the earth's atmosphere. In addition, attempts at corroboration might reveal that the model is actually incorrect. Careful measurements might expose the fact that the gravitational force increases as the body falls closer to earth. Very careful measurements might reveal relativistic effects. Technically, the familiar Falling Body Model is just wrong, even under excessive restrictions such as ``in a perfect vacuum'' and ``over small distances.'' But it is an incredibly useful model nonetheless. There are several morals here. Models need not be complete to be useful. Models need not be perfectly accurate to be useful. The user of a model must understand its limitations. [{IMAGE}]") (COUNT (LISTS STRINGS ACL2-BUILT-INS) "Count the number of occurrences of an item in a string or true-list Example Forms: (count #\\D \"DabcDefcDe\") ; = 3 (count #\\D \"DabcDefcDe\" :start 1) ; = 2 (count #\\D \"DabcDefcDe\" :start 1 :end 5) ; = 1 (count #\\D \"DabcDefcDe\" :start 1 :end 4) ; = 0 (count #\\z \"DabcDefcDe\") ; = 0 (count '(a b) '(17 (a b) 23 (a b) (c d))) ; = 2 General Form: (count item sequence &key start end) (Count item sequence) returns the number of times item occurs in sequence. The [guard] for calls of count (which is actually a macro in ACL2) specifies that sequence is a string or a true-list, and that start, which defaults to 0, and end, which defaults to the length of sequence, are valid indices into sequence. See any Common Lisp documentation for more information about count, which is a Common Lisp utility. At this time ACL2 does not support keyword arguments for count other than :start and :end; we may add support for the :from-end keyword upon request. Macro: (defmacro count (item sequence &key (start '0) end) (cons 'count-fn (cons item (cons sequence (cons start (cons end 'nil))))))") (CPU-CORE-COUNT (PARALLELISM ACL2-BUILT-INS) "The number of cpu cores This [documentation] topic relates to the experimental extension of ACL2 supporting parallel execution and proof; see [parallelism]. Unless the ACL2 executable supports parallel execution (see [parallelism]), this function returns (mv 1 state). Otherwise: (Cpu-core-count state) returns (mv core-count state), where core-count is determined as follows. If environment variable ACL2_CORE_COUNT has a non-empty value, then that value should represent a positive integer (else an error occurs), which is the returned core-count. Otherwise, the returned core-count may be obtained from the underlying Common Lisp implementation, else as a positive integer value from [state] global variable 'cpu-core-count (see [assign]). Otherwise an error occurs. Example: (cpu-core-count state) ==> (mv 4 state) Cpu-core-count has the following logical definition. Function: (defun cpu-core-count (state) (declare (xargs :stobjs state :guard t)) (mv-let (nullp val state) (read-acl2-oracle state) (declare (ignore nullp)) (mv val state)))") (CURRENT-PACKAGE (LD) "The package used for reading and printing Current-package is an [ld] special (see [ld]). The accessor is (current-package state) and the updater is (set-current-package val state), or more conventionally, (in-package val). The value of current-package is actually the string that names the package. (Common Lisp's ``package'' objects do not exist in ACL2.) The current package must be known to ACL2, i.e., it must be one of the initial packages or a package defined with [defpkg] by the user. When printing symbols, the package prefix is displayed if it is not the current-package and may be optionally displayed otherwise. Thus, if current-package is \"ACL2\" then the symbol 'ACL2::SYMB may be printed as SYMB or ACL2::SYMB, while 'MY-PKG::SYMB must be printed as MY-PKG::SYMB. But if current-package is \"MY-PKG\" then the former symbol must be printed as ACL2::SYMB while the latter may be printed as SYMB. In Common Lisp, current-package also affects how objects are read from character streams. Roughly speaking, read and print are inverses if the current-package is fixed, so reading from a stream produced by printing an object must produce an equal object. In ACL2, the situation is more complicated because we never read objects from character streams, we only read them from object ``streams'' (channels). Logically speaking, the objects in such a channel are fixed regardless of the setting of current-package. However, our host file systems do not support the idea of Lisp object files and instead only support character files. So when you open an object input channel to a given (character file) we must somehow convert it to a list of ACL2 objects. This is done by a deus ex machina (``a person or thing that appears or is introduced suddenly and unexpectedly and provides a contrived solution to an apparently insoluble difficulty,'' Webster's Ninth New Collegiate Dictionary). Roughly speaking, the deus ex machina determines what sequence of calls to read-object will occur in the future and what the current-package will be during each of those calls, and then produces a channel containing the sequence of objects produced by an analogous sequence of Common Lisp reads with *current-package* bound appropriately for each. A simple rule suffices to make sane file [io] possible: before you read an object from an object channel to a file created by printing to a character channel, make sure the current-package at read-time is the same as it was at print-time.") (CURRENT-THEORY (THEORIES THEORY-FUNCTIONS) "Currently [enable]d rules as of logical name Examples: (current-theory :here) (current-theory 'lemma3) See [logical-name]. General Form: (current-theory logical-name) Returns the current theory as it existed immediately after the introduction of [logical-name] provided it is evaluated in an environment in which the variable symbol WORLD is bound to the current ACL2 logical world, (w state). Thus, ACL2 !>(current-theory :here) will cause an (unbound variable) error while ACL2 !>(let ((world (w state))) (current-theory :here)) will return the current theory in world. See [theories] and see [logical-name] for a discussion of theories in general and why the commonly used ``theory functions'' such as current-theory are really macros that expand into terms involving the variable world. The theory returned by current-theory is in fact the theory selected by the [in-theory] event most recently preceding logical name, extended by the rules introduced up through [logical-name]. You may experience a fencepost problem in deciding which logical name to use. [Deflabel] can always be used to mark unambiguously for future reference a particular point in the development of your theory. The order of [events] in the vicinity of an [encapsulate] is confusing. See [encapsulate]. This ``function'' is actually a macro that expands to a term mentioning the single free variable [world]. When theory expressions are evaluated by [in-theory] or the :[in-theory] hint, [world] is bound to the current ACL2 [world].") (CUSTOM-KEYWORD-HINTS (HINTS) "User-defined hints See [add-custom-keyword-hint] for a discussion of how advanced users can define their own hint keywords. For examples, see the community books directory books/hints/, in particular basic-tests.lisp. Subtopics [Show-custom-keyword-hint-expansion] Print out custom keyword hints when they are expanded") (CW (IO ACL2-BUILT-INS) "Print to the comment window Example: (cw \"The goal is ~p0 and the alist is ~x1.~%\" (untranslate term t nil) unify-subst) Logically, this expression is equivalent to nil. However, it has the effect of first printing to the so-called ``comment window'' the [fmt] string as indicated. Thus, cw is like fmt (see [fmt]) except in three important ways. First, it is a macro whose calls expand to calls of a :[logic] mode function. Second, it neither takes nor returns the ACL2 [state]; logically cw simply returns nil, although it prints to a comment window that just happens to share the terminal screen with the standard character output [*standard-co*]. Third, its fmt args are positional references, so that for example (cw \"Answers: ~p0 and ~p1\" ans1 ans2) prints in the same manner as: (fmt \"Answers: ~p0 and ~p1\" (list (cons #\\0 ans1) (cons #\\1 ans2)) *standard-co* state nil) Typically, calls of cw are embedded in [prog2$] forms, e.g., (prog2$ (cw ...) (mv a b c)) which has the side-effect of printing to the comment window and logically returning (mv a b c). General Form: (cw fmt-string arg1 arg2 ... argn) where n is between 0 and 9 (inclusive). The macro uses [fmt-to-comment-window], passing it the column 0 and [evisc-tuple] nil, after assembling the appropriate alist binding the [fmt] vars #\\0 through #\\9; see [fmt]. If you want (a) more than 10 vars, (b) vars other than the digit chars, (c) a different column, or (d) a different evisc-tuple, then call [fmt-to-comment-window] instead. Also see [cw!], which is useful if you want to be able to read the printed forms back in. Finally, we discuss another way to create formatted output that also avoids the need to pass in the ACL2 [state]. The idea is to use wormholes; see [wormhole]. Below is a function you can write, along with some calls, providing an illustration of this approach. (defun my-fmt-to-comment-window (str alist) (wormhole 'my-fmt-to-comment-window '(lambda (whs) whs) (list str alist) '(pprogn (fms (car (@ wormhole-input)) (cadr (@ wormhole-input)) *standard-co* state nil) (value :q)) :ld-verbose nil :ld-error-action :return ; harmless return on error :ld-prompt nil)) ; A non-erroneous call: (my-fmt-to-comment-window \"Here is ~x0 for your inspection~%\" (list (cons #\\0 'foo))) ; An error inside the fmt string (unbound fmt var); note that even ; with the error, the wormhole is exited. (my-fmt-to-comment-window \"Here is ~x1 for your inspection~%\" (list (cons #\\0 'foo))) ; A guard violation in the binding; note that even with the error, ; the wormhole is exited. (my-fmt-to-comment-window \"Here is ~x0 for your inspection~%\" (list (cons #\\0 (car 'foo))))") (CW! (IO ACL2-BUILT-INS) "Print to the comment window This is the same as [cw], except that [cw] inserts backslash (\\) characters when forced to print past the right margin, in order to make the output a bit clearer in that case. Use cw! instead if you want to be able to read the forms back in.") (CW-GSTACK (BREAK-REWRITE DEBUGGING) "Debug a rewriting loop or stack overflow Example Forms: (cw-gstack) (cw-gstack :frames 10) ; show only the top 10 frames (cw-gstack :frames '(1 10)) ; same as above: show only frames 1 through 10 (cw-gstack :frames '(10 20)) ; show only frames 10 through 20 (cw-gstack :evisc-tuple (evisc-tuple 3 4 nil nil)) ; print with print-level 3 and print-length 4 (cw-gstack :evisc-tuple nil) ; print using default ``evisceration'', ; essentially the same as just above (cw-gstack :evisc-tuple '(nil 3 4 (hide))) ; same as just above General Form: (cw-gstack :frames frames :evisc-tuple evisc-tuple) where :frames and :evisc-tuple are optional, but if they are supplied, their values are evaluated. The value of frames should be either a natural number or a list of two natural numbers, the first less than the second; and the value of evisc-tuple should be an evisc-tuple (see [evisc-tuple]). If :evisc-tuple is omitted, then substructures deeper than 3 are replaced by ``#'' and those longer than 4 are replaced by ``...'', and terms of the form (hide ...) are printed as . Also see [set-iprint] for an alternative to printing ``#'' and ``...''. Stack overflows may occur, perhaps caused by looping rewrite rules. In some Lisps, stack overflows may manifest themselves as segmentation faults, causing the entire ACL2 image to crash. Finding looping rewrite rules can be tricky, especially if you are using books supplied by other people. (However, see [set-rewrite-stack-limit] for a way to avoid stack overflows caused by rewriter loops.) Normally, a stack overflow will cause the printing of an error message that suggests how to proceed. Just follow those instructions, and you will generally be able to see what is causing the loop. Suggestion: Once you have found the loop and fixed it, you should execute the ACL2 command :[brr] nil, so that you don't slow down subsequent proof attempts.") (DEAD-EVENTS (MISCELLANEOUS) "Using proof supporters to identify dead code and unused theorems Below, when we talk about ``an event A'', we mean an event whose name is A. When event A is used in a proof performed to admit event B that you submit to ACL2, we say that A is a ``proof-supporter'' of B. ACL2 stores an association list such that for every event B with at least one proof-supporter, B is associated with a list of all of its proof-supporters, sorted by [symbol-<]. The following form evaluates to that alist, which is called the ``proof-supporters-alist''. (global-val 'proof-supporters-alist (w state)) By ``used in a proof'' above, we mean: applied as a rule or supplied explicitly via [hints] of type :use, :by, or :clause-processor. That is, the [events] ``used in a proof'' for admitting an event E are those listed in the summary printed at the conclusion of admitting E. Note that if proofs are skipped when admitting event E, say because the last admission of E was done by [include-book] (or certify-book, which ends with an [include-book]), then there will be no entry in that alist for E. (An exception is made however for [encapsulate] [events], where proof-supporters are remembered from the first pass; see below.) So if you want the proof-supporters-alist to include supporters for events in a book, use [ld] rather than [include-book] or [certify-book] to process the events in that book. If however you are interested in the proof-supporters FROM a book that support a later event, then it is fine to include that book. The case for [encapsulate] is slightly tricky. Consider an example of the following form. A ; event preceding the encapsulate (encapsulate () B (local C) ; uses A and B in a proof D ; uses C in a proof ) At the conclusion of this [encapsulate] event, the proof-supporters-alist associates D with A and B, but not C (which has disappeared, since it is [local]). Note that this sort of ``transitive closure'' operation is only performed when necessary due to the disappearance of [local] [events]. For example, if we replace (local C) above by just C, then D is associated in the proof-supporters-alist only with C, not with A or B. If you want the transitive closure of the relation computed by the proof-supporters-alist, you have to compute it yourself. (This was a deliberate design decision, in order to avoid slowing down event processing.) However, there is help available on how to do such a computation: A community book, books/misc/dead-events.lisp, does such a transitive closure, and moreover uses that information to find ``dead events'' relative to a list of ``desired'' events. For example, suppose you use [ld] to process the events, with proofs, in a book intended to prove theorems MAIN-1 and MAIN-2. (Remember, [certify-book] will not save such information.) Suppose furthermore that the book begins with some [include-book] forms followed by (deflabel book-start). You could evaluate this form: (dead-events '(main-1 main-2) :start 'book-start) The result is a list of events that you probably can delete from the book without causing any proofs to fail. See the dead-events.lisp book for further documentation. You might also find the code in the above book to be helpful for writing your own utilities based on the proof-supporters-alist.") (DEALING-WITH-KEY-COMBINATIONS-OF-FUNCTION-SYMBOLS (INTRODUCTION-TO-THE-THEOREM-PROVER) "How to get rid of key combinations of function symbols Suppose REV reverses a list, MEMBER checks that its first argument is an element of its second, and SQUARES-PLUS-3P is some complicated predicate. Suppose you're proving some Main Theorem that involves those concepts and the theorem prover presents you with the following hideous formula as a key checkpoint. What action should you take? Hint: Don't read the formula ``for sense,'' i.e., don't try to understand what this formula is saying! Just look at every subterm involving a nest of two function symbols and ask if you know something about those two symbols that allows you to simplify that one subterm. (IMPLIES (AND (CONSP X) (MEMBER (+ 3 (* I I)) (REV X)) (LIST-OF-INTEGERS X) (INTEGERP I) (<= 0 I) (INTEGERP K) (<= 0 K) (< I K) (SQUARES-PLUS-3P K X) (NOT (EQUAL (CAR X) (+ 3 (* I I)))) (NOT (MEMBER (+ 3 (* I I)) X))) (SQUARES-PLUS-3P K (REV X)))? The experienced ACL2 user will stop reading at the second hypothesis! (MEMBER (+ 3 (* I I)) (REV X)) The combination of MEMBER and REV can be simplified. The question ``is e a member of (REV x)'' can be answered by asking ``is e a member of x''. The two questions are equivalent. This insight comes from your intuition about the semantics of REV -- it just reorders the elements but doesn't add or delete any. The second question is simpler since it doesn't mention REV, so this is a good transformation to make. And the theorem that they are equivalent is simpler than the key checkpoint above because it involves fewer functions and smaller expressions. You might formalize this insight as (equal (member e (rev x)) (member e x)) But this conjecture is not a theorem, because (member e x) returns the cdr of x that begins with e, not just a Boolean (t or nil) indicating whether e is an element of x. The location of the first e in (rev x) is generally different than the location in x. So when we say the two questions are ``equivalent'' we don't mean they are equal. We mean that they're propositionally equivalent: both nil or both non-nil. This sense of equivalence is called ``if and only if'' and is checked by the function iff. So our intuitive insight can be phrased as this theorem: (iff (member e (rev x)) (member e x)) Suggesting that this formulation of the insight is ``obvious'' begs many questions. Mathematically, we could have avoided iff and just written two implications: (and (implies (member e x) (member e (rev x))) (implies (member e (rev x)) (member e x))). or (and (implies (member e x) (member e (rev x))) (implies (not (member e x)) (not (member e (rev x))))). Or we could have used iff but ``oriented'' it the other way: (iff (member e x) (member e (rev x))) We choose to write (iff (member e (rev x)) (member e x)) because of our knowledge of how ACL2 turns formulas into rules! We deal with this at greater length later. But just to drive the point home, if we issue the command: (defthm member-rev (iff (member e (rev x)) (member e x))) ACL2 will build in a rule that causes every propositional occurrence of (MEMBER e (REV x)) to be replaced by (MEMBER e x). (By ``propositional occurrence'' we mean an occurrence in which the value is tested, as by IF or the propositional connectives. Remember, one might use member to determine the location of an element too.) Note carefully: if you do not tell ACL2 how to make a rule from a theorem, it makes a rewrite rule. Rewrite rules always replace instances of the left-hand side by the corresponding instances of the right-hand side. That is, when interpreted as a rewrite rule, (iff alpha beta) makes ACL2 replace alpha by beta. Probably the biggest mistake new users make is forgetting that every theorem they prove creates a very specific rule. You must remember that you are programming ACL2 with these rules. Being careless in your statement of theorems is tantamount to being careless in your programming. What you get is a mess. Had we proved the same equivalence, but with the iff commuted, we would be giving ACL2 bad advice. We would be telling it ``replace instances of (MEMBER e x) by the corresponding instances of (MEMBER e (REV x))''! If ACL2 had that rule and ever tried to simplify any member expression, e.g., (MEMBER A B), it would get into an infinite loop, e.g., producing the following sequence of transformations: (MEMBER A B) (MEMBER A (REV B)) (MEMBER A (REV (REV B))) ... until it eventually exhausted some resource. Recall that we entertained the idea of phrasing our insight about member and rev with implications rather than iff. Generally speaking, implications produce weaker rules -- rules that apply less often. We discuss that later. Now suppose we've proved member-rev, oriented so as to rewrite (member e (rev x)) to (member e x), and built it in as a rewrite rule. Then suppose we repeated the attempt to prove our Main Theorem. This time, when the prover is processing the hideous Key Checkpoint printed above, our new lemma, member-rev, will hit it. It will transform the formula to: (IMPLIES (AND (CONSP X) (MEMBER (+ 3 (* I I)) X) ; <-- the hyp has simplified (LIST-OF-INTEGERS X) (INTEGERP I) (<= 0 I) (INTEGERP K) (<= 0 K) (< I K) (SQUARES-PLUS-3P K X) (NOT (EQUAL (CAR X) (+ 3 (* I I)))) (NOT (MEMBER (+ 3 (* I I)) X))) (SQUARES-PLUS-3P K (REV X)))? and then that will collapse to T, since the IMPLIES has contradictory hypotheses (note the last hypothesis above). By proving member-rev we proved the hideous checkpoint. We never had to look at the rest of the formula or think about why it is a theorem. Furthermore, attacking the main theorem again, from scratch, with member-rev in the database, may eliminate other checkpoints that came up the last time we tried to prove our main goal. So we recommend addressing one checkpoint at a time. This example illustrates that purely local thinking -- looking for simplifiable combinations of function symbols -- can sometimes lead to proofs and should always be your first reaction to a key checkpoint: what local fact do you know that would clean up the formula? Don't think about deep questions like ``why is this true?'' until you can't see any way to make it simpler. It is important to train yourself to see combinations of function symbols and to create strong rules for eliminating them. We will give you opportunities to practice this later in the tutorial. If you have been reading the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-key-checkpoints].") (DEALING-WITH-TAU-PROBLEMS (INTRODUCTION-TO-THE-TAU-SYSTEM) "Some advice on dealing with problems caused by the tau system For background on the tau system, see [introduction-to-the-tau-system]. The two most common problems caused by the tau system have to do with the system's interaction with ``legacy'' proof scripts. Such scripts may suffer because they were not designed to exploit tau reasoning and which may configure the tau database in quite incomplete and arbitrary ways. The two most common problems we have seen are (a) significant slow downs in a few proofs and (b) failed proof attempts due to hints being misapplied because the tau system caused subgoals to be renumbered. We discuss the rather limited means of dealing with these problems here. In [future-work-related-to-the-tau-system] we list some major inadequacies of the tau system. If the tau system contributes to a proof, the [rune] (:[executable-counterpart] tau-system) will be listed among the Rules in the Summary. However, merely by being attempted the tau system can slow down proofs in which it makes no contribution. The most brutal and fool-proof way to isolate a proof from the tau system is to disable the entire system. This can be done globally by (in-theory (disable (tau-system))) ; (:executable-counterpart tau-system) or locally with a subgoal specific hint: ... :hints ((\"...subgoal id...\" :in-theory (disable (tau-system)))) Conducting a proof with and without the participation of the tau system can help you determine whether tau reasoning is helping or hurting. Dealing with Slowdowns The [time-tracker] utility was added to allow users to investigate whether excessive amounts of time are being spent in a given function. It was then used to annotate the code for the tau system as described in [time-tracker-tau]. The result is that if ``excessive'' time is spent in tau reasoning, messages to that effect will be printed to the proof log. The question is: aside from disabling the tau system how can the proof be sped up? There are two common causes of slowdown in the tau system. The first stems from the system's use of :[executable-counterpart]s to determine whether a constant has a given tau. Recall that a tau is a conjunction of monadic predicates. To determine whether some constant satisfies the tau, the predicates are executed. If you have a hard-to-compute predicate this can be very slow. The most typical such predicates in ACL2 applications are those that check invariants, e.g., that recognize ``good states'' or ``well-formed data.'' These are often written inefficiently because they are intended only for used in theorems and, before the tau system was added, they may have never been applied to constants. The most common constants tau predicates are applied to are 0, T, and NIL, although different models may stress other constants. To understand why NIL for example is frequently tested, if the test of an IF-expression is computed to have tau s then the next question we ask is ``does nil satisfy s?'' You may determine whether the tau system is spending time executing tau predicates by observing the rewriter --- see [dmr] --- or by interrupting the system and getting a backtrace (see [set-debugger-enable]). If excessive time is being spent in a tau predicate, a draconian solution is to disable the :[executable-counterpart] of that predicate, for example in either of these equivalent ways. The tau system does not execute disabled :[executable-counterpart]s. (in-theory (disable (:executable-counterpart foo))) (in-theory (disable (foo))) In either case above, you may prefer to provide local :[in-theory] :[hints] rather than :in-theory [events]. Disabling the executable counterpart of expensive tau predicates will weaken the tau system, probably only negligibly, because it can no longer run the predicates to determine whether they admits given constants. A more sophisticated solution is to make the tau system record values of the :[logic]-mode function in question, so that the system will look up the necessary values rather than running the function every time the question arises. It will look up recorded values whether the executable counterpart of the tau predicate is enabled or disabled. Here is an example of a lemma that can provide such a solution. See the discussion of the Eval form of :[tau-system] rules. (defthm lemma (and (foo 0) (foo 17) (foo t) (not (foo '(a b c)))) :rule-classes :tau-system) It might be difficult to determine which constants are being repeatedly tested, although tracing ([trace$]) suspected tau predicates will show what they are being called on. At the moment there are no better user-level tools to discover this. However, some users may wish to consider the following hack: In the ACL2 source file tau.lisp, immediately after the definition of the system function ev-fncall-w-tau-recog, there is a comment which contains some raw Lisp code that can be used to investigate whether tau's use of evaluation on constants is causing a problem and to determine which constants are involved. The second main cause of slowdowns by the tau system is that the system contains ``too many'' conjunctive rules (see the Conjunctive form in [tau-system]). Unfortunately, we have no tools for either identifying the problem or addressing it! That said, let us tell you what we do know! Conjunctive rules are used to ``complete'' each tau as it is built. Referring to the weekdayp example in [tau-system], if a tau is constructed that recognizes weekdays but not MON, TUE, THU, or FRI, it is completed by adding that the tau recognizes (only) WED. This means that when we construct a tau we scan all known conjunctive rules and see whether all but one of the literals of any conjunctive rule are present. This can be expensive. To mitigate this expense, the tau system caches the computation on a per proof basis (the cache is cleared after every proof). To learn what conjunctive rules there are in your system, evaluate (assoc 'tau-conjunctive-rules (tau-database (w state))) Perhaps by sending the implementors that list, we can think of ways to index the conjunctive rules to save time. Dealing with Misapplied Hints The second common problem caused by the tau system in legacy proof scripts is that it can cause subgoals to be renumbered and thus cause hints to be missed. The only ways to address this problem is either to disable the tau system (locally or globally by disabling (:executable-counterpart tau-system)) or change the legacy hints to use the new subgoal names.") (DEBUGGING (TOP ACL2) "Tools for debugging failed or slow proofs, or misbehaving functions. Subtopics [Accumulated-persistence] To get statistics on which [rune]s are being tried [Break-rewrite] The read-eval-print loop entered to [monitor] rules [Cw-gstack] Debug a rewriting loop or stack overflow [Disassemble$] Disassemble a function [Dmr] Dynamically monitor rewrites and other prover activity [Failed-forcing] How to deal with a proof [failure] in a forcing round [Failure] How to deal with a proof failure [Forward-chaining-reports] To see reports about the forward chaining process [Guard-debug] Generate markers to indicate sources of [guard] proof obligations [Measure-debug] Generate markers to indicate sources of [measure] proof obligations [Nil-goal] How to proceed when the prover generates a goal of nil [Print-gv] Print a form whose evaluation caused a guard violation [Proof-checker] An interactive tool for controlling ACL2's proof processes. [Proof-tree] Proof tree displays [Pstack] Seeing what the prover is up to [Redo-flat] Redo on failure of a [progn], [encapsulate], or [certify-book] [Set-debugger-enable] Control whether Lisp errors and breaks invoke the Lisp debugger [Set-guard-msg] Specify what is printed when a [guard] is violated [Splitter] Reporting of rules whose application may have caused case splits [Time-tracker] Display time spent during specified evaluation [Trace] Tracing functions in ACL2 [Walkabout] Explore an ACL2 cons tree") (DECLARE (PROGRAMMING ACL2-BUILT-INS) "Extra declarations that can occur in function definitions, [let] bindings, and so forth. Common Lisp provides a declaration mechanism that allows the programmer to explain additional information to the compiler. For instance: * The programmer might declare that some variable always has some particular type. The compiler might then, depending on its optimization/safety settings, either add run-time checks to ensure that this really is true, or optimize the compiled code by assuming the variable has the correct type. * The programmer might declare that some variable is ignored. The compiler might then, instead of warning the programmer that the variable is never used, explicitly check to make sure that it really is never used. ACL2 supports the above kinds of declarations, and also adds its own kinds of declarations for specifying things like the [guard]s and [measure]s of functions, as described in [xargs]. There are also other kinds of Common Lisp declarations that ACL2 does not support, e.g., pertaining to inlining, safety settings, variable lifetime, and so forth. Usage Examples: (declare (ignore x y z)) (declare (ignorable x y z) (type integer i j k) (type (satisfies integerp) m1 m2)) (declare (xargs :guard (and (integerp i) (<= 0 i)) :guard-hints ((\"Goal\" :use (:instance lemma3 (x (+ i j))))))) General Form: (declare d1 ... dn) where, in ACL2, each di is of one of the following forms: (ignore v1 ... vn) where each vi is a variable introduced in the immediately superior lexical environment. These variables must not occur free in the scope of the declaration. This declaration can be useful for inhibiting compiler warnings; see also [set-ignore-ok]. (ignorable v1 ... vn) where each vi is a variable introduced in the immediately superior lexical environment. These variables need not occur free in the scope of the declaration. This declaration can be useful for inhibiting compiler warnings; see also [set-ignore-ok]. (type type-spec v1 ... vn) where each vi is a variable introduced in the immediately superior lexical environment and type-spec is a type specifier (as described in the documentation for [type-spec]). This declaration can be useful for optimizing Common Lisp execution speed. See also [the]. (xargs :key1 val1 ... :keyn valn) where the legal values of the keys and values are described in the documentation for [xargs]. These declarations are only allowed at the top level of definitions ([defun] and [defmacro], as shown below), and convey information such as the [guard] and [measure] for a function. (optimize ...) for example, (optimize (safety 3)). This is allowed only at the top level of [defun] forms and is probably only rarely of any interest. See any Common Lisp documentation for more information. Declarations in ACL2 may occur only where dcl occurs below: * (DEFUN name args doc-string dcl ... dcl body) * (DEFMACRO name args doc-string dcl ... dcl body) * (LET ((v1 t1) ...) dcl ... dcl body) * (MV-LET (v1 ...) term dcl ... dcl body) * (FLET ((name args dcl ... dcl body) ...)) Of course, if a form macroexpands into one of these (e.g., as [let*] expands into nested [let]s and our er-let* expands into nested [mv-let]s) then declarations are permitted as handled by the macros involved. Declare is defined in Common Lisp. See any Common Lisp documentation for more information. Subtopics [Declare-stobjs] Declaring a formal parameter name to be a single-threaded object [Set-ignore-ok] Allow unused formals and locals without an ignore or ignorable declaration [Type-spec] Type specifiers can be used in Common Lisp type declarations and [the] forms, and may result in improved efficiency of execution. [Xargs] Extra arguments, for example to give [hints] to [defun]") (DECLARE-STOBJS (STOBJ DECLARE) "Declaring a formal parameter name to be a single-threaded object When a [defun] uses one of its formals as a single-threaded object ([stobj]), the defun must include a declaration that the formal is to be so used. An exception is the formal ``[state],'' which if not declared as explained below, may still be used provided an appropriate global ``declaration'' is issued: see [set-state-ok]. If the formal in question is counters then an appropriate declaration is (declare (xargs :stobjs counters)) or, more generally, (declare (xargs :stobjs (... counters ...))) where all the single-threaded formals are listed. For such a declaration to be legal it must be the case that all the names have previously been defined as single-threaded objects with [defstobj]. When an argument is declared to be single-threaded the guard of the function is augmented by conjoining to it the condition that the argument satisfy the recognizer for the single-threaded object. Furthermore, the syntactic checks done to enforce the legal use of single-threaded objects are also sufficient to allow these guard conjuncts to be automatically proved. The obvious question arises: Why does ACL2 insist that you declare stobj names before using them in defuns if you can only declare names that have already been defined with defstobj? What would go wrong if a formal were treated as a single-threaded object if and only if it had already been so defined? Suppose that one user, say Jones, creates a book in which counters is defined as a single-threaded object. Suppose another user, Smith, creates a book in which counters is used as an ordinary formal parameter. Finally, suppose a third user, Brown, wishes to use both books. If Brown includes Jones' book first and then Smith's, then Smith's function treats counters as single-threaded. But if Brown includes Smith's book first, the argument is treated as ordinary. ACL2 insists on the declaration to ensure that the definition is processed the same way no matter what the context.") (DEFABBREV (MACROS EVENTS PROGRAMMING) "A convenient form of macro definition for simple expansions Examples: (defabbrev snoc (x y) (append y (list x))) (defabbrev sq (x) (declare (type (signed-byte 8) x)) (* x x)) General Form: (defabbrev name (v1 ... vn) doc-string decl1 ... declk body) where name is a new function symbol, the vi are distinct variable symbols, and body is a term. The decli, if supplied, should be legal declare forms; see [declare]. Doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. Roughly speaking, the defabbrev event is akin to defining f so that (f v1 ... vn) = body. But rather than do this by adding a new axiom, defabbrev defines f to be a macro so that (f a1 ... an) expands to body, with the ``formals,'' vi, replaced by the ``actuals,'' ai. For example, if snoc is defined as shown in the first example above, then (snoc (+ i j) temp) is just an abbreviation for (append temp (list (+ i j))). In order to generate efficiently executable Lisp code, the macro that defabbrev introduces uses a [let] to bind the ``formals'' to the ``actuals.'' Consider the second example above. Logically speaking, (sq (ack i j)) is an abbreviation for (* (ack i j) (ack i j)). But in fact the macro for sq introduced by defabbrev actually arranges for (sq (ack i j)) to expand to: (let ((x (ack i j))) (* x x)) which executes more efficiently than (* (ack i j) (ack i j)). In the theorem prover, the let above expands to ((lambda (x) (* x x)) (ack i j)) and thence to (* (ack i j) (ack i j)). It is important to note that the term in body should not contain a call of name --- i.e., defabbrev should not be used in place of defun when the function is recursive. ACL2 will not complain when the defabbrev form is processed, but instead ACL2 will more than likely go into an infinite loop during macroexpansion of any form that has a call of name. It is also important to note that the parameters of any call of a macro defined by defabbrev will, as is the case for the parameters of a function call, be evaluated before the body is evaluated, since this is the evaluation order of [let]. This may lead to some errors or unexpected inefficiencies during evaluation if the body contains any conditionally evaluted forms like cond, case, or if. Consider the following example. (defabbrev foo (x y) (if (test x) (bar y) nil)) Notice a typical one-step expansion of a call of foo (see [trans1]): ACL2 !>:trans1 (foo expr1 expr2) (LET ((X EXPR1) (Y EXPR2)) (IF (TEST X) (BAR Y) NIL)) ACL2 !> Now imagine that expr2 is a complicated expression whose evaluation is intended only when the predicate test holds of expr1. The expansion above suggests that expr2 will always be evaluated by the call (foo expr1 expr2), which may be inefficient (since perhaps we only need that value when test is true of expr1). The evaluation of expr2 may even cause an error, for example in :[program] mode if the expression expr2 has been constructed in a manner that could cause a guard violation unless test holds of expr1.") (DEFABSSTOBJ (EVENTS STOBJ) "Define a new abstract single-threaded object We assume familiarity with single-threaded objects; see [stobj] and see [defstobj]. The event defabsstobj defines a so-called ``abstract stobj'', a notion we introduce briefly now and then explain in more depth below. The evaluation of a [defstobj] event produces logical definitions for several functions: a recognizer, which characterizes the [stobj] in terms of lists; a creator, which produces an initial suitable list structure; and field accessors and updators, defined in terms of [nth] and [update-nth]. Defabsstobj provides a way to define alternate definitions for ``stobj primitives'' for a corresponding single-threaded object. These stobj primitives include a recognizer, a creator, and other ``exported'' functions. In essence, defabsstobj establishes interface functions, or ``exports'', on a new stobj that is a copy of an indicated ``concrete'' stobj that already exists. We begin below with an introduction to abstract [stobj]s. We then explain the [defabsstobj] event by way of an example. We conclude by giving summary documentation for the defabsstobj event. For another introduction to abstract stobjs, see the paper ``Abstract Stobjs and Their Application to ISA Modeling'' by Shilpi Goel, Warren A. Hunt, Jr., and Matt Kaufmann, in the proceedings of {ACL2 Workshop 2013 | http://www.cs.uwyo.edu/~ruben/acl2-13}. INTRODUCTION We start with a brief review of [stobj]s and some potential problems with them, followed by an introduction to abstract stobjs and how they can avoid these problems. Prior experience with stobjs will probably help the reader to absorb the ideas below. Recall that single-threaded objects, or [stobj]s, provide a way for ACL2 users to stay within the ACL2 logic, where every data object is an atom or a [cons] of data objects, while obtaining the benefits of fast evaluation through destructive updates. Consider for example this very simple event. (defstobj st fld) This event introduces a recognizer, stp, and a creator, create-st, for a data structure consisting of a single field accessed and updated by functions fld and update-fld, respectively. Each of these four primitive functions has both a logical definition, which is used when the prover reasons about the function, and an executable definition, which is used in raw Lisp. In the logic, stp recognizes objects that have the requisite fields. In raw Lisp, there is a ``live stobj'', which is an array object whose fields correspond to those specified by the [defstobj] event, implemented as Lisp arrays. Here are the logical definition and the executable definition, respectively, that are introduced for the field accessor, fld, introduced above. Notice that since a stobj is represented in raw Lisp using an array, the raw Lisp accessor uses a raw Lisp array accessor, svref. (You can see all the logical and executable definitions by evaluating the form (trace$ defstobj-axiomatic-defs defstobj-raw-defs) before evaluating the [defstobj] form.) ; logical definition (defun fld (st) (declare (xargs :guard (stp st) :verify-guards t)) (nth 0 st)) ; executable (raw Lisp) definition (defun fld (st) (svref st 0)) Sophisticated programming with stobjs can provide efficient implementations of algorithms, but may require the preservation of a complex invariant. One can, of course, define a function to implement such an invariant after introducing the stobj, as follows. ; Introduce a stobj. (defstobj st fld1 ... fldk) ; Define an invariant on that stobj. (defun good-stp (st) (declare (xargs :stobjs st)) ...) ; Define some basic functions that update the stobj and preserve the ; invariant. (defun update-st (... st ...) (declare (xargs :stobjs st :guard (and (good-stp st) ...))) ...) ... ; Prove that the invariant is indeed preserved by those basic functions. (defthm good-stp-update-st (implies (and (good-stp st) ...) (good-stp (update-st ... st ...)))) ... ; Implement algorithms built on the basic functions. (defun foo (... st ...) (declare (xargs :stobjs st :guard (and (good-stp st) ...))) ... (update-st ... st ...) ...) ; Prove invariance theorems about these algorithms. (defthm good-stp-foo (implies (and (good-stp st) ...) (good-stp (foo ... st ...)))) ... ; Prove other properties of these algorithms. (defthm foo-is-correct (implies (and (good-stp st) ...) (some-property (foo ... st ...)))) ... But there are at least two potential difficulties in using stobjs as described above. 1. When foo is executed on concrete data in the ACL2 loop, the guard check may be expensive because (good-stp st) is expensive. 2. Reasoning about foo (using rules like foo-is-correct above) involves proving hypotheses of invariance theorems, which may be complicated for the user to manage or slow for the theorem prover. The defabsstobj event offers an opportunity to address these issues. It introduces a new stobj, which we call an ``abstract stobj'', which is associated with a corresponding ``concrete stobj'' introduced by an earlier [defstobj] event. The defabsstobj event specifies a logical (:LOGIC) and an executable (:EXEC) definition for each primitive operation, or ``stobj primitive'', involving that stobj. As is the case for [defstobj], the logical definition is what ACL2 reasons about, and is appropriate to apply to an ACL2 object satisfying the logical definition of the recognizer function for the stobj. The executable definition is applied in raw Lisp to a live stobj, which is an array object associated with the given stobj name. We can picture a sequence of updates to corresponding abstract and concrete stobjs as follows. Initially in this picture, st$a0 and st$c0 are a corresponding abstract and concrete stobj (respectively). Then an update, u1, is applied with :LOGIC and :EXEC functions u$a1 and u$c1, respectively. The resulting abstract and concrete stobj, st$a1 and st$c1, correspond as before. Then a second update, u2, is applied with :LOGIC and :EXEC functions u$a2 and u$c2, respectively --- again preserving the correspondence. And so on. Abstract u$a1 u$a2 u$a3 (:logic) st$a0 --> st$a1 --> st$a2 --> ... ^ ^ ^ ^ Correspondence | | | ... | v v v v u$c1 u$c2 u$c3 Concrete st$c0 --> st$c1 --> st$c2 --> ... (:exec) We conclude this introduction with some remarks about implementation. Consider an abstract stobj st with corresponding concrete stobj st$c. The live stobjs for st and st$c have the same structure, but are distinct arrays. Indeed, the raw Lisp creator function for st$c is called to create a new initial live stobj for st. As we will see below, reads and writes in raw Lisp to the live stobj for st are ultimately performed using the primitive accessors and updaters defined for st$c. One might think of the live stobjs for st and st$c as being congruent stobjs (see [defstobj]), except that the stobjs themselves are not congruent: the stobj primitives introduced for st may be applied to st but not arbitrary field updaters of st$c, for example. As one might expect, the :EXEC function for an exported function is applied to the live stobj for st in raw Lisp. EXAMPLE We present examples, with detailed comments intended to explain abstract stobjs, in two community books: books/misc/defabsstobj-example-1.lisp and books/misc/defabsstobj-example-2.lisp. In this section we outline the first of these. We suggest that after you finish this [documentation] topic, you read through those two books. Here is the first of two closely related defabsstobj [events] from the book defabsstobj-example-1.lisp, but in expanded form. We will show the abbreviated form later, which omits most of data in the form that is immediately below. Thus most of the information shown here is default information. We believe that the comments below explain most or all of what you need to know in order to start using defabsstobj, and that you will learn the remainder when you see error messages. For example, we do not say in the comments below that every :LOGIC and :EXEC function must be [guard]-verified, but that is indeed a requirement. (defabsstobj st ; The new abstract stobj is named st. ; The concrete stobj corresponding to st is st$c: :concrete st$c ; The recognizer for the new abstract stobj is stp, which is defined to be ; st$ap in the logic, and is executed on the live stobj in raw Lisp using ; st$cp. :recognizer (stp :logic st$ap :exec st$cp) ; The initial stobj is defined as create-st (a function of no arguments), ; which is defined logically as create-st$a, though create-st$c is invoked to ; create the initial live stobj for st. The :correspondence and :preserved ; keywords refer to proof obligations, discussed below. :creator (create-st :logic create-st$a :exec create-st$c :correspondence create-st{correspondence} :preserved create-st{preserved}) ; Proof obligations are generated that involve a correspondence between the ; new abstract stobj and corresponding concrete stobj. The function ; st$corr, which need not be executable (see :DOC defun-nx), takes two ; arguments, a concrete stobj and an abstract stobj. This function symbol is ; used in the statements of the proof obligations. :corr-fn st$corr ; In this example we have four exports. In each case a new function is ; introduced that has the same signature as its :EXEC function, except that ; st$c is replaced by st. The :LOGIC and :EXEC functions are as specified, ; and the other keywords refer to proof obligations that we discuss below. :exports ((lookup :logic lookup$a :exec mem$ci :correspondence lookup{correspondence} :guard-thm lookup{guard-thm}) (update :logic update$a :exec update-mem$ci :correspondence update{correspondence} :preserved update{preserved} :guard-thm update{guard-thm}) (misc :logic misc$a :exec misc$c :correspondence misc{correspondence}) (update-misc :logic update-misc$a :exec update-misc$c :correspondence update-misc{correspondence} :preserved update-misc{preserved})) :doc nil) Note that all stobj primitives (recognizer, creator, and exported functions) are defined in the ACL2 loop in terms of their :LOGIC functions and in raw Lisp in terms of their :EXEC functions. In the ACL2 loop, a [defun] form defines a function, while in raw Lisp, a [defmacro] form defines a macro (for efficiency). We first illustrate how that works for the recognizer. (You can see all the logical and executable definitions by evaluating the form (trace$ defabsstobj-axiomatic-defs defabsstobj-raw-defs) before evaluating the [defstobj] form.) ; In the ACL2 loop: (defun stp (st) (declare (xargs :guard 't)) (st$ap st)) ; In raw Lisp: (defmacro stp (&rest args) (cons 'st$cp args)) The definitions are made similarly for exported functions, with [guard]s derived from their :LOGIC functions as follows. Consider the exported function update in our example. Its :LOGIC function, update$a, has formals (k val st$a) and the following guard. (and (and (integerp k) (<= 0 k) (<= k 49)) (and (integerp val) (<= 0 val)) (st$ap st$a) (mem$c-entryp val)) The formals of update are obtained by starting with the formals of its :EXEC function, update-mem$ci --- which are (i v st$c) --- and replacing the concrete stobj name st$c by the new stobj name st. The formals of update are thus (i v st). The guard for update is obtained in two steps. The first step is to substitute the formals of update for the formals of update$a in the guard for update$a, to obtain the following. (and (and (integerp i) (<= 0 i) (<= i 49)) (and (integerp v) (<= 0 v)) (st$ap st) (mem$c-entryp v)) The second step is to replace, for each new stobj primitive p, the :LOGIC function for p by p itself. The only :LOGIC function occurring in the formula just above is st$ap, which is the :LOGIC funcction for stp. The guard for update is thus as follows. (and (and (integerp i) (<= 0 i) (<= i 49)) (and (integerp v) (<= 0 v)) (stp st) (mem$c-entryp v)) We turn now to the proof obligations, as promised above. There are three types: :CORRESPONDENCE, :PRESERVED, and :GUARD-THM. All required lemmas may be printed simply by defining the necessary :LOGIC and :EXEC functions and then submitting the defabsstobj event. (To advanced users: also see [defabsstobj-missing-events] for a utility that returns the required formulas in translated form.) Although the defabsstobj event will fail if the required lemmas have not been proved, first it will print the [defthm] forms that must be admitted in order to complete submission of the defabsstobj event. (Note that although the those theorems are stated exactly in the form expected by the system, you are welcome to supply whatever :[rule-classes] you prefer, even though the system creates :rule-classes nil by default.) The detailed theory explaining the need for these lemmas may be found in a comment in ACL2 source file other-events.lisp, in a comment entitled ``Essay on the Correctness of Abstract Stobjs''. Here, we give an informal sense of the importance of these lemmas as we present examples of them. Fundamental is the notion of evaluation in the logic versus evaluation using live stobjs, where one imagines tracking the current value of each abstract stobj during each of these two evaluations. We start with the :CORRESPONDENCE lemmas. These guarantee that evaluation in the logic agrees with evaluation using live stobjs, in the sense that the only difference is between a logical stobj and a live stobj, where the two correspond in the sense of the function specified by :CORR-FN. We start with the :CREATOR function where the statement is quite simple, stating that the :CORR-FN holds initially. (defthm create-st{correspondence} (st$corr (create-st$c) (create-st$a))) For the exported functions, there are essentially two cases. If an exported function returns other than the new abstract stobj, then the theorem asserts the equality of the results of applying the :LOGIC and :EXEC functions for the exported function. Hypotheses include the :CORR-FN correspondence followed by the [guard] for the :LOGIC function, which is stated in terms of the formal parameters of the :EXEC function except using the abstract stobj (here, st) in place of the concrete stobj (here, st$c). The conclusion uses the :EXEC formals, modified in the call of the :LOGIC function (here, lookup$a) to use the abstract stobj, as in the hypotheses. (defthm lookup{correspondence} (implies (and (st$corr st$c st) (integerp i) (<= 0 i) (<= i 49) (st$ap st)) (equal (mem$ci i st$c) (lookup$a i st))) :rule-classes nil) By contrast, if the exported function returns the new abstract stobj, then the conclusion uses the correspondence function insted of EQUAL, as in the following. (defthm update{correspondence} (implies (and (st$corr st$c st) (integerp i) (<= 0 i) (<= i 49) (integerp v) (<= 0 v) (st$ap st) (mem$c-entryp v)) (st$corr (update-mem$ci i v st$c) (update$a i v st))) :rule-classes nil) For exported functions that return multiple values, such conclusions are conjoined together over the returned values. The :PRESERVED lemmas guarantee that updates to the abstract stobj preserve its recognizer. The fact that every exported function has this property provides justification for an optimization performed by ACL2 during generation of proof obligations for [guard] verification, by assuming that the recognizer always holds. The :PRESERVED lemma for the :CREATOR shows that the recognizer holds initially. (defthm create-st{preserved} (st$ap (create-st$a))) Here is a typical such lemma, for the exported function update. Note that there is no such lemma for lookup, since lookup does not return st. (defthm update{preserved} (implies (and (integerp i) (<= 0 i) (<= i 49) (integerp v) (<= 0 v) (st$ap st) (mem$c-entryp v)) (st$ap (update$a i v st)))) Finally, we consider the :GUARD-THM lemmas. These serve to guarantee that the [guard] holds for each call of an :EXEC function. During guard verification, logical definitions are used; in particular, since each exported function is defined in the logic as the corresponding call of its :LOGIC function, guard verification shows that each call of the :LOGIC function for an exported function satisfies that function's guard. But why is this true for raw Lisp evaluation using live stobjs, where the :EXEC function is called for an exported function? The :GUARD-THM lemmas provide the answer, as they state that if the :LOGIC function's guard holds, then the :EXEC function's guard holds. Here is an example. Note that the hypotheses come from the correspondence of the concrete and abstract function as guaranteed by the :CORR function, together with the guard of the :LOGIC function; and the conclusion comes from the guard of the :EXEC function. (defthm lookup{guard-thm} (implies (and (st$corr st$c c) (integerp i) (<= 0 i) (<= i 49) (st$ap st)) (and (integerp i) (<= 0 i) (< i (mem$c-length st$c)))) :rule-classes nil) We conclude this EXAMPLE section by showing a short form for the defabsstobj form displayed above. (defabsstobj st :exports ((lookup :exec mem$ci) (update :exec update-mem$ci) misc update-misc)) SUMMARY DOCUMENTATION The General Form is as shown below, where the order of keywords is unimportant. Duplicate keywords are discouraged; while permitted, only the first (leftmost) occurrence of a given keyword is used. Only the :exports keyword is required. (defabsstobj st :concrete concrete :recognizer recognizer :creator creator :corr-fn corr-fn :congruent-to congruent-to :protect-default protect-default :exports (e1 ... ek) :doc doc) The keyword argument :EXPORTS must be supplied, and missing or nil keyword arguments have defaults as indicated below. All arguments must satisfy the conditions below. Before we describe the arguments, we define a notion of a ``function spec'' and its ``completion''. A function spec is either a symbol or else a list of the form (fn :kwd1 val1 ... :kwdn valn), that is, a symbol followed by a [keyword-value-listp]. We view the case of a symbol, s, as the function spec (s), with no keywords. There must be no duplicate keywords. In each case that we expect a function spec, the context provides a set of valid keywords for that function spec; it is an error to provide any other keyword in the function spec. Each function spec is interpreted as its ``completion'', obtained by extending the function spec with a default value for each valid keyword as indicated below. With that interpretation, the ``exported function'' of a function spec is its car, and that function symbol and each keyword value must be a guard-verified function symbol; and moreover, the :EXEC function must not include the new abstract stobj name, st, among its formals. We are ready to describe the arguments of defabsstobj. St is a symbol, which names the new abstract stobj. Concrete is the name of an existing stobj that is not an abstract stobj, i.e., was introduced with [defstobj] (not [defabsstobj]). Recognizer is a function spec (for the recognizer function). The valid keywords are :LOGIC and :EXEC. The default for recognizer is obtained by adding the suffix \"P\" to name. The default value for :LOGIC is formed by adding the suffix \"$AP\" to recognizer; for :EXEC, by adding the suffix \"$CP\". The :EXEC function must be the recognizer for the specified :CONCRETE stobj. Creator is a function spec (for the creator function). The valid keywords are :LOGIC and :EXEC. The default for creator is obtained by adding the prefix \"CREATE-\" to name. The default value for :LOGIC is formed by adding the suffix \"$A\" to creator; for :EXEC, by adding the suffix \"$C\". The :CREATOR function must be the creator for the specified :CONCRETE stobj, as ACL2 checks that the :CREATOR function takes no arguments and returns the :CONCRETE stobj. Corr-fn is a known function symbol that takes two arguments (for the correspondence theorems). The default for corr-fn is obtained by adding the suffix \"$CORR\" to name. Congruent-to should either be nil (the default) or the name of an abstract stobj previously introduced (by [defabsstobj]). In the latter case, the current and previous abstract stobj should have the same concrete stobj (not merely congruent concrete stobjs), and their :EXPORTS fields should have the same length and also correspond, as follows: the ith export of each should have the same :LOGIC and :EXEC symbols. See [defstobj] for more about congruent stobjs. Note that if two names are congruent, then they are either both ordinary stobjs or both abstract stobjs. Protect-default should either be nil (the default) or t. It provides the value of keyword :PROTECT for each member of exports that does not explicitly specify :PROTECT. See the discussion of exports below. An important aspect of the congruent-to parameter is that if it is not nil, then the checks for lemmas --- {CORRESPONDENCE}, {GUARD-THM}, and {PRESERVED} --- are omitted. Thus, the values of keyword :CORR-FN, and the values of keywords :CORRESPONDENCE, :GUARD-THM, and :PRESERVED in each export (as we discuss next), are irrelevant; they are not inferred and they need not be supplied. The value of :EXPORTS is a non-empty true list. Each ei is a function spec (for an exported function). The valid keywords are :LOGIC, :EXEC, :CORRESPONDENCE, and :GUARD-THM, :PROTECT, and also :PRESERVED if and only if the specified :EXEC function returns the :CONCRETE stobj. The default values for all of these keywords except :PROTECT are obtained by respectively adding the suffix \"$A\" \"$C\", \"{CORRESPONDENCE}\", \"{GUARD-THM}\", or \"{PRESERVED}\". For :PROTECT, the default is nil unless the defabsstobj event specifies :PROTECT-DEFAULT t. Doc, if non-nil, is a string that can provide documentation but is essentially ignored by ACL2. Not shown is the keyword, :MISSING; the effect of :missing t is to turn the call of defabsstobj into a corresponding call of [defabsstobj-missing-events]. Note that a defabsstobj event will fail if the required lemmas --- that is, those for valid keywords :CORRESPONDENCE, :GUARD-THM, and :PRESERVED --- have not been proved, unless proofs are being skipped. The exemption when skipping proofs allows the supporting lemmas to be [local] to [books] and [encapsulate] [events]. If the [ld] special [ld-skip-proofsp] is t, then the missing [events] are printed with a warning before the defabsstobj event is admitted; but if ld-skip-proofsp is the symbol INCLUDE-BOOK, then that warning is omitted. (Also see [skip-proofs] and see [ld-skip-proofsp].) If however proofs are not being skipped, then the defabsstobj event will fail after printing the missing events. Advanced users may wish to see [defabsstobj-missing-events] for a utility that returns a data structure containing the missing lemmas. Let st be an abstract stobj with corresponding concrete stobj st$c. let f be an exported function for st and let f$a and f$c be the corresponding :LOGIC and :EXEC functions, respectively. The formals of f are obtained by taking the formals of f$c and replacing st$c by st. The [guard] for f is derived as follows from the guard of f$a. First, the formals of f$a are replaced by the formals of f in the guard of f$a, to obtain a term we denote here as guard-pre. Now for each exported function symbol g of st with corresponding :LOGIC function g$a, form a functional substitution by consing g$a with g. Finally, apply that functional substitution to guard-pre; the result is the guard of f. That guard must satisfy the usual conditions of a guard: thus, it must return a single non-[stobj] value and satisfy normal syntactic restrictions, including single-threadedness in its handling of stobjs. Remark. Because of how guards are created for exported functions, and in particular because :LOGIC functions are replaced as discussed above, a good discipline is to define :LOGIC functions that are not intended for general use, but are intended only for use as :LOGIC functions of corresponding stobj primitives. For example, suppose that you use length as the :LOGIC function for some stobj primitive, f (as opposed to using your own function, say, foo-length or foo$a). Then every call of length will be replaced by f when creating the guard of a stobj primitive from the guard of its :LOGIC function. This might not be what you intended if you were using length in that guard simply to compute the length of an ordinary list. There are a few additional restrictions, as follows. All exported function names must be new (unless redefinition is on; see [ld-redefinition-action]), and there must be no duplicates among them. The :CONCRETE stobj name must be a formal parameter of the :EXEC fn of every function spec, except for the :CREATOR function spec. Also the input signatures of the :LOGIC and :EXEC function for a function spec must agree, except perhaps at the position of that :CONCRETE formal. For function specs other than the :CREATOR function spec, the output signatures of the :LOGIC and :EXEC functions must have the same length and must agree, except perhaps at position p_out of the :CONCRETE stobj in the :EXEC function's output. If p_in is the position of the :CONCRETE stobj in the :EXEC function's formals, then the :LOGIC function's output at position p_out should match the :LOGIC function's formal at position p_in. The :PROTECT keyword is something that you should ignore unless you get an error message about it, pertaining to modifying the concrete stobj non-atomically. In that case, you can eliminate the error by providing :PROTECT t in the function spec, or by providing defabsstobj keyword argument :PROTECT-DEFAULT t at the top level. The above explanation is probably all you need to know about :PROTECT, but just below is a more complete explanation for those who desire it. Further information is also available if you need it; see [set-absstobj-debug], and see the example uses of these keywords in community book books/misc/defabsstobj-example-2.lisp. For those who are interested, here is a more detailed discussion of :PROTECT and :PROTECT-DEFAULT, as promised above. It applies to any function spec for an export (hence not to the :CREATOR function spec). If the :EXEC function is a stobj primitive, then clearly the following property holds: any execution of a call of that function can only update the concrete stobj at most once --- i.e., modification of the concrete stobj is atomic. ACL2 can deduce this property not only for stobj primitives but for many other functions as well. However, if ACL2 cannot deduce this property, then it will cause an error saying that the :EXEC function ``appears capable of modifying the concrete stobj, , non-atomically.'' That message also explains how to eliminate this error: provide :PROTECT t for the function spec. Alternatively, all function specs without an explicit :PROTECT keyword can be implicitly supplied :PROTECT t by supplying the value t for the :PROTECT-DEFAULT keyword parameter of the defabsstobj event. However, beware that when :PROTECT is t, the generated raw Lisp code runs slightly less efficiently --- though perhaps with negligible efficiency loss if the :EXEC function is not trivial. Community books books/misc/defabsstobj-example-3.lisp and books/misc/defabsstobj-example-4.lisp provide related information. We conclude with some remarks. Unlike [defstobj], there is no :renaming argument. Instead, the scheme described above provides a flexible way to assign names. Also unlike [defstobj], there is no :inline or :non-memoizable argument; :inline is essentially t, in the sense that stobj primitives are macros in raw Lisp; and the :non-memoizable argument is derived implicitly from the value of that argument (nil by default) for the corresponding concrete stobj. Those who use [hons-enabled] ACL2 executables (built by default), which includes function memoization (see [memoize]), may be aware that the memo table for a function is flushed whenever it is the case that one of its stobj inputs is updated. In fact, such flushing happens even when a stobj that is congruent to one of its stobj inputs is updated. For that purpose, an abstract stobj is considered to be congruent to its corresponding concrete stobj. Subtopics [Set-absstobj-debug] Obtain debugging information upon atomicity violation for an abstract stobj") (DEFABSSTOBJ-MISSING-EVENTS (EVENTS) "Obtain the [events] needed to admit a [defabsstobj] event We assume familiarity with [defabsstobj]. Defabsstobj-missing-events is a macro is for advanced users (who, for example, understand the role of the translate and untranslate functions), who want programmatic access to the [defthm] events required to admit a specific defabsstobj event. This macro has the same syntax as [defabsstobj] --- to use it, just replace a call of [defabsstobj] by a call of defabsstobj-missing-events on the same arguments. The result is an error triple (mv erp val state). If erp is nil, then val is the list of all objects (name formula . old-formula), where a [defthm] event named name remains to be admitted whose translated formula is formula, and where old-formula is nil unless the indicated event already exists (hence with a different formula), in which case old-formula is the existing translated formula. To build a [defthm] event from the above value, val, we suggest evaluating a form like (untranslate formula t (w state)).") (DEFATTACH (EVENTS) "Execute constrained functions using corresponding attached functions This [documentation] topic is organized into the following sections: Introductory example. Syntax and semantics of defattach. Three primary uses of defattach. Miscellaneous remarks, with discussion of possible user errors. Please see [encapsulate] if you intend to use defattach but are not already familiar with the use of encapsulate to introduce constrained functions. See community book books/misc/defattach-example.lisp for a small example. it illustrates how defattach may be used to build something like ``higher-order'' programs, in which constrained functions may be refined to different executable functions. More uses of defattach may be found in the ACL2 source code, specifically, file boot-strap-pass-2.lisp. The argument :skip-checks t enables easy experimentation with defattach, by permitting use of :[program] mode functions and the skipping of semantic checks. Also permitted is :skip-checks nil (the default) and :skip-checks :cycles, which turns off only the update of the extended ancestor relation (see below) and hence the check for cycles in this relation; see below. We do not make any logical claims when the value of :skip-checks is non-nil; indeed, a trust tag is required in this case (see [defttag]). Remark for [hons-enabled] ACL2 executables (built by default): the interaction of memoization and attachments is not tracked for attachments introduced with a non-nil value of :skip-checks. For more discussion of :skip-checks t, see [defproxy]; we do not discuss :skip-checks further, here. Introductory example. 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 ...] T ACL2 !>(defun g (x) (declare (xargs :guard (or (consp x) (null x)))) (cons 17 (car x))) [... output omitted ...] 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 ...] :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> (ACL2_*1*_ACL2::G (3 4)) 3> (G (3 4)) <3 (G (17 . 3)) <2 (ACL2_*1*_ACL2::G (17 . 3)) <1 (ACL2_*1*_ACL2::F (17 . 3)) (17 . 3) ACL2 !>(defattach f nil) ; unattach f (remove its attachment) [... output omitted ...] :ATTACHMENTS-RECORDED ACL2 !>(f '(3 4)) ; undefined function error once again 1> (ACL2_*1*_ACL2::F (3 4)) 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 !> Syntax and semantics of defattach. The log above shows that the event (defattach f g) allows g to be used for evaluating calls of f. From a logical perspective, the evaluation takes place in the addition to the current session of an ``attachment equation'' axiom (universally quantified over all x) for each defattach event: (equal (f x) (g x)) ;;; attachment equation axiom for (defattach f g) Below we explain defattach in some detail. But it is important to keep in mind that evaluation with the attachment equations takes place in an extension of the logical theory of the session. ACL2 guarantees that this so-called ``evaluation theory'' remains consistent, assuming the absence of [defaxiom] [events] from the user. This guarantee is a consequence of a more general guarantee: an ACL2 logical [world] exists in which (loosely speaking) the attachment equation for (defattach f g), as (defun f (...) (g ...)), takes the place of the original defining event for f, for each defattach event. This more general guarantee holds even if there are [defaxiom] events, though as explained below, no function symbol that syntactically supports a defaxiom formula is allowed to get an attachment. A deeper discussion of the logical issues is available (but not intended to be read by most users) in a long comment in the ACL2 source code labeled ``Essay on Defattach.'' 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))) :otf-flg t)) ; as above, except with an :otf-flg of t for the proof that ; the guard of f implies the guard of g (defattach (f g) :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\" :use my-thm)) :otf-flg t) ; as above, except with an :otf-flg of t for the proof that ; the constraints on f hold for g (defattach (f g) (h j)) ; Attach g to f and attach j to h (defattach (f g :attach nil) (h j)) ; Same as just above, including the same proof obligations, ; except for one difference: because of :attach nil, calls ; of f will not be evaluated, i.e., there will be no ; executable attachment of g to f (defattach (f nil) (h j)) ; Attach j to h and unattach f (defattach (f g :hints ((\"Goal\" :in-theory (enable foo)))) (h j :hints ((\"Goal\" :in-theory (enable bar)))) :hints ((\"Goal\" :use my-thm))) ; Attach g to f and attach j to h, with 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 above General Forms: (defattach f g) ; single attach or, if g is nil, unattach (defattach (f1 g1 :kwd val ...) ... (fk gk :kwd' val' ...) :kwd'' val'' ...) where each indicated keyword-value pair is optional and each keyword is one of :ATTACH, :HINTS, :OTF-FLG, or :INSTRUCTIONS. The value of each :ATTACH keyword is either t or nil, with default t except that the value of :ATTACH at the ``top level,'' after each entry (fi gi ...), is the default for each :ATTACH keyword supplied in such an entry. We discuss the :ATTACH keyword later in this [documentation] topic. The associated values for the other keywords have the usual meanings for the proof obligations described below: the guard proof obligation for keywords within each (fi gi ...) entry, and the constraint proof obligation for keywords at the top level. No keyword may occur twice in the same context, i.e., within the same (fi gi ...) entry or at the top level; and :INSTRUCTIONS may not occur in the same context with :HINTS or :OTF-FLG. 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. For the second General Form we say that gi is ``attached to'' fi (by the defattach event) if gi is not nil, and otherwise we say that fi is ``unattached'' (by the defattach event). It is also convenient to refer to as an ``attachment pair'' (of the event) if gi is not nil. We may refer to the set of fi as the ``attachment nest'' of each fi. We start with a brief introduction to the first General Form 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.'' Notable exceptions, where we do not use attachments during evaluation, are for macroexpansion, evaluation of [defconst] and [defpkg] terms, evaluation during [table] events, some [stobj] operations including all [updates], and especially evaluation of ground terms (terms without free variables) during proofs. However, even for these cases we allow the use of attachments in the first argument of [prog2$] and, more generally, the next-to-last (i.e., second) argument of [return-last] when its first argument is not of the form 'm for some macro, m. To see why attachments are disallowed during evaluation of ground terms during proofs (except for the [prog2$] and [return-last] cases mentioned above), 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, since that would be unsound, as 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, the result is the removal of the existing attachment to f, if any. After this removal, calls of f will once again cause errors saying that ``ACL2 cannot ev the call of undefined function f ...''. In this case not only is the previous attachment to f removed; moreover, for every function symbol f' in the attachment nest of f in the defattach event that introduced the existing attachment to f, then f' is unattached. (An example near the end of this [documentation] topic shows why this unattachment needs to be done.) Such removal takes place before the current defattach is processed, but is restored if the new event fails to be admitted. We focus henceforth on the second General Form. There must be at least one attachment, i.e., i must be at least 1. All keywords are optional; their role is described below. The fi must be distinct constrained function symbols, that is, function symbols all introduced in [signature]s of [encapsulate] [events] (or macros such as [defstub] that generate [encapsulate] events). Each non-nil gi is a :[logic]-mode function symbol that has had its guards verified, with the same [signature] as fi (though formal parameters for fi and gi may have different names). (Note: The macro defattach!, defined in community book books/misc/defattach-bang, avoids this restriction.) This event generates proof obligations and an ordering check, both described below. The effect of this event is first to remove any existing attachments for all the function symbols fi, as described above for the first General Form, and then to attach each gi to fi. Proof obligations must be checked before making attachments. For this discussion we assume that each gi is non-nil (otherwise first remove all attachment pairs for which gi is nil). Let s be the functional substitution mapping each fi to gi. For any term u, we write u\\s for the result of applying s to u; that is, u\\s is the ``functional instance'' obtained by replacing each fi by gi in u. Let G_fi and G_gi be the guards of fi and gi, respectively. Let G_fi' be the result of replacing each formal of fi by the corresponding formal of gi in G_fi. ACL2 first proves, for each i (in order), the formula (implies G_fi' G_gi)\\s. If this sequence of proofs succeeds, then the remaining formula to prove is the functional instance C\\s of the conjunction C of the constraints on the symbols fi; see [constraint]. This last proof obligation is thus similar to the one generated by functional instantiation (see [constraint]). 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]). Thus, you will likely avoid some proofs with the sequence (defattach f g) (defattach f nil) (defattach f g) (defattach f nil) ... rather than the sequence: (defattach f g) :u (defattach f g) :u ... It remains to describe an ordering check. We begin with the following motivating example. (defstub f (x) t) ; constrained function with no constraints (defun g (x) (declare (xargs :guard t)) (not (f x))) (defattach f g) ; ILLEGAL! Were the above defattach event to succeed, the evaluation theory (discussed above) would be inconsistent: (f x) equals (g x) by the new attachment equation, which in turn equals (not (f x)) by definition of g. The evaluation would therefore be meaningless. Also, from a practical perspective, there would be an infinite loop resulting from any call of f. We consider a function symbol g to be an ``extended immediate ancestor of'' a function symbol f if either of the following two criteria is met: (a) g occurs in the formula that introduces f (i.e., definition body or constraint) and g is introduced by an event different from (earlier than) the event introducing f; or (b) g is attached to f. For a proposed defattach event, we check that this relation has no cycles, where for condition (b) we include all attachment pairs that would result, including those remaining from earlier defattach events. Of course, a special case is that no function symbol may be attached to itself. Similarly, no function symbol may be attached to any of its ``siblings'' --- function symbols introduced by the same event --- as siblings are considered equivalent for purposes of the acyclicity check. Three primary uses of defattach. We anticipate three uses of defattach: (1) Constrained function execution (2) Sound modification of the ACL2 system (3) Program refinement We discuss these in turn. (1) The example at the beginning of this [documentation] illustrates constrained function execution. (2) ACL2 is written essentially in itself. Thus, there is an opportunity to attaching to system functions. For example, encapsulated function too-many-ifs-post-rewrite, in the ACL2 source code, receives an attachment of too-many-ifs-post-rewrite-builtin, which implements a heuristic used in the rewriter. To find all such examples, search the source code for the string `-builtin'. Over time, we expect to continue replacing ACL2 source code in a similar manner. We invite the ACL2 community to assist in this ``open architecture'' enterprise; feel free to email the ACL2 implementors if you are interested in such activity. (3) Recall that for an attachment pair , a proof obligation is (speaking informally) that g satisfies the constraint on f. Yet more informally speaking, g is ``more defined'' than f; we can think of g as ``refining'' f. With these informal notions as motivation, we can view defattach as providing refinement though the following formal observation: the evaluation theory extends the theory of the ACL2 session, specifically by the addition of all attachment equations. For the logic-inclined, it may be useful to think model-theoretically: The class of models of the evaluation theory is non-empty but is a subset of the class of models of the current session theory. Miscellaneous remarks, with discussion of possible user errors. We conclude with remarks on some details. A defattach event is never redundant (see [redundant-events]); in that sense it is analogous to [in-theory]. As mentioned above, the use of attachments is disabled for evaluation of ground terms during proofs. However, attachments can be used on code during the proof process, essentially when the ``program refinement'' is on theorem prover code rather than on functions we are reasoning about. The attachment to too-many-ifs-post-rewrite described above provides one example of such attachments. Meta functions and clause-processor functions can also have attachments, with the restriction that no common ancestor with the evaluator can have an attachment; see [evaluator-restrictions]. For an attachment pair , evaluation of f never consults the [guard] of f. Rather, control passes to g, whose guard is checked if necessary. The proof obligation related to guards, as described above, guarantees that any legal call of f is also a legal call of g. Thus for guard-verified code that results in calls of f in raw Lisp, it is sound to replace these calls with corresponding calls of g. Defattach events are illegal inside any [encapsulate] event with a non-empty [signature] unless they are [local] to the [encapsulate]. We next discuss a restriction based on a notion of a function symbol syntactically supporting an event. Function symbol f is ancestral in event E if either f occurs in E, or (recursively) f occurs in an event E' that introduces some function symbol g that is ancestral in E. We require that no function symbol ancestral in the formula of a [defaxiom] event may have an attachment. Theoretical reasons are discussed in comments in the ACL2 source code, but here we give a little example showing the need for some such restriction: without it, we show how to prove nil! (defn g1 () 1) (defn g2 () 2) (defstub f1 () t) (defstub f2 () t) (defund p (x) (declare (ignore x)) t) (defevaluator evl evl-list ((p x))) (defaxiom f1-is-f2 (equal (f1) (f2))) (defun meta-fn (x) (cond ((equal (f1) (f2)) x) (t *nil*))) (defthm bad-meta-rule (equal (evl x a) (evl (meta-fn x) a)) :rule-classes ((:meta :trigger-fns (p)))) (defattach f1 g1) (defattach f2 g2) (defthm contradiction nil :hints ((\"Goal\" :use ((:instance (:theorem (not (p x))) (x t))))) :rule-classes nil) To see all attachments: (all-attachments (w state)). (Note that attachments introduced with a non-nil value of :skip-checks will be omitted from this list.) Next we discuss the :ATTACH keyword. There is rarely if ever a reason to specify :ATTACH T, but the following (admittedly contrived) example shows why it may be necessary to specify :ATTACH NIL. First we introduce three new function symbols. (defstub f (x) t) (defun g (x) (f x)) (encapsulate ((h (x) t)) (local (defun h (x) (g x))) (defthm h-prop (equal (h x) (g x)))) Now suppose we want to attach the function [ACL2-numberp] to both f and h. (defattach (f acl2-numberp) (h acl2-numberp)) Such an attempt fails, because the following constraint is generated but is not a theorem: (EQUAL (ACL2-NUMBERP X) (G X)). Clearly we also need to attach to g as well. (defattach (f acl2-numberp) (h acl2-numberp) (g acl2-numberp)) But this fails for a different reason, as explained by the error message: ACL2 Error in ( DEFATTACH (F ACL2-NUMBERP) ...): It is illegal to attach to function symbol G, because it was introduced with DEFUN. See :DOC defattach. That is: logically, we need to attach acl2-numberp to g, but we cannot actually attach to g because it was introduced with [defun], not with [encapsulate]. So we specify :ATTACH NIL for the attachment to g, saying that no actual attachment should be made to the code for g, even though for logical purposes we should consider that g has been given the indicated attachment. (defattach (f acl2-numberp) (h acl2-numberp) (g acl2-numberp :attach nil)) Finally, we can check that f, g, and h execute as expected. ACL2 !>(assert-event (and (f 3) (not (f t)) (g 3) (not (g t)) (h 3) (not (h t)))) :PASSED ACL2 !> We conclude with an example promised above, showing why it is necessary in general to unattach all function symbols in an existing attachment nest when unattaching any one of those function symbols. Consider the following example. (defstub f1 () t) (encapsulate ((f2 () t)) (local (defun f2 () (f1))) (defthm f2=f1 (equal (f2) (f1)))) (encapsulate ((f3 () t)) (local (defun f3 () (f1))) (defthm f3=f1 (equal (f3) (f1)))) (defun four () (declare (xargs :guard t)) 4) (defun five () (declare (xargs :guard t)) 5) (defattach (f1 four) (f2 four)) (defattach (f1 five) (f3 five)) The second defattach replaces erases the existing attachment pair before installing the new attachment pairs and . After the second defattach, both (f1) and (f3) evaluate to 5. Now suppose that the attachment pair were not erased. Then we would have (f1) evaluating to 5 and (f2) evaluating to 4, contradicting the constraint f2=f1. The evaluation theory would thus be inconsistent, and at a more concrete level, the user might well be surprised by evaluation results if the code were written with the assumption specified in the constraint f2=f1. Subtopics [Ignored-attachment] Why attachments are sometimes not used") (DEFAULT (ARRAYS ACL2-BUILT-INS) "Return the :default from the [header] of a 1- or 2-dimensional array Example Form: (default 'delta1 a) General Form: (default name alist) where name is an arbitrary object and alist is a 1- or 2-dimensional array. This function returns the contents of the :default field of the [header] of alist. When [aref1] or [aref2] is used to obtain a value for an index (or index pair) not bound in alist, the default value is returned instead. Thus, the array alist may be thought of as having been initialized with the default value. default operates in virtually constant time if alist is the semantic value of name. See [arrays]. Function: (defun default (name l) (declare (xargs :guard (or (array1p name l) (array2p name l)))) (cadr (assoc-keyword :default (cdr (header name l)))))") (DEFAULT-BACKCHAIN-LIMIT (RULE-CLASSES) "Specifying the backchain limit for a rule See [backchain-limit]. The initial value is (nil nil). To inspect the current value (as explained elsewhere; see [backchain-limit]): (default-backchain-limit wrld :ts) ; for type-set reasoning (default-backchain-limit wrld :rewrite) ; for rewriting") (DEFAULT-DEFUN-MODE (MISCELLANEOUS) "The default [defun-mode] of [defun]'d functions When a [defun] is processed and no :mode xarg is supplied, the function default-defun-mode is used. To find the default [defun-mode] of the current ACL2 [world], type (default-defun-mode (w state)). See [defun-mode] for a discussion of [defun-mode]s. To change the default [defun-mode] of the ACL2 [world], type one of the keywords :[program] or :[logic]. The default ACL2 [prompt] displays the current default [defun-mode] by showing the character p for :[program] mode, and omitting it for :[logic] mode; see [default-print-prompt]. The default [defun-mode] may be changed using the keyword [command]s :[program] and :[logic], which are equivalent to the [command]s (program) and (logic). Each of these names is documented separately: see [program] and see [logic]. The default [defun-mode] is stored in the [table] [ACL2-defaults-table] and hence may also be changed by a [table] [command]. See [table] and also see [ACL2-defaults-table]. Both mode-changing [command]s are [events]. While [events] that change the default [defun-mode] are permitted within an [encapsulate] or the text of a book, their effects are [local] in scope to the duration of the encapsulation or inclusion. For example, if the default [defun-mode] is :[logic] and a book is included that contains the event (program), then subsequent [events] within the book are processed with the default [defun-mode] :[program]; but when the [include-book] event completes, the default [defun-mode] will still be :[logic]. [Command]s that change the default [defun-mode] are not permitted inside [local] forms.") (DEFAULT-HINTS (HINTS) "A list of hints added to every proof attempt Examples: ACL2 !>(default-hints (w state)) ((computed-hint-1 clause) (computed-hint-2 clause stable-under-simplificationp)) The value returned by this function is added to the right of the :[hints] argument of every [defthm] and [thm] command, and to hints provided to [defun]s as well (:hints, :guard-hints, and (for ACL2(r)) :std-hints). See [set-default-hints] for a more general discussion. Advanced users only: see [override-hints] for an advanced variant of default hints that are not superseded by :[hints] arguments. Subtopics [Add-default-hints] Add to the default hints [Add-default-hints!] Add to the default hints non-[local]ly [Default-hints-table] A [table] used to provide [hints] for proofs [Remove-default-hints] Remove from the default hints [Remove-default-hints!] Remove from the default hints non-[local]ly [Set-default-hints] Set the default hints [Set-default-hints!] Set the default hints non-[local]ly") (DEFAULT-HINTS-TABLE (DEFAULT-HINTS) "A [table] used to provide [hints] for proofs Please see [set-default-hints], see [add-default-hints], and see [remove-default-hints] for how to use this table. For completeness, we mention here that under the hood, these events all update the default-hints-table by updating its key, t, for example as follows. (table default-hints-table t '((computed-hint-1 clause) (computed-hint-2 clause stable-under-simplificationp))) The use of default hints is explained elsewhere; see [set-default-hints]. Advanced users only: see [override-hints] for an advanced variant of default hints.") (DEFAULT-PRINT-PROMPT (LD) "The default [prompt] printed by [ld] Example prompt: ACL2 p!s> The [prompt] printed by ACL2 displays the current package, followed by a space, followed by zero or more of the three [characters] as specified below, followed by the character [>] printed one or more times, reflecting the number of recursive calls of [ld]. The three [characters] in the middle are as follows: p ; when (default-defun-mode (w state)) is :program ! ; when guard checking is on s ; when (ld-skip-proofsp state) is t See [default-defun-mode], see [set-guard-checking], and see [ld-skip-proofsp]. Also see [ld-prompt] to see how to install your own [prompt]. Here are some examples with ld-skip-proofsp nil. ACL2 !> ; logic mode with guard checking on ACL2 > ; logic mode with guard checking off ACL2 p!> ; program mode with guard checking on ACL2 p> ; program mode with guard checking off Here are some examples with [default-defun-mode] of :[logic]. ACL2 > ; guard checking off, ld-skip-proofsp nil ACL2 s> ; guard checking off, ld-skip-proofsp t ACL2 !> ; guard checking on, ld-skip-proofsp nil ACL2 !s> ; guard checking on, ld-skip-proofsp t Finally, here is the prompt in raw mode (see [set-raw-mode]), regardless of the settings above: ACL2 P>") (DEFAULT-RULER-EXTENDERS (RULER-EXTENDERS) "The default [ruler-extenders] for [defun]'d functions When a [defun] is processed and no :ruler-extenders xarg is supplied, the function default-ruler-extenders is used to obtain the current ruler-extenders; see [ruler-extenders]. To find the default [ruler-extenders] of the current ACL2 [world], type (default-ruler-extenders (w state)). While [events] that change the default [ruler-extenders] are permitted within an [encapsulate] or the text of a book, their effects are [local] in scope to the duration of the encapsulation or inclusion. See [default-defun-mode] for an analogous discussion for defun-modes.") (DEFAULT-TOTAL-PARALLELISM-WORK-LIMIT (PARALLEL-PROOF) "For ACL2(p): returns the default value for global total-parallelism-work-limit See [set-total-parallelism-work-limit].") (DEFAULT-VERIFY-GUARDS-EAGERNESS (POINTERS) "See [set-verify-guards-eagerness].") (DEFAXIOM (EVENTS) "Add an axiom WARNING: We strongly recommend that you not add axioms. If at all possible you should use [defun] or [mutual-recursion] to define new concepts recursively or use [encapsulate] to constrain them constructively. If your goal is to defer a proof by using a top-down style, consider using [skip-proofs]; see the discussion on ``Top-Down Proof'' in Section B.1.2 of ``Computer-Aided Reasoning: An Approach.'' Adding new axioms frequently renders the logic inconsistent. Example: (defaxiom sbar (equal t nil) :rule-classes nil) General Form: (defaxiom name term :rule-classes rule-classes :doc doc-string) where name is a new symbolic name (see [name]), term is a term intended to be a new axiom, rule-classes is a legal value for :rule-classes (see [rule-classes]), and doc-string, if non-nil, is a string that can provide documentation but is essentially ignored by ACL2. The two keyword arguments are optional. If :[rule-classes] is not supplied, the list (:rewrite) is used; if you wish the axiom to generate no rules, specify :[rule-classes] nil.") (DEFCHOOSE (EVENTS) "Define a Skolem (witnessing) function Examples: (defchoose choose-x-for-p1-and-p2 (x) (y z) (and (p1 x y z) (p2 x y z))) (defchoose choose-x-for-p1-and-p2 x (y z) ; equivalent to the above (and (p1 x y z) (p2 x y z))) ; The following is as above, but strengthens the axiom added to pick a sort ; of canonical witness, as described below. (defchoose choose-x-for-p1-and-p2 x (y z) (and (p1 x y z) (p2 x y z)) :strengthen t) (defchoose choose-x-and-y-for-p1-and-p2 (x y) (z) (and (p1 x y z) (p2 x y z))) General Form: (defchoose fn (bound-var1 ... bound-varn) (free-var1 ... free-vark) body :doc doc-string :strengthen b), where fn is the symbol you wish to define and is a new symbolic name (see [name]), (bound-var1 ... bound-varn) is a list of distinct `bound' variables (see below), (free-var1 ... free-vark) is the list of formal parameters of fn and is disjoint from the bound variables, and body is a term. The use of lambda-list keywords (such as &optional) is not allowed. Doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. The :strengthen keyword argument is optional; if supplied, it must be t or nil. The system treats fn very much as though it were declared in the [signature] of an [encapsulate] event, with a single axiom exported as described below. If you supply a :use hint (see [hints]), :use fn, it will refer to that axiom. No rule (of class :[rewrite] or otherwise; see [rule-classes]) is created for fn. Defchoose is only executed in [defun-mode] :[logic]; see [defun-mode]. Also see [defun-sk]. In the most common case, where there is only one bound variable, it is permissible to omit the enclosing parentheses on that variable. The effect is the same whether or not those parentheses are omitted. We describe this case first, where there is only one bound variable, and then address the other case. Both cases are discussed assuming :strengthen is nil, which is the default. We deal with the case :strengthen t at the end. The effect of the form (defchoose fn bound-var (free-var1 ... free-vark) body) is to introduce a new function symbol, fn, with formal parameters (free-var1 ... free-vark). Now consider the following axiom, which states that fn picks a value of bound-var so that the body will be true, if such a value exists: (1) (implies body (let ((bound-var (fn free-var1 ... free-vark))) body)) This axiom is ``clearly conservative'' under the conditions expressed above: the function fn simply picks out a ``witnessing'' value of bound-var if there is one. For a rigorous statement and proof of this conservativity claim, see [conservativity-of-defchoose]. Next consider the case that there is more than one bound variable, i.e., there is more than one bound-var in the following. (defchoose fn (bound-var1 ... bound-varn) (free-var1 ... free-vark) body) Then fn returns a multiple value with n components, and formula (1) above is expressed using [mv-let] as follows: (implies body (mv-let (bound-var1 ... bound-varn) (fn free-var1 ... free-vark) body)) We now discuss the case that :strengthen t is supplied. For simplicity we return to our simplest case, with defchoose applied to function fn, a single free variable y, and a single bound variable bound-var. The idea is that if we pick the ``smallest'' witnessing bound-var for two different free variables y and y1, then either those two witnesses are the same, or else one is less than the other, in which case the smaller one is a witness for its free variable but not for the other. (See comments in source function defchoose-constraint-extra for more details.) Below, body1 is the result of replacing y by y1 in body. (2) (or (equal (fn y) (fn y1)) (let ((bound-var (fn y))) (and body (not body1))) (let ((bound-var (fn y1))) (and body1 (not body)))) An important application of this additional axiom is to be able to define a ``fixing'' function that picks a canonical representative of each equivalence class, for a given equivalence relation. The following events illustrate this point. (encapsulate ((equiv (x y) t)) (local (defun equiv (x y) (equal x y))) (defequiv equiv)) (defchoose efix (x) (y) (equiv x y) :strengthen t) (defthm equiv-implies-equal-efix-1 (implies (equiv y y1) (equal (efix y) (efix y1))) :hints ((\"Goal\" :use efix)) :rule-classes (:congruence)) (defthm efix-fixes (equiv (efix x) x) :hints ((\"Goal\" :use ((:instance efix (y x)))))) If there is more than one bound variable, then (2) is modified in complete analogy to (1) to use [mv-let] in place of [let]. Comment for logicians: As we point out in the documentation for [defun-sk], defchoose is ``appropriate,'' by which we mean that it is conservative, even in the presence of epsilon-0 induction. For a proof, See [conservativity-of-defchoose]. Subtopics [Conservativity-of-defchoose] Proof of conservativity of [defchoose]") (DEFCONG (EVENTS) "Prove [congruence] rule Defcong is used to prove that one [equivalence] relation preserves another in a given argument position of a given function. Example: (defcong set-equal iff (memb x y) 2) is an abbreviation for (defthm set-equal-implies-iff-memb-2 (implies (set-equal y y-equiv) (iff (memb x y) (memb x y-equiv))) :rule-classes (:congruence)) See [congruence] and also see [equivalence]. NOTE: defcong may only be used to create classic [congruence] rules, not [patterned-congruence] rules. General Form: (defcong equiv1 equiv2 term k :rule-classes rule-classes :instructions instructions :hints hints :otf-flg otf-flg :event-name event-name :doc doc) where equiv1 and equiv2 are known [equivalence] relations; term is a call of a function fn, other than if, on the correct number of distinct variable arguments, (fn x1 ... xn); k is a positive integer less than or equal to the arity of fn; and other arguments are as specified in the documentation for [defthm]. The defcong macro expands into a call of [defthm]. The name of the [defthm] event is equiv1-implies-equiv2-fn-k unless an :event-name keyword argument is supplied for the name. The term of the theorem is (implies (equiv1 xk yk) (equiv2 (fn x1... xk ...xn) (fn x1... yk ...xn))). The rule-class :[congruence] is added to the [rule-classes] specified, if it is not already there. All other arguments to the generated [defthm] form are as specified by the keyword arguments above.") (DEFCONST (EVENTS PROGRAMMING) "Define a constant Examples: (defconst *digits* '(0 1 2 3 4 5 6 7 8 9)) (defconst *n-digits* (the unsigned-byte (length *digits*))) General Form: (defconst name term doc-string) where name is a symbol beginning and ending with the character *, term is a variable-free term that is evaluated to determine the value of the constant, and doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. When a constant symbol is used as a [term], ACL2 replaces it by its value; see [term]. Note that defconst uses a ``safe mode'' to evaluate its form, in order to avoids soundness issues but with an efficiency penalty (perhaps increasing the evaluation time by several hundred percent). If efficiency is a concern, or if for some reason you need the form to be evaluated without safe mode (e.g., you are an advanced system hacker using trust tags to traffic in raw Lisp code), consider using [defconsts] instead. Also see [using-tables-efficiently] for an analogous issue with [table] events. It may be of interest to note that defconst is implemented at the lisp level using defparameter, as opposed to defconstant. (Implementation note: this is important for proper support of undoing and redefinition.) We close with a technical remark, perhaps of interest only who make use of the [hons-enabled] features of ACL2. For an event of the form (defconst *C* (quote OBJ)), i.e., (defconst *C* 'OBJ), then the value associated with *C* is OBJ; that is, the value of *C* is [eq] to the actual object OBJ occurring in the defconst form. So for example, if [make-event] is used to generate such a defconst event, as it is in the two books mentioned above, and OBJ is a fast alist (see [fast-alists]), then the value of *C* is a fast alist. This guarantee disappears if the term in the defconst form is not a quoted object, i.e., if it is not of the form (quote OBJ). Subtopics [Sharp-dot-reader] Read-time evaluation of constants") (DEFDOC (EVENTS) "Deprecated event (formerly for adding documentation) This event is deprecated; see [xdoc] for information about [documentation] in ACL2. Defdoc [events] are never considered redundant (see [redundant-events]).") (DEFEQUIV (EVENTS) "Prove that a function is an [equivalence] relation Example: (defequiv set-equal) is an abbreviation for (defthm set-equal-is-an-equivalence (and (booleanp (set-equal x y)) (set-equal x x) (implies (set-equal x y) (set-equal y x)) (implies (and (set-equal x y) (set-equal y z)) (set-equal x z))) :rule-classes (:equivalence)) See [equivalence]. General Form: (defequiv fn :rule-classes rule-classes :instructions instructions :hints hints :otf-flg otf-flg :event-name event-name :doc doc) where fn is a function symbol of arity 2, event-name, if supplied, is a symbol, and all other arguments are as specified in the documentation for [defthm]. The defequiv macro expands into a call of defthm. The name of the defthm is fn-is-an-equivalence, unless event-name is supplied, in which case event-name is the name used. The term generated for the defthm event states that fn is Boolean, reflexive, symmetric, and transitive. The rule-class :equivalence is added to the [rule-classes] specified, if it is not already there. All other arguments to the generated defthm form are as specified by the other keyword arguments above.") (DEFEVALUATOR (EVENTS) "Introduce an evaluator function Example: (defevaluator evl evl-list ((length x) (member-equal x y))) See [meta]. General Form: (defevaluator ev ev-list ((g1 x1 ... xn_1) ... (gk x1 ... xn_k)) where ev and ev-list are new function symbols and g1, ..., gk are old function symbols with the indicated number of formals, i.e., each gi has n_i formals. This function provides a convenient way to constrain ev and ev-list to be mutually-recursive evaluator functions for the symbols g1, ..., gk. Roughly speaking, an evaluator function for a fixed, finite set of function symbols is a restriction of the universal evaluator to terms composed of variables, constants, lambda expressions, and applications of the given functions. However, evaluator functions are constrained rather than defined, so that the proof that a given metafunction is correct vis-a-vis a particular evaluator function can be lifted (by functional instantiation) to a proof that it is correct for any larger evaluator function. See [meta] for a discussion of metafunctions. Defevaluator executes an [encapsulate] after generating the appropriate [defun] and [defthm] events. Perhaps the easiest way to understand what defevaluator does is to execute the keyword command :trans1 (defevaluator evl evl-list ((length x) (member-equal x y))) and inspect the output. This trick is also useful in the rare case that the event fails because a hint is needed. In that case, the output of :[trans1] can be edited by adding hints, then submitted directly. Formally, ev is said to be an ``evaluator function for g1, ..., gk, with mutually-recursive counterpart ev-list'' iff ev and ev-list are constrained functions satisfying just the [constraint]s discussed below. Ev and ev-list must satisfy [constraint]s (0)-(4) and (k): (0) How to ev an arbitrary function application: (implies (and (consp x) (syntaxp (not (equal a ''nil))) (not (equal (car x) 'quote))) (equal (ev x a) (ev (cons (car x) (kwote-lst (ev-list (cdr x) a))) nil))) (1) How to ev a variable symbol: (implies (symbolp x) (equal (ev x a) (and x (cdr (assoc-equal x a))))) (2) How to ev a constant: (implies (and (consp x) (equal (car x) 'quote)) (equal (ev x a) (cadr x))) (3) How to ev a lambda application: (implies (and (consp x) (consp (car x))) (equal (ev x a) (ev (caddar x) (pairlis$ (cadar x) (ev-list (cdr x) a))))) (4) How to ev an argument list: (implies (consp x-lst) (equal (ev-list x-lst a) (cons (ev (car x-lst) a) (ev-list (cdr x-lst) a)))) (implies (not (consp x-lst)) (equal (ev-list x-lst a) nil)) (k) For each i from 1 to k, how to ev an application of gi, where gi is a function symbol of n arguments: (implies (and (consp x) (equal (car x) 'gi)) (equal (ev x a) (gi (ev x1 a) ... (ev xn a)))), where xi is the (cad...dr x) expression equivalent to (nth i x). Defevaluator defines suitable witnesses for ev and ev-list, proves the theorems about them, and constrains ev and ev-list appropriately. We expect defevaluator to work without assistance from you, though the proofs do take some time and generate a lot of output. The proofs are done in the context of a fixed theory, namely the value of the constant *defevaluator-form-base-theory*. (Aside: (3) above may seem surprising, since the bindings of a are not included in the environment that is used to evaluate the lambda body, (caddar x). However, ACL2 lambda expressions are all closed: in (lambda (v1 ... vn) body), the only free variables in body are among the vi. See [term].)") (DEFEXEC (EVENTS MBE) "Attach a terminating executable function to a definition Suppose you define a function (fn x) with a [guard] of (good-input-p x), and you know that when the guard holds, the measure decreases on each recursive call. Unfortunately, the definitional principle (see [defun]) ignores the guard. For example, if the definition has the form (defun fn (x) (declare (xargs :guard (good-input-p x))) (if (not-done-yet x) (... (fn (destr x)) ...) ...)) then in order to admit this definition, ACL2 must prove the appropriate formula asserting that (destr x) is ``smaller than'' x under the assumption (not-done-yet x) but without the assumption (good-input-p x), even if (not-done-yet x) is true. In essence, it may be necessary to submit instead the following definition. (defun fn (x) (declare (xargs :guard (good-input-p x))) (if (good-input-p x) (if (not-done-yet x) (... (fn (destr x)) ...) ...) nil) But it is unfortunate that when calls of fn are evaluated, for example when fn is applied to an explicit constant during a proof, then a call of good-input-p must now be evaluated on each recursive call. Fortunately, defexec provides a way to keep the execution efficient. For the example above we could use the following form. (defexec fn (x) (declare (xargs :guard (good-input-p x))) (mbe :logic (if (good-input-p x) (if (not-done-yet x) (... (fn (destr x)) ...) ...) nil) :exec (if (not-done-yet x) (... (fn (destr x)) ...) ...))) Here ``[mbe]'' stands for ``must be equal'' and, roughly speaking, its call above is logically equal to the :logic form but is evaluated using the :exec form when the guard holds. See [mbe]. The effect is thus to define fn as shown in the [defun] form above, but to cause execution of fn using the :exec body. The use of defexec instead of [defun] in the example above causes a termination proof to be performed, in order to guarantee that evaluation always theoretically terminates, even when using the :exec form for evaluation. Example: ; Some of the keyword arguments in the declarations below are irrelevant or ; unnecessary, but they serve to illustrate their use. (defexec f (x) (declare (xargs :measure (+ 15 (acl2-count x)) :ruler-extenders :basic :hints ((\"Goal\" :in-theory (disable nth))) :guard-hints ((\"Goal\" :in-theory (disable last))) :guard (and (integerp x) (<= 0 x) (< x 25))) (exec-xargs :test (and (integerp x) (<= 0 x)) :default-value 'undef ; defaults to nil :measure (nfix x) :ruler-extenders :basic :well-founded-relation o<)) (mbe :logic (if (zp x) 1 (* x (f (- x 1)))) :exec (if (= x 0) 1 (* x (f (- x 1)))))) The above example macroexpands to the following. (ENCAPSULATE () (LOCAL (ENCAPSULATE () (SET-IGNORE-OK T) (SET-IRRELEVANT-FORMALS-OK T) (LOCAL (DEFUN F (X) (DECLARE (XARGS :VERIFY-GUARDS NIL :HINTS ((\"Goal\" :IN-THEORY (DISABLE NTH))) :MEASURE (NFIX X) :RULER-EXTENDERS :BASIC :WELL-FOUNDED-RELATION O<)) (IF (AND (INTEGERP X) (<= 0 X)) (IF (= X 0) 1 (* X (F (- X 1)))) 'UNDEF))) (LOCAL (DEFTHM F-GUARD-IMPLIES-TEST (IMPLIES (AND (INTEGERP X) (<= 0 X) (< X 25)) (AND (INTEGERP X) (<= 0 X))) :RULE-CLASSES NIL)))) (DEFUN F (X) (DECLARE (XARGS :MEASURE (+ 15 (ACL2-COUNT X)) :RULER-EXTENDERS :BASIC :HINTS ((\"Goal\" :IN-THEORY (DISABLE NTH))) :GUARD-HINTS ((\"Goal\" :IN-THEORY (DISABLE LAST))) :GUARD (AND (INTEGERP X) (<= 0 X) (< X 25)))) (MBE :LOGIC (IF (ZP X) 1 (* X (F (- X 1)))) :EXEC (IF (= X 0) 1 (* X (F (- X 1))))))) Notice that in the example above, the :[hints] in the [local] definition of F are inherited from the :hints in the [xargs] of the defexec form. We discuss such inheritance below. CAVEAT: Termination is not considered for calls of [mbe] under the top-level call. Moreover, the :exec part of an [mbe] call under the :logic part of any superior mbe call is completely ignored. General Form: (defexec fn (var1 ... varn) doc-string dcl ... dcl (mbe :LOGIC logic-body :EXEC exec-body)) where the syntax is identical to the syntax of [defun] where the body is a call of mbe, with the exceptions described below. Thus, fn is the symbol you wish to define and is a new symbolic name and (var1 ... varn) is its list of formal parameters (see [name]). The first exception is that at least one dcl (i.e., [declare] form) must specify a :guard, guard. The second exception is that one of the dcls is allowed to contain an element of the form (exec-xargs ...). The exec-xargs form, if present, must specify a non-empty [keyword-value-listp] each of whose keys is one of :test, :default-value, or one of the standard [xargs] keys of :measure, :ruler-extenders, :well-founded-relation, :hints, or :stobjs. Any of these five standard xargs keys that is present in an xargs of some dcl but is not specified in the (possibly nonexistent) exec-xargs form is considered to be specified in the exec-xargs form, as illustrated in the example above for :hints. (So for example, if you want :hints in the final, non-local definition but not in the local definition, then specify the :hints in the xargs but specify :hints nil in the exec-xargs.) If :test is specified and not nil, let test be its value; otherwise let test default to guard. If :default-value is specified, let default-value be its value; else default-value is nil. Default-value should have the same [signature] as exec-body; otherwise the defexec form will fail to be admitted. The above General Form's macroexpansion is of the form (PROGN encap final-def), where encap and final-def are as follows. Final-def is simply the result of removing the exec-xargs declaration (if any) from its [declare] form, and is the result of evaluating the given defexec form, since encap is of the following form. ; encap (ENCAPSULATE () (set-ignore-ok t) ; harmless for proving termination (set-irrelevant-formals-ok t) ; harmless for proving termination (local local-def) (local local-thm)) The purpose of encap is to ensure the the executable version of name terminates on all arguments. Thus, local-def and local-thm are as follows, where the xargs of the [declare] form are the result of adding :VERIFY-GUARDS NIL to the result of removing the :test and (optional) :default-value from the exec-xargs. ; local-def (DEFUN fn formals (DECLARE (XARGS :VERIFY-GUARDS NIL ...)) (IF test exec-body default-value)) ; local-thm (DEFTHM fn-EXEC-GUARD-HOLDS (IMPLIES guard test) :RULE-CLASSES NIL) We claim that if the above local-def and local-thm are admitted, then all evaluations of calls of fn terminate. The concern is that the use of [mbe] in final-def allows for the use of exec-body for a call of fn, as well as for subsequent recursive calls, when guard holds and assuming that the guards have been verified for final-def. However, by local-thm we can conclude in this case that test holds, in which case the call of fn may be viewed as a call of the version of fn defined in local-def. Moreover, since guards have been verified for final-def, then guards hold for subsequent evaluation of exec-body, and in particular for recursive calls of fn, which can thus continue to be viewed as calls using local=def.") (DEFINE-PC-HELP (PROOF-CHECKER) "Define a macro command whose purpose is to print something Example: (define-pc-help pp () (if (goals t) (io? proof-checker nil state (state-stack) (fms0 \"~|~y0~|\" (list (cons #0 (fetch-term (conc t) (current-addr t)))))) (print-all-goals-proved-message state))) General Form: (define-pc-help name args &rest body) This defines a macro command named name, as explained further below. The body should (after removing optional declarations) be a form that returns state as its single value. Typically, it will just print something. What (define-pc-help name args &rest body) really does is to create a call of define-pc-macro that defines name to take arguments args, to have the declarations indicated by all but the last form in body, and to have a body that (via pprogn) first executes the form in the last element of body and then returns a call to the command skip (which will return (mv nil t state)).") (DEFINE-PC-MACRO (PROOF-CHECKER) "Define a proof-checker macro command Example: (define-pc-macro ib (&optional term) (value (if term `(then (induct ,term) bash) `(then induct bash)))) The example above captures a common paradigm: one attempts to prove the current goal by inducting and then simplifying the resulting goals. (see [proof-checker-commands] for documentation of the command then, which is itself a pc-macro command, and commands induct and bash.) Rather than issuing (then induct bash), or worse yet issuing induct and then issuing bash for each resulting goals, the above definition of ib would let you issue ib and get the same effect. General Form: (define-pc-macro cmd args doc-string dcl ... dcl body) where cmd is the name of the pc-macro than you want to define, args is its list of formal parameters. Args may include lambda-list keywords &optional and &rest; see [macro-args], but note that here, args may not include &key or &whole. The value of body should be an error triple (see [error-triples]), of the form (mv erp xxx state) for some erp and xxx. If erp is nil, then xxx is handed off to the proof-checker's instruction interpreter. Otherwise, evaluation typically halts. We may write more on the full story later if there is interest in reading it.") (DEFINE-PC-META (PROOF-CHECKER) "Define a proof-checker meta command Built-in proof-checker meta commands include undo and restore, and others (lisp, exit, and sequence); see [proof-checker-commands]. The advanced proof-checker user can define these as well. See ACL2 source file proof-checker-b.lisp for examples, and contact the ACL2 implementors if those examples do not provide sufficient documentation.") (DEFINE-TRUSTED-CLAUSE-PROCESSOR (EVENTS) "Define a trusted (unverified) goal-level simplifier This [documentation] assumes familiarity with :clause-processor rules; see [clause-processor]. Briefly put, a clause-processor is a user-defined function that takes as input the ACL2 representation of a goal --- a clause --- and returns a list of goals (i.e., a list of clauses). A :clause-processor rule is a way to inform ACL2 that a clause-processor has been proved correct and now may be specified in :clause-processor [hints]. Here we describe a utility, define-trusted-clause-processor, that provides another way to inform ACL2 that a function is to be considered a clause-processor that can be specified in a :clause-processor hint. You can find examples of correct and incorrect use of this utility in community book books/clause-processors/basic-examples. Consider the simple example already presented for :clause-processor rules (again, see [clause-processor]), for a simple clause-processor named note-fact-clause-processor. Instead of introducing an evaluator and proving a correctness theorem with :rule-classes :clause-processor, we can simply inform ACL2 that we trust the function note-fact-clause-processor to serve as a clause-processor. (define-trusted-clause-processor note-fact-clause-processor nil :ttag my-ttag) A non-nil :ttag argument generates a [defttag] event in order to acknowledge the dependence of the ACL2 session on the (unproved) correctness of this clause-processor. That argument can be omitted if there is currently an active trust tag. See [defttag]. Because we are trusting this clause-processor, rather than having proved it correct, we refer to it as a ``trusted'' clause-processor to contrast with a proved-correct, or ``verified'', clause-processor. Now that the event displayed above has established note-fact-clause-processor as a (trusted) clause-processor, we can use it in a :clause-processor hint, for example as follows. Notice that the output is identical to that for the corresponding example presented for the verified case (see [clause-processor]), except that the word ``verified'' has been replaced by the word ``trusted''. ACL2 !>(thm (equal (car (cons x y)) x) :hints ((\"Goal\" :clause-processor (note-fact-clause-processor clause '(equal a a))))) [Note: A hint was supplied for our processing of the goal above. Thanks!] We now apply the trusted :CLAUSE-PROCESSOR function NOTE-FACT-CLAUSE- PROCESSOR to produce two new subgoals. Subgoal 2 (IMPLIES (EQUAL A A) (EQUAL (CAR (CONS X Y)) X)). But we reduce the conjecture to T, by the :executable-counterpart of IF and the simple :rewrite rule CAR-CONS. Subgoal 1 (EQUAL A A). But we reduce the conjecture to T, by primitive type reasoning. Q.E.D. Summary Form: ( THM ...) Rules: ((:EXECUTABLE-COUNTERPART IF) (:EXECUTABLE-COUNTERPART NOT) (:FAKE-RUNE-FOR-TYPE-SET NIL) (:REWRITE CAR-CONS)) Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) Proof succeeded. ACL2 !> Indeed, if one runs this example first and subsequently verifies the clause-processor, one will see the word ``trusted'' change to ``verified''. The general form is as follows. (define-trusted-clause-processor cl-proc ;;; clause-processor function supporters ;;; see below &key label ;;; optional, but required if doc is non-nil doc ;;; optional ttag ;;; discussed above partial-theory ;;; optional encapsulate event ) If a :label LAB is supplied, then a subsidiary [deflabel] event will be generated with name LAB, which will enable you to to undo this define-trusted-clause-processor event using: :[ubt] LAB. If you supply a :label then you may supply a :doc argument to use with that generated [deflabel] event. We discussed the :ttag argument above. The entire form is considered redundant (skipped) if it is identical to one already executed in the current ACL2 world; but if it is not redundant, then cl-proc must not already have been similarly designated as a trusted clause-processor. Note that cl-proc may be defined either in :program-mode or :logic-mode. The supporters argument should be a true list of function symbols in the current ACL2 world. It is important that this list include user-defined functions whose definitions support the correctness of the clause-processor function. Otherwise, [local] definitions of those missing supporters can render the use of this clause-processor unsound, as discussed in the paper referenced at the end of the [clause-processor] documentation topic. Moreover, ACL2 assumes for dependent clause-processors (discussed below) that every function symbol constrained by the ``promised encapsulate'' of that event is either among those supporters or ancestral in one of them (i.e. a supporter of a supporter, a supporter of one of those, etc.). Dependent clause-processors and promised encapsulates: The :partial-theory argument Suppose you want to introduce a clause-processor to reason about a complex hardware simulator that is implemented outside ACL2. Sawada and Reeber had just such a problem, as reported in their FMCAD 2006 paper. Indeed, they used [sys-call] to implement a :[program]-mode function in ACL2 that can invoke that simulator. In principle one could code the simulator directly in ACL2; but it would be a tremendous amount of work that has no practical purpose, given the interface to the external simulator. So: In what sense can we have a clause-processor that proves properties about a simulator when that simulator is not fully axiomatized in ACL2? Our answer, in a nutshell, is this: The above :partial-theory argument provides a way to write merely some of the [constraint]s on the external tool (or even no constraints at all), with the understanding that such constraints are present implicitly in a stronger ``promised'' encapsulate, for example by exporting the full definition. If a trusted clause-processor is introduced with a :partial-theory argument, we call it a ``dependent'' clause-processor, because its correctness is dependent on the constraints implicitly introduced by the :partial-theory encapsulate form. The implicit constraints should logically imply the constraints actually introduced by the explicit encapsulate, but they should also be sufficient to justify every possible invocation of the clause-processor in a :clause-processor hint. The user of a define-trusted-clause-processor form is making a guarantee --- or, is relying on a guarantee provided by the writer of that form --- that in principle, there exists a so-called ``promised encapsulate'': an encapsulate form with the same [signature] as the :partial-theory encapsulate form associated with the trusted clause-processor, but whose constraints introduced are the aforementioned implicit constraints. There are several additional requirements on a :partial-theory argument. First, it must be an [encapsulate] event with non-empty [signature]. Moreover, the functions introduced by that event must be exactly those specified in the signature, and no more. And further still, the define-trusted-clause-processor form cannot be executed inside any [encapsulate] form with non-empty [signature]; we can think of this situation as attempting to associate more than one encapsulate with the functions introduced in the inner encapsulate. The :partial-theory event will (in essence) be executed as part of the evaluation of the define-trusted-clause-processor form. Again, a critical obligation rests on the user who provides a :partial-theory: there must exist (in principle at least) a corresponding promised encapsulate form with the same [signature] that could logically be admitted, whenever the above define-trusted-clause-processor form is evaluated successfully, that justifies the designation of cl-proc as a clause-processor. See also the paper mentioned above for more about promised encapsulates. A key consequence is that the [constraint]s are unknown for the functions introduced in (the signature of) a :partial-theory [encapsulate] form. Thus, functional instantiation (see [functional-instantiation-example]) is disabled for function in the signature of a :partial-theory form. A remark on the underlying implementation You can see all of the current trusted clause-processors by issuing the command (table trusted-clause-processor-table). Those that are dependent clause-processors will be associated in the resulting association list with a pair whose car is the list of supporters and whose cdr is t, i.e., with (supporters . t); the others will be associated just with (supporters). Thus, define-trusted-clause-processor is actually a macro that generates (among other things) a table event for a table named trusted-clause-processor-table; see [table]. You are invited to use :[trans1] to see expansions of calls of this macro. A technique for using raw Lisp to define a trusted clause-processor The following code is intended to give an idea for how one might define the ``guts'' of a trusted clause-processor in raw Lisp. The idea is to stub out functions, such as acl2-my-prove below, that you want to define in raw Lisp; and then, load a raw Lisp file to overwrite any such function with the real code. But then we make any such overwritten function untouchable. (This last step is important because otherwise, one can prove nil using a :functional-instance :use hint, by exploiting the fact that this function has executable code for which there is no corresponding definitional axiom.) Note: The point here is only to illustrate the use of raw Lisp, so we do not bother to define or explain functions hint-to-termlist or disjoin-clause-segments-to-clause, which this example assumes are defined elsewhere; their meanings are not important for this example. (defstub acl2-my-prove (term hint) t) (program) (defttag :my-cl-proc) (progn ; We wrap everything here in a single progn, so that the entire form is ; atomic. That's important because we want the use of push-untouchable to ; prevent anything besides my-clause-processor from calling acl2-my-prove. (progn! (set-raw-mode-on state) (load \"my-hint-raw.lsp\") ; defines my-prove in raw Lisp (defun acl2-my-prove (term hint) (my-prove term hint))) (defun my-clause-processor (cl hint) (declare (xargs :guard (pseudo-term-listp cl) :mode :program)) (if (acl2-my-prove (disjoin cl) hint) (disjoin-clause-segments-to-clause (pairlis$ (hint-to-termlist hint) nil) cl) (prog2$ (cw \"~|~%NOTE: Unable to prove goal with ~ my-clause-processor and indicated hint.~|\") (list cl)))) (push-untouchable acl2-my-prove t) )") (DEFINITION (RULE-CLASSES) "Make a rule that acts like a function definition See [rule-classes] for a general discussion of rule classes and how they are used to build rules from formulas. An example :[corollary] formula from which a :definition rule might be built is: Examples: (defthm open-len-twice (implies (true-listp x) (equal (len x) (if (null x) 0 (if (null (cdr x)) 1 (+ 2 (len (cddr x))))))) :rule-classes :definition) ; Same as above, with :controller-alist made explicit: (defthm open-len-twice (implies (true-listp x) (equal (len x) (if (null x) 0 (if (null (cdr x)) 1 (+ 2 (len (cddr x))))))) :rule-classes ((:definition :controller-alist ((len t))))) General Form: (implies hyp (equiv (fn a1 ... an) body)) where equiv is an equivalence relation and fn is a function symbol other than [if], [hide], [force] or [case-split]. Such rules allow ``alternative'' definitions of fn to be proved as theorems but used as definitions. These rules are not true ``definitions'' in the sense that they (a) cannot introduce new function symbols and (b) do not have to be terminating recursion schemes. They are just conditional rewrite rules that are controlled the same way we control recursive definitions. We call these ``definition rules'' or ``generalized definitions''. Consider the general form above. Generalized definitions are stored among the :[rewrite] rules for the function ``defined,'' fn above, but the procedure for applying them is a little different. During rewriting, instances of (fn a1 ... an) are replaced by corresponding instances of body provided the hyps can be established as for a :[rewrite] rule and the result of rewriting body satisfies the criteria for function expansion. There are two primary criteria, either of which permits expansion. The first is that the ``recursive'' calls of fn in the rewritten body have arguments that already occur in the goal conjecture. The second is that the ``controlling'' arguments to fn are simpler in the rewritten body. The notions of ``recursive call'' and ``controllers'' are complicated by the provisions for mutually recursive definitions. Consider a ``clique'' of mutually recursive definitions. Then a ``recursive call'' is a call to any function defined in the clique and an argument is a ``controller'' if it is involved in the measure that decreases in all recursive calls. These notions are precisely defined by the definitional principle and do not necessarily make sense in the context of generalized definitional equations as implemented here. But because the heuristics governing the use of generalized definitions require these notions, it is generally up to the user to specify which calls in body are to be considered recursive and what the controlling arguments are. This information is specified in the :clique and :controller-alist fields of the :definition rule class. The :clique field is the list of function symbols to be considered recursive calls of fn. In the case of a non-recursive definition, the :clique field is empty; in a singly recursive definition, it should consist of the singleton list containing fn; otherwise it should be a list of all of the functions in the mutually recursive clique with this definition of fn. If the :clique field is not provided it defaults to nil if fn does not occur as a function symbol in body and it defaults to the singleton list containing fn otherwise. Thus, :clique must be supplied by the user only when the generalized definition rule is to be treated as one of several in a mutually recursive clique. The :controller-alist is an alist that maps each function symbol in the :clique to a mask specifying which arguments are considered controllers. The mask for a given member of the clique, fn, must be a list of t's and nil's of length equal to the arity of fn. A t should be in each argument position that is considered a ``controller'' of the recursion. For a function admitted under the principle of definition, an argument controls the recursion if it is one of the arguments measured in the termination argument for the function. But in generalized definition rules, the user is free to designate any subset of the arguments as controllers. Failure to choose wisely may result in the ``infinite expansion'' of definitional rules but cannot render ACL2 unsound since the rule being misused is a theorem. If the :controller-alist is omitted it can sometimes be defaulted automatically by the system. If the :clique is nil, the :controller-alist defaults to nil. If the :clique is a singleton containing fn, the :controller-alist defaults to the controller alist computed by (defun fn args body). (The user can obtain some control over this analysis by setting the default ruler-extenders; see [ruler-extenders].) If the :clique contains more than one function, the user must supply the :controller-alist specifying the controllers for each function in the clique. This is necessary since the system cannot determine and thus cannot analyze the other definitional equations to be included in the clique. For example, suppose fn1 and fn2 have been defined one way and it is desired to make ``alternative'' mutually recursive definitions available to the rewriter. Then one would prove two theorems and store each as a :definition rule. These two theorems would exhibit equations ``defining'' fn1 and fn2 in terms of each other. No provision is here made for exhibiting these two equations as a system of equations. One is proved and then the other. It just so happens that the user intends them to be treated as mutually recursive definitions. To achieve this end, both :definition rules should specify the :clique (fn1 fn2) and should specify a suitable :controller-alist. If, for example, the new definition of fn1 is controlled by its first argument and the new definition of fn2 is controlled by its second and third (and they each take three arguments) then a suitable :controller-alist would be ((fn1 t nil nil) (fn2 nil t t)). The order of the pairs in the alist is unimportant, but there must be a pair for each function in the clique. Inappropriate heuristic advice via :clique and :controller-alist can cause ``infinite expansion'' of generalized definitions, but cannot render ACL2 unsound. Note that the actual definition of fn1 has the runic name (:definition fn1). The runic name of the alternative definition is (:definition lemma), where lemma is the name given to the event that created the generalized :definition rule. This allows theories to switch between various ``definitions'' of the functions. By default, a :definition rule establishes the so-called ``body'' of a function. The body is used by :expand [hints], and it is also used heuristically by the theorem prover's preprocessing (the initial simplification using ``simple'' rules that is controlled by the preprocess symbol in :do-not [hints]), induction analysis, and the determination for when to warn about non-recursive functions in rules. The body is also used by some heuristics involving whether a function is recursively defined, and by the expand, x, and x-dumb commands of the [proof-checker]. See [rule-classes] for a discussion of the optional field :install-body of :definition rules, which controls whether a :definition rule is used as described in the paragraph above. Note that even if :install-body nil is supplied, the rewriter will still rewrite with the :definition rule; in that case, ACL2 just won't install a new body for the top function symbol of the left-hand side of the rule, which for example affects the application of :expand hints as described in the preceding paragraph. Also see [set-body] and see [show-bodies] for how to change the body of a function symbol. Note only that if you prove a definition rule for function foo, say, foo-new-def, you will need to refer to that definition as foo-new-def or as (:DEFINITION foo-new-def). That is because a :definition rule does not change the meaning of the symbol foo for :use [hints], nor does it change the meaning of the symbol foo in theory expressions; see [theories], in particular the discussion there of runic designators. Similarly :[pe] foo and :[pf] foo will still show the original definition of foo. The definitional principle, [defun], actually adds :definition rules. Thus the handling of generalized definitions is exactly the same as for ``real'' definitions because no distinction is made in the implementation. Suppose (fn x y) is [defun]'d to be body. Note that [defun] (or [defuns] or [mutual-recursion]) can compute the clique for fn from the syntactic presentation and it can compute the controllers from the termination analysis. Provided the definition is admissible, [defun] adds the :definition rule (equal (fn x y) body). Subtopics [Bind-free] To bind free variables of a rewrite, definition, or linear rule [Case-split] Like force but immediately splits the top-level goal on the hypothesis [Force] Identity function used to force a hypothesis [Set-body] Set the definition body [Show-bodies] Show the potential definition bodies [Simple] :[definition] and :[rewrite] rules used in preprocessing [Syntaxp] Attach a heuristic filter on a rule") (DEFLABEL (EVENTS) "Build a landmark and/or add a [documentation] topic Examples: (deflabel interp-section) General Form: (deflabel name :doc doc-string) where name is a new symbolic name (see [name]) and doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. By virtue of the fact that deflabel is an event, it marks the current [history] with the name. For example, you may wish to undo back through some label or compute a theory expression (see [theories]) in terms of some labels. Deflabel [events] are never considered redundant. See [redundant-events].") (DEFLOCK (PARALLEL-PROGRAMMING) "Define a wrapper macro that provides mutual exclusion in ACL2(p) This [documentation] topic relates to the experimental extension of ACL2 supporting parallel evaluation and proof; see [parallelism]. Example Form: (deflock *my-lock*) General Form: (deflock *symbol*) where *symbol* is a symbol whose first and last characters are both the character #\\*. A call of this macro generates a definition of another macro, named with-, where is the given symbol with the leading and trailing * characters removed. This newly defined macro will guarantee mutually exclusive execution when called in the body of the raw Lisp definition of a function, as is typically the case for [guard]-verified functions, for :[program] mode functions, and for calls of macro [top-level]. (See [guard-evaluation-table] for details of how raw Lisp code might not be invoked when guard-checking (see [set-guard-checking]) has value :none or :all.) To see how mutual exclusion is guaranteed, consider the raw Lisp code generated for the macro, with-, that is introduced by a call of deflock. This code uses a lock (with the given *symbol* as its name), which guarantees that for any two forms that are each in the scope of a call of with-, the forms do not execute concurrently. Note that a call of deflock expands into the application of progn to two events, as illustrated below. ACL2 !>:trans1 (deflock *my-cw-lock*) (PROGN (TABLE LOCK-TABLE '*MY-CW-LOCK* T) (DEFMACRO WITH-MY-CW-LOCK (&REST ARGS) (LIST* 'WITH-LOCK '*MY-CW-LOCK* ARGS))) ACL2 !> Thus, deflock forms are legal embedded event forms (see [embedded-event-form]) for [books] as well as [encapsulate] and [progn] [events]. The following log shows a lock in action. Recall that locks work as expected in [guard]-verified and :[program] mode functions; they do not, however, work in :[logic] mode functions that have not been guard-verified, as illustrated below. ACL2 !>(deflock *my-cw-lock*) [[.. output omitted ..]] WITH-MY-CW-LOCK ACL2 !>(defun foo (n) (declare (xargs :guard (natp n) :verify-guards nil)) (plet ((x1 (with-my-cw-lock (cw \"~x0\" (make-list n)))) (x2 (with-my-cw-lock (cw \"~x0\" (make-list n))))) (and (null x1) (null x2)))) [[.. output omitted ..]] FOO ACL2 !>(foo 20) (NIL NIL NIL NIL( NIL NIL NIL NIL NIL NILNIL NIL NILNIL NIL NILNIL NIL NILNIL NIL NIL NILNIL NIL NIL NIL NILNIL NIL NILNIL ) NIL NIL NIL NIL NIL NIL NIL NIL) T ACL2 !>(verify-guards foo) [[.. output omitted ..]] FOO ACL2 !>(foo 20) (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL) T ACL2 !>") (DEFMACRO (MACROS EVENTS PROGRAMMING) "Define a macro Example Defmacros: (defmacro xor (x y) (list 'if x (list 'not y) y)) (defmacro git (sym key) (list 'getprop sym key nil '(quote current-acl2-world) '(w state))) (defmacro one-of (x &rest rst) (declare (xargs :guard (symbol-listp rst))) (cond ((null rst) nil) (t (list 'or (list 'eq x (list 'quote (car rst))) (list* 'one-of x (cdr rst)))))) Example Expansions: term macroexpansion (xor a b) (if a (not b) b) (xor a (foo b)) (if a (not (foo b)) (foo b)) (git 'car 'lemmas) (getprop 'car 'lemmas nil 'current-acl2-world (w state)) (one-of x a b c) (or (eq x 'a) (or (eq x 'b) (or (eq x 'c) nil))) (one-of x 1 2 3) ill-formed (guard violation) General Form: (defmacro name macro-args doc-string dcl ... dcl body) where name is a new symbolic name (see [name]), macro-args specifies the formal parameters of the macro, and body is a term. The formal parameters can be specified in a much more general way than is allowed by ACL2 [defun] [events]; see [macro-args] for a description of keyword (&key) and optional (&optional) parameters as well as other so-called ``lambda-list keywords'', &rest and &whole. Doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. Each dcl is an optional declaration (see [declare]) except that the only [xargs] keyword permitted by defmacro is :[guard]. For compute-intensive applications see the community book misc/defmac.lisp, which can speed up macroexpansion by introducing an auxiliary defun. For more information, evaluate the form (include-book \"misc/defmac\" :dir :system) and then evaluate :doc defmac. Macroexpansion occurs when a form is read in, i.e., before the evaluation or proof of that form is undertaken. To experiment with macroexpansion, see [trans]. When a form whose [car] is name arises as the form is read in, the arguments are bound as described in CLTL pp. 60 and 145, the [guard] is checked, and then the body is evaluated. The result is used in place of the original form. In ACL2, macros do not have access to the ACL2 state, [state]. (If [state] or any user-defined stobj (see [stobj]) is a macro argument, it is treated as an ordinary variable, bound at macro-expansion time to a piece of syntax.) This is in part a reflection of CLTL, p. 143, ``More generally, an implementation of Common Lisp has great latitude in deciding exactly when to expand macro calls with a program. ... Macros should be written in such a way as to depend as little as possible on the execution environment to produce a correct expansion.'' In ACL2, the product of macroexpansion is independent of the current environment and is determined entirely by the macro body and the functions and constants it references. It is possible, however, to define macros that produce expansions that refer to [state] or other single-threaded objects (see [stobj]) or variables not among the macro's arguments. See the git example above. For a related utility that does have access to the ACL2 [state], see [make-event].") (DEFMACRO-LAST (EVENTS) "Define a macro that returns its last argument, but with side effects This is an advanced feature that requires a trust tag. For explanation, including an example, see [return-last].") (DEFN (DEFUN EVENTS) "Definition with [guard] t Defn is [defun] with [guard] t.") (DEFND (DEFUN EVENTS) "[disable]d definition with [guard] t Defnd is [defund] with [guard] t.") (DEFPKG (EVENTS PACKAGES PROGRAMMING) "Define a new symbol package Example: (defpkg \"MY-PKG\" (union-eq *acl2-exports* *common-lisp-symbols-from-main-lisp-package*)) General Form: (defpkg \"name\" term doc-string) where \"name\" is a non-empty string consisting of standard characters (see [standard-char-p]), none of which is lower case, that names the package to be created; term is a variable-free expression that evaluates to a list of symbols, where no two distinct symbols in the list may have the same [symbol-name], to be imported into the newly created package; and doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. The name of the new package must be ``new'': the host lisp must not contain any package of that name. There are two exceptions to this newness rule, discussed at the end of this documentation. (There is actually an additional argument, book-path, that is used for error reporting but has no logical content. Users should generally ignore this argument, as well as the rest of this sentence: a book-path will be specified for [defpkg] events added by ACL2 to the [portcullis] of a book's [certificate]; see [hidden-death-package].) Defpkg forms can be entered at the top-level of the ACL2 [command] loop. They should not occur in [books] (see [certify-book]). After a successful defpkg it is possible to ``intern'' a string into the package using [intern-in-package-of-symbol]. The result is a symbol that is in the indicated package, provided the imports allow it. For example, suppose 'my-pkg::abc is a symbol whose [symbol-package-name] is \"MY-PKG\". Suppose further that the imports specified in the defpkg for \"MY-PKG\" do not include a symbol whose [symbol-name] is \"XYZ\". Then (intern-in-package-of-symbol \"XYZ\" 'my-pkg::abc) returns a symbol whose [symbol-name] is \"XYZ\" and whose [symbol-package-name] is \"MY-PKG\". On the other hand, if the imports to the defpkg does include a symbol with the name \"XYZ\", say in the package \"LISP\", then (intern-in-package-of-symbol \"XYZ\" 'my-pkg::abc) returns that symbol (which is uniquely determined by the restriction on the imports list above). See [intern-in-package-of-symbol]. Upon admission of a defpkg event, the function pkg-imports is extended to compute a list of all symbols imported into the given package, without duplicates. Defpkg is the only means by which an ACL2 user can create a new package or specify what it imports. That is, ACL2 does not support the Common Lisp functions make-package or import. Currently, ACL2 does not support exporting at all. The Common Lisp function [intern] is weakly supported by ACL2; see [intern]. A more general form of that function is also provided: see [intern$]. We now explain the two exceptions to the newness rule for package names. The careful experimenter will note that if a package is created with a defpkg that is subsequently undone, the host lisp system will contain the created package even after the undo. Because ACL2 hangs onto [world]s after they have been undone, e.g., to implement :[oops] but, more importantly, to implement error recovery, we cannot actually destroy a package upon undoing it. Thus, the first exception to the newness rule is that name is allowed to be the name of an existing package if that package was created by an undone defpkg and the newly proposed set of imports is identical to the old one. See [package-reincarnation-import-restrictions]. This exception does not violate the spirit of the newness rule, since one is disinclined to believe in the existence of undone packages. The second exception is that name is allowed to be the name of an existing package if the package was created by a defpkg with identical set of imports. That is, it is permissible to execute ``redundant'' defpkg [command]s. The redundancy test is based on the values of the two import forms (comparing them after sorting and removing duplicates), not on the forms themselves. Finally, we explain why we require the package name to contain standard characters, none of which is lower case. We have seen at least one implementation that handled lower-case package names incorrectly. Since we see no need for lower-case characters in package names, which can lead to confusion anyhow (note for example that foo::bar is a symbol whose [symbol-package-name] is \"FOO\", not \"foo\"), we simply disallow them. Since the notion of ``lower case'' is only well-specified in Common Lisp for standard characters, we restrict to these. NOTE: Also see [managing-ACL2-packages] for contributed documentation on managing ACL2 packages. Subtopics [Hidden-death-package] Handling [defpkg] [events] that are [local] [Hidden-defpkg] Handling defpkg events that are local") (DEFPROXY (EVENTS) "Define a non-executable :[program]-mode function for attachment This event is provided for those who want to experiment with [defattach] using :[program] mode functions, and without proof obligations or constraints on cycles in the extended ancestors graph; see [defattach]. If you merely want to define a stub or a non-executable function, see [defstub] or see [defun-nx], respectively. See community book books/misc/defproxy-test.lisp for an extended (but simple) example. Example Forms: (defproxy subr1 (* *) => *) (defproxy add-hash (* * hashtable) => (mv * hashtable)) General Form: (defproxy name args-sig => output-sig) where name is a new function symbol and (name . args-sig) => output-sig) is a signature; see [signature]. The macro defproxy provides a convenient way to introduce a ``proxy'': a :program mode function that can be given attachments for execution (see [defattach]), assuming that there is an active trust tag (see [defttag]). Thus, a defproxy calls expands to a [defun] form with the following [xargs] [declare] form: :non-executable :program. Note that [verify-termination] is not permitted for such a function. However, it is permitted to put the proxy function into :[logic] mode by use of an [encapsulate] event; indeed, this is the way to ``upgrade'' an attachment so that the normal checks are performed and no trust tag is necessary. In order to take advantage of a [defproxy] form, one provides a subsequent defattach form to attach an executable function to the defproxy-introduced function. When :skip-checks t is provided in a [defattach] form, the usual checks for defattach [events] are skipped, including proof obligations and the check that the extended ancestor relation has no cycles (see [defattach]). There must be an active trust tag (see [defttag]) in order to use :skip-checks t. In that case the use of :skip-checks t is permitted; but note that its use is in fact required if a :[program] mode function is involved, and even if a :[logic] mode function is involved that has not been [guard]-verified. 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 :[logic] mode functions and does not skip checks. The idea is to reintroduce the proxy function using an [encapsulate] form, which does not require redefinition (see [ld-redefinition-action]) to be enabled, and either to put the attachment into :[logic] mode with the [guard] verified, as we do in the example below, or else to attach to a different [guard]-verified :[logic] mode function. 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 [guard]s in the case that [defattach] has been called with keyword argument :skip-checks t. We illustrate with examples, where we assume an attachment pair (f . g) created by an event (defattach ... (f g) ... :skip-checks t ...). A good model for the treatment of :skip-checks t is dependent on whether f was introduced with defproxy or with [encapsulate]: for defproxy, the normal guard-related checks are treated as skipped, while for [encapsulate], they are assumed to hold. First suppose that f was introduced using defproxy, and consider the following example. (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 (f 3) in ACL2, then the top-level so-called ``executable counterpart'' (i.e., the logically-defined funcction, also known as the ``*1*'' function) of f is invoked. It calls the executable counterpart of g, which calls the executable counterpart of [car], which in turn checks the [guard] of [car] and causes a guard violation error (unless we first turn off guard-checking; see [set-guard-checking]). 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 strengtheing the guard of g. (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 (f 3) is as before, except that this time the guard violation occurs at the time that g is called. 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 f is introduced using [encapsulate] instead of using defproxy. (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 f was introduced by [encapsulate] instead of by defproxy, ACL2 assumes that the usual guard properties hold. In particular, it assumes that (informally speaking) the guard of f implies the guard of g; see [defattach] for details. So in this case, ACL2 proceeds under that assumption even though it's actually false, and the result is a raw Lisp error. ACL2 !>(trace$ f g) ((F) (G)) ACL2 !>(f 3) 1> (ACL2_*1*_ACL2::F 3) 2> (G 3) *********************************************** ************ ABORTING from raw Lisp *********** Error: Attempt to take the car of 3 which is not listp. *********************************************** If you didn't cause an explicit interrupt (Control-C), then the root cause may be call of a :program mode function that has the wrong guard specified, or even no guard specified (i.e., an implicit guard of t). See :DOC guards. To enable breaks into the debugger (also see :DOC acl2-customization): (SET-DEBUGGER-ENABLE T) ACL2 !> If you replace g by its definition in the first example of this series, i.e. with a guard (implicitly) of t, you will see the same error, this time because the [defattach] event assumed that g was guard-verified.") (DEFPUN (EVENTS) "Define a tail-recursive function symbol Defpun is a macro developed by Pete Manolios and J Moore that allows tail-recursive definitions. It is defined in community book books/misc/defpun.lisp, so to use it, execute the following event. (include-book \"misc/defpun\" :dir :system) Details of defpun are provided by Manolios and Moore in the ``Partial Functions in ACL2'' published with the {ACL2 2000 workshop | http://www.cs.utexas.edu/users/moore/acl2/workshop-2000/}. Also see {Partial Functions in ACL2 | http://www.cs.utexas.edu/users/moore/publications/defpun/index.html}. A variant, defp, has been developed by Matt Kaufmann to allow more general forms of tail recursion. If defpun doesn't work for you, try defp by first executing the following event. (include-book \"misc/defp\" :dir :system) Sandip Ray has contributed a variant of defpun, defpun-exec, that supports executability. See community book books/defexec/defpun-exec/defpun-exec.lisp: (include-book \"defexec/defpun-exec/defpun-exec\" :dir :system) He has also contributed community book books/misc/misc2/defpun-exec-domain-example.lisp, for functions that are uniquely defined in a particular domain.") (DEFREC (EVENTS) "Introduce a record structure, like a struct in C. The defrec macro is built into ACL2 and is frequently used in the ACL2 sources to define basic kinds of structures. Better Alternatives to Defrec While defrec may be a reasonable choice for writing [program]-mode code, most users would likely be better served by using one of the many, richer alternatives to [defrec] that are available in various books. See for instance macros such as: * The [std::defaggregate] macro from [std/util], * The [defdata] macro, * The [fty::defprod] macro from the [fty::fty] library, and * The data-structures/structures book. A major reason to favor these macros over defrec is that they introduce the constructors and accessors for the structure as proper functions, rather than mere macros. This is very helpful when you are trying to use ACL2 to reason about code that works with structures. For instance, it means that your proof goals will involve terms like (employee->position x) instead of (cdddr x). Another reason is that defrec does not support putting constraints on the fields of your structure. For instance, you might want to have an employee structure where the name field is always a string. You can't do this with defrec, but any of the above macros support it. Some of the above macros also have other useful features, e.g., integration with [b*], support for [xdoc] documentation, and so forth. Usage A typical use of defrec might look like this: (defrec employee ;; name of the structure (name salary . position) ;; fields of the structure nil) ;; \"cheap\" flag This will result in the introduction of: * A \"weak\" recognizer function, weak-employee-p, which recognizes cons structures that have the right shape. We call the recognizer weak because it doesn't impose any constraints on the fields, e.g., there is no requirement that the name of an employee must be a string or that the salary must be a number. * A [make] macro that can be used like this: (make employee :name \"Jimmy\" :salary 0 :position \"Unpaid Intern\") * A [change] macro that can be used like this: (let ((jimmy (make-employee :name \"Jimmy\" ...))) (change employee jimmy :salary 300000 :position \"Vice President\")) * Suitable [access] macros that can be used like this: (let ((jimmy (make-employee :name \"Jimmy\" ...))) (access employee jimmy :name)) Subtopics [Access] Accessor macro for [defrec] structures. [Change] Mutator macro for [defrec] structures. [Make] Constructor macro for [defrec] structures.") (DEFREFINEMENT (EVENTS) "Prove that equiv1 refines equiv2 Example: (defrefinement equiv1 equiv2) is an abbreviation for (defthm equiv1-refines-equiv2 (implies (equiv1 x y) (equiv2 x y)) :rule-classes (:refinement)) See [refinement]. General Form: (defrefinement equiv1 equiv2 :rule-classes rule-classes :instructions instructions :hints hints :otf-flg otf-flg :event-name event-name :doc doc) where equiv1 and equiv2 are known [equivalence] relations, event-name, if supplied, is a symbol and all other arguments are as specified in the documentation for [defthm]. The defrefinement macro expands into a call of defthm. The name supplied is equiv1-refines-equiv2, unless event-name is supplied, in which case it is used as the name. The term supplied states that equiv1 refines equiv2. The rule-class :refinement is added to the rule-classes specified, if it is not already there. All other arguments to the generated defthm form are as specified by the other keyword arguments above.") (DEFSTOBJ (EVENTS STOBJ) "Define a new single-threaded object Note: Novices are advised to avoid defstobj, perhaps instead using community books [std::defaggregate] or books/data-structures/structures.lisp. At the least, consider using ([set-verify-guards-eagerness] 0) to avoid [guard] verification. On the other hand, after you learn to use defstobj, see [defabsstobj] for another way to introduce single-threaded objects. Example: (defconst *mem-size* 10) ; for use of *mem-size* just below (defstobj st (reg :type (array (unsigned-byte 31) (8)) :initially 0) (p-c :type (unsigned-byte 31) :initially 555) halt ; = (halt :type t :initially nil) (mem :type (array (unsigned-byte 31) (*mem-size*)) :initially 0 :resizable t)) General Form: (defstobj name (field1 :type type1 :initially val1 :resizable b1) ... (fieldk :type typek :initially valk :resizable bk) :renaming alist :doc doc-string :inline flg :congruent-to old-stobj-name :non-memoizable nm-flg) where name is a new symbol, each fieldi is a symbol, each typei is either a type-indicator (a [type-spec] or [stobj] name) or of the form (ARRAY type-indicator max), each vali is an object satisfying typei, and each bi is t or nil. Each pair :initially vali and :resizable bi may be omitted; more on this below. The :renaming alist argument is optional and allows the user to override the default function names introduced by this event. The doc-string is also optional. The :inline flg Boolean argument is also optional and declares to ACL2 that the generated access and update functions for the stobj should be implemented as macros under the hood (which has the effect of inlining the function calls). The optional :congruent-to old-stobj-name argument specifies an existing stobj with exactly the same structure, and is discussed below. The optional :non-memoizable nm-flg Boolean argument is ignored when nm-flg is nil and is uninteresting when using classic ACL2 rather than a (default) [hons-enabled] ACL2 executable; otherwise, it instructs ACL2 to lay down faster code for functions that return the new stobj but disallows memoization of any function that takes the new stobj as an argument. We describe further restrictions on the fieldi, typei, vali, and on alist below. We recommend that you read about single-threaded objects (stobjs) in ACL2 before proceeding; see [stobj]. The effect of this event is to introduce a new single-threaded object (i.e., a ``[stobj]''), named name, and the associated recognizers, creator, accessors, updaters, constants, and, for fields of ARRAY type, length and resize functions. The Single-Threaded Object Introduced The defstobj event effectively introduces a new global variable, named name, which has as its initial logical value a list of k elements, where k is the number of ``field descriptors'' provided. The elements are listed in the same order in which the field descriptors appear. If the :type of a field is (ARRAY type-indicator (max)) then max is a non-negative integer or a symbol introduced by [defconst]) whose value is a non-negative integer, and the corresponding element of the stobj is initially of length specified by max. Whether the value :type is of the form (ARRAY type-indicator (max)) or, otherwise, just type-indicator, then type-indicator is typically a type-spec; see [type-spec]. However, type-indicator can also be the name of a stobj that was previously introduced (by defstobj or [defabsstobj]). We ignore this ``nested stobj'' case below; see [nested-stobjs] for a discussion of stobjs within stobjs. The keyword value :initially val specifies the initial value of a field, except for the case of a :type (ARRAY type-indicator (max)), in which case val is the initial value of the corresponding array. Note that the actual representation of the stobj in the underlying Lisp may be quite different; see [stobj-example-2]. For the moment we focus entirely on the logical aspects of the object. In addition, the defstobj event introduces functions for recognizing and creating the stobj and for recognizing, accessing, and updating its fields. For fields of ARRAY type, length and resize functions are also introduced. Constants are introduced that correspond to the accessor functions. Restrictions on the Field Descriptions in Defstobj Each field descriptor is of the form: (fieldi :TYPE typei :INITIALLY vali) Note that the type and initial value are given in ``keyword argument'' format and may be given in either order. The typei and vali ``arguments'' are not evaluated. If omitted, the type defaults to t (unrestricted) and the initial value defaults to nil. Each typei must be either a [type-spec] or else a list of the form (ARRAY type-spec (max)). (Again, we are ignoring the case of nested stobjs, discussed elsewhere; see [nested-stobjs].) The latter forms are said to be ``array types.'' Examples of legal typei are: (INTEGER 0 31) (SIGNED-BYTE 31) (ARRAY (SIGNED-BYTE 31) (16)) (ARRAY (SIGNED-BYTE 31) (*c*)) ; where *c* has a non-negative integer value The typei describes the objects which are expected to occupy the given field. Those objects in fieldi should satisfy typei. We are more precise below about what we mean by ``expected.'' We first present the restrictions on typei and vali. Non-Array Types When typei is a [type-spec] it restricts the contents, x, of fieldi according to the ``meaning'' formula given in the table for [type-spec]. For example, the first typei above restricts the field to be an integer between 0 and 31, inclusive. The second restricts the field to be an integer between -2^30 and (2^30)-1, inclusive. The initial value, vali, of a field description may be any ACL2 object but must satisfy typei. Note that vali is not a form to be evaluated but an object. A form that evaluates to vali could be written 'vali, but defstobj does not expect you to write the quote mark. For example, the field description (days-off :initially (saturday sunday)) describes a field named days-off whose initial value is the list consisting of the two symbols SATURDAY and SUNDAY. In particular, the initial value is NOT obtained by applying the function saturday to the variable sunday! Had we written (days-off :initially '(saturday sunday)) it would be equivalent to writing (days-off :initially (quote (saturday sunday))) which would initialize the field to a list of length two, whose first element is the symbol quote and whose second element is a list containing the symbols saturday and sunday. Array Types When typei is of the form (ARRAY type-spec (max)), the field is supposed to be a list of items, initially of length specified by max, each of which satisfies the indicated type-spec. Max must be a non-negative integer or a defined constant evaluating to a non-negative integer. Thus, each of (ARRAY (SIGNED-BYTE 31) (16)) (ARRAY (SIGNED-BYTE 31) (*c*)) ; given previous event (defconst *c* 16) restricts the field to be a list of integers, initially of length 16, where each integer in the list is a (SIGNED-BYTE 31). We sometimes call such a list an ``array'' (because it is represented as an array in the underlying Common Lisp). The elements of an array field are indexed by position, starting at 0. Thus, the maximum legal index of an array field one less than is specified by max. Note that the value of max must be less than the Common Lisp constant array-dimension-limit, and also (though this presumably follows) less than the Common Lisp constant array-total-size-limit. Note also that the ARRAY type requires that the max be enclosed in parentheses. This makes ACL2's notation consistent with the Common Lisp convention of describing the (multi-)dimensionality of arrays. But ACL2 currently supports only single dimensional arrays in stobjs. For array fields, the initial value vali must be an object satisfying the [type-spec] of the ARRAY description. The initial value of the field is a list of max repetitions of vali. Array fields can be ``resized,'' that is, their lengths can be changed, if :resizable t is supplied as shown in the example and General Form above. The new length must satisfy the same restriction as does max, as described above. Each array field in a defstobj event gives rise to a length function, which gives the length of the field, and a resize function, which modifies the length of the field if :resizable t was supplied with the field when the defstobj was introduced and otherwise causes an error. If :resizable t was supplied and the resize function specifies a new length k, then: if k is less than the existing array length, the array is shortened simply by dropping elements with index at least k; otherwise, the array is extended to length k by mapping the new indices to the initial value (supplied by :initially, else default nil). Array resizing is relatively slow, so we recommend using it somewhat sparingly. The Default Function Names To recap, in (defstobj name (field1 :type type1 :initially val1) ... (fieldk :type typek :initially valk) :renaming alist :doc doc-string :inline inline-flag) name must be a new symbol, each fieldi must be a symbol, each typei must be a [type-spec] or (ARRAY type-spec (max)), and each vali must be an object satisfying typei. Roughly speaking, for each fieldi, a defstobj introduces a recognizer function, an accessor function, and an updater function. The accessor function, for example, takes the stobj and returns the indicated component; the updater takes a new component value and the stobj and return a new stobj with the component replaced by the new value. But that summary is inaccurate for array fields. The accessor function for an array field does not take the stobj and return the indicated component array, which is a list of length specified by max. Instead, it takes an additional index argument and returns the indicated element of the array component. Similarly, the updater function for an array field takes an index, a new value, and the stobj, and returns a new stobj with the indicated element replaced by the new value. These functions --- the recognizer, accessor, and updater, and also length and resize functions in the case of array fields --- have ``default names.'' The default names depend on the field name, fieldi, and on whether the field is an array field or not. For clarity, suppose fieldi is named c. The default names are shown below in calls, which also indicate the arities of the functions. In the expressions, we use x as the object to be recognized by field recognizers, i as an array index, v as the ``new value'' to be installed by an updater, and name as the single-threaded object. non-array field array field recognizer (cP x) (cP x) accessor (c name) (cI i name) updater (UPDATE-c v name) (UPDATE-cI i v name) length (c-LENGTH name) resize (RESIZE-c k name) Finally, a recognizer and a creator for the entire single-threaded object are introduced. The creator returns the initial stobj, but may only be used in limited contexts; see [with-local-stobj]. If the single-threaded object is named name, then the default names and arities are as shown below. top recognizer (nameP x) creator (CREATE-name) For example, the event (DEFSTOBJ $S (X :TYPE INTEGER :INITIALLY 0) (A :TYPE (ARRAY (INTEGER 0 9) (3)) :INITIALLY 9)) introduces a stobj named $S. The stobj has two fields, X and A. The A field is an array. The X field contains an integer and is initially 0. The A field contains a list of integers, each between 0 and 9, inclusively. Initially, each of the three elements of the A field is 9. This event introduces the following sequence of definitions: (DEFUN XP (X) ...) ; recognizer for X field (DEFUN AP (X) ...) ; recognizer of A field (DEFUN $SP ($S) ...) ; top-level recognizer for stobj $S (DEFUN CREATE-$S () ...) ; creator for stobj $S (DEFUN X ($S) ...) ; accessor for X field (DEFUN UPDATE-X (V $S) ...) ; updater for X field (DEFUN A-LENGTH ($S) ...) ; length of A field (DEFUN RESIZE-A (K $S) ...) ; resizer for A field (DEFUN AI (I $S) ...) ; accessor for A field at index I (DEFUN UPDATE-AI (I V $S) ...) ; updater for A field at index I Avoiding the Default Function Names If you do not like the default names listed above you may use the optional :renaming alist to substitute names of your own choosing. Each element of alist should be of the form (fn1 fn2), where fn1 is a default name and fn2 is your choice for that name. For example (DEFSTOBJ $S (X :TYPE INTEGER :INITIALLY 0) (A :TYPE (ARRAY (INTEGER 0 9) (3)) :INITIALLY 9) :renaming ((X XACCESSOR) (CREATE-$S MAKE$S))) introduces the following definitions (DEFUN XP (X) ...) ; recognizer for X field (DEFUN AP (X) ...) ; recognizer of A field (DEFUN $SP ($S) ...) ; top-level recognizer for stobj $S (DEFUN MAKE$S () ...) ; creator for stobj $S (DEFUN XACCESSOR ($S) ...) ; accessor for X field (DEFUN UPDATE-X (V $S) ...) ; updater for X field (DEFUN A-LENGTH ($S) ...) ; length of A field (DEFUN RESIZE-A (K $S) ...) ; resizer for A field (DEFUN AI (I $S) ...) ; accessor for A field at index I (DEFUN UPDATE-AI (I V $S) ...) ; updater for A field at index I Note that even though the renaming alist substitutes ``XACCESSOR'' for ``X'' the updater for the X field is still called ``UPDATE-X.'' That is because the renaming is applied to the default function names, not to the field descriptors in the event. Use of the :renaming alist may be necessary to avoid name clashes between the default names and and pre-existing function symbols. Constants Defstobj events also introduce constant definitions (see [defconst]). One constant is introduced for each accessor function by prefixing and suffixing a `*' character on the function name. The value of that constant is the position of the field being accessed. For example, if the accessor functions are a, b, and c, in that order, then the following constant definitions are introduced. (defconst *a* 0) (defconst *b* 1) (defconst *c* 2) These constants are used for certain calls of [nth] and [update-nth] that are displayed to the user in proof output. For example, for stobj st with accessor functions a, b, and c, in that order, the term (nth '2 st) would be printed during a proof as (nth *c* st). Also see [term], in particular the discussion there of untranslated terms, and see [nth-aliases-table]. Inspecting the Effects of a Defstobj Because the stobj functions are introduced as ``sub-events'' of the defstobj the history commands :[pe] and :[pc] will not print the definitions of these functions but will print the superior defstobj event. To see the definitions of these functions use the history command :[pcb!]. To see an s-expression containing the definitions what constitute the raw Lisp implementation of the event, evaluate the form (nth 4 (global-val 'cltl-command (w state))) immediately after the defstobj event has been processed. A defstobj is considered redundant only if the name, field descriptors, renaming alist, and inline flag are identical to a previously executed defstobj. Note that a redundant defstobj does not reset the [stobj] fields to their initial values. Inlining and Performance The :inline keyword argument controls whether or not accessor, updater, and length functions are inlined (as macros under the hood, in raw Lisp). If :inline t is provided then these are inlined; otherwise they are not. The advantage of inlining is potentially better performance; there have been contrived examples, doing essentially nothing except accessing and updating array fields, where inlining reduced the time by a factor of 10 or more; and inlining has sped up realistic examples by a factor of at least 2. Inlining may get within a factor of 2 of C execution times for such contrived examples, and within a few percent of C execution times on realistic examples. A drawback to inlining is that redefinition may not work as expected, much as redefinition may not work as expected for macros: defined functions that call a macro, or inlined stobj function, will not see a subsequent redefinition of the macro or inlined function. Another drawback to inlining is that because inlined functions are implemented as macros in raw Lisp, tracing (see [trace$]) will not show their calls. These drawbacks are avoided by default, but the user who is not concerned about them is advised to specify :inline t. Specifying Congruent Stobjs Two stobjs are may be considered to be ``congruent'' if they have the same structure, that is, their defstobj events are identical when ignoring field names. In particular, every stobj is congruent to itself. In order to tell ACL2 that a new stobj st2 is indeed to be considered as congruent to an existing stobj st1, the defstobj event introducing st2 is given the keyword argument :congruent-to st1. Congruence is an equivalence relation: when you specify a new stobj to be congruent to an old one, you are also specifying that the new stobj is congruent to all other stobjs that are congruent to the old one. Thus, continuing the example above, if you specify that st3 is :congruent-to st2, then st1, st2, and st3 will all be congruent to each other. When two stobjs are congruent, ACL2 allows you to substitute one for another in a function call. Any number of stobjs may be replaced with congruent stobjs in the call, provided no two get replaced with the same stobj. The return values are correspondingly modified: if stobj st1 is replaced by st2 at an argument position, and if st1 is returned in the output [signature] of the function, then st2 is returned in place of st1. The following example illustrates congruent stobjs. For more examples of how to take advantage of congruent stobjs, and also of how to misuse them, see community book books/misc/congruent-stobjs-test.lisp. (defstobj st1 fld1) (defstobj st2 fld2 :congruent-to st1) (defstobj st3 fld3 :congruent-to st2) ; equivalently, :congruent-to st1 (defun f (st1 st2 st3) (declare (xargs :stobjs (st1 st2 st3))) (list (fld2 st1) (fld3 st2) (fld1 st3))) (update-fld1 1 st1) (update-fld1 2 st2) ; notice use of update-fld1 on st2 (update-fld1 3 st3) ; notice use of update-fld1 on st3 (assert-event (equal (f st3 st2 st1) '(3 2 1))) The following example shows an error that occurs when stobj arguments are repeated, i.e., at least two stobj arguments (in this case, three) get replaced by the same stobj. ACL2 !>(f st1 st1 st1) ACL2 Error in TOP-LEVEL: The form ST1 is being used, as an argument to a call of F, where the single-threaded object ST2 was expected, even though these are congruent stobjs. See :DOC defstobj, in particular the discussion of congruent stobjs. Note: this error occurred in the context (F ST1 ST1 ST1). ACL2 !>") (DEFSTUB (EVENTS) "Stub-out a function symbol Examples: ACL2 !>(defstub subr1 (* * state) => (mv * state)) ACL2 !>(defstub add-hash (* * hashtable) => hashtable) General Forms: (defstub name args-sig => output-sig) (defstub name args-sig => output-sig :doc doc-string) Name is a new function symbol and (name . args-sig) => output-sig) is a [signature]. Doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. See also the ``Old Style'' heading below. Defstub macro expands into an [encapsulate] event (see [encapsulate]). Thus, no axioms are available about name but it may be used wherever a function of the given signature is permitted. Exception: if output-sig is of the form (mv ...), then a :[type-prescription] rule is introduced stating that name returns a value satisfying [true-listp]. Old Style: Old Style General Form: (defstub name formals output) (defstub name formals output :doc doc-string) where name is a new function symbol, formals is its list of formal parameters, and output is either a symbol (indicating that the function returns one result) or a term of the form (mv s1 ... sn), where each si is a symbol (indicating that the function returns n results). Whether and where the symbol [state] occurs in formals and output indicates how the function handles [state]. It should be the case that (name formals output) is in fact a signature (see [signature]). Note that with the old style notation it is impossible to stub-out a function that uses any single-threaded object other than state. The old style is preserved for compatibility with earlier versions of ACL2.") (DEFTHEORY (EVENTS THEORIES) "Define a theory (to [enable] or [disable] a set of rules) Example: (deftheory interp-theory (set-difference-theories (universal-theory :here) (universal-theory 'interp-section))) General Form: (deftheory name term :doc doc-string) where name is a new symbolic name (see [name]), term is a term that when evaluated will produce a theory (see [theories]), and doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. Except for the variable [world], term must contain no free variables. Term is evaluated with [world] bound to the current world (see [world]) and the resulting theory is then converted to a runic theory (see [theories]) and associated with name. Henceforth, this runic theory is returned as the value of the theory expression (theory name). The value returned is the length of the resulting theory. For example, in the following, the theory associated with 'FOO has 54 [rune]s: ACL2 !>(deftheory foo (union-theories '(binary-append) (theory 'minimal-theory))) Summary Form: ( DEFTHEORY FOO ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) 54 ACL2 !> Note that the theory being defined depends on the context. For example, consider the following (contrived) example book. (in-package \"ACL2\") (defund foo (x) (consp x)) ; defund disables foo (local (in-theory (enable foo))) (deftheory my-theory (current-theory :here)) (in-theory (disable foo)) (defthm foo-property (implies (consp x) (foo x)) :hints ((\"Goal\" :in-theory (enable my-theory)))) At the time foo-property is proved admissible during book certification (see [certify-book]), the [local] [in-theory] event has previously been evaluated, so the [definition] of foo is [enable]d. Thus, the :in-theory hint on foo-property will [enable] foo, and the theorem proves. HOWEVER, when the book is later included (see [include-book]), the [local] event is skipped, so the definition of foo is [disable]d at the time the [theory] my-theory is defined. Hence, unlike the case for the admissibility pass of the book's certification, that theory does not include the definition of foo when the book is included. There is, however, a way to ensure that a [theory] defined in a book is the same at [include-book] time as it was during the admissibility pass of the book's certification; see [deftheory-static]. Note that a deftheory event is never redundant, see [redundant-events].") (DEFTHEORY-STATIC (EVENTS THEORIES) "Define a `static' theory (to [enable] or [disable] a set of rules) This macro provides a variant of [deftheory], such that the resulting theory is the same at [include-book] time as it was at [certify-book] time. We assume that the reader is familiar with [theories]; see [deftheory]. We begin here by illustrating how deftheory-static differs from [deftheory]. Suppose for example that the following events are the first two events in a book, where that book is certified in the initial ACL2 [world] (see [ground-zero]). (deftheory my-theory (current-theory :here)) (deftheory-static my-static-theory (current-theory :here)) Now suppose we include that book after executing the following event. (in-theory (disable car-cons)) Suppose that later we execute (in-theory (theory 'my-theory)). Then the rule car-cons will be disabled, because it was disabled at the time the expression (current-theory :here) was evaluated when processing the deftheory of my-theory while including the book. However, if we execute (in-theory (theory 'my-static-theory)), then the rule car-cons will be enabled, because the value of the theory my-static-theory was saved at the time the book was certified. General Form: (deftheory-static name term :doc doc-string) The arguments are handled the same as for [deftheory]. Thus, name is a new symbolic name (see [name]), term is a term that when evaluated will produce a theory (see [theories]), and doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. Except for the variable [world], term must contain no free variables. Term is evaluated with [world] bound to the current world (see [world]) and the resulting theory is then converted to a runic theory (see [theories]) and associated with name. Henceforth, this runic theory is returned as the value of the theory expression (theory name). As for [deftheory], the value returned is the length of the resulting theory. We conclude with an optional discussion about the implementation of deftheory-static, for those familiar with [make-event]. The following macroexpansion of the deftheory-static form above shows how this works (see [trans1]). ACL2 !>:trans1 (deftheory-static my-static-theory (current-theory :here)) (MAKE-EVENT (LET ((WORLD (W STATE))) (LIST 'DEFTHEORY 'MY-STATIC-THEORY (LIST 'QUOTE (CURRENT-THEORY :HERE))))) ACL2 !> The idea is that upon evaluation of this make-event form, the first step is to evaluate the indicated [let] expression to obtain a form (deftheory my-theory '(...)), where ``(...)'' is a list of all [rune]s in current theory. If this form is in a book being certified, then the resulting deftheory form is stored in the book's certificate, and is used when the book is included later.") (DEFTHM (EVENTS) "Prove and name a theorem Examples: (defthm assoc-of-app (equal (app (app a b) c) (app a (app b c)))) The following nonsensical example illustrates all the optional arguments but is illegal because not all combinations are permitted. See [hints] for a complete list of [hints]. (defthm main (implies (hyps x y z) (concl x y z)) :rule-classes (:REWRITE :GENERALIZE) :instructions (induct prove promote (dive 1) x (dive 2) = top (drop 2) prove) :hints ((\"Goal\" :do-not '(generalize fertilize) :in-theory (set-difference-theories (current-theory :here) '(assoc)) :induct (and (nth n a) (nth n b)) :use ((:instance assoc-of-append (x a) (y b) (z c)) (:functional-instance (:instance p-f (x a) (y b)) (p consp) (f assoc))))) :otf-flg t) General Form: (defthm name term :rule-classes rule-classes :instructions instructions :hints hints :otf-flg otf-flg :doc doc-string) where name is a new symbolic name (see [name]), term is a term alleged to be a theorem, and [rule-classes], [instructions], [hints], and [otf-flg] are as described in their respective [documentation]. Doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. The five keyword arguments above are all optional, however you may not supply both :[instructions] and :[hints], since one drives the proof checker and the other drives the theorem prover. If :[rule-classes] is not specified, the list (:rewrite) is used; if you wish the theorem to generate no rules, specify :[rule-classes] nil. When ACL2 processes a defthm event, it first tries to prove the [term] using the indicated hints (see [hints]) or [instructions] (see [proof-checker]). If it is successful, it stores the rules described by the rule-classes (see [rule-classes]), proving the necessary corollaries. Subtopics [Otf-flg] Allow more than one initial subgoal to be pushed for induction") (DEFTHMD (EVENTS) "Prove and name a theorem and then disable it Use defthmd instead of [defthm] when you want to disable a theorem immediately after proving it. This macro has been provided for users who prefer working in a mode where theorems are only enabled when explicitly directed by :[in-theory]. Specifically, the form (defthmd NAME TERM ...) expands to: (progn (defthmd NAME TERM ...) (with-output :off summary (in-theory (disable NAME))) (value-triple '(:defthmd NAME))). Note that defthmd commands are never redundant (see [redundant-events]). Even if the defthm event is redundant, then the [in-theory] event will still be executed. The summary for the [in-theory] event is suppressed. See [defthm] for documentation of defthm.") (DEFTTAG (INTERFACING-TOOLS EVENTS) "Introduce a trust tag (ttag) Introduction. This event is intended for advanced users who, in essence, want to build extensions of ACL2. The typical intended use is to create [books] that extend the functionality of ACL2 in ways not allowed without a so-called ``active trust tag''. A trust tag thus represents a contract: The writer of such a book is guaranteeing that the book extends ACL2 in a ``correct'' way as defined by the writer of the book. The writer of the book will often have a small section of the book in the scope of an active trust tag that can be inspected by potential users of that book: (defttag :some-ttag) ; install :some-ttag as an active trust tag (defttag nil) ; remove active trust tag Why might trust tags be needed? The evaluation of certain functions can introduce bugs and even unsoundness, but can be useful in restricted ways that avoid such issues. For example, [sys-call] can be used in an unsafe way, for example to overwrite files, or worse; see [sys-call] for a frightening example from Bob Boyer. The following example shows that the function [sys-call] is restricted by default, but can be called after installing an active trust tag. ACL2 !>(sys-call \"pwd\" nil) ACL2 Error in TOP-LEVEL: The SYS-CALL function cannot be called unless a trust tag is in effect. See :DOC defttag. ACL2 !>(defttag t) ; Install :T as an active trust tag. TTAG NOTE: Adding ttag :T from the top level loop. T ACL2 !>(sys-call \"pwd\" nil) ; print the current directory and return NIL /u/kaufmann NIL ACL2 !>(defttag nil) ; Remove the active trust tag (using value NIL). NIL ACL2 !>(sys-call \"pwd\" nil) ; Now we get the error again: ACL2 Error in TOP-LEVEL: The SYS-CALL function cannot be called unless a trust tag is in effect. See :DOC defttag. ACL2 !> Of course, using [sys-call] with the Linux command pwd is not likely to cause any soundness problems! So suppose we want to create a function that prints the working directory. We might put the following [events] into a book that is to be certified. (in-package \"ACL2\") (defttag :pwd-ttag) (defun print-working-dir () (declare (xargs :mode :program)) (sys-call \"pwd\" nil)) (defttag nil) ; optional (books end with this implicitly) We can certify this book with a specification that :pwd-ttag is a legal trust tag: (certify-book \"pwd\" 0 t :ttags (:pwd-ttag)) One can now use this book by executing [include-book] with keyword parameter :ttags (:pwd-ttag) and then calling function print-working-dir: (include-book \"pwd\" :ttags (:pwd-ttag)) (print-working-dir) ; working directory is printed to terminal Detailed documentation. General Forms: (defttag tag-name) (defttag tag-name :doc doc-string) where tag-name is a symbol. Doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. (For the rest of this discussion we ignore the :doc argument.) Note however that (other than the :doc argument), if tag-name is not nil then it is converted to a ``corresponding [keyword]'': a symbol in the \"KEYWORD\" package with the same [symbol-name] as tag-name. Thus, for example, (defttag foo) is equivalent to (defttag :foo). Moreover, a non-nil symbol with a [symbol-name] of \"NIL\" is illegal for trust tags; thus, for example, (defttag :nil) is illegal. This event introduces or removes a so-called active trust tag (or ``ttag'', pronounced ``tee tag''). An active ttag is a [keyword] symbol that is associated with potentially unsafe evaluation. For example, calls of [sys-call] are illegal unless there is an active trust tag. An active trust tag can be installed using a defttag event. If one introduces an active ttag and then writes definitions with calls [sys-call], presumably in a defensibly ``safe'' way, then responsibility for those calls is attributed to that ttag. This attribution (or blame!) is at the level of [books]; a book's [certificate] contains a list of ttags that are active in that book, or in a book that is included (possibly [local]ly), or in a book included in a book that is included (either inclusion being potentially [local]), and so on. We explain all this in more detail below. (Defttag :tag-name) is essentially equivalent to (table acl2-defaults-table :ttag :tag-name) and hence is [local] to any [books] and [encapsulate] [events] in which it occurs; see [ACL2-defaults-table]. We say more about the scope of defttag forms below. Note: This is an event! It does not print the usual event summary but nevertheless executes the above [table] event and hence changes the ACL2 logical [world], and is so recorded. Although no event summary is printed, it is important to note that the ``TTAG NOTE'', discussed below, is always printed for a non-nil :tag-name (unless deferred; see [set-deferred-ttag-notes]). Active ttags. Suppose tag-name is a non-nil symbol. Then (defttag :tag-name) sets :tag-name to be the (unique) ``active ttag.'' There must be an active ttag in order for there to be any mention of certain function and macro symbols, including [sys-call]; evaluate the form (strip-cars *ttag-fns-and-macros*) to see the full list of such symbols. On the other hand, (defttag nil) removes the active ttag, if any; there is then no active ttag. The scope of a defttag form in a book being certified or included is limited to subsequent forms in the same book before the next defttag (if any) in that book. Similarly, if a defttag form is evaluated in the top-level loop, then its effect is limited to subsequent forms in the top-level loop before the next defttag in the top-level loop (if any). Moreover, [certify-book] is illegal when a ttag is active; of course, in such a circumstance one can execute (defttag nil) in order to allow book certification. Ttag notes and the ``certifier.'' When a defttag is executed with an argument other than nil, output is printed, starting on a fresh line with: TTAG NOTE. For example: ACL2 !>(defttag :foo) TTAG NOTE: Adding ttag :FOO from the top level loop. :FOO ACL2 !> If the defttag occurs in an included book, the message looks like this. TTAG NOTE (for included book): Adding ttag :FOO from file /u/smith/acl2/my-book.lisp. The ``TTAG NOTE'' message is always printed on a single line. The intention is that one can search the standard output for all such notes in order to find all defttag events. In a sense, defttag events can allow you to define your own system on top of ACL2 (for example, see [progn!]). So in order for someone else (who we might call the ``certifier'') to be confident that your collection of [books] is meaningful, that certifier should certify all the user-supplied books from scratch and check either that no :ttags were supplied to [certify-book], or else look for every TTAG NOTE in the standard output in order to locate all defttag [events] with non-nil tag name. In this way, the certifier can in principle decide whether to be satisfied that those defttag events did not allow inappropriate forms in the user-supplied books. In order to eliminate much of the output from TTAG NOTEs, see [set-deferred-ttag-notes]. Note however that the resulting security is somewhat less; therefore, a TTAG NOTE is printed when invoking set-deferred-ttag-notes to defer printing of ttag notes. Allowed ttags when certifying and including books. A defttag form may not be evaluated unless its argument is a so-called ``allowed'' ttag. All ttags are allowed in the interactive top-level loop. However, during [certify-book] and [include-book], the set of allowed ttags is restricted according to the :ttags keyword argument. If this argument is omitted then no ttag is allowed, so a defttag call will fail during book certification or inclusion in this case. This restriction applies even to defttag forms already evaluated in the so-called certification [world] at the time [certify-book] is called. But note that (defttag nil) is always legal. A :ttags argument of [certify-book] and [include-book] can have value :all, indicating that every ttag is allowed, i.e., no restriction is being placed on the arguments, just as in the interactive top-level loop. In the case of include-book, an omitted :ttags argument or an argument of :default is treated as :all, except that warnings will occur when the book's [certificate] includes ttags; but for certify-book, an omitted ttags argument is treated as nil. Otherwise, if the :ttags argument is supplied but not :all, then its value is a true list of ttag specifications, each having one of the following forms, where sym is a non-nil symbol which is treated as the corresponding [keyword]. (1) :sym (2) (:sym) (3) (:sym x1 x2 ... xk), where k > 0 and each xi is a string, except that one xi may be nil. In Case (1), (defttag :sym) is allowed to occur in at most one book or else in the top-level loop (i.e., the certification world for a book under certification or a book being included). Case (2) allows (defttag :sym) to occur in an unlimited number of books. For case (3) the xi specify where (defttag :sym) may occur, as follows. The case that xi is nil refers to the top-level loop, while all other xi are filenames, where the \".lisp\" extension is optional and relative pathnames are considered to be relative to the connected book directory (see [cbd]). Note that the restrictions on (defttag :sym) apply equally to any equivalent for based on the notion of ``corresponding keyword'' discussed above, e.g., (defttag acl2::sym). An error message, as shown below, illustrates how ACL2 enforcess the notion of allowed ttags. Suppose that you call [certify-book] with argument :ttags (:foo), where you have already executed (defttag :foo) in the certification world (i.e., before calling [certify-book]). Then ACL2 immediately associates the ttag :foo with nil, where again, nil refers to the top-level loop. If ACL2 then encounters (defttag foo) inside that book, you will get the following error (using the full book name for the book, as shown): ACL2 Error in ( TABLE ACL2-DEFAULTS-TABLE ...): The ttag :FOO associated with file /u/smith/work/my-book.lisp is not among the set of ttags permitted in the current context, specified as follows: ((:FOO NIL)). See :DOC defttag. In general the structure displayed by the error message, which is ((:FOO NIL)) in this case, represents the currently allowed ttags with elements as discussed in (1) through (3) above. In this case, that list's unique element is (:FOO NIL), meaning that ttag :FOO is only allowed at the top level (as represented by NIL). Associating ttags with books and with the top-level loop. When a book is certified, each form (defttag tag) that is encountered for non-nil tag in that book or an included book is recorded in the generated [certificate], which associates the keyword corresponding to tag with the [full-book-name] of the book containing that deftag. If such a defttag form is encountered outside a book, hence in the [portcullis] of the book being certified or one of its included books, then that keyword is associated with nil in the generated [certificate]. Note that the notion of ``included book'' here applies to the recursive notion of a book either included directly in the book being certified or else included in such a book, where we account even for [local]ly included books. For examples of ways to take advantage of ttags, see [hacker], [include-raw], [quicklisp], and more generally [interfacing-tools]. See also [ttags-seen], [progn!], [remove-untouchable], [set-raw-mode], and [sys-call]. Subtopics [Push-untouchable] Add name or list of names to the list of untouchable symbols [Remove-untouchable] Remove names from lists of untouchable symbols [Set-deferred-ttag-notes] Modify the verbosity of TTAG NOTE printing [Set-raw-mode] Enter or exit ``raw mode,'' a raw Lisp environment [Set-raw-mode-on!] Enter ``raw mode,'' a raw Lisp environment") (DEFUN (EVENTS PROGRAMMING) "Define a function symbol Examples: (defun app (x y) (if (consp x) (cons (car x) (app (cdr x) y)) y)) (defun fact (n) (declare (xargs :guard (and (integerp n) (>= n 0)))) (if (zp n) 1 (* n (fact (1- n))))) General Form: (defun fn (var1 ... varn) doc-string dcl ... dcl body), where fn is the symbol you wish to define and is a new symbolic name (see [name]), (var1 ... varn) is its list of formal parameters (see [name]), and body is its body. The definitional axiom is logically admissible provided certain restrictions are met. These are sketched below. Note that ACL2 does not support the use of lambda-list keywords (such as &optional) in the formals list of functions. We do support some such keywords in macros and often you can achieve the desired syntax by defining a macro in addition to the general version of your function. See [defmacro]. Doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. The declarations (see [declare]), dcl, are also optional. If more than one dcl form appears, they are effectively grouped together as one. Perhaps the most commonly used ACL2 specific declaration is of the form (declare (xargs :guard g :measure m)). This declaration in the defun of some function fn has the effect of making the ``[guard]'' for fn be the term g and the ``measure'' be the term m. The notion of ``measure'' is crucial to ACL2's definitional principle. The notion of ``guard'' is not, and is discussed elsewhere; see [verify-guards] and see [set-verify-guards-eagerness]. Note that the :measure is ignored in :[program] mode; see [defun-mode]. We now briefly discuss the ACL2 definitional principle, using the following definition form which is offered as a more or less generic example. (defun fn (x y) (declare (xargs :guard (g x y) :measure (m x y))) (if (test x y) (stop x y) (step (fn (d x) y)))) Note that in our generic example, fn has just two arguments, x and y, the [guard] and measure terms involve both of them, and the body is a simple case split on (test x y) leading to a ``non-recursive'' branch, (stop x y), and a ``recursive'' branch. In the recursive branch, fn is called after ``decrementing'' x to (d x) and some step function is applied to the result. Of course, this generic example is quite specific in form but is intended to illustrate the more general case. Provided this definition is admissible under the logic, as outlined below, it adds the following axiom to the logic. Defining Axiom: (fn x y) = (if (test x y) (stop x y) (step (fn (d x) y))) Note that the [guard] of fn has no bearing on this logical axiom. This defining axiom is actually implemented in the ACL2 system by a :[definition] rule, namely (equal (fn x y) (if (test a b) (stop a b) (step (fn (d a) b)))). See [definition] for a discussion of how definition rules are applied. Roughly speaking, the rule causes certain instances of (fn x y) to be replaced by the corresponding instances of the body above. This is called ``opening up'' (fn x y). The instances of (fn x y) opened are chosen primarily by heuristics which determine that the recursive calls of fn in the opened body (after simplification) are more desirable than the unopened call of fn. This discussion has assumed that the definition of fn was admissible. Exactly what does that mean? First, fn must be a previously unaxiomatized function symbol (however, see [ld-redefinition-action]). Second, the formal parameters must be distinct variable names. Third, the [guard], measure, and body should all be terms and should mention no free variables except the formal parameters. Thus, for example, body may not contain references to ``global'' or ``special'' variables; ACL2 constants or additional formals should be used instead. The final conditions on admissibility concern the termination of the recursion. Roughly put, all applications of fn must terminate. In particular, there must exist a binary relation, rel, and some unary predicate mp such that rel is well-founded on objects satisfying mp, the measure term m must always produce something satisfying mp, and the measure term must decrease according to rel in each recursive call, under the hypothesis that all the tests governing the call are satisfied. By the meaning of well-foundedness, we know there are no infinitely descending chains of successively rel-smaller mp-objects. Thus, the recursion must terminate. The only primitive well-founded relation in ACL2 is [o<] (see [o<]), which is known to be well-founded on the [o-p]s (see [o-p]). For the proof of well-foundedness, see [proof-of-well-foundedness]. However it is possible to add new well-founded relations. For details, see [well-founded-relation]. We discuss later how to specify which well-founded relation is selected by defun and in the present discussion we assume, without loss of generality, that it is [o<] on the [o-p]s. For example, for our generic definition of fn above, with measure term (m x y), two theorems must be proved. The first establishes that m produces an ordinal: (o-p (m x y)). The second shows that m decreases in the (only) recursive call of fn: (implies (not (test x y)) (o< (m (d x) y) (m x y))). Observe that in the latter formula we must show that the ``m-size'' of (d x) and y is ``smaller than'' the m-size of x and y, provided the test, (test x y), in the body fails, thus leading to the recursive call (fn (d x) y). See [o<] for a discussion of this notion of ``smaller than.'' It should be noted that the most commonly used ordinals are the natural numbers and that on natural numbers, [o<] is just the familiar ``less than'' relation ([<]). Thus, it is very common to use a measure m that returns a nonnegative integer, for then (o-p (m x y)) becomes a simple conjecture about the type of m and the second formula above becomes a conjecture about the less-than relationship of nonnegative integer arithmetic. The most commonly used measure function is [ACL2-count], which computes a nonnegative integer size for all ACL2 objects. See [ACL2-count]. Probably the most common recursive scheme in Lisp [programming] is when some formal is supposed to be a list and in the recursive call it is replaced by its [cdr]. For example, (test x y) might be simply (atom x) and (d x) might be (cdr x). In that case, (acl2-count x) is a suitable measure because the [ACL2-count] of a [cons] is strictly larger than the [ACL2-count]s of its [car] and [cdr]. Thus, ``recursion by [car]'' and ``recursion by [cdr]'' are trivially admitted if [ACL2-count] is used as the measure and the definition protects every recursive call by a test insuring that the decremented argument is a [consp]. Similarly, ``recursion by [1-]'' in which a positive integer formal is decremented by one in recursion, is also trivially admissible. See [built-in-clause] to extend the class of trivially admissible recursive schemes. We now turn to the question of which well-founded relation defun uses. It should first be observed that defun must actually select both a relation (e.g., [o<]) and a domain predicate (e.g., [o-p]) on which that relation is known to be well-founded. But, as noted elsewhere (see [well-founded-relation]), every known well-founded relation has a unique domain predicate associated with it and so it suffices to identify simply the relation here. The [xargs] field of a [declare] permits the explicit specification of any known well-founded relation with the keyword :[well-founded-relation]. An example is given below. If the [xargs] for a defun specifies a well-founded relation, that relation and its associated domain predicate are used in generating the termination conditions for the definition. If no :[well-founded-relation] is specified, defun uses the :[well-founded-relation] specified in the [ACL2-defaults-table]. See [set-well-founded-relation] to see how to set the default well-founded relation (and, implicitly, its domain predicate). The initial default well-founded relation is [o<] (with domain predicate [o-p]). This completes the brief sketch of the ACL2 definitional principle. Optionally, see [ruler-extenders] for a more detailed discussion of the termination analysis and resulting proof obligations for admissibility, as well as a discussion of the relation to how ACL2 stores induction schemes. On very rare occasions ACL2 will seem to \"hang\" when processing a definition, especially if there are many subexpressions of the body whose function symbol is [if] (or which macroexpand to such an expression). In those cases you may wish to supply the following to [xargs]: :normalize nil. This is an advanced feature that turns off ACL2's usual propagation upward of if tests. The following example illustrates all of the available declarations and most hint keywords, but is completely nonsensical. For documentation, see [xargs] and see [hints]. (defun example (x y z a b c i j) (declare (ignore a b c) (type integer i j) (xargs :guard (symbolp x) :measure (- i j) :ruler-extenders :basic :well-founded-relation my-wfr :hints ((\"Goal\" :do-not-induct t :do-not '(generalize fertilize) :expand ((assoc x a) (member y z)) :restrict ((<-trans ((x x) (y (foo x))))) :hands-off (length binary-append) :in-theory (set-difference-theories (current-theory :here) '(assoc)) :induct (and (nth n a) (nth n b)) :use ((:instance assoc-of-append (x a) (y b) (z c)) (:functional-instance (:instance p-f (x a) (y b)) (p consp) (f assoc))))) :guard-hints ((\"Subgoal *1/3'\" :use ((:instance assoc-of-append (x a) (y b) (z c))))) :mode :logic :normalize nil :verify-guards nil :non-executable t :otf-flg t)) (example-body x y z i j)) Subtopics [Defn] Definition with [guard] t [Defnd] [disable]d definition with [guard] t [Defun-inline] Define a potentially inlined function symbol and associated macro [Defun-mode] Determines whether a function definition is a logical act [Defun-notinline] Define a not-to-be-inlined function symbol and associated macro [Defun-nx] Define a non-executable function symbol [Defund] Define a function symbol and then disable it [Defund-inline] Define a potentially disabled, inlined function symbol and associated macro [Defund-notinline] Define a disabled, not-to-be-inlined function symbol and associated macro [Mutual-recursion] Define some mutually recursive functions [Ruler-extenders] Control for ACL2's termination and induction analyses [Set-bogus-defun-hints-ok] Allow unnecessary ([xargs] :hints ...). [Set-ignore-ok] Allow unused formals and locals without an ignore or ignorable declaration [Set-irrelevant-formals-ok] Allow irrelevant formals in definitions [Set-measure-function] Set the default measure function symbol [Set-well-founded-relation] Set the default well-founded relation [Xargs] Extra arguments, for example to give [hints] to [defun]") (DEFUN-INLINE (DEFUN EVENTS) "Define a potentially inlined function symbol and associated macro You may be able to improve performance by replacing an event (defun f ...) with a corresponding event (defun-inline f ...), in order to encourage the host Lisp compiler to inline calls of f. Example Form: (defun-inline lng (x) (declare (xargs :guard (true-listp x))) (if (endp x) 0 (1+ (lng (cdr x))))) General Form: (defun-inline fn (var1 ... varn) doc-string dcl ... dcl body) satisfying the same requirements as in the General Form for [defun]. The effect is to define a macro fn and a function fn$inline (i.e., a symbol in the same package as fn but whose [symbol-name] has the suffix \"$INLINE\", such that each call of fn expands to a call of the function symbol fn$inline on the same arguments. Moreover, [table] [events] are generated that allow the use of fn in [theory] expressions to represent fn$inline and that cause any untranslated (user-level) call of fn$inline to be printed as the corresponding call of fn. Doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. A form (defun-inline f ...) actually defines a function named f$inline and a corresponding macro named f whose calls expand to calls of f$inline, while providing the illusion that there is just the ``function'' f. For example, the Example Form above macroexpands in one step to the following form. (progn (defmacro lng (non-stobj-var0) (list 'lng$inline non-stobj-var0)) (add-macro-fn lng lng$inline) (defun lng$inline (x) (declare (xargs :guard (true-listp x))) (if (endp x) 0 (1+ (lng (cdr x)))))) Note that the above call of [add-macro-fn] generates the aforementioned two table events (see [add-macro-fn]), which provide the illusion that we are just defining a function lng, as you can see in the following log: lng appears rather than lng$inline. ACL2 !>(set-gag-mode nil) ACL2 !>(thm (equal (lng (append x y)) (+ (lng x) (lng y))) :hints ((\"Goal\" :in-theory (enable lng)))) [.. output omitted ..] Subgoal *1/2 (IMPLIES (AND (NOT (ENDP X)) (EQUAL (LNG (APPEND (CDR X) Y)) (+ (LNG (CDR X)) (LNG Y)))) (EQUAL (LNG (APPEND X Y)) (+ (LNG X) (LNG Y)))). [.. output omitted ..] Under the hood, ACL2 arranges that every function symbol with suffix \"$INLINE\" is presented to the compiler as one whose calls we would prefer to inline. Technically: the Common Lisp form (declaim (inline f$inline)) is generated for a function symbol f$inline before that symbol's definition is submitted. However, the Common Lisp spec explicitly avoids requiring that the compiler respect this declaim form. Fortunately, Common Lisp implementations often do respect it. Also see [defund-inline], see [defun-notinline], and see [defund-notinline]. Remarks. (1) None of these macros (including defun-inline) is supported for use inside a [mutual-recursion]. (2) Every function symbol defined in ACL2 whose [symbol-name] has the suffix \"$INLINE\" is proclaimed to be inline; similarly for \"$NOTINLINE\" and notinline. (3) No special treatment for inlining (or notinlining) is given for function symbols locally defined by [flet], with two exceptions: when explicitly declared inline or notinline by the flet form, and for symbols discussed in (1) and (2) above that, at some point in the current ACL2 session, were defined as function symbols in ACL2 (even if not currently defined because of undoing or being [local]). (4) The function symbol actually being defined by (defun-inline foo ...) is foo$inline. As mentioned above, one can be oblivious to this fact when writing [theory] expressions or perusing prover output. However, for other purposes (for example, [verify-guards] and [defabsstobj] :exports) you will need to supply the name of the function symbol rather than the name of the macro; e.g., for the above form (defun-inline foo ...), you may subsequently issue the event (verify-guards foo$inline) but not (verify-guards foo). (5) Obscure Remark. Suppose that you certify a book with compilation (the default) in one host Lisp, saving the expansion file. Suppose that you then compile in another host Lisp by using [include-book] with argument :load-compiled-file :comp. Then in subsequent sessions, including that book with the second host Lisp will not result in any inline or notinline behavior for functions defined in the book. This may be fixed in a future release if someone complains.") (DEFUN-MODE (DEFUN) "Determines whether a function definition is a logical act Two ``[defun-mode]s'' are supported, :[program] and :[logic]. Roughly speaking, :[program] mode allows you to prototype a function for execution without any proof burdens, while :[logic] mode allows you to add a new definitional axiom to the logic. The system comes up in :[logic] mode. Execution of functions whose [defun-mode] is :[program] may render ACL2 unsound! See [defun-mode-caveat]. Note that calls of [local] and of many [events] are skipped in :program mode; see [program]. When you define a function in the ACL2 logic, that function can be run on concrete data. But it is also possible to reason deductively about the function because each definition extends the underlying logic with a definitional axiom. To ensure that the logic is sound after the addition of this axiom, certain restrictions have to be met, namely that the recursion terminates. This can be quite challenging. Because ACL2 is a [programming] language, you often may wish simply to program in ACL2. For example, you may wish to define your system and test it, without any logical burden. Or, you may wish to define ``utility'' functions --- functions that are executed to help manage the task of building your system but functions whose logical properties are of no immediate concern. Such functions might be used to generate test data or help interpret the results of tests. They might create files or explore the ACL2 database. The termination arguments for such functions are an unnecessary burden provided no axioms about the functions are ever used in deductions. Thus, ACL2 introduces the idea of the ``[defun-mode]'' of a function. The :mode keyword of [defun]'s [declare] xarg allows you to specify the [defun-mode] of a given definition. If no :mode keyword is supplied, the default [defun-mode] is used; see [default-defun-mode]. There are two [defun-mode]s, each of which is written as a keyword: :[program] --- logically undefined but executable outside deductive contexts. :[logic] --- axiomatically defined as per the ACL2 definitional principle. It is possible to change the [defun-mode] of a function from :[program] to :[logic]. We discuss this below. We think of functions having :[program] mode as ``dangerous'' functions, while functions having :[logic] mode are ``safe.'' The only requirement enforced on :[program] mode functions is the syntactic one: each definition must be well-formed ACL2. Naively speaking, if a :[program] mode function fails to terminate then no harm is done because no axiom is added (so inconsistency is avoided) and some invocations of the function may simply never return. This simplistic justification of :[program] mode execution is faulty because it ignores the damage that might be caused by ``mis-guarded'' functions. See [defun-mode-caveat]. We therefore implicitly describe an imagined implementation of [defun-mode]s that is safe and, we think, effective. But please see [defun-mode-caveat]. The default [defun-mode] is :[logic]. This means that when you [defun] a function the system will try to prove termination. If you wish to introduce a function of a different [defun-mode] use the :mode [xargs] keyword. Below we show fact introduced as a function in :[program] mode. (defun fact (n) (declare (xargs :mode :program)) (if (or (not (integerp n)) (= n 0)) 1 (* n (fact (1- n))))) No axiom is added to the logic as a result of this definition. By introducing fact in :[program] mode we avoid the burden of a termination proof, while still having the option of executing the function. For example, you can type ACL2 !>(fact 3) and get the answer 6. If you type (fact -1) you will get a hard lisp error due to ``infinite recursion.'' However, the ACL2 theorem prover knows no axioms about fact. In particular, if the term (fact 3) arises in a proof, the theorem prover is unable to deduce that it is 6. From the perspective of the theorem prover it is as though fact were an undefined function symbol of arity 1. Thus, modulo certain important issues (see [defun-mode-caveat]), the introduction of this function in :[program] mode does not imperil the soundness of the system --- despite the fact that the termination argument for fact was omitted --- because nothing of interest can be proved about fact. Indeed, we do not allow fact to be used in logical contexts such as conjectures submitted for proof. It is possible to convert a function from :[program] mode to :[logic] mode at the cost of proving that it is admissible. This can be done by invoking (verify-termination fact) which is equivalent to submitting the [defun] of fact, again, but in :[logic] mode. (defun fact (n) (declare (xargs :mode :logic)) (if (or (not (integerp n)) (= n 0)) 1 (* n (fact (1- n))))) This particular event will fail because the termination argument requires that n be nonnegative. A repaired [defun], for example with [=] replaced by [<=], will succeed, and an axiom about fact will henceforth be available. Technically, [verify-termination] submits a redefinition of the :[program] mode function. This is permitted, even when [ld-redefinition-action] is nil, because the new definition is identical to the old (except for its :mode and, possibly, other non-logical properties). See [guard] for a discussion of how to restrict the execution of functions. [Guard]s may be ``verified'' for functions in :[logic] mode; see [verify-guards]. Subtopics [Logic] To set the default [defun-mode] to :logic [Program] To set the default [defun-mode] to :[program]") (DEFUN-MODE-CAVEAT (COMMON-LISP) "Potential soundness issue for functions with [defun-mode] :[program] Technically speaking, in the current implementation, the execution of functions having [defun-mode] :[program] may damage the ACL2 system in a way that renders it unsound. In practice, we have never seen this happen; so, the explanations below can be viewed as extremely paranoid. Nevertheless, here we document this concern, even if it should be taken with more than a grain of salt. See [defun-mode] for a discussion of [defun-mode]s. That discussion describes an imagined implementation that is slightly different from this one. This note explains that the current implementation is open to unsoundness. For discussion of a different soundness issue that is also related to function execution, see [generalized-booleans]. The execution of a function having [defun-mode] :[program] may violate Common Lisp [guard]s on the subroutines used. (This may be true even for calls of a function on arguments that satisfy its [guard], because ACL2 has not verified that its [guard] is sufficient to protect its subroutines.) When a [guard] is violated at runtime all bets are off. That is, no guarantees are made either about the answer being ``right'' or about the continued rationality of the ACL2 system itself. For example, suppose you make the following [defun]: (defun crash (i) (declare (xargs :mode :program :guard (integerp i))) (car i)) Note that the declared guard does not in fact adequately protect the subroutines in the body of crash; indeed, satisfying the guard to crash will guarantee that the [car] expression is in violation of its guard. Because this function is admitted in :[program]-mode, no checks are made concerning the suitability of the guard. Furthermore, in the current ACL2 implementation, crash is executed directly in Common Lisp. Thus if you call crash on an argument satisfying its guard you will cause an erroneous computation to take place. ACL2 !>(crash 7) Error: Caught fatal error [memory may be damaged] ... There is no telling how much damage is done by this errant computation. In some lisps your ACL2 job may actually crash back to the operating system. In other lisps you may be able to recover from the ``hard error'' and resume ACL2 in a damaged but apparently functional image. THUS, HAVING A FUNCTION WITH [defun-mode] :[program] IN YOUR SYSTEM ABSOLVES US, THE ACL2 IMPLEMENTORS, FROM RESPONSIBILITY FOR THE SOUNDNESS OF OUR SYSTEM. Furthermore ACL2 DOES NOT YET PROVIDE ANY MEANS OF REGAINING ASSURANCES OF SOUNDNESS AFTER THE INTRODUCTION OF A FUNCTION IN :[program] MODE, EVEN IF IT IS ULTIMATELY CONVERTED TO :[logic] MODE (since its execution could have damaged the system in a way that makes it possible to verify its termination and [guard]s unsoundly). Finally, THE VAST MAJORITY OF ACL2 SYSTEM CODE IS IN :[program] MODE AND SO ALL BETS ARE OFF FROM BEFORE YOU START! This hopeless state of current affairs will change, we think. We think we have defined our functions ``correctly'' in the sense that they can be converted, without ``essential'' modification, to :[logic] mode. We think it very unlikely that a mis-guarded function in :[program] mode (whether ours or yours) will cause unsoundness without some sort of hard lisp error accompanying it. We think that ultimately we can make it possible to execute your functions (interpretively) without risk to the system, even when some have :[program] mode. In that imagined implementation, code using functions having :[program] mode would run more slowly, but safely. These functions could be introduced into the logic ex post facto, whereupon the code's execution would speed up because Common Lisp would be allowed to execute it directly. We therefore ask that you simply pretend that this is that imagined implementation, introduce functions in :[program] mode, use them as convenient and perhaps ultimately introduce some of them in :[logic] mode and prove their properties. If you use the system this way we can develop (or dismiss) this style of formal system development. BUT BE ON THE LOOKOUT FOR SCREWUPS DUE TO DAMAGE CAUSED BY THE EXECUTION OF YOUR FUNCTIONS HAVING :[program] MODE!") (DEFUN-NOTINLINE (DEFUN EVENTS) "Define a not-to-be-inlined function symbol and associated macro See [defun-inline] for an analogous utility that supports inlining. The present utility is probably far less useful; it tells the compiler not to inline calls of the function being defined. Also see [defund-notinline] for a variant of this event that disables the newly-defined function symbol. Under the hood, (defun-inline f ...) and (defun-notinline f ...) cause evaluation of Common Lisp forms (declaim (inline f$inline)) and (declaim (notinline f$notinline)), respectively. According to the Common Lisp spec, the compiler need not respect the first of these (for inline), but it must respect the second of these (for notinline). Fortunately, Common Lisp implementations often do respect the first of these as well.") (DEFUN-NX (DEFUN EVENTS) "Define a non-executable function symbol Example: (set-state-ok t) (defun-nx foo (x state) (mv-let (a b c) (cons x state) (list a b c b a))) ; Note ``ill-formed'' call of foo just below. (defun bar (state y) (foo state y)) The macro defun-nx introduces definitions using the [defun] macro, always in :[logic] mode, such that the calls of the resulting function cannot be evaluated. Such a definition is admitted without enforcing syntactic restrictions for executability, in particular for single-threadedness (see [stobj]) and multiple-values passing (see [mv] and see [mv-let]). After such a definition is admitted, the usual syntactic rules for [state] and user-defined [stobj]s are relaxed for calls of the function it defines. Also see [non-exec] for a way to designate subterms of function bodies, or subterms of code to be executed at the top level, as non-executable. The syntax of defun-nx is identical to that of [defun]. A form (defun-nx name (x1 ... xk) ... body) expands to the following form. (defun name (x1 ... xk) (declare (xargs :non-executable t :mode :logic)) ... (prog2$ (throw-nonexec-error 'name (list x1 ... xk)) body)) Note that because of the insertion of the above call of throw-nonexec-error, no formal is ignored when using defun-nx. During proofs, the error is silent; it is ``caught'' by the proof mechanism and generally results in the introduction of a call of [hide] during a proof. If an error message is produced by evaluating a call of the function on a list of arguments that includes state or user-defined [stobj]s, these arguments will be shown as symbols such as || in the error message. In the case of a user-defined stobj bound by [with-local-stobj] or [stobj-let], the symbol printed will include the suffix {instance}, for example, |{instance}|. It is harmless to include :non-executable t in your own [xargs] [declare] form; defun-nx will still lay down its own such declaration, but ACL2 can tolerate the duplication. Note that defund-nx is also available. It has an effect identical to that of defun-nx except that as with [defund], it leaves the function disabled. If you use guards (see [guard]), please be aware that even though syntactic restrictions are relaxed for defun-nx, guard verification proceeds exactly as for [defun]. If you want ACL2 to skip a form for purposes of generating guard proof obligations, use the macro [non-exec], which generates a call of throw-nonexec-error that differs somewhat from the one displayed above. See [non-exec]. See [defun] for documentation of defun.") (DEFUN-SK (EVENTS) "Define a function whose body has an outermost quantifier Examples: (defun-sk exists-x-p0-and-q0 (y z) (exists x (and (p0 x y z) (q0 x y z)))) (defun-sk exists-x-p0-and-q0 (y z) ; equivalent to the above (exists (x) (and (p0 x y z) (q0 x y z)))) (defun-sk forall-x-y-p0-and-q0 (z) (forall (x y) (and (p0 x y z) (q0 x y z))) :strengthen t) General Form: (defun-sk fn (var1 ... varn) body &key rewrite doc quant-ok skolem-name thm-name witness-dcls strengthen) where fn is the symbol you wish to define and is a new symbolic name (see [name]), (var1 ... varn) is its list of formal parameters (see [name]), and body is its body, which must be quantified as described below. The &key argument doc, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. In the case that n is 1, the list (var1) may be replaced by simply var1. The other arguments are explained below. For a simple example, see [defun-sk-example]. For a more elaborate example, see [Tutorial4-Defun-Sk-Example]. See [quantifier-tutorial] for a careful beginner's introduction that takes you through typical kinds of quantifier-based reasoning in ACL2. Also see [quantifiers] for an example illustrating how the use of recursion, rather than explicit quantification with defun-sk, may be preferable. Below we describe the defun-sk event precisely. First, let us consider the examples above. The first example, again, is: (defun-sk exists-x-p0-and-q0 (y z) (exists x (and (p0 x y z) (q0 x y z)))) It is intended to represent the predicate with formal parameters y and z that holds when for some x, (and (p0 x y z) (q0 x y z)) holds. In fact defun-sk is a macro that adds the following two [events], as shown just below. The first event guarantees that if this new predicate holds of y and z, then the term shown, (exists-x-p0-and-q0-witness y z), is an example of the x that is therefore supposed to exist. (Intuitively, we are axiomatizing exists-x-p0-and-q0-witness to pick a witness if there is one. We comment below on the use of [defun-nx]; for now, consider defun-nx to be [defun].) Conversely, the second event below guarantees that if there is any x for which the term in question holds, then the new predicate does indeed hold of y and z. (defun-nx exists-x-p0-and-q0 (y z) (let ((x (exists-x-p0-and-q0-witness y z))) (and (p0 x y z) (q0 x y z)))) (defthm exists-x-p0-and-q0-suff (implies (and (p0 x y z) (q0 x y z)) (exists-x-p0-and-q0 y z))) Now let us look at the third example from the introduction above: (defun-sk forall-x-y-p0-and-q0 (z) (forall (x y) (and (p0 x y z) (q0 x y z)))) The intention is to introduce a new predicate (forall-x-y-p0-and-q0 z) which states that the indicated conjunction holds of all x and all y together with the given z. This time, the axioms introduced are as shown below. The first event guarantees that if the application of function forall-x-y-p0-and-q0-witness to z picks out values x and y for which the given term (and (p0 x y z) (q0 x y z)) holds, then the new predicate forall-x-y-p0-and-q0 holds of z. Conversely, the (contrapositive of) the second axiom guarantees that if the new predicate holds of z, then the given term holds for all choices of x and y (and that same z). (defun-nx forall-x-y-p0-and-q0 (z) (mv-let (x y) (forall-x-y-p0-and-q0-witness z) (and (p0 x y z) (q0 x y z)))) (defthm forall-x-y-p0-and-q0-necc (implies (not (and (p0 x y z) (q0 x y z))) (not (forall-x-y-p0-and-q0 z)))) The examples above suggest the critical property of defun-sk: it indeed does introduce the quantified notions that it claims to introduce. Notice that the [defthm] event just above, forall-x-y-p0-and-q0-necc, may not be of optimal form as a rewrite rule. Users sometimes find that when the quantifier is forall, it is useful to state this rule in a form where the new quantified predicate is a hypothesis instead. In this case that form would be as follows: (defthm forall-x-y-p0-and-q0-necc (implies (forall-x-y-p0-and-q0 z) (and (p0 x y z) (q0 x y z)))) ACL2 will turn this into one :[rewrite] rule for each conjunct, (p0 x y z) and (q0 x y z), with hypothesis (forall-x-y-p0-and-q0 z) in each case. In order to get this effect, use :rewrite :direct, in this case as follows. (defun-sk forall-x-y-p0-and-q0 (z) (forall (x y) (and (p0 x y z) (q0 x y z))) :rewrite :direct) We now turn to a detailed description of defun-sk, starting with a discussion of its arguments as shown in the \"General Form\" above. The third argument, body, must be of the form (Q bound-vars term) where: Q is the symbol [forall] or [exists] (in the \"ACL2\" package), bound-vars is a variable or true list of variables disjoint from (var1 ... varn) and not including [state], and term is a term. The case that bound-vars is a single variable v is treated exactly the same as the case that bound-vars is (v). The result of this event is to introduce a ``Skolem function,'' whose name is the keyword argument skolem-name if that is supplied, and otherwise is the result of modifying fn by suffixing \"-WITNESS\" to its name. The following definition and one of the following two theorems (as indicated) are introduced for skolem-name and fn in the case that bound-vars (see above) is a single variable v. The name of the [defthm] event may be supplied as the value of the keyword argument :thm-name; if it is not supplied, then it is the result of modifying fn by suffixing \"-SUFF\" to its name in the case that the quantifier is [exists], and \"-NECC\" in the case that the quantifier is [forall]. (defun-nx fn (var1 ... varn) (let ((v (skolem-name var1 ... varn))) term)) (defthm fn-suff ;in case the quantifier is EXISTS (implies term (fn var1 ... varn))) (defthm fn-necc ;in case the quantifier is FORALL (implies (not term) (not (fn var1 ... varn)))) In the forall case, however, the keyword pair :rewrite :direct may be supplied after the body of the defun-sk form, in which case the contrapositive of the above form is used instead: (defthm fn-necc ;in case the quantifier is FORALL (implies (fn var1 ... varn) term)) This is often a better choice for the \"-NECC\" rule, provided ACL2 can parse term as a :[rewrite] rule. A second possible value of the :rewrite argument of defun-sk is :default, which gives the same behavior as when :rewrite is omitted. Otherwise, the value of :rewrite should be the term to use as the body of the fn-necc theorem shown above; ACL2 will attempt to do the requisite proof in this case. If that term is weaker than the default, the properties introduced by defun-sk may of course be weaker than they would be otherwise. Finally, note that the :rewrite keyword argument for defun-sk only makes sense if the quantifier is forall; it is thus illegal if the quantifier is exists. Enough said about :rewrite! In the case that bound-vars is a list of at least two variables, say (bv1 ... bvk), the definition above (with no keywords) is the following instead, but the theorem remains unchanged. (defun-nx fn (var1 ... varn) (mv-let (bv1 ... bvk) (skolem-name var1 ... varn) term)) In order to emphasize that the last element of the list, body, is a term, defun-sk checks that the symbols [forall] and [exists] do not appear anywhere in it. However, on rare occasions one might deliberately choose to violate this convention, presumably because [forall] or [exists] is being used as a variable or because a macro call will be eliminating ``calls of'' [forall] and [exists]. In these cases, the keyword argument quant-ok may be supplied a non-nil value. Then defun-sk will permit [forall] and [exists] in the body, but it will still cause an error if there is a real attempt to use these symbols as quantifiers. The use of [defun-nx] above, rather than [defun], disables certain checks that are required for evaluation, in particular the single-threaded use of [stobj]s. However, there is a price: calls of these defined functions cannot be evaluated; see [defun-nx]. Normally that is not a problem, since these notions involve quantifiers. But you are welcome to replace this [declare] form with your own, as follows: if you supply a list of declare forms to keyword argument :witness-dcls, these will become the declare forms in the generated [defun]. Note that if your value of witness-dcls does not contain the form (declare (xargs :non-executable t)), then the appropriate wrapper for non-executable functions will not be added automatically, i.e., [defun] will be used in place of defun-nx. Note also that if [guard] verification is attempted, then it will likely fail with an error message complaining that ``guard verification may depend on local properties.'' In that case, you may wish to delay guard verification, as in the following example. (encapsulate () (defun-sk foo (x) (exists n (and (integerp n) (< n x))) :witness-dcls ((declare (xargs :guard (integerp x) :verify-guards nil)))) (verify-guards foo)) Defun-sk is a macro implemented using [defchoose]. Hence, it should only be executed in [defun-mode] :[logic]; see [defun-mode] and see [defchoose]. Advanced feature: If argument :strengthen t is passed to defun-sk, then :strengthen t will generate the extra constraint that that is generated for the corresponding defchoose event; see [defchoose]. You can use the command :[pcb!] to see the event generated by a call of the defun-sk macro. If you find that the rewrite rules introduced with a particular use of defun-sk are not ideal, even when using the :rewrite keyword discussed above (in the forall case), then at least two reasonable courses of action are available for you. Perhaps the best option is to prove the [rewrite] rules you want. If you see a pattern for creating rewrite rules from your defun-sk events, you might want to write a macro that executes a defun-sk followed by one or more [defthm] events. Another option is to write your own variant of the defun-sk macro, say, my-defun-sk, for example by modifying a copy of the definition of defun-sk from the ACL2 sources. If you want to represent nested quantifiers, you can use more than one defun-sk event. For example, in order to represent (forall x (exists y (p x y z))) you can use defun-sk twice, for example as follows. (defun-sk exists-y-p (x z) (exists y (p x y z))) (defun-sk forall-x-exists-y-p (z) (forall x (exists-y-p x z))) Some distracting and unimportant warnings are inhibited during defun-sk. Note for ACL2(r) users (see [real]): In ACL2(r), the keyword :CLASSICALP is also supported. Its legal values are t (the default) and nil, and it determines whether or not (respectively) ACL2(r) will consider fn to be a classical function. It must be the case that the value is t (perhaps implicitly, by default) if and only if body is classical. Note that this way of implementing quantifiers is not a new idea. Hilbert was certainly aware of it 60 years ago! Also see [conservativity-of-defchoose] for a technical argument that justifies the logical conservativity of the [defchoose] event in the sense of the paper by Kaufmann and Moore entitled ``Structured Theory Development for a Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2 (2001), pp. 161-203). Subtopics [Defun-sk-example] A simple example using [defun-sk] [Exists] Existential quantifier [Forall] Universal quantifier [Quantifier-tutorial] A Beginner's Guide to Reasoning about Quantification in ACL2 [Quantifiers] Issues about quantification in ACL2") (DEFUN-SK-EXAMPLE (DEFUN-SK) "A simple example using [defun-sk] For a more through, systematic beginner's introduction to quantification in ACL2, see [quantifier-tutorial]. The following example illustrates how to do proofs about functions defined with [defun-sk]. The events below can be put into a certifiable book (see [books]). The example is contrived and rather silly, in that it shows how to prove that a quantified notion implies itself, where the antecedent and conclusion are defined with different [defun-sk] events. But it illustrates the formulas that are generated by [defun-sk], and how to use them. Thanks to Julien Schmaltz for presenting this example as a challenge. (in-package \"ACL2\") (encapsulate (((p *) => *) ((expr *) => *)) (local (defun p (x) x)) (local (defun expr (x) x))) (defun-sk forall-expr1 (x) (forall (y) (implies (p x) (expr y)))) (defun-sk forall-expr2 (x) (forall (y) (implies (p x) (expr y))))) ; We want to prove the theorem my-theorem below. What axioms are there that ; can help us? If you submit the command ; :pcb! forall-expr1 ; then you will see the following two key events. (They are completely ; analogous of course for FORALL-EXPR2.) ; (DEFUN FORALL-EXPR1 (X) ; (LET ((Y (FORALL-EXPR1-WITNESS X))) ; (IMPLIES (P X) (EXPR Y)))) ; ; (DEFTHM FORALL-EXPR1-NECC ; (IMPLIES (NOT (IMPLIES (P X) (EXPR Y))) ; (NOT (FORALL-EXPR1 X))) ; :HINTS ; ((\"Goal\" :USE FORALL-EXPR1-WITNESS))) ; We see that the latter has value when FORALL-EXPR1 occurs negated in a ; conclusion, or (therefore) positively in a hypothesis. A good rule to ; remember is that the former has value in the opposite circumstance: negated ; in a hypothesis or positively in a conclusion. ; In our theorem, FORALL-EXPR2 occurs positively in the conclusion, so its ; definition should be of use. We therefore leave its definition enabled, ; and disable the definition of FORALL-EXPR1. ; (thm ; (implies (and (p x) (forall-expr1 x)) ; (forall-expr2 x)) ; :hints ((\"Goal\" :in-theory (disable forall-expr1)))) ; ; ; which yields this unproved subgoal: ; ; (IMPLIES (AND (P X) (FORALL-EXPR1 X)) ; (EXPR (FORALL-EXPR2-WITNESS X))) ; Now we can see how to use FORALL-EXPR1-NECC to complete the proof, by ; binding y to (FORALL-EXPR2-WITNESS X). ; We use defthmd below so that the following doesn't interfere with the ; second proof, in my-theorem-again that follows. (defthmd my-theorem (implies (and (p x) (forall-expr1 x)) (forall-expr2 x)) :hints ((\"Goal\" :use ((:instance forall-expr1-necc (x x) (y (forall-expr2-witness x))))))) ; The following illustrates a more advanced technique to consider in such ; cases. If we disable forall-expr1, then we can similarly succeed by having ; FORALL-EXPR1-NECC applied as a :rewrite rule, with an appropriate hint in how ; to instantiate its free variable. See :doc hints. (defthm my-theorem-again (implies (and (P x) (forall-expr1 x)) (forall-expr2 x)) :hints ((\"Goal\" :in-theory (disable forall-expr1) :restrict ((forall-expr1-necc ((y (forall-expr2-witness x))))))))") (DEFUND (DEFUN EVENTS) "Define a function symbol and then disable it Use defund instead of [defun] when you want to disable a function immediately after its definition in :[logic] mode. This macro has been provided for users who prefer working in a mode where functions are only enabled when explicitly directed by :[in-theory]. Specifically, the form (defund NAME FORMALS ...) expands to: (progn (defun NAME FORMALS ...) (with-output :off summary (in-theory (disable NAME))) (value-triple '(:defund NAME))). Only the :[definition] rule (and, for recursively defined functions, the :[induction] rule) for the function are disabled. In particular, defund does not disable either the :[type-prescription] or the :[executable-counterpart] rule. Also, the summary for the [in-theory] event is suppressed. If the function is defined in :[program] mode, either because the [default-defun-mode] is :[program] or because :mode :program has been specified in an [xargs] form of a [declare] form, then no [in-theory] event is executed. (More precisely, [in-theory] events are ignored when the [default-defun-mode] is :[program], and if :mode :program is specified then defund does not generate an [in-theory] event.) Note that defund commands are never redundant (see [redundant-events]) when the [default-defun-mode] is :[logic], because the [in-theory] event will always be executed. See [defun] for documentation of defun.") (DEFUND-INLINE (DEFUN EVENTS) "Define a potentially disabled, inlined function symbol and associated macro Defund-inline is a variant of [defun-inline], the difference being that defund-inline disables the newly-defined function symbol. See [defun-inline].") (DEFUND-NOTINLINE (DEFUN EVENTS) "Define a disabled, not-to-be-inlined function symbol and associated macro Defund-notinline is a variant of [defun-notinline], the difference being that defund-notinline disables the newly-defined function symbol. See [defun-notinline].") (DEFUNS (MUTUAL-RECURSION) "An alternative to [mutual-recursion] Example: (DEFUNS (evenlp (x) (if (consp x) (oddlp (cdr x)) t)) (oddlp (x) (if (consp x) (evenlp (cdr x)) nil))) General Form: (DEFUNS defuns-tuple1 ... defuns-tuplen) is equivalent to (MUTUAL-RECURSION (DEFUN . defuns-tuple1) ... (DEFUN . defuns-tuplen)) In fact, defuns is the more primitive of the two and [mutual-recursion] is just a macro that expands to a call of [defun] after stripping off the [defun] at the [car] of each argument to [mutual-recursion]. We provide and use [mutual-recursion] rather than defuns because by leaving the [defun]s in place, [mutual-recursion] forms can be processed by the Emacs tags program. See [mutual-recursion].") (DELETE-ASSOC (ALISTS ACL2-BUILT-INS) "Remove the first pair from an association list for a given key General Forms: (delete-assoc key alist) (delete-assoc key alist :test 'eql) ; same as above (eql as equality test) (delete-assoc key alist :test 'eq) ; same, but eq is equality test (delete-assoc key alist :test 'equal) ; same, but equal is equality test (Delete-assoc key alist) returns an alist that is the same as the list alist, except that the first pair in alist with a [car] of key is deleted, if there is one; otherwise alist is returned. Note that the order of the elements of alist is unchanged (though one may be deleted). The [guard] for a call of delete-assoc depends on the test. In all cases, the second argument must satisfy [alistp]. If the test is [eql], then either the first argument must be suitable for [eql] (see [eqlablep]) or the second argument must satisfy [eqlable-alistp]. If the test is [eq], then either the first argument must be a symbol or the second argument must satisfy [symbol-alistp]. See [equality-variants] for a discussion of the relation between delete-assoc and its variants: (delete-assoc-eq key alist) is equivalent to (delete-assoc key alist :test 'eq); (delete-assoc-equal key alist) is equivalent to (delete-assoc key alist :test 'equal). In particular, reasoning about any of these primitives reduces to reasoning about the function delete-assoc-equal. Function: (defun delete-assoc-equal (key alist) (declare (xargs :guard (alistp alist))) (cond ((endp alist) nil) ((equal key (caar alist)) (cdr alist)) (t (cons (car alist) (delete-assoc-equal key (cdr alist))))))") (DELETE-ASSOC-EQ (POINTERS) "See [delete-assoc].") (DELETE-ASSOC-EQUAL (POINTERS) "See [delete-assoc].") (DELETE-INCLUDE-BOOK-DIR (BOOKS-REFERENCE) "Unlink keyword for :dir argument of [ld] and [include-book] Example Forms: ; Remove association of a directory with :smith for include-book and ld: (delete-include-book-dir :smith) General Form: (delete-include-book-dir kwd) where kwd is a [keywordp]. The effect of this event is to modify the meaning of the :dir keyword argument of [include-book] and [ld] as indicated by the example above, namely by removing association of a directory with the indicated keyword for purposes of the :dir argument of [include-book] and [ld]. See [add-include-book-dir] for how to associate a new directory with a keyword. Note: This is an event! It does not print the usual event summary but nevertheless changes the ACL2 logical [world] and is so recorded. This macro is [local] to any [books] and [encapsulate] [events] in which it occurs; see [add-include-book-dir] for a discussion of this aspect of both macros. For non-local associations of keywords with directories, see [add-include-book-dir!] and [delete-include-book-dir!]. Note that delete-include-book-dir may only be used to remove keywords added by calls of [add-include-book-dir], and [delete-include-book-dir!] may only be used to remove keywords added by calls of [add-include-book-dir!]") (DELETE-INCLUDE-BOOK-DIR! (BOOKS-REFERENCE) "Non-[local]ly unlink keyword for :dir argument of [ld] and [include-book] Please see [delete-include-book-dir], which has completely analogous syntax and semantics, but is used for removing associations previously placed by [add-include-book-dir]. By contrast, delete-include-book-dir! removes associations previously placed by [add-include-book-dir!]. Note: This is an event! It does not print the usual event summary but nevertheless changes the ACL2 logical [world] and is so recorded. This macro is essentially a [table] event that updates the table include-book-dir!-table, which associates keywords with absolute pathnames. However, as with [delete-include-book-dir], direct table updates are disallowed; you must use delete-include-book-dir! to remove from the table and [add-include-book-dir!] to add to the table. It is illegal to call delete-include-book-dir! in a [local] context. For an explanation, see [add-include-book-dir!].") (DENOMINATOR (NUMBERS ACL2-BUILT-INS) "Divisor of a ratio in lowest terms Completion Axiom (completion-of-denominator): (equal (denominator x) (if (rationalp x) (denominator x) 1)) [Guard] for (denominator x): (rationalp x)") (DIGIT-CHAR-P (CHARACTERS ACL2-BUILT-INS) "The number, if any, corresponding to a given character (digit-char-p ch) is the integer corresponding to the character ch in base 10. For example, (digit-char-p #\\3) is equal to the integer 3. More generally, an optional second argument specifies the radix (default 10, as indicated above). The [guard] for digit-char-p (more precisely, for the function our-digit-char-p that calls of this macro expand to) requires its second argument to be an integer between 2 and 36, inclusive, and its first argument to be a character. Digit-char-p is a Common Lisp function, though it is implemented in the ACL2 logic as an ACL2 macro. See any Common Lisp documentation for more information. Macro: (defmacro digit-char-p (ch &optional (radix '10)) (cons 'our-digit-char-p (cons ch (cons radix 'nil)))) Function: (defun our-digit-char-p (ch radix) (declare (xargs :guard (and (characterp ch) (integerp radix) (<= 2 radix) (<= radix 36)))) (let ((l (assoc ch '((#\\0 . 0) (#\\1 . 1) (#\\2 . 2) (#\\3 . 3) (#\\4 . 4) (#\\5 . 5) (#\\6 . 6) (#\\7 . 7) (#\\8 . 8) (#\\9 . 9) (#\\a . 10) (#\\b . 11) (#\\c . 12) (#\\d . 13) (#\\e . 14) (#\\f . 15) (#\\g . 16) (#\\h . 17) (#\\i . 18) (#\\j . 19) (#\\k . 20) (#\\l . 21) (#\\m . 22) (#\\n . 23) (#\\o . 24) (#\\p . 25) (#\\q . 26) (#\\r . 27) (#\\s . 28) (#\\t . 29) (#\\u . 30) (#\\v . 31) (#\\w . 32) (#\\x . 33) (#\\y . 34) (#\\z . 35) (#\\A . 10) (#\\B . 11) (#\\C . 12) (#\\D . 13) (#\\E . 14) (#\\F . 15) (#\\G . 16) (#\\H . 17) (#\\I . 18) (#\\J . 19) (#\\K . 20) (#\\L . 21) (#\\M . 22) (#\\N . 23) (#\\O . 24) (#\\P . 25) (#\\Q . 26) (#\\R . 27) (#\\S . 28) (#\\T . 29) (#\\U . 30) (#\\V . 31) (#\\W . 32) (#\\X . 33) (#\\Y . 34) (#\\Z . 35))))) (cond ((and l (< (cdr l) radix)) (cdr l)) (t nil))))") (DIGIT-TO-CHAR (CHARACTERS ACL2-BUILT-INS) "Map a digit to a character Example: ACL2 !>(digit-to-char 8) #\\8 For an integer n from 0 to 15, (digit-to-char n) is the character corresponding to n in hex notation, using uppercase letters for digits exceeding 9. If n is in the appropriate range, that result is of course also the binary, octal, and decimal digit. The [guard] for digit-to-char requires its argument to be an integer between 0 and 15, inclusive. Function: (defun digit-to-char (n) (declare (xargs :guard (and (integerp n) (<= 0 n) (<= n 15)))) (case n (1 #\\1) (2 #\\2) (3 #\\3) (4 #\\4) (5 #\\5) (6 #\\6) (7 #\\7) (8 #\\8) (9 #\\9) (10 #\\A) (11 #\\B) (12 #\\C) (13 #\\D) (14 #\\E) (15 #\\F) (otherwise #\\0)))") (DIMENSIONS (ARRAYS ACL2-BUILT-INS) "Return the :dimensions from the [header] of a 1- or 2-dimensional array Example Form: (dimensions 'delta1 a) General Form: (dimensions name alist) where name is arbitrary and alist is a 1- or 2-dimensional array. This function returns the dimensions list of the array alist. That list will either be of the form (dim1) or (dim1 dim2), depending on whether alist is a 1- or 2-dimensional array. Dim1 and dim2 will be integers and each exceed by 1 the maximum legal corresponding index. Thus, if dimensions returns, say, '(100) for an array a named 'delta1, then (aref1 'delta1 a 99) is legal but (aref1 'delta1 a 100) violates the [guard]s on [aref1]. Dimensions operates in virtually constant time if alist is the semantic value of name. See [arrays]. Function: (defun dimensions (name l) (declare (xargs :guard (or (array1p name l) (array2p name l)))) (cadr (assoc-keyword :dimensions (cdr (header name l)))))") (DISABLE (THEORIES THEORY-FUNCTIONS) "Deletes names from current theory Example: (disable fact (fact) associativity-of-app) General Form: (disable name1 name2 ... namek) where each namei is a runic designator; see [theories]. The result is the theory that contains all the names in the current theory except those listed. Note that this is merely a function that returns a theory. The result is generally a very long list of [rune]s and you will probably regret printing it. For related utilities, see [enable] and see [e/d]. The standard way to ``disable'' a fixed set of names, is as follows; see [hints] and see [in-theory]. :in-theory (disable name1 name2 ... namek) ; in a hint (in-theory (disable name1 name2 ... namek)) ; as an event (local ; often desirable, to avoid exporting from the current context (in-theory (disable name1 name2 ... namek))) Note that all the names are implicitly quoted. If you wish to disable a computed list of names, lst, use the theory expression (set-difference-theories (current-theory :here) lst).") (DISABLE-FORCING (FORCE) "To disallow forced case-splits General Form: ACL2 !>:disable-forcing ; disallow forced case splits See [force] and see [case-split] for a discussion of forced case splits, which are inhibited by this command. Disable-forcing is actually a macro that [disable]s the executable counterpart of the function symbol force; see [force]. When you want to use [hints] to turn off forced case splits, use a form such as one of the following (these are equivalent). :in-theory (disable (:executable-counterpart force)) :in-theory (disable (force)) The following example shows how this works. First evaluate these forms. (defstub f1 (x) t) (defstub f2 (x) t) (defaxiom ax (implies (case-split (f2 x)) (f1 x))) (thm (f1 x)) You will see the application of the rule, ax, in the proof of the [thm] call above. However, if you first evaluate (disable-forcing), then there will be no application of ax. To restore forced case splitting, see [enable-forcing].") (DISABLE-IMMEDIATE-FORCE-MODEP (FORCE) "[force]d hypotheses are not attacked immediately General Form: ACL2 !>:disable-immediate-force-modep This event causes ACL2 to delay [force]d hypotheses to the next forcing round, rather than attacking them immediately. See [immediate-force-modep]. Or for more basic information, first see [force] for a discussion of [force]d case splits. Disable-immediate-force-modep is a macro that [disable]s the executable counterpart of the function symbol [immediate-force-modep]. When you want to [disable] this mode in [hints], use a form such as one of the following (these are equivalent). :in-theory (disable (:executable-counterpart immediate-force-modep)) :in-theory (disable (immediate-force-modep))") (DISABLEDP (THEORIES) "Determine whether a given name or rune is disabled Examples: :disabledp foo ; returns a list of all disabled runes whose base ; symbol is foo (see [rune]) (disabledp 'foo) ; same as above (i.e., :disabledp foo) :disabledp (:rewrite bar . 1) ; returns t if the indicated rune is ; disabled, else nil (disabledp (:rewrite bar . 1)); same as immediately above (disabledp '(:definition binary-append)) ; returns t if the indicated definition is disabled, else nil (disabledp '(:d append)) ; same as above Also see [pr], which gives much more information about the rules associated with a given event. Disabledp takes one argument, which is a symbol, a [rune], or a runic abbreviation such as (:d append) (see [theories]). In the former case it returns the list of disabled runes associated with that name, in the sense that the rune's ``base symbol'' is that name (see [rune]) or, if the event named is a [defmacro] event, then the list of disabled runes associated with the function corresponding to that macro name, if any (see [macro-aliases-table]). In the other cases, where the argument is a [rune] or a runic abbreviation for a rune, disabledp returns t if the rune is disabled, and nil otherwise.") (DISASSEMBLE$ (COMPILATION DEBUGGING) "Disassemble a function The macro disassemble$ provides a convenient interface to the underlying disassemble utility of the host Common Lisp implementation, which prints assembly code for a given function symbol at the terminal. If the argument is instead a macro alias for a function symbol (see [macro-aliases-table]), then it prints assembly code for that function symbol instead. Disassemble$ works by including the community book books/misc/disassemble.lisp, which defines the supporting function disassemble$-fn, and then by calling that function. Note that the arguments to disassemble$ are evaluated. Also note that disassemble$ is intended as a top-level utility for the ACL2 loop, not to be called in code; for such a purpose, include the above book and call disassemble$-fn directly. Example Forms: (disassemble$ 'foo) (disassemble$ 'foo :recompile t) General Forms: (disassemble$ form) (disassemble$ form :recompile flg) where form evaluates to a function symbol or a macro alias for a function symbol and flg evaluates to any value. If flg is nil, then the existing definition of that function symbol is disassembled. But if flg is supplied and has a value other than nil or :default, and if that function symbol is defined in the ACL2 loop (not merely in raw Lisp; for example, see [set-raw-mode]), then the disassembly will be based on a recompilation of that ACL2 definition. Normally this recompilation is not necessary, but for some host Lisps, it may be useful; in particular, for CCL the above book arranges that source code information is saved, so that the output is annotated with such information. When recompilation takes place, the previous definition is restored after disassembly is complete. Finally, if flg is omitted or has the value :default --- i.e., in the default case --- then recompilation may take place or not, depending on the host Lisp. The values of (@ host-lisp) for which recompilation takes place by default may be found by looking at the above book, or by including it and evaluating the constant *host-lisps-that-recompile-by-default*. As of this writing, CCL is the only such Lisp (because that is the one for which we can obtain source annotation in the output by recompiling).") (DIVE-INTO-MACROS-TABLE (PROOF-CHECKER ACL2-PC::DV) "Right-associated function information for the [proof-checker] Examples: ACL2 !>(dive-into-macros-table (w state)) ((CAT . EXPAND-ADDRESS-CAT) (LXOR . EXPAND-ADDRESS-LXOR) This table associates macro names with functions used by the [proof-checker]'s DV and numeric diving commands (e.g., 3) in order to dive properly into subterms. See [proof-checker], in particular the documentation for DV. This table can be extended easily. See [add-dive-into-macro] and also see [remove-dive-into-macro]. The symbol associated with a macro should be a function symbol taking four arguments, in this order: * car-addr the first number in the list given to the [proof-checker]'s DV command * raw-term the untranslated term into which we will dive * term the translated term into which we will dive * wrld the current ACL2 logical [world] The function will normally return a list of positive integers, representing the (one-based) address for diving into term that corresponds to the single-address dive into raw-term by car-address. However, it can return (cons str alist), where str is a string suitable for [fmt] and args is the corresponding alist for [fmt]. Referring to the example above, expand-address-cat would be such a function, which will be called on raw-term values that are calls of cat. See the community book books/misc/rtl-untranslate.lisp for the definition of such a function. See [table] for a general discussion of tables. Subtopics [Add-dive-into-macro] Associate [proof-checker] diving function with macro name [Remove-dive-into-macro] Removes association of [proof-checker] diving function with macro name") (DMR (DEBUGGING BREAK-REWRITE ACCUMULATED-PERSISTENCE) "Dynamically monitor rewrites and other prover activity In addition to utilities that allow you to set breakpoints or print rewriting information to the screen --- see [break-rewrite] --- ACL2 provides a utility for watching the activity of the rewriter and some other proof processes, in real time. This utility is called ``dmr'', which is an acronym for ``dynamically monitor rewrites''. The utility comes in two parts: an ACL2 component that frequently updates a file (the ``dmr file'') containing the relevant information, and an Emacs component that frequently updates an Emacs buffer (the ``dmr buffer'') with the contents of that file. Other editors could, in principle, be programmed to display that file; anyone developing such a capability is invited to contribute it to the ACL2 community. The dmr utility can be extremely helpful for expensive proofs, especially when ACL2 is not providing any output to the terminal. The [break-rewrite] and [accumulated-persistence] utilities may be a bit easier to use, so you might want to try those first. But the dmr utility can be a very helpful debugging aide, as it can visually give you a sense of where ACL2 is spending its time. The Emacs portion of this utility is already loaded if you load the distributed Emacs file emacs/emacs-acl2.el. Otherwise, invoke the following Emacs command, say by typing Control-X Control-E after the right parenthesis, where DIR is the directory of your ACL2 distribution. (load \"/emacs/monitor.el\") ; absolute pathnames might work best You only need to do that once. Then each time you want to observe the rewriter in action, invoke the following to see it displayed in a buffer, which we call the ``dmr buffer'': Control-t 1 But first you will need to enable monitoring at the ACL2 level: (dmr-start) Monitoring has some cost. So if you have started it, then at some point you may want to turn it off when not using it. Any time the dmr buffer (generally called \"acl2-dmr-\") is not visible, Emacs monitoring is turned off. You can also turn off Emacs monitoring explicitly, with: Control-t 2 At the ACL2 level you can disable monitoring as follows: (dmr-stop) Interpreting the dmr buffer display. We explain the dmr buffer display by way of the following example. It is a snapshot of a dmr buffer taken from one of the community books, books/workshops/2004/legato/support/proof-by-generalization-mult.lisp. 0. (DEFTHM . WP-ZCOEF-G-MULTIPLIES) 1. SIMPLIFY-CLAUSE 2. Rewriting (to simplify) the atom of literal 18; argument(s) 1 4. Rewriting (to simplify) the expansion; argument(s) 3|2 7. Applying (:DEFINITION WP-ZCOEF-G) * 8. Rewriting (to simplify) the rewritten body; argument(s) 2|1|2|2 * 13. Applying (:REWRITE MOD-ZERO . 2) * 14. Rewriting (to establish) the atom of hypothesis 4 * 15. Applying (:META META-INTEGERP-CORRECT) Each line indicates an ACL2 activity that leads to the activity shown on the line just below it. Moreover, lines are sometimes collapsed to make the display more compact. Consider for example the first few lines. Above, we are proving a theorem named WP-ZCOEF-G-MULTIPLIES. Lines 1 and 2 show the clause simplification process invokes the rewriter on the 18th literal. (Recall that a clause is a disjunction of literals; for example the clause {(NOT A), (NOT B), C} would be displayed as (IMPLIES (AND A B) C).) This 18th literal mentioned on line 2 is a function call (f arg1 ...), and ``argument(s) 1'' indicates that the rewriter, which works inside-out, is considering the first argument (``arg1''). Thus the display could instead have shown the following. 2. Rewriting (to simplify) the atom of literal 18 3. Rewriting (to simplify) the first argument 4. Rewriting (to simplify) the expansion; argument(s) 3|2 But it saved space to combine lines 2 and 3. Line 4 suggests that the above arg1 is a function call that has been opened up because of an :expand hint or, perhaps, an expansion directed explicitly by the prover (as can happen during induction). The annotation ``argument(s) 3|2'' then indicates that the rewriter is diving into the third argument of the expansion, and then into the second argument of that. Let us call the result term7 (since it is the one to be considered on line 7). Now consider the next two lines: 7. Applying (:DEFINITION WP-ZCOEF-G) * 8. Rewriting (to simplify) the rewritten body; argument(s) 2|1|2|2 Line 7 is saying that term7 (defined above) is modified by applying the definition of WP-ZCOEF-G to it. Line 8 then says that the body of this definition has been rewritten (with its formals bound to the actuals from term7) and the rewriter is diving into the subterms of that rewritten body, as indicated. Notice also that line 8 is the first line marked with an asterisk (``*'') in the margin. This line is the first that is different from what was shown the previous time the display was updated (about 1/10 second earlier, by default). When a line is marked with an asterisk, so are all the lines below it; so the lines without an asterisk are those that have been stable since the last display. In this example we may see line 7 marked without an asterisk for a while, which suggests that the rule (:DEFINITION WP-ZCOEF-G) is expensive. (Also see [accumulated-persistence].) In general, a line that persists for awhile without a leading asterisk can suggest why the proof is taking a long time. Finally, note the indentation of line 14 relative to line 13. Extra indentation occurs when an attempt is being made to relieve a hypothesis (i.e., rewrite it to t). In particular, rewrites that will be incorporated directly into a (top-level) literal are all indented just two spaces, starting with the first rewrite directly under a process such as SIMPLIFY-CLAUSE (shown line 1 above). If the indentation is at least the value of raw Lisp variable *dmr-indent-max* (by default, 20), then the indentation is restricted to that column, but ACL2 prints {n} where n is the column that would have been used for indentation if there were no maximum. You can move the cursor around in the dmr buffer even while it is being updated. But emacs will attempt to keep the cursor no later than the first asterisk (``*'') in the margin. Thus, you can move the cursor around in the stable part of the display, and emacs will keep the cursor in that stable part. WARNING: Things could go terribly wrong if the same user runs two different ACL2 sessions with dmr active, because the same file will be written by two different ACL2 processes. WARNING: For dmr to work, emacs and ACL2 need to be run on the same machine because the file used to communicate between ACL2 and emacs is under /tmp. Except, you can probably hack around that restriction by changing *dmr-file-name* in ACL2 (in raw Lisp) and correspondingly in Emacs file monitor.el. More generally, advanced users are welcome to search for the string User-settable dmr variables in ACL2 files interface-raw.lisp and emacs/monitor.el in order to customize their dmr environments. In order to update the dmr file with the latest stack information, interrupt ACL2 and then evaluate: (dmr-flush). In order to support resumption of the interrupted proof (assuming your host Common Lisp supports resumption), evaluation of (dmr-start) will automatically enable the debugger if it is not already enabled and not fully disabled with value :never (see [set-debugger-enable]). If such automatic enabling takes place, then (dmr-stop) will restore the old setting of the debugger unless, after (dmr-start) enables the debugger but before (dmr-stop) is called, you call [set-debugger-enable] (or more precisely: function set-debugger-enable-fn is called). Note for users of the experimental extension ACL2(p) (see [parallelism]): when waterfall-parallelism has been set to a non-nil value (see [set-waterfall-parallelism]), statistics about parallel execution are printed instead of the usual information.") (DO-NOT (HINTS) "Instruct the theorem prover not to do certain things. See [hints] for documentation about the :do-not keyword for prover :hints. See [do-not-hint] for documentation about the do-not macro that controls a mechanism for automatically suggesting :do-not and :do-not-induct hints.") (DO-NOT-INDUCT (POINTERS) "See [hints] for keyword :do-not-induct.") (DOC (DOCUMENTATION) "[Documentation] at the terminal The :doc command may be used at the ACL2 prompt to access the ACL2 system [documentation]. Usually it may also access documentation defined in books. However, most users will probably access the ACL2 documentation in other ways; see [documentation]. In particular, consider using the {ACL2+Books Manual | http://www.cs.utexas.edu/users/moore/acl2/v7-1/combined-manual/index.html}, for topics documented in the ACL2 community [books] or in the ACL2 system (where the latter are rearranged). Alternatively, consider using the ACL2-doc Emacs browser; see [ACL2-doc]. Examples: ACL2 !>:doc DEFTHM ; print documentation of DEFTHM ACL2 !>:doc logical-name ; print documentation of LOGICAL-NAME General Form: ACL2>:doc name") (DOCUMENTATION (ACL2) "Information about options for downloading and viewing the ACL2 documentation, contributing documentation, and the available tools for documenting your own books. Available Documentation If you are new to ACL2, see the [ACL2-tutorial] for introductory tours, tutorials, and information about textbooks about ACL2. The {ACL2 home page | http://www.cs.utexas.edu/users/moore/acl2} also provides many links to academic publications about ACL2, including the ACL2 Workshop series. Beyond these resources, ACL2 has a vast ACL2+Books Manual with reference material covering the ACL2 system itself and also many [community-books]. There are a few ways to access the manual: * The online version (recommended). If you expect to have an internet connection while using the documentation, you may prefer to use the online version of the {ACL2+Books Manual | http://www.cs.utexas.edu/users/moore/acl2/v7-1/combined-manual/index.html}. * A local version. If you sometimes work without an internet connection, you can {download | download/} a local copy of any web-based XDOC manual using the \"down arrow\" icon at the top of the page. You can alternately build your own copy of the manual; see [Building_the_ACL2+Books_Manual]. * The ACL2-Doc Emacs version. If you would like to view the documentation using Emacs instead of a web browser, there is a feature-rich Emacs-based documentation browser provided by the ACL2 system. See [ACL2-doc] for details. While you are using ACL2, you can get documentation at the terminal with the :[doc] command, e.g., by typing :doc rewrite. This is often handy, but note that it won't show you any documentation for books that you haven't loaded yet! Separately from the ACL2+Books Manual, the ACL2 User's Manual is distributed with ACL2. This is much like the ACL2+Books Manual but it does not include documentation from the books. A web-based copy is included with the ACL2 distribution in directory doc/manual/, and you can easily get to it by opening file doc/home-page.html in your browser. Documenting Your Books ACL2's documentation is written using [xdoc]. You can use XDOC to document your own books and to build custom manuals for your organization. ACL2's documentation is found in the [community-books] and everyone is welcome to edit and contribute to it. See in particular the file books/system/doc/acl2-doc.lisp. Other Resources If you want documentation on an ACL2 function or macro that is not documented, there are still several alternatives. ACL2 !>:args fn will print the arguments and some other relevant information about the named function or macro. This information is all gleaned from the definition and hence this is a definitive way to determine if fn is defined as a function or macro. You might also want to type: ACL2 !>:pc fn which will print the [command] that introduced fn. You should see [command-descriptor] for details on the kinds of input you can give the :[pc] command. Subtopics [ACL2-doc] A custom Emacs browser for reading ACL2 [documentation] [Args] args, [guard], type, [constraint], etc., of a function symbol [Broken-link] Placeholder for link to documentation that resides in the community books [Doc] [Documentation] at the terminal [Documentation-copyright] Copyright and authorship of documentation [Finding-documentation] Searching the documentation [Pointers] Links pointing to relevant documentation topics") (DOCUMENTATION-COPYRIGHT (COPYRIGHT DOCUMENTATION) "Copyright and authorship of documentation There are two manuals associated with ACL2: the ACL2 User's Manual and the ACL2+Books Manual. See [documentation]. The former is distributed with ACL2, you can reach many links into it from the ACL2 home page. The latter may be preferred for routine browsing, since it extends the ACL2 User's Manual with documentation obtained from the [community-books]. The ACL2 User's Manual is copyrighted under the terms of the LICENSE file distributed with ACL2. Its original authors are the ACL2 authors, but it is now defined in an ACL2 community book, books/system/doc/acl2-doc.lisp, so that members of the ACL2 community may contribute to it. The ACL2+Books Manual is a mechanically generated mashup derived from both the ACL2 User's Manual and the [community-books]. The ACL2+Books Manual thus has contributions from many authors. At the top of each topic, in a line under the topic name, you will generally find either ``ACL2 Sources'' or the name of a Community Book. In the former case, the text is from the ACL2 User's Manual and is authored, copyrighted, and licensed as per the ACL2 [copyright]. When a book is named, the content was extracted from that book which may be inspected for authorship, copyright, and license terms. There are two standard tools for browsing these manuals, other than using the :[doc] command at the terminal. * The ACL2 [Xdoc] Fancy Viewer. This tool, written by Jared Davis, is included with the web-based version of each manual. Information on copyright and licensing are provided in {its LICENSE file | LICENSE}. * The [ACL2-doc] Emacs browser. This tool, authored by Matt Kaufmann and J Strother Moore, is distributed with ACL2 and is licensed under the terms of the LICENSE file distributed with ACL2.") (DOUBLE-REWRITE (REWRITE) "Cause a term to be rewritten twice Logically, double-rewrite is the [identity] function: (double-rewrite x) is equal to x. However, the ACL2 rewriter treats calls of double-rewrite in the following special manner. When it encounters a term (double-rewrite u), it first rewrites u in the current context, and then the rewriter rewrites the result. Such double-rewriting is rarely necessary, but it can be useful when rewriting under non-trivial equivalence relations (see [equivalence]). The following example will illustrate the issue. ; Define an equivalence relation. (defun my-equiv (x y) (equal x y)) (defequiv my-equiv) ; Define a unary function whose argument is preserved by my-equiv. (defun foo (x) (declare (ignore x)) t) (defcong my-equiv equal (foo x) 1) ; Define some other unary functions. (defun g (x) x) (defun h1 (x) x) (defun h2 (x) x) ; Prove some lemmas and then disable the functions above. (defthm lemma-1 (my-equiv (h1 x) (h2 x))) (defthm lemma-2 (foo (h2 x))) (defthm lemma-3 (implies (foo x) (equal (g x) x))) (in-theory (union-theories (theory 'minimal-theory) '(lemma-1 lemma-2 lemma-3 my-equiv-implies-equal-foo-1))) ; Attempt to prove a simple theorem that follows ``obviously'' from the ; events above. (thm (equal (g (h1 a)) (h1 a))) We might expect the proof of this final thm to succeed by the following reasoning. It is immediate from lemma-3 provided we can establish (foo (h1 a)). By the defcong event above, we know that (foo (h1 a)) equals (foo (h2 a)) provided (my-equiv (h1 a) (h2 a)); but this is immediate from lemma-1. And finally, (foo (h2 a)) is true by lemma-2. Unfortunately, the proof fails. But fortunately, ACL2 gives the following useful warning when lemma-3 is submitted: ACL2 Warning [Double-rewrite] in ( DEFTHM LEMMA-3 ...): In the :REWRITE rule generated from LEMMA-3, equivalence relation MY-EQUIV is maintained at one problematic occurrence of variable X in hypothesis (FOO X), but not at any binding occurrence of X. Consider replacing that occurrence of X in this hypothesis with (DOUBLE-REWRITE X). See :doc double- rewrite for more information on this issue. We can follow the warning's advice by changing lemma-3 to the following. (defthm lemma-3 (implies (foo (double-rewrite x)) (equal (g x) x))) With this change, the proof succeeds for the final thm above. In practice, it should suffice for users to follow the advice given in the ``Double-rewrite'' warnings, by adding calls of double-rewrite around certain variable occurrences. But this can cause inefficiency in large proof efforts. For that reason, and for completeness, it seems prudent to explain more carefully what is going on; and that is what we do for the remainder of this [documentation] topic. Optionally, also see the paper ``Double Rewriting for Equivalential Reasoning in ACL2'' by Matt Kaufmann and J Strother Moore, in the proceedings of the 2006 ACL2 Workshop (paper is published in ACM Digital Library, {http://portal.acm.org/toc.cfm?id=1217975 | http://portal.acm.org/toc.cfm?id=1217975}). Suggesting congruence rules. Sometimes the best way to respond to a ``Double-rewrite'' warning may be to prove a congruence rule. Consider for example this rule. (defthm insert-sort-is-id (perm (insert-sort x) x)) Assuming that perm has been identified as an [equivalence] relation (see [defequiv]), we will get the following warning. ACL2 Warning [Double-rewrite] in ( DEFTHM INSERT-SORT-IS-ID ...): In a :REWRITE rule generated from INSERT-SORT-IS-ID, equivalence relation PERM is maintained at one problematic occurrence of variable X in the right-hand side, but not at any binding occurrence of X. Consider replacing that occurrence of X in the right-hand side with (DOUBLE-REWRITE X). See :doc double-rewrite for more information on this issue. The problem is that the second occurrence of x (the right-hand side of the rule insert-sort-is-id) is in a context where perm is to be maintained, yet in this example, the argument x of insert-sort on the left-hand side of that rule is in a context where perm will not be maintained. This can lead one to consider the possibility that perm could be maintained in that left-hand side occurrence of x, and if so, to prove the following congruence rule. (defcong perm perm (insert-sort x) 1) This will eliminate the above warning for insert-sort-is-id. More important, this [defcong] event would probably be useful, since it would allow rewrite rules with equivalence relation perm to operate on the first argument of any call of insert-sort whose context calls for maintaining perm. Details on double-rewrite. The reader who wants these details may first wish to see [equivalence] for relevant review. The ACL2 rewriter takes a number of contextual arguments, including the generated equivalence relation being maintained (see [congruence]) and an association list that maps variables to terms. We call the latter alist the unify-subst because it is produced by unifying (actually matching) a pattern against a current term; let us explain this point by returning to the example above. Consider what happens when the rewriter is given the top-level goal of the thm above. (equal (g (h1 a)) (h1 a)) This rewrite is performed with the empty alist (unify-subst), and is begun by rewriting the first argument (in that same empty unify-subst): (g (h1 a)) Note that the only equivalence relation being maintained at this point is equal. Now, the rewriter notices that the left-hand side of lemma-3, which is (g x), matches (g (h1 a)). The rewriter thus creates a unify-subst binding x to (h1 a): ((x . (h1 a))). It now attempts to rewrite the hypothesis of lemma-3 to t under this unify-subst. Consider what happens now if the hypothesis of lemma-3 is (foo x). To rewrite this hypothesis under a unify-subst of ((x . (h1 a))), it will first rewrite x under this unify-subst. The key observation here is that this rewrite takes place simply by returning the value of x in the unify-subst, namely (h1 a). No further rewriting is done! The efficiency of the ACL2 rewriter depends on such caching of previous rewriting results. But suppose that, instead, the hypothesis of lemma-3 is (foo (double-rewrite x)). As before, the rewriter dives to the first argument of this call of foo. But this time the rewriter sees the call (double-rewrite x), which it handles as follows. First, x is rewritten as before, yielding (h1 a). But now, because of the call of double-rewrite, the rewriter takes (h1 a) and rewrites it under the empty unify-subst. What's more, because of the defcong event above, this rewrite takes place in a context where it suffices to maintain the equivalence relation my-equiv. This allows for the application of lemma-1, hence (h1 a) is rewritten (under unify-subst = nil) to (h2 a). Popping back up, the rewriter will now rewrite the call of foo to t using lemma-2. The example above explains how the rewriter treats calls of double-rewrite, but it may leave the unfortunate impression that the user needs to consider each :[rewrite] or :[linear] rule carefully, just in case a call of double-rewrite may be appropriate. Fortunately, ACL2 provides a ``[Double-rewrite]'' warning to inform the user of just this sort of situation. If you don't see this warning when you submit a (:[rewrite] or :[linear]) rule, then the issue described here shouldn't come up for that rule. Such warnings may appear for hypotheses or right-hand side of a :[rewrite] rule, and for hypotheses or full conclusion (as opposed to just the trigger term) of a :[linear] rule. If you do see a ``[Double-rewrite]'' warning, then should you add the indicated call(s) of double-rewrite? At the time of writing this [documentation], the answer is not clear. Early experiments with double rewriting suggested that it may be too expensive to call double-rewrite in every instance where a warning indicates that there could be an advantage to doing so. And at the time of this writing, the ACL2 regression suite has about 1900 such warnings (but note that books were developed before double-rewrite or the ``[Double-rewrite]'' warning were implemented), which suggests that one can often do fine just ignoring such warnings. However, it seems advisable to go ahead and add the calls of double-rewrite indicated by the warnings unless you run across efficiency problems caused by doing so. Of course, if you decide to ignore all such warnings you can execute the event: ([set-inhibit-warnings] \"Double-rewrite\"). Finally, we note that it is generally not necessary to call double-rewrite in order to get its effect in the following case, where the discussion above might have led one to consider a call of double-rewrite: a hypothesis is a variable, or more generally, we are considering a variable occurrence that is a branch of the top-level IF structure of a hypothesis. The automatic handling of this case, by a form of double rewriting, was instituted in ACL2 Version_2.9 and remains in place with the introduction of double-rewrite. Here is a simple illustrative example. Notice that foo-holds applies to prove the final [thm] below, even without a call of double-rewrite in the hypothesis of foo-holds, and that there is no ``[Double-rewrite]'' warning when submitting foo-holds. (encapsulate (((foo *) => *) ((bar *) => *)) (local (defun foo (x) (declare (ignore x)) t)) (local (defun bar (x) (declare (ignore x)) t)) (defthm foo-holds (implies x (equal (foo x) t))) (defthm bar-holds-propositionally (iff (bar x) t))) (thm (foo (bar y)))") (DYNAMICALLY-MONITOR-REWRITES (POINTERS) "See [dmr].") (E/D (THEORIES THEORY-FUNCTIONS) "Enable/disable rules The macro e/d creates theory expressions for use in [in-theory] hints and events. It provides a convenient way to [enable] and [disable] simultaneously, without having to write arcane theory expressions. For related utilities, see [enable] and see [disable]. Examples: (e/d (lemma1 lemma2)) ; equivalent to (enable lemma1 lemma2) (e/d () (lemma)) ; equivalent to (disable lemma) (e/d (lemma1) (lemma2 lemma3)) ; Enable lemma1 then disable lemma2, lemma3. (e/d () (lemma1) (lemma2)) ; Disable lemma1 then enable lemma2. General Form: (e/d enables-0 disables-0 ... enables-n disables-n) where each enables-i and disables-i is a list of runic designators; see [theories], see [enable], and see [disable]. The e/d macro takes any number of lists suitable for the [enable] and [disable] macros, and creates a theory that is equal to (current-theory :here) after executing the following commands. (in-theory (enable . enables-0)) (in-theory (disable . disables-0)) ... (in-theory (enable . enables-n)) (in-theory (disable . disables-n))") (EARLY-TERMINATION (PARALLEL-PROGRAMMING) "Early termination for [pand] and [por]. This [documentation] topic relates to the experimental extension of ACL2 supporting parallel execution and proof; see [parallelism]. The evaluation of (and expr1 expr2) returns nil if expr1 evaluates to nil, avoiding the evaluation of expr2. More generally, the evaluation of (and expr1 expr2 ... exprk) terminates with a return value of nil as soon as any expri evaluates to nil --- no exprj is evaluated in this case for j > i. This so-called ``lazy evaluation'' of [and] terms can thus save some computation; roughly speaking, the smaller the i, the more computation is saved. If the above call of [and] is replaced by its parallel version, [pand], then there can be even more opportunity for skipping work. The arguments to [pand] can be evaluated in parallel, in which case the first such evaluation that returns with a value of nil, if any, causes the remaining such evaluations to abort. Consider the following functions that compute whether a tree is valid (see [granularity] for a discussion of the granularity form). (defun valid-tip (x) (declare (xargs :guard t)) (or (eq x 'A) (eq x 'T) (eq x 'C) (eq x 'G))) (defun pvalid-tree (x depth) (declare (xargs :guard (natp depth))) (if (atom x) (valid-tip x) (pand (declare (granularity (< depth 10))) (pvalid-tree (car x) (1+ depth)) (pvalid-tree (cdr x) (1+ depth))))) We would like to stop execution as soon as any tip is found to be invalid. So, when computing the conjunction of terms by using [pand], once one of those terms evaluates to nil, the computations for the other terms are aborted and the [pand] call returns nil. By using [pand], we can in principle attain a speedup factor greater than the number of available cores. The concept of early termination also applies to [por], except that early termination occurs when an argument evaluates to non-nil.") (EC-CALL (GUARD ACL2-BUILT-INS) "Execute a call in the ACL2 logic instead of raw Lisp The name ``ec-call'' represents ``executable-counterpart call.'' This utility is intended for users who are familiar with guards. See [guard] for a general discussion of guards. Logically, ec-call behaves like the identity macro; during proofs, (ec-call TERM) is typically replaced quickly by TERM during a proof attempt. However, ec-call causes function calls to be evaluated in the ACL2 logic rather than raw Lisp, as explained below. General Form: (ec-call (fn term1 ... termk)) where fn is a known function symbol other than those in the list that is the value of the constant *ec-call-bad-ops*. (But see the Final Note below for an exception pertaining to inlining.) In particular, fn is not a macro. Semantically, (ec-call (fn term1 ... termk)) equals (fn term1 ... termk). However, this use of ec-call has two effects. (1) [Guard] verification generates no proof obligations from the guard of fn for this call. Indeed, guards need not have been verified for fn. (2) During evaluation, after the arguments of fn are evaluated as usual, the executable counterpart of fn is called, rather than fn as defined in raw Lisp. That is, the call of fn is made on its evaluated arguments as though this call is being made in the ACL2 top-level loop, rather than in raw Lisp. In particular, the [guard] of fn is checked, at least by default (see [set-guard-checking]). Note that in the term (ec-call (fn term1 ... termk)), only the indicated call of fn is made in the logic; each termi is evaluated in the normal manner. If you want an entire term evaluated in the logic, wrap ec-call around each function call in the term (other than calls of if and ec-call). Technical Remark (probably best ignored). During evaluation of a call of [defconst] or [defpkg] in raw Lisp, a form (ec-call (fn term1 ... termk)) is treated as (fn term1 ... termk), that is, without calling the executable counterpart of fn. This situation occurs when loading a compiled file (or expansion file) on behalf of an [include-book] event. The reason is technical: executable counterparts are defined below a book's events in the book's compiled file. End of Technical Remark. Here is a small example. We define foo recursively but with guard verification inhibited on the recursive call, which is to be evaluated in the ACL2 logic. ACL2 !>(defun foo (x y) (declare (xargs :guard (consp y))) (if (consp x) (cons (car x) (ec-call (foo (cdr x) (cdr y)))) (car y))) The admission of FOO is trivial, using the relation O< (which is known to be well-founded on the domain recognized by O-P) and the measure (ACL2-COUNT X). We could deduce no constraints on the type of FOO. Computing the guard conjecture for FOO.... The guard conjecture for FOO is trivial to prove. FOO is compliant with Common Lisp. Summary Form: ( DEFUN FOO ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FOO ACL2 !>(foo '(2 3 4 5) '(6 7)) ACL2 Error in TOP-LEVEL: The guard for the function call (FOO X Y), which is (CONSP Y), is violated by the arguments in the call (FOO '(4 5) NIL). 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 !> The error above arises because eventually, foo recurs down to a value of parameter y that violates the guard. This is clear from tracing (see [trace$] and see [trace]). Each call of the executable counterpart of foo (the so-called ``*1*'' function for foo) checks the guard and then invokes the raw Lisp version of foo. The raw Lisp version calls the executable counterpart on the recursive call. When the guard check fails we get a violation. ACL2 !>(trace$ foo) ((FOO)) ACL2 !>(foo '(2 3 4 5) '(6 7)) 1> (ACL2_*1*_ACL2::FOO (2 3 4 5) (6 7)) 2> (FOO (2 3 4 5) (6 7)) 3> (ACL2_*1*_ACL2::FOO (3 4 5) (7)) 4> (FOO (3 4 5) (7)) 5> (ACL2_*1*_ACL2::FOO (4 5) NIL) ACL2 Error in TOP-LEVEL: The guard for the function call (FOO X Y), which is (CONSP Y), is violated by the arguments in the call (FOO '(4 5) NIL). 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 !> If we turn off guard errors then we can see the trace as above, but where we avoid calling the raw Lisp function when the guard fails to hold. ACL2 !>:set-guard-checking nil Masking guard violations but still checking guards except for self- recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING :NONE. See :DOC set-guard-checking. ACL2 >(foo '(2 3 4 5) '(6 7)) 1> (ACL2_*1*_ACL2::FOO (2 3 4 5) (6 7)) 2> (FOO (2 3 4 5) (6 7)) 3> (ACL2_*1*_ACL2::FOO (3 4 5) (7)) 4> (FOO (3 4 5) (7)) 5> (ACL2_*1*_ACL2::FOO (4 5) NIL) 6> (ACL2_*1*_ACL2::FOO (5) NIL) 7> (ACL2_*1*_ACL2::FOO NIL NIL) <7 (ACL2_*1*_ACL2::FOO NIL) <6 (ACL2_*1*_ACL2::FOO (5)) <5 (ACL2_*1*_ACL2::FOO (4 5)) <4 (FOO (3 4 5)) <3 (ACL2_*1*_ACL2::FOO (3 4 5)) <2 (FOO (2 3 4 5)) <1 (ACL2_*1*_ACL2::FOO (2 3 4 5)) (2 3 4 5) ACL2 > Final note: although in general, the form (ec-call (fn term1 ... termk)) is only legal if fn is a function symbol, such a form is also legal if fn is introduced with [defun-inline], or with [define] using keyword argument :inline t. In those cases, fn is a macro whose calls expand to corresponding calls of fn$INLINE, the symbol in the same package as fn but with the string \"$INLINE\" added as a suffix to the [symbol-name] of fn. We do not however extend this exception to macros in general, even when [add-macro-fn] has been invoked. Consider the following example. (encapsulate () (defun foo () nil) (defun bar () t) (defmacro mac () nil) (add-macro-alias mac foo) (local (add-macro-alias mac bar)) (defun h () (ec-call (mac))) (defthm bad (h))) Consider what would happen if this were legal, where (ec-call (mac)) used the macro-alias, foo, for mac. Then in the first pass of the [encapsulate] form above, the final [defthm] event would prove, since (ec-call (mac)) is treated as (ec-call (bar)). But on the second pass, ACL2 would store bad as a theorem even though (h) would evaluate to nil, since the macro-alias of mac is foo on the second pass.") (EIGHTH (NTH ACL2-BUILT-INS) "Eighth member of the list See any Common Lisp documentation for details.") (ELIM (RULE-CLASSES) "Make a destructor elimination rule See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. The following example of an :elim rule is an important one, and is built into ACL2. (defaxiom car-cdr-elim (implies (consp x) (equal (cons (car x) (cdr x)) x)) :rule-classes :elim) The class of :elim rules is fundamentally quite different from the more common class of :[rewrite] rules. Briefly put, a :rewrite rule replaces instances of its left-hand side with corresponding instances of its right-hand side. But an :elim rule, on the other hand, has the effect of generalizing so-called ``destructor'' function applications to variables. In essence, applicability of a :rewrite rule is based on matching its left-hand side, while applicability of an :elim rule is based on the presence of at least one destructor term. For example, a conjecture about (car x) and (cdr x) can be replaced by a conjecture about new variables x1 and x2, as shown in the following example. (Run the command :mini-proveall and search for CAR-CDR-ELIM to see the full proof containing this excerpt.) Subgoal *1/1' (IMPLIES (AND (CONSP X) (TRUE-LISTP (REV (CDR X)))) (TRUE-LISTP (APP (REV (CDR X)) (LIST (CAR X))))). The destructor terms (CAR X) and (CDR X) can be eliminated by using CAR-CDR-ELIM to replace X by (CONS X1 X2), (CAR X) by X1 and (CDR X) by X2. This produces the following goal. Subgoal *1/1'' (IMPLIES (AND (CONSP (CONS X1 X2)) (TRUE-LISTP (REV X2))) (TRUE-LISTP (APP (REV X2) (LIST X1)))). This simplifies, using primitive type reasoning, to Subgoal *1/1''' (IMPLIES (TRUE-LISTP (REV X2)) (TRUE-LISTP (APP (REV X2) (LIST X1)))). The resulting conjecture is often simpler and hence more amenable to proof. The application of an :elim rule thus replaces a variable by a term that contains applications of so-called ``destructor'' functions to that variable. The example above is typical: the variable x is replaced by the term (cons (car x) (cdr x)), which applies a so-called ``constructor'' function, [cons], to applications (car x) and (cdr x) of destructor functions [car] and [cdr] to that same variable, x. But that is only part of the story. ACL2 then generalizes the destructor applications (car x) and (cdr x) to new variables x1 and x2, respectively, and ultimately the result is a simpler conjecture. More generally, the application of an :elim rule replaces a variable by a term containing applications of destructors; there need not be a clear-cut notion of ``constructor.'' But the situation described above is typical, and we will focus on it, giving full details when we introduce the ``General Form'' below. Notice that the situation can be complicated a bit by a rule's hypotheses. For example, the replacement specified by the rule car-cdr-elim (shown near the beginning of this discussion) is only valid if the variable being replaced is a cons structure. Thus, when ACL2 applies car-cdr-elim to replace a variable v, it will split into two cases: one case in which (consp v) is true, in which v is replaced by (cons (car v) (cdr v)) and then (car v) and (cdr v) are generalized to new variables; and one case in which (consp v) is false. In practice, (consp v) is often provable, perhaps even literally present as a hypotheses; then of course there is no need to introduce the second case. That is why there is no such second case in the example above. You might find :elim rules to be useful whenever you have in mind a data type that can be built up from its fields with a ``constructor'' function and whose fields can be accessed by corresponding ``destructor'' functions. So for example, if you have a ``house'' data structure that represents a house in terms of its address, price, and color, you might have a rule like the following. Example: (implies (house-p x) (equal (make-house (address x) (price x) (color x)) x)) The application of such a rule is entirely analogous to the application of the rule car-cdr-elim discussed above. We discuss such rules and their application more carefully below. General Form: (implies hyp (equiv lhs x)) where equiv is a known equivalence relation (see [defequiv]); x is a variable symbol; and lhs contains one or more terms (called ``destructor terms'') of the form (fn v1 ... vn), where fn is a function symbol and the vi are distinct variable symbols, v1, ..., vn include all the variable symbols in the formula, no fn occurs in lhs in more than one destructor term, and all occurrences of x in lhs are inside destructor terms. To use an :elim rule, the theorem prover waits until a conjecture has been maximally simplified. It then searches for an instance of some destructor term (fn v1 ... vn) in the conjecture, where the instance for x is some variable symbol, vi, and every occurrence of vi outside the destructor terms is in an equiv-hittable position. If such an instance is found, then the theorem prover instantiates the :elim formula as indicated by the destructor term matched; splits the conjecture into two goals, according to whether the instantiated hypothesis, hyp, holds; and in the case that it does hold, generalizes all the instantiated destructor terms in the conjecture to new variables and then replaces vi in the conjecture by the generalized instantiated lhs. An occurrence of vi is ``equiv-hittable'' if sufficient congruence rules (see [defcong]) have been proved to establish that the propositional value of the clause is not altered by replacing that occurrence of vi by some equiv-equivalent term. If an :elim rule is not applied when you think it should have been, and the rule uses an equivalence relation, equiv, other than equal, it is most likely that there is an occurrence of the variable that is not equiv-hittable. Easy occurrences to overlook are those in the governing hypotheses. If you see an unjustified occurrence of the variable, you must prove the appropriate congruence rule to allow the :elim to fire. Further examples of how ACL2 :elim rules are used may be found in the corresponding discussion of ``Elimation of Destructors'' for Nqthm, in Section 10.4 of A Computational Logic Handbook.") (EMACS (ACL2-TUTORIAL) "Emacs support for ACL2 Many successful ACL2 users run in an shell under the Emacs editor. If you do so, then you may wish to load the distributed file emacs/emacs-acl2.el. The file begins with considerable comments describing what it offers. It is intended to work both with GNU Emacs and XEmacs. In particular, the above file provides the ACL2-Doc browser, a convenient tool for viewing, in Emacs, documentation for both the ACL2 system and the documented community books. See [ACL2-Doc]. If you are not comfortable with Emacs, you may prefer to use an Eclipse-based interface; see [ACL2-sedan].") (EMBEDDED-EVENT-FORM (EVENTS) "Forms that may be embedded in other [events] Examples: (defun hd (x) (if (consp x) (car x) 0)) (local (defthm lemma23 ...)) (progn (defun fn1 ...) (local (defun fn2 ...)) ...) General Form: An embedded event form is a term, x, such that: * x is a call of an event function other than [defpkg] (see [events] for a listing of the event functions); * x is of the form ([local] x1) where x1 is an embedded event form; * x is of the form ([skip-proofs] x1) where x1 is an embedded event form; * x is of the form ([make-event] &), where & is any term whose expansion is an embedded event (see [make-event]); * x is of the form ([with-output] ... x1), ([with-prover-step-limit] ... x1 ...), or ([with-prover-time-limit] ... x1), where x1 is an embedded event form; * x is a call of [encapsulate], [progn], [progn!], or [include-book]; * x macroexpands to one of the forms above; or * [intended only for the implementation] x is (RECORD-EXPANSION x1 x2), where x1 and x2 are embedded event forms. However, we add the following restrictions for [local] contexts. * An embedded event form may not set the [ACL2-defaults-table] when in the context of [local]. Thus for example, the form (local (table acl2-defaults-table :defun-mode :program)) is not an embedded event form, nor is the form (local (program)), since the latter sets the [ACL2-defaults-table] implicitly. An example at the end of the discussion below illustrates why there is this restriction. * A call of [defaxiom] is illegal in the context of [local]. Without this restriction, one could locally assert a strong axiom like (equal t nil) and then non-locally prove that formula, leaving you in an ACL2 logical [world] in which it appears that the formula is actually provable without such an axiom. * A call of [add-include-book-dir!] or [delete-include-book-dir!] is illegal in the context of [local]. For an explanation, see [add-include-book-dir!]. Only embedded event forms are allowed in a book after its initial [in-package] form. See [books]. However, you may find that [make-event] allows you to get the effect you want for a form that is not an embedded event form. For example, you can put the following into a book, which assigns the value 17 to [state] global variable x: (make-event (er-progn (assign x 17) (value '(value-triple nil))) :check-expansion t) When an embedded event is executed while [ld-skip-proofsp] is '[include-book], those parts of it inside [local] forms are ignored. Thus, (progn (defun f1 () 1) (local (defun f2 () 2)) (defun f3 () 3)) will define f1, f2, and f3 when [ld-skip-proofsp] is nil or t, but will define only f1 and f3 when [ld-skip-proofsp] is '[include-book]. Discussion: [Encapsulate], [progn], and [include-book] place restrictions on the kinds of forms that may be processed. These restrictions ensure that the non-local [events] are indeed admissible provided that the sequence of [local] and non-local [events] is admissible when proofs are done, i.e., when ld-skip-proofs is nil. But [progn!] places no such restrictions, hence is potentially dangerous and should be avoided unless you understand the ramifications; so it is illegal unless there is an active trust tag (see [defttag]). [Local] permits the hiding of an event or group of [events] in the sense that [local] [events] are processed when we are trying to establish the admissibility of a sequence of [events] embedded in [encapsulate] forms or in [books], but are ignored when we are constructing the [world] produced by assuming that sequence. Thus, for example, a particularly ugly and inefficient :[rewrite] rule might be made [local] to an [encapsulate] that ``exports'' a desirable theorem whose proof requires the ugly lemma. To see why we can't allow just anything as an embedded event, consider allowing the form (if (ld-skip-proofsp state) (defun foo () 2) (defun foo () 1)) followed by (defthm foo-is-1 (equal (foo) 1)). When we process the [events] with [ld-skip-proofsp] is nil, the second [defun] is executed and the [defthm] succeeds. But when we process the [events] with [ld-skip-proofsp] '[include-book], the second [defun] is executed, so that foo no longer has the same definition it did when we proved foo-is-1. Thus, an invalid formula is assumed when we process the [defthm] while skipping proofs. Thus, the first form above is not a legal embedded event form. If you encounter a situation where these restrictions seem to prevent you from doing what you want to do, then you may find make-event to be helpful. See [make-event]. [Defpkg] is not allowed because it affects how things are read after it is executed. But all the forms embedded in an event are read before any are executed. That is, (encapsulate nil (defpkg \"MY-PKG\" nil) (defun foo () 'my-pkg::bar)) makes no sense since my-pkg::bar must have been read before the [defpkg] for \"MY-PKG\" was executed. Finally, let us elaborate on the restriction mentioned earlier related to the [ACL2-defaults-table]. Consider the following form. (encapsulate () (local (program)) (defun foo (x) (if (equal 0 x) 0 (1+ (foo (- x)))))) See [local-incompatibility] for a discussion of how [encapsulate] processes event forms. Briefly, on the first pass through the [events] the definition of foo will be accepted in [defun] mode :[program], and hence accepted. But on the second pass the form (local (program)) is skipped because it is marked as [local], and hence foo is accepted in [defun] mode :[logic]. Yet, no proof has been performed in order to admit foo, and in fact, it is not hard to prove a contradiction from this definition!") (ENABLE (THEORIES THEORY-FUNCTIONS) "Adds names to current theory Example: (enable fact (fact) associativity-of-app) General Form: (enable name1 name2 ... namek) where each namei is a runic designator; see [theories]. The result is the theory that contains all the names in the current theory plus those listed. Note that this is merely a function that returns a theory. The result is generally a very long list of [rune]s and you will probably regret printing it. For related utilities, see [disable] and see [e/d]. The standard way to ``enable'' a fixed set of names, is as follows; see [hints] and see [in-theory]. :in-theory (enable name1 name2 ... namek) ; in a hint (in-theory (enable name1 name2 ... namek)) ; as an event (local ; often desirable, to avoid exporting from the current context (in-theory (enable name1 name2 ... namek))) Note that all the names are implicitly quoted. If you wish to enable a computed list of names, lst, use the theory expression (union-theories (current-theory :here) lst).") (ENABLE-FORCING (FORCE) "To allow forced case splits General Form: ACL2 !>:enable-forcing ; allowed forced case splits See [force] and see [case-split] for a discussion of forced case splits, which are turned back on by this command. See [disable-forcing] for an example showing how to turn off forced case splits. Enable-forcing is actually a macro that [enable]s the executable counterpart of the function symbol force; see [force]. When you want to use [hints] to turn on forced case splits, use a form such as one of the following (these are equivalent). :in-theory (enable (:executable-counterpart force)) :in-theory (enable (force))") (ENABLE-IMMEDIATE-FORCE-MODEP (FORCE) "[force]d hypotheses are attacked immediately General Form: ACL2 !>:enable-immediate-force-modep This event causes ACL2 to attack [force]d hypotheses immediately instead of delaying them to the next forcing round. See [immediate-force-modep]. Or for more basic information, first see [force] for a discussion of [force]d case splits. Enable-immediate-force-modep is a macro that [enable]s the executable counterpart of the function symbol [immediate-force-modep]. When you want to [enable] this mode in [hints], use a form such as one of the following (these are equivalent). :in-theory (enable (:executable-counterpart immediate-force-modep)) :in-theory (enable (immediate-force-modep))") (ENCAPSULATE (EVENTS) "Hide some [events] and/or constrain some functions Encapsulate provides a way to execute a sequence of [events] and then hide some of the resulting effects. There are two kinds of encapsulations: ``trivial'' and ``non-trivial''. We discuss these briefly before providing detailed [documentation]. A trivial encapsulation is an event of the following form. (encapsulate () ; nil here indicates \"trivial\" ... ) We use the term ``sub-events'' to refer to through . Each sub-event may be ``[local]'', that is, of the form (local ); the other sub-events are called ``non-local''. When this encapsulate form is submitted to ACL2, it is processed in two passes. On the first pass, each sub-event is printed (by default) and processed in sequence; admission of the encapsulate fails if any fails to be admitted. Then a second pass is made after rolling back the logical [world] to what it was just before executing the encapsulate form. In the second pass, only the non-[local] forms are evaluated, again in order, and proofs are skipped. For example, the following trivial encapsulation exports a single event, member-equal-reverse. The lemma member-revappend is used (as a [rewrite] rule) to prove member-equal-reverse on the first pass, but since member-revappend is [local], it is ignored on the second (final) pass. (encapsulate () (local (defthm member-revappend (iff (member-equal a (revappend x y)) (or (member-equal a x) (member-equal a y))) :hints ((\"Goal\" :induct (revappend x y))))) (defthm member-equal-reverse (iff (member-equal a (reverse x)) (member-equal a x)))) Of course, one might prefer to prove these [events] at the top level, rather than within an encapsulation; but the point here is to illustrate that you can have [local] [events] that do not become part of the logical [world]. (Such a capability is also provided at the level of [books]; in particular, see [include-book].) Note that trivial encapsulates must introduce at least one sub-event, or else they are treated as no-ops, with no effect on the logical [world]. Consider the following example. ACL2 !>(encapsulate nil (local (defun f (x) x))) To verify that the encapsulated event correctly extends the current theory we will evaluate it. The theory thus constructed is only ephemeral. Encapsulated Event: ACL2 !>>(LOCAL (DEFUN F (X) X)) Since F is non-recursive, its admission is trivial. We observe that the type of F is described by the theorem (EQUAL (F X) X). Summary Form: ( DEFUN F ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) F End of Encapsulated Event. ACL2 Observation in ( ENCAPSULATE NIL (LOCAL ...) ...): The submitted encapsulate event has created no new ACL2 events, and thus is leaving the ACL2 logical world unchanged. See :DOC encapsulate. Summary Form: ( ENCAPSULATE NIL (LOCAL ...) ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) :EMPTY-ENCAPSULATE ACL2 !> After the above evaluation, we are left in the [world] with which we began. For example, if you evaluate the above form in the initial ACL2 world, you can see the following both before and after that evaluation. ACL2 !>:pbt 0 0:x(EXIT-BOOT-STRAP-MODE) ACL2 !> On the other hand, non-trivial encapsulations provide a way to introduce axioms about new function symbols, without introducing inconsistency and without introducing complete definitions. The following example illustrates how that works. (encapsulate ; The following list has a single signature, introducing a function foo of ; one argument that returns one value. (The list is non-empty, so we call ; this a \"non-trivial\" encapsulation.) ( ((foo *) => *) ) ; Introduce a ``witness'' (example) for foo, marked as local so that ; it is not exported: (local (defun foo (x) x)) ; Introduce a non-local property to be exported: (defthm foo-preserves-consp (implies (consp x) (consp (foo x)))) ) The form above introduces a new function symbol, foo, with the indicated property and no definition. In fact, the output from ACL2 concludes as follows. The following constraint is associated with the function FOO: (IMPLIES (CONSP X) (CONSP (FOO X))) To understand this example, we consider how non-trivial encapsulations are processed. The same two passes are made as for trivial encapsulations, and the ([local]) definition of foo is ignored on the second pass, and hence does not appear in the resulting ACL2 logical [world]. But before the second pass, each [signature] is stored in the [world]. Thus, when the theorem foo-preserves-consp is encountered in the second pass, foo is a known function symbol with the indicated signature. If any event fails while evaluating a call of encapsulate, the entire encapsulate call is deemed to have failed, and the logical [world] is rolled back to what it was immediately before the encapsulate call. We now provide detailed documentation. But discussion of redundancy for encapsulate events may be found elsewhere; see [redundant-encapsulate]. Other Examples: (encapsulate (((an-element *) => *)) ; The list of signatures above could also be written ; ((an-element (lst) t)) (local (defun an-element (lst) (if (consp lst) (car lst) nil))) (local (defthm member-equal-car (implies (and lst (true-listp lst)) (member-equal (car lst) lst)))) (defthm thm1 (implies (null lst) (null (an-element lst)))) (defthm thm2 (implies (and (true-listp lst) (not (null lst))) (member-equal (an-element lst) lst)))) (encapsulate () ; empty signature: no constrained functions indicated (local (defthm hack (implies (and (syntaxp (quotep x)) (syntaxp (quotep y))) (equal (+ x y z) (+ (+ x y) z))))) (defthm nthcdr-add1-conditional (implies (not (zp (1+ n))) (equal (nthcdr (1+ n) x) (nthcdr n (cdr x)))))) General Form: (encapsulate (signature ... signature) ev1 ... evn) where each [signature] is a well-formed signature, each signature describes a different function symbol, and each evi is an embedded event form (See [embedded-event-form]). Also see [signature], in particular for a discussion of how a signature can assign a [guard] to a function symbol. There must be at least one evi. The evi inside [local] special forms are called ``local'' [events] below. [Events] that are not [local] are sometimes said to be ``exported'' by the encapsulation. We make the further restriction that no [defaxiom] event may be introduced in the scope of an encapsulate (not even by encapsulate or [include-book] events that are among the evi). Furthermore, no non-[local] [include-book] event is permitted in the scope of any encapsulate with a non-empty list of signatures. To be well-formed, an encapsulate event must have the properties that each event in the body (including the [local] ones) can be successfully executed in sequence and that in the resulting theory, each function mentioned among the [signature]s was introduced via a [local] event and has the [signature] listed. (A utility is provided to assist in debugging failures of such execution; see [redo-flat].) In addition, the body may contain no ``local incompatibilities'' which, roughly stated, means that the [events] that are not [local] must not syntactically require symbols defined by [local] [events], except for the functions listed in the [signature]s. See [local-incompatibility]. Finally, no non-[local] recursive definition in the body may involve in its suggested induction scheme any function symbol listed among the [signature]s. See [subversive-recursions]. Observe that if the [signature]s list is empty, the resulting ``trivial'' encapsulate may still be useful for deriving theorems to be exported whose proofs require lemmas you prefer to hide (i.e., made [local]). Whether trivial or not (i.e., whether the signature is empty or not), encapsulate exports the results of evaluating its non-[local] [events], but its [local] [events] are ignored for the resulting logical [world]. The result of a non-trivial encapsulate event is an extension of the logic in which, roughly speaking, the functions listed in the [signature]s are constrained to have the [signature]s listed and to satisfy the non-[local] theorems proved about them. In fact, other functions introduced in the encapsulate event may be considered to have ``[constraint]s'' as well. (See [constraint] for details, which are only relevant to functional instantiation.) Since the [constraint]s were all theorems in the ``ephemeral'' or ``local'' theory, we are assured that the extension produced by encapsulate is sound. In essence, the [local] definitions of the constrained functions are just ``witness functions'' that establish the consistency of the [constraint]s. Because those definitions are [local], they are not present in the theory produced by encapsulation. After a non-trivial encapsulate event is admitted, theorems about the constrained function symbols may then be proved --- theorems whose proofs necessarily employ only the [constraint]s. Thus, those theorems may be later functionally instantiated, as with the :functional-instance lemma instance (see [lemma-instance]), to derive analogous theorems about different functions, provided the constraints (see [constraint]) can be proved about the new functions. The [default-defun-mode] for the first event in an encapsulation is the default [defun-mode] ``outside'' the encapsulation. But since [events] changing the [defun-mode] are permitted within the body of an encapsulate, the default [defun-mode] may be changed. However, [defun-mode] changes occurring within the body of the encapsulate are not exported. In particular, the [ACL2-defaults-table] after an encapsulate is always the same as it was before the encapsulate, even though the encapsulate body might contain [defun-mode] changing [events], :[program] and :[logic]. See [defun-mode]. More generally, after execution of an encapsulate event, the value of [ACL2-defaults-table] is restored to what it was immediately before that event was executed. See [ACL2-defaults-table]. We make some remarks on [guard]s and evaluation. Calls of functions introduced in the [signature]s list cannot be evaluated in the ACL2 read-eval-print loop. See [defattach] for a way to overcome this limitation. Moreover, any :[guard] supplied in the signature is automatically associated in the [world] with its corresponding function symbol, with no requirement other than that the guard is a legal term all of whose function symbols are in :[logic] mode with their [guard]s verified. In particular, there need not be any relationship between a guard in a signature and the guard in a local witness function. Finally, note that for functions introduced non-[local]ly inside a non-trivial encapsulate event, [guard] verification is illegal unless ACL2 determines that the proof obligations hold outside the [encapsulate] event as well. (encapsulate ((f (x) t)) (local (defun f (x) (declare (xargs :guard t)) (consp x))) ;; ERROR! (defun g (x) (declare (xargs :guard (f x))) (car x))) The order of the [events] in the vicinity of an encapsulate is confusing. We discuss it in some detail here because when logical names are being used with theory functions to compute sets of rules, it is sometimes important to know the order in which [events] were executed. (See [logical-name] and see [theory-functions].) What, for example, is the set of function names extant in the middle of an encapsulation? If the most recent event is previous and then you execute an encapsulate constraining an-element with two non-[local] [events] in its body, thm1 and thm2, then the order of the [events] after the encapsulation is (reading chronologically forward): previous, thm1, thm2, an-element (the encapsulate itself). Actually, between previous and thm1 certain extensions were made to the [world] by the superior encapsulate, to permit an-element to be used as a function symbol in thm1. Remark for ACL2(r) (see [real]). For ACL2(r), [encapsulate] can be used to introduce classical and non-classical functions, as determined by the signatures; see [signature]. Those marked as classical (respectively non-classical) must have classical (respectively, non-classical) [local] witness functions. A related requirement applies to functional instantiation; see [lemma-instance]. Subtopics [Constraint] Restrictions on certain functions introduced in [encapsulate] [events] [Functional-instantiation] An analogue in ACL2 of higher-order logical reasoning. Functional instantiation allows you to prove theorems ``by analogy'' with previous theorems. See [hints] and see [lemma-instance]. [Redundant-encapsulate] Redundancy of [encapsulate] [events] [Signature] How to specify the arity of a constrained function") (ENDP (LISTS ACL2-BUILT-INS) "Recognizer for empty lists In the ACL2 logic, (endp x) is the same as (atom x). See [atom]. Unlike [atom], the [guard] for endp requires that x is a [cons] pair or is nil. Thus, endp is typically used as a termination test for functions that recur on a [true-listp] argument. See [guard] for general information about [guard]s. Endp is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun endp (x) (declare (xargs :guard (or (consp x) (eq x nil)))) (atom x))") (ENTER-BOOT-STRAP-MODE (HISTORY) "The first millisecond of the Big Bang ACL2 functions, e.g., [if], that show enter-boot-strap-mode as their defining [command] are in fact primitives. It is impossible for the system to display defining axioms about these symbols. Enter-boot-strap-mode is a Common Lisp function but not an ACL2 function. It magically creates from nil an ACL2 property list [world] that lets us start the boot-strapping process. That is, once enter-boot-strap-mode has created its [world], it is possible to process the [defconst]s, [defun]s, and [defaxiom]s, necessary to bring up the rest of the system. Before that [world] is created, the attempt by ACL2 even to translate a [defun] form, say, would produce an error because [defun] is undefined. Several ACL2 functions show enter-boot-strap-mode as their defining [command]. Among them are [if], [cons], [car], and [cdr]. These functions are characterized by axioms rather than definitional equations --- axioms that in most cases are built into our code and hence do not have any explicit representation among the rules and formulas in the system.") (EQ (EQUAL EQUALITY-VARIANTS ACL2-BUILT-INS) "Equality of symbols Eq is the function for determining whether two objects are identical (i.e., have the exact same store address in the current von Neumann implementation of Common Lisp). It is the same as [equal] in the ACL2 logic. Eq is a Common Lisp function. In order to ensure conformance with Common Lisp, the ACL2 [guard] on eq requires at least one of the arguments to eq to be a symbol. Common Lisp guarantees that if x is a symbol, then x is eq to y if and only if x is [equal] to y. Thus, the ACL2 user should think of eq as nothing besides a fast means for checking [equal] when one argument is known to be a symbol. In particular, it is possible that an eq test will not even require the cost of a function call but will be as fast as a single machine instruction. Function: (defun eq (x y) (declare (xargs :guard (if (symbolp x) t (symbolp y)))) (equal x y))") (EQL (EQUAL EQUALITY-VARIANTS ACL2-BUILT-INS) "Test equality (of two numbers, symbols, or [characters]) (eql x y) is logically equivalent to (equal x y). Unlike [equal], eql has a [guard] requiring at least one of its arguments to be a number, a symbol, or a character. Generally, eql is executed more efficiently than [equal]. For a discussion of the various ways to test against 0, See [zero-test-idioms]. Eql is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun eql (x y) (declare (xargs :guard (or (eqlablep x) (eqlablep y)))) (equal x y))") (EQLABLE-ALISTP (ALISTS ACL2-BUILT-INS) "Recognizer for a true list of pairs whose [car]s are suitable for [eql] The predicate eqlable-alistp tests whether its argument is a [true-listp] of [consp] objects whose [car]s all satisfy [eqlablep]. Function: (defun eqlable-alistp (x) (declare (xargs :guard t)) (cond ((atom x) (equal x nil)) (t (and (consp (car x)) (eqlablep (car (car x))) (eqlable-alistp (cdr x))))))") (EQLABLE-LISTP (EQLABLEP EQUAL LISTS ACL2-BUILT-INS) "Recognizer for a true list of objects each suitable for [eql] The predicate eqlable-listp tests whether its argument is a [true-listp] of objects satisfying [eqlablep]. Function: (defun eqlable-listp (l) (declare (xargs :guard t)) (if (consp l) (and (eqlablep (car l)) (eqlable-listp (cdr l))) (equal l nil)))") (EQLABLEP (EQUAL ACL2-BUILT-INS) "The [guard] for the function [eql] The predicate eqlablep tests whether its argument is suitable for [eql], at least one of whose arguments must satisfy this predicate in Common Lisp. (Eqlablep x) is true if and only if its argument is a number, a symbol, or a character. Function: (defun eqlablep (x) (declare (xargs :guard t)) (or (acl2-numberp x) (symbolp x) (characterp x))) Subtopics [Eqlable-listp] Recognizer for a true list of objects each suitable for [eql]") (EQUAL (BASICS ACL2-BUILT-INS) "True equality (equal x y) is equal to t or nil, according to whether or not x and y are the same value. For a discussion of the various idioms for testing against 0, See [zero-test-idioms]. Subtopics [=] Test equality of two numbers [Eq] Equality of symbols [Eql] Test equality (of two numbers, symbols, or [characters]) [Eqlable-listp] Recognizer for a true list of objects each suitable for [eql] [Eqlablep] The [guard] for the function [eql] [Hons-equal] ([hons-equal] x y) is a recursive equality check that optimizes when parts of its arguments are [normed].") (EQUALITY-VARIANTS (PROGRAMMING) "Versions of a function using different equality tests The ACL2 environment includes not only a logic but also a programming language, which is based on Common Lisp. Execution efficiency may be increased by using fast equality tests: [eq] for symbols and [eql] for numbers, symbols, and characters (see [eqlablep]). Several list-processing functions built into ACL2 thus have three variants, depending on whether the equality function used is [eq], [eql], or [equal]; a list is provided below. ACL2 has taken measures to ensure that one can reason about a single logical function even when one uses these different variants. Consider for example the case of list membership. Common Lisp provides a utility for this purposes, [member], which can take a :TEST keyword argument, default [eql]. So for example, one might write (member a x :TEST 'eq) if either a is a symbol or x is a list of symbols, so that the fastest equality test ([eq]) may be used when comparing a to successive elements of the list, x. One might elsewhere write (member b (foo y)), which is equivalent to (member b (foo y) :TEST 'eql), for example if b is a number. If one wants to reason about both (member a x :TEST 'eq) and (member b y), it might be helpful for both calls of member to be the same logically, even though Common Lisp will execute them differently (using [eq] or [eql], respectively). ACL2 arranges that in fact, both references to [member] generate calls of [member-equal] in the theorem prover. In fact, since [member] can take the optional :TEST keyword argument, then in ACl2 it must be defined as a macro, not a function (see [defun]). ACL2 arranges that a call of member generates a corresponding call of the function [member-equal], regardless of the value of TEST, in a manner that produces [member-equal] in prover output. More generally, you can expect ACL2 to treat your use of [member] as though you had written [member-equal], for example in the way it stores [rewrite] rules and other kinds of rules as well (see [rule-classes]). We say little here about how this is all arranged by ACL2, other than to mention that [mbe] is utilized (so, you might see mention in proof logs) of the function [return-last] that implements [mbe]. Such details, which involve a notion of ``macro alias'' and probably can be ignored by most users, may be found elsewhere; see [equality-variants-details]. As a convenience to the user, the macro member-eq is provided that expands to a corresponding call of member with :TEST 'eq, as follows. ACL2 !>:trans1 (member-eq (foo x) (bar y)) (MEMBER (FOO X) (BAR Y) :TEST 'EQ) ACL2 !> For efficiency we recommend using the -equal equality variant, for example [member-equal] or ([member] ... :TEST 'equal), in certain contexts: [defmacro], [defpkg], [defconst], and [value-triple] forms. However, the implementation of equality variants has been designed so that when defining a function, one may choose freely in a definition an equality variant of primitive F, to get efficient execution but where subsequent reasoning is about F-equal. For details about the above recommendation and for a discussion of the implementation, see [equality-variants-details]. The following alphabetical list includes all primitives that have equality variants. Each macro F listed below takes an optional :TEST keyword argument of 'eq, 'eql, or 'equal, where 'eql is the default. For each such F, a function F-equal is defined such that for logical purposes (in particular theorem proving), each call of F expands to a corresponding call of F-equal. For convenience, a macro F-eq is also defined, so that a call of F-eq expands to a corresponding call of F with :TEST 'eq. [add-to-set] [assoc] [delete-assoc] [intersection$] ; (see Note below) [intersectp] [member] [no-duplicatesp] position-ac [position] [put-assoc] [rassoc] [remove-duplicates] [remove1] [remove] [set-difference$] ; (see Note below) [subsetp] [union$] ; (see Note below) Note: Three of the macros above have names ending with the character, `$': [intersection$], [set-difference$], and [union$]. In each case there is a corresponding Common Lisp primitive without the trailing `$': intersection, set-difference, and union. However, Common Lisp does not specify the order of elements in the list returned by those primitives, so ACL2 has its own. Nevertheless, the only use of the trailing `$' is to distinguish the primitives; associated functions and macros, for example union-eq and intersection-equal, do not include the `$' character in their names. We conclude with a brief discussion of [guards]. The expansion of any of the above macros depends on the keyword argument, which generates a function call with a guard suitable for the equality test being used. Consider for example the call (member x lst :test 'eq), or equivalently, (member-eq x lst). Expanding these macros leads to a call of [mbe]; you can see how that goes by using :[trans1]. Ultimately, the guard being checked is that of the function member-eq-exec, which is as follows. (if (symbolp x) (true-listp lst) (symbol-listp lst)) Care has been taken to ensure that this guard is checked during evaluation and also that it generates suitable proof obligations for guard verification (see [verify-guards]). A guard violation might look something like this: ACL2 !>(member-eq 3 '(4 5)) ACL2 Error in TOP-LEVEL: The guard for the function call (MEMBER-EQ-EXEC$GUARD-CHECK X LST), which is (IF (SYMBOLP X) (TRUE-LISTP LST) (SYMBOL-LISTP LST)), is violated by the arguments in the call (MEMBER-EQ-EXEC$GUARD-CHECK 3 '(4 5)). See :DOC set-guard-checking for information about suppressing this check with (set-guard-checking :none), as recommended for new users. To debug see :DOC print-gv, see :DOC trace, and see :DOC wet. ACL2 !> Above, member-eq-exec$guard-check is a function generated as part of ACL2's expansion of member with :test 'eq, and this function symbol can be quite reasonably ignored. The important thing is that it refers to the guard for member-eq-exec, which as the name may suggest is intended to guard the execution of a call of [member-eq], or a call of [member] with :test 'eq. The important part of the message above is the guard actually being violated: (IF (SYMBOLP X) (TRUE-LISTP LST) (SYMBOL-LISTP LST)). Subtopics [=] Test equality of two numbers [Eq] Equality of symbols [Eql] Test equality (of two numbers, symbols, or [characters]) [Equality-variants-details] Details about [equality-variants]") (EQUALITY-VARIANTS-DETAILS (EQUALITY-VARIANTS) "Details about [equality-variants] Here we present details about equality variants, none of which is likely to be important to the majority of ACL2 users. Please see [equality-variants] for relevant background. We begin by presenting [events] that implement the equality variants for [member], as these illustrate the events introduced for all macros having equality variants. The definition of [member], just below, calls the macro let-mbe, which in turn is just an abbreviation for a combination of [let] and [mbe]. Here is a simplified version of the definition of this macro. For relevant background, see [mbe]. (defmacro let-mbe (bindings &key logic exec) `(let ,bindings (mbe :logic ,logic :exec ,exec))) This use of [let] arranges that each argument of a call of member is evaluated only once. The actual definition of the macro let-mbe is a bit more complex, in order to guarantee that [guard]s are appropriately checked. For purposes of this discussion we ignore this simplification. (You can find the definition of let-mbe in ACL2 source file axioms.lisp.) Consider the following definition from ACL2 source file axioms.lisp. Notice that it invokes the macro let-mbe, discussed above. (defmacro member (x l &key (test ''eql)) (declare (xargs :guard (or (equal test ''eq) (equal test ''eql) (equal test ''equal)))) (cond ((equal test ''eq) `(let-mbe ((x ,x) (l ,l)) :logic (member-equal x l) :exec (member-eq-exec x l))) ((equal test ''eql) `(let-mbe ((x ,x) (l ,l)) :logic (member-equal x l) :exec (member-eql-exec x l))) (t ; (equal test 'equal) `(member-equal ,x ,l)))) Inspection of the definition above shows that every call of [member] expands to one that is logically equivalent to the corresponding call of [member-equal], which is defined as follows. (defun member-equal (x lst) (declare (xargs :guard (true-listp lst))) (cond ((endp lst) nil) ((equal x (car lst)) lst) (t (member-equal x (cdr lst))))) The following two definitions model equality variants of [member] for tests [eq] and [eql], respectively. (defun member-eq-exec (x lst) (declare (xargs :guard (if (symbolp x) (true-listp lst) (symbol-listp lst)))) (cond ((endp lst) nil) ((eq x (car lst)) lst) (t (member-eq-exec x (cdr lst))))) (defun member-eql-exec (x lst) (declare (xargs :guard (if (eqlablep x) (true-listp lst) (eqlable-listp lst)))) (cond ((endp lst) nil) ((eql x (car lst)) lst) (t (member-eql-exec x (cdr lst))))) At this point the user can write (member x y) or (member-equal x y) to call equality variants of member with test eql or equal, respectively. We thus provide the following macro for the eq variant. (defmacro member-eq (x lst) `(member ,x ,lst :test 'eq)) [Guard] proof obligations generated by calls of member will include those based on its use of mbe, and are supported by the following two lemmas. (defthm member-eq-exec-is-member-equal (equal (member-eq-exec x l) (member-equal x l))) (defthm member-eql-exec-is-member-equal (equal (member-eql-exec x l) (member-equal x l))) Finally, the following two events arrange that in certain contexts such as [theories] (including the use of [in-theory] in [events] and [hints]), [member-eq] and [member] are treated as references to [member-equal]. (add-macro-alias member-eq member-equal) (add-macro-alias member member-equal) Note however that these events do not affect printing of calls during proofs: calls of member and member-eq will be macroexpanded away, leaving you with calls of member-equal that are displayed in proof output. For a way to change this behavior, see [add-macro-fn]. We conclude this topic by exploring the following recommendation made in the [documentation] for [equality-variants]. For efficiency we recommend using the -equal equality variant, for example [member-equal] or ([member] ... :TEST 'equal), in certain contexts: [defmacro], [defpkg], [defconst], and [value-triple] forms. ACL2 relies on the underlying Common Lisp for evaluation. It also processes events in the ACL2 logic. In order to guarantee consistency of its logical and Common Lisp evaluations, ACL2 uses a ``safe mode'' to avoid ill-guarded calls. In particular, consider the use of [mbe] in execution of a call of an equality variant of a primitive, F, other than its F-equal variant. The [mbe] call discussed above requires a connection to be established between the :logic and :exec forms. For example, if F is called with :TEST 'eql (either explicitly or as the default), then ACL2 will call both F-eql-exec and F-equal, and check that the two results are equal. The following partial log illustrates the point above. We define a macro that calls [member], and when a call of this macro is expanded during processing of a subsequent definition, we see that two membership functions are called on the same arguments. ACL2 !>(defmacro mac (lst) (list 'quote (and (true-listp lst) (member 'c lst :test 'eq)))) Summary Form: ( DEFMACRO MAC ...) Rules: NIL Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) MAC ACL2 !>(trace$ member-equal member-eq-exec) ((MEMBER-EQUAL) (MEMBER-EQ-EXEC)) ACL2 !>(defun f () (mac (a b c d))) 1> (ACL2_*1*_ACL2::MEMBER-EQ-EXEC C (A B C D)) 2> (MEMBER-EQ-EXEC C (A B C D)) <2 (MEMBER-EQ-EXEC (C D)) <1 (ACL2_*1*_ACL2::MEMBER-EQ-EXEC (C D)) 1> (ACL2_*1*_ACL2::MEMBER-EQUAL C (A B C D)) 2> (MEMBER-EQUAL C (A B C D)) <2 (MEMBER-EQUAL (C D)) <1 (ACL2_*1*_ACL2::MEMBER-EQUAL (C D)) Since F is non-recursive, its admission is trivial. If performance is an issue then we can avoid such a problem, for example as follows. In a fresh session, let us define a suitable wrapper for calling [member] with :TEST 'eq. This time, the trace in our partial log shows that we have avoided calling two membership functions. ACL2 !>(defun mem-eq (x lst) (declare (xargs :guard (if (symbolp x) (true-listp lst) (symbol-listp lst)))) (member x lst :test 'eq)) [[ ... output omitted here ... ]] MEM-EQ ACL2 !>(defmacro mac (lst) (list 'quote (and (true-listp lst) (mem-eq 'c lst)))) Summary Form: ( DEFMACRO MAC ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) MAC ACL2 !>(trace$ member-equal member-eq-exec mem-eq) ((MEMBER-EQUAL) (MEMBER-EQ-EXEC) (MEM-EQ)) ACL2 !>(defun f () (mac (a b c d))) 1> (ACL2_*1*_ACL2::MEM-EQ C (A B C D)) 2> (MEM-EQ C (A B C D)) <2 (MEM-EQ (C D)) <1 (ACL2_*1*_ACL2::MEM-EQ (C D)) Since F is non-recursive, its admission is trivial.") (EQUIVALENCE (RULE-CLASSES) "Mark a relation as an equivalence relation See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. Example: (defthm r-equal-is-an-equivalence ; assumes that r-equal has been defined (and (booleanp (r-equal x y)) (r-equal x x) (implies (r-equal x y) (r-equal y x)) (implies (and (r-equal x y) (r-equal y z)) (r-equal x z))) :rule-classes :equivalence) Also see [defequiv]. General Form: (and (booleanp (equiv x y)) (equiv x x) (implies (equiv x y) (equiv y x)) (implies (and (equiv x y) (equiv y z)) (equiv x z))) except that the order of the conjuncts and terms and the choice of variable symbols is unimportant. The effect of such a rule is to identify equiv as an equivalence relation. Note that only Boolean 2-place function symbols can be treated as equivalence relations. See [congruence] and see [refinement] for closely related concepts. The macro form (defequiv equiv) is an abbreviation for a [defthm] of rule-class :equivalence that establishes that equiv is an equivalence relation. It generates the formula shown above. See [defequiv]. When equiv is marked as an equivalence relation, its reflexivity, symmetry, and transitivity are built into the system in a deeper way than via :[rewrite] rules. More importantly, after equiv has been shown to be an equivalence relation, lemmas about equiv, e.g., (implies hyps (equiv lhs rhs)), when stored as :[rewrite] rules, cause the system to rewrite certain occurrences of (instances of) lhs to (instances of) rhs. Roughly speaking, an occurrence of lhs in the kth argument of some fn-expression, (fn ... lhs' ...), can be rewritten to produce (fn ... rhs' ...), provided the system ``knows'' that the value of fn is unaffected by equiv-substitution in the kth argument. Such knowledge is communicated to the system via ``congruence lemmas.'' For example, suppose that r-equal is known to be an equivalence relation. The :[congruence] lemma (implies (r-equal s1 s2) (equal (fn s1 n) (fn s2 n))) informs the rewriter that, while rewriting the first argument of fn-expressions, it is permitted to use r-equal rewrite-rules. See [congruence] for details about :[congruence] lemmas. Interestingly, congruence lemmas are automatically created when an equivalence relation is stored, saying that either of the equivalence relation's arguments may be replaced by an equivalent argument. That is, if the equivalence relation is fn, we store congruence rules that state the following fact: (implies (and (fn x1 y1) (fn x2 y2)) (iff (fn x1 x2) (fn y1 y2))) Another aspect of equivalence relations is that of ``refinement.'' We say equiv1 ``refines'' equiv2 iff (equiv1 x y) implies (equiv2 x y). :[refinement] rules permit you to establish such connections between your equivalence relations. The value of refinements is that if the system is trying to rewrite something while maintaining equiv2 it is permitted to use as a :[rewrite] rule any refinement of equiv2. Thus, if equiv1 is a refinement of equiv2 and there are equiv1 rewrite-rules available, they can be brought to bear while maintaining equiv2. See [refinement]. The system initially has knowledge of two equivalence relations, equality, denoted by the symbol [equal], and propositional equivalence, denoted by [iff]. [Equal] is known to be a refinement of all equivalence relations and to preserve equality across all arguments of all functions. Typically there are five steps involved in introducing and using a new equivalence relation, equiv. (1) Define equiv, (2) prove the :equivalence lemma about equiv, (3) prove the :[congruence] lemmas that show where equiv can be used to maintain known relations, (4) prove the :[refinement] lemmas that relate equiv to known relations other than equal, and (5) develop the theory of conditional :[rewrite] rules that drive equiv rewriting. More will be written about this as we develop the techniques. For now, here is an example that shows how to make use of equivalence relations in rewriting. Among the theorems proved below is (defthm insert-sort-is-id (perm (insert-sort x) x)) Here perm is defined as usual with delete and is proved to be an equivalence relation and to be a congruence relation for [cons] and [member]. Then we prove the lemma (defthm insert-is-cons (perm (insert a x) (cons a x))) which you must think of as you would (insert a x) = (cons a x). Now prove (perm (insert-sort x) x). The base case is trivial. The induction step is (consp x) & (perm (insert-sort (cdr x)) (cdr x)) -> (perm (insert-sort x) x). Opening insert-sort makes the conclusion be (perm (insert (car x) (insert-sort (cdr x))) x). Then apply the induction hypothesis (rewriting (insert-sort (cdr x)) to (cdr x)), to make the conclusion be (perm (insert (car x) (cdr x)) x) Then apply insert-is-cons to get (perm (cons (car x) (cdr x)) x). But we know that (cons (car x) (cdr x)) is x, so we get (perm x x) which is trivial, since perm is an equivalence relation. Here are the events. (encapsulate (((lt * *) => *)) (local (defun lt (x y) (declare (ignore x y)) nil)) (defthm lt-non-symmetric (implies (lt x y) (not (lt y x))))) (defun insert (x lst) (cond ((atom lst) (list x)) ((lt x (car lst)) (cons x lst)) (t (cons (car lst) (insert x (cdr lst)))))) (defun insert-sort (lst) (cond ((atom lst) nil) (t (insert (car lst) (insert-sort (cdr lst)))))) (defun del (x lst) (cond ((atom lst) nil) ((equal x (car lst)) (cdr lst)) (t (cons (car lst) (del x (cdr lst)))))) (defun mem (x lst) (cond ((atom lst) nil) ((equal x (car lst)) t) (t (mem x (cdr lst))))) (defun perm (lst1 lst2) (cond ((atom lst1) (atom lst2)) ((mem (car lst1) lst2) (perm (cdr lst1) (del (car lst1) lst2))) (t nil))) (defthm perm-reflexive (perm x x)) (defthm perm-cons (implies (mem a x) (equal (perm x (cons a y)) (perm (del a x) y))) :hints ((\"Goal\" :induct (perm x y)))) (defthm perm-symmetric (implies (perm x y) (perm y x))) (defthm mem-del (implies (mem a (del b x)) (mem a x))) (defthm perm-mem (implies (and (perm x y) (mem a x)) (mem a y))) (defthm mem-del2 (implies (and (mem a x) (not (equal a b))) (mem a (del b x)))) (defthm comm-del (equal (del a (del b x)) (del b (del a x)))) (defthm perm-del (implies (perm x y) (perm (del a x) (del a y)))) (defthm perm-transitive (implies (and (perm x y) (perm y z)) (perm x z))) (defequiv perm) (in-theory (disable perm perm-reflexive perm-symmetric perm-transitive)) (defcong perm perm (cons x y) 2) (defcong perm iff (mem x y) 2) (defthm atom-perm (implies (not (consp x)) (perm x nil)) :rule-classes :forward-chaining :hints ((\"Goal\" :in-theory (enable perm)))) (defthm insert-is-cons (perm (insert a x) (cons a x))) (defthm insert-sort-is-id (perm (insert-sort x) x)) (defun app (x y) (if (consp x) (cons (car x) (app (cdr x) y)) y)) (defun rev (x) (if (consp x) (app (rev (cdr x)) (list (car x))) nil)) (defcong perm perm (app x y) 2) (defthm app-cons (perm (app a (cons b c)) (cons b (app a c)))) (defthm app-commutes (perm (app a b) (app b a))) (defcong perm perm (app x y) 1 :hints ((\"Goal\" :induct (app y x)))) (defthm rev-is-id (perm (rev x) x)) (defun == (x y) (if (consp x) (if (consp y) (and (equal (car x) (car y)) (== (cdr x) (cdr y))) nil) (not (consp y)))) (defthm ==-reflexive (== x x)) (defthm ==-symmetric (implies (== x y) (== y x))) (defequiv ==) (in-theory (disable ==-symmetric ==-reflexive)) (defcong == == (cons x y) 2) (defcong == iff (consp x) 1) (defcong == == (app x y) 2) (defcong == == (app x y) 1) (defthm rev-rev (== (rev (rev x)) x))") (EQUIVALENT-FORMULAS-DIFFERENT-REWRITE-RULES (INTRODUCTION-TO-THE-THEOREM-PROVER) "Logically equivalent formulas can generate radically different rules Consider the rewrite rules that would be generated from the three commands below. In all three cases, the fact being stated relates the nth element of the reverse of x to the nth element of x. In fact, the three formulas are simple rearrangements of each other and are all equivalent. The theorem prover treats all three formulas equivalently when proving them. But the rules generated from them are very different. (defthm nth-rev-1 (implies (and (natp n) (< n (len x))) (equal (nth n (rev x)) (nth (- (len x) (+ 1 n)) x)))) (defthm nth-rev-2 (implies (and (natp n) (< n (len x))) (equal (nth (- (len x) (+ 1 n)) x) (nth n (rev x))))) (defthm nth-rev-3 (implies (and (natp n) (not (equal (nth n (rev x)) (nth (- (len x) (+ 1 n)) x)))) (not (< n (len x))))) Here are the three rewrite rules: nth-rev-1: Replace instances of (NTH n (REV x)) by (NTH (- (LEN x) (+ 1 n)) x), if you can establish that n is a natural number less than the length of x. nth-rev-2: Replace instances of (NTH (- (LEN x) (+ 1 n)) x) by (NTH n (REV x)), if you can establish that n is a natural number less than the length of x. nth-rev-3: Replace instances of (< n (LEN x)) by NIL if you can establish that n is a natural number and that (NTH n (REV x)) is different from (NTH (- (LEN x) (+ 1 n)) x). As the driver of ACL2, you have to decide which rule you want when you give the command to prove it. If you tell the theorem prover to use both nth-rev-1 and nth-rev-2, ACL2 will enter an infinite loop when it sees any term matching either NTH expression. Most users would choose form nth-rev-1 of the rule. It eliminates rev from the problem -- at the expense of introducing some arithmetic. But arithmetic is so fundamental it is rarely possible to avoid it and it is likely to be in the problem already since you're indexing into (rev x). The nth-rev-2 form of the rule is ``bad'' because it introduces rev into a problem where it might not have appeared. The nth-rev-3 version is ``bad'' because it makes the theorem prover shift its attention from a simple arithmetic inequality to a complicated property of nth and rev, which might not be in the problem. Use your browser's Back Button now to return to [introduction-to-rewrite-rules-part-1].") (ER (ERRORS ACL2-BUILT-INS) "Print an error message and ``cause an error'' See [fmt] for a general discussion of formatted printing in ACL2. All calls of er print formatted strings, just as is done by [fmt]. Example Forms: (er hard 'top-level \"Illegal inputs, ~x0 and ~x1.\" a b) (er hard? 'top-level \"Illegal inputs, ~x0 and ~x1.\" a b) (er soft 'top-level \"Illegal inputs, ~x0 and ~x1.\" a b) The examples above all print an error message to standard output saying that a and b are illegal inputs. However, the first two abort evaluation after printing an error message (while logically returning nil, though in ordinary evaluation the return value is never seen); while the third returns (mv t nil state) after printing an error message. The result in the third case can be interpreted as an ``error'' when programming with the ACL2 [state], something most ACL2 users will probably not want to do unless they are building systems of some sort; see [programming-with-state]. If state is not available in the current context then you will probably want to use (er hard ...) or (er hard? ...) to cause an error; for example, if you are returning two values, you may write (mv (er hard ...) nil). The difference between the hard and hard? forms is one of guards. Use hard if you want the call to generate a (clearly impossible) guard proof obligation of (essentially) NIL. But use hard? if you want to be able to call this function in guard-verified code, since the call generates a (trivially satisfied) guard proof obligation of T. Er is a macro, and the above three examples expand to calls of ACL2 functions, as shown below. See [illegal], see [hard-error], and see [error1]. The first two have guards of (essentially) NIL and T, respectively, while [error1] is in :[program] mode. General forms: (er hard ctx fmt-string arg1 arg2 ... argk) ==> {macroexpands, in essence, to:} (ILLEGAL CTX FMT-STRING (LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk))) (er hard? ctx fmt-string arg1 arg2 ... argk) ==> {macroexpands, in essence, to:} (HARD-ERROR CTX FMT-STRING (LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk))) (er soft ctx fmt-string arg1 arg2 ... argk) ==> {macroexpands, in essence, to:} (ERROR1 CTX FMT-STRING (LIST (CONS #\\0 ARG1) (CONS #\\1 ARG2) ... (CONS #\\k ARGk))) Technical note for raw Lisp programmers only: It is possible to cause hard errors to signal actual raw Lisp errors. See [hard-error].") (ER-PROGN (ERRORS PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "Perform a sequence of state-changing ``error triples'' Example: (er-progn (check-good-foo-p (f-get-global 'my-foo state) state) (value (* (f-get-global 'my-foo state) (f-get-global 'bar state)))) This sequencing primitive is only useful when programming with [state], something that very few users will probably want to do. See [state]. Er-progn is used much the way that [progn] is used in Common Lisp, except that it expects each form within it to evaluate to an ``error triple'' of the form (mv erp val state); see [error-triples]. The first such form, if any, that evaluates to such a triple where erp is not nil yields the error triple returned by the er-progn. If there is no such form, then the last form returns the value of the er-progn form. General Form: (er-progn ... ) where each is an expression that evaluates to an error triple (see [programming-with-state]). The above form is essentially equivalent to the following (``essentially'' because in fact, care is taken to avoid variable capture). (mv-let (erp val state) (cond (erp (mv erp val state)) (t (mv-let (erp val state) (cond (erp (mv erp val state)) (t ... (mv-let (erp val state) (cond (erp (mv erp val state)) (t )))))))))") (ERROR-TRIPLES (ERRORS PROGRAMMING-WITH-STATE) "A common ACL2 programming idiom When evaluation returns three values, where the first two are ordinary (non-[stobj]) objects and the third is the ACL2 [state], the result may be called an ``error triple''. If an error triple is (mv erp val state), we think of erp as an error flag and val as the returned value. By default, if the result of evaluating a top-level form is an error triple (mv erp val state), then that result is not printed if erp is non-nil or if val is the keyword :INVISIBLE, and otherwise val is printed with a preceding space. For example: ACL2 !>(+ 3 4) ; ordinary value 7 ACL2 !>(mv nil (+ 3 4) state) ; error triple, error component of nil 7 ACL2 !>(mv t (+ 3 4) state) ; error triple, non-nil error component ACL2 !>(mv nil :invisible state) ; special case for :INVISIBLE ACL2 !> See [programming-with-state] for a discussion of error triples and how to program with them. Also see [ld-error-triples] and see [ld] for a discussion of the value :COMMAND-CONVENTIONS for keyword :LD-POST-EVAL-PRINT.") (ERROR-TRIPLES-AND-PARALLELISM (PARALLEL-PROGRAMMING) "How to avoid error triples in ACL2(p) This [documentation] topic relates to the experimental extension of ACL2 supporting parallel execution and proof; see [parallelism]. ACL2 supports the use of error triples in many features; e.g., [computed-hints]. (For background on error triples, see [programming-with-state].) However, ACL2(p) does not support the use of error triples in some of these features (e.g., [computed-hints]) while [waterfall-parallelism] is enabled. You may see an error message like the following when running ACL2(p) with [waterfall-parallelism] enabled: ACL2 Error in ( THM ...): Since we are translating a form in ACL2(p) intended to be executed with waterfall parallelism enabled, the form (MY-STATE-MODIFYING-COMPUTED-HINT ID STATE) was expected to represent an ordinary value, not an error triple (mv erp val state), as would be acceptable in a serial execution of ACL2. Therefore, the form returning a tuple of the form (* * STATE) is an error. See :DOC unsupported- waterfall-parallelism-features and :DOC error-triples-and-parallelism for further explanation. In this particular example, the cause of the error was trying to use a computed hint that returned state, which is not allowed when executing the waterfall in parallel (see [unsupported-waterfall-parallelism-features] for other related information). Often, the only reason users need to return state is so they can perform some output during the proof process. In this case, we suggest using one of the state-free output functions, like [cw] or [observation-cw]. If the user is concerned about the interleaving of their output with other output, these calls can be surrounded with the macro [with-output-lock]. Another frequent reason users return state is so they can cause a soft error and halt the proof process. In this case, we suggest instead calling [er] with the hard or hard? severity. By using these mechanisms, the user avoids modifying [state], a requirement for much of the code written in ACL2(p). You may encounter other similar error messages when using [computed-hints], [custom-keyword-hints], or [override-hints]. Chances are that you are somehow returning an error triple when an ordinary value is needed. If this turns out not to be the case, please let the ACL2 implementors know.") (ERROR1 (ERRORS ACL2-BUILT-INS) "Print an error message and cause a ``soft error'' (Error1 ctx str alist) returns (mv t nil state). An error message is first printed using the the ``context'' ctx, as well as the string str and alist alist that are of the same kind as expected by [fmt]. See [fmt]. Error1 can be interpreted as causing an ``error'' when programming with the ACL2 [state], something most ACL2 users will probably not want to do; see [ld-error-triples] and see [er-progn]. In order to cause errors with :[logic] mode functions, see [hard-error] and see [illegal]. Better yet, see [er] for a macro that provides a unified way of signaling errors. As mentioned above, error1 always returns (mv t nil state). But if a call (error1 ctx str alist) is encountered during evaluation, then the string str is first printed using the association list alist (as in [fmt]). Here is a trivial, contrived example. ACL2 !>(error1 'my-context \"Printing 4: ~n0\" (list (cons #\\0 4)) state) ACL2 Error in MY-CONTEXT: Printing 4: four ACL2 !>") (ERRORS (PROGRAMMING) "Support for causing runtime errors, breaks, assertions, etc. Subtopics [Assert$] Cause a hard error if the given test is false [Assert*] Create a [guard] proof obligation that given test holds [Break$] Cause an immediate Lisp break [Breaks] Common Lisp breaks [Er] Print an error message and ``cause an error'' [Er-progn] Perform a sequence of state-changing ``error triples'' [Error-triples] A common ACL2 programming idiom [Error1] Print an error message and cause a ``soft error'' [Hard-error] Print an error message and stop execution [Illegal] Print an error message and stop execution") (ESCAPE-TO-COMMON-LISP (COMMON-LISP) "Escaping to Common Lisp Example: ACL2 !>:Q There is essentially no Common Lisp escape feature in the [lp] (but see [set-raw-mode]). This is part of the price of purity. To execute a form in Common Lisp as opposed to ACL2, exit [lp] with :[q], submit the desired forms to the Common Lisp read-eval-print loop, and reenter ACL2 with (lp).") (EVALUATING_APP_ON_SAMPLE_INPUT (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Evaluating App on Sample Input [{IMAGE}] {IMAGE} ACL2 !>(app nil '(x y z)) (X Y Z) ACL2 !>(app '(1 2 3) '(4 5 6 7)) (1 2 3 4 5 6 7) ACL2 !>(app '(a b c d e f g) '(x y z)) ; click [here] for an explanation (A B C D E F G X Y Z) ACL2 !>(app (app '(1 2) '(3 4)) '(5 6)) (1 2 3 4 5 6) ACL2 !>(app '(1 2) (app '(3 4) '(5 6))) (1 2 3 4 5 6) ACL2!>(let ((a '(1 2)) (b '(3 4)) (c '(5 6))) (equal (app (app a b) c) (app a (app b c)))) T {IMAGE} As we can see from these examples, ACL2 functions can be executed more or less as Common Lisp. The last three examples suggest an interesting property of app. [{IMAGE}]") (EVALUATOR-RESTRICTIONS (META) "Some restrictions on the use of evaluators in meta-level rules Note: This topic, which explains some subtleties for evaluators, can probably be skipped by most readers. Rules of class :[meta] and of class :[clause-processor] are stated using so-called ``evaluator'' functions. Here we explain some restrictions related to evaluators. Below we refer primarily to :meta rules, but the discussion applies equally to :clause-processor rules. In a nutshell, we require that a rule's evaluator does not support other functions in the rule, and we require that the evaluator not be introduced under a non-trivial encapsulate. We also require that no function has an attachment (see [defattach]) that is both ancestral in the evaluator and also ancestral in the meta or clause-processor functions. We explain these restrictions in detail below. An argument given elsewhere (see [meta], in particular ``Aside for the logic-minded'') explains that the correctness argument for applying metatheoretic simplifiers requires that one be able to ``grow'' an evaluator (see [defevaluator]) to handle all functions in the current ACL2 [world]. Then we may, in essence, functionally instantiate the original evaluator to the new (``grown'') evaluator, provided that the new evaluator satisfies all of the axioms of the original. We therefore require that the evaluator function does not support the formula of any [defaxiom] event. This notion of ``support'' (sometimes denoted ``is an ancestor of'') is defined recursively as follows: a function symbol supports a formula if either it occurs in that formula, or else it supports the definition or constraint for some function symbol that occurs in that formula. Moreover, we require that neither the evaluator function nor its list version support the definition or constraint for any other function symbol occurring in the proposed :meta theorem. We also require that the evaluator does not support the formula of a :meta rule's metafunction (nor, if there is one, hypothesis metafunction) or of a :clause-processor rule's clause-processor function. This requirement, along with with the analogous requirement for [defaxiom] [events] stated above, are necessary in order to carry out the functional instantiation argument alluded to above, as follows (where the reader may find it useful to have some familiarity with the paper ``Structured Theory Development for a Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2 (2001), pages 161-203). By the usual conservativity argument, we know that the rule follows logically from the axiomatic events for its supporters. This remains true if we functionally instantiate the evaluator with one corresponding to all the functions symbols of the current session, since none of the definitions of supporters of defaxioms or metafunctions are hit by that functional substitution. Notice though that the argument above depends on knowing that the rule is not itself an axiom about the evaluator! Therefore, we also restrict evaluators so that they are not defined in the scope of a superior [encapsulate] event with non-empty signature, in order to avoid an even more subtle problem. The aforementioned correctness argument depends on knowing that the rule is provable from the axioms on the evaluator and metafunction (and hypothesis metafunction, if any). The additional restriction avoids unsoundness! The following events, if allowed, produce a proof that (f x) equals t even though, as shown below, that does not follow logically from the axioms introduced. ; Introduce our metafunction. (defun my-cancel (term) (case-match term (('f ('g)) *t*) (& term))) ; Introduce our evaluator and prove our meta rule, but in the same ; encapsulate! (encapsulate ((f (x) t)) (local (defun f (x) (declare (ignore x)) t)) (defevaluator evl evl-list ((f x))) (defthm correctness-of-my-cancel (equal (evl x a) (evl (my-cancel x) a)) :rule-classes ((:meta :trigger-fns (f))))) ; Prove that (f x) = t. (encapsulate () (local (defstub c () t)) (local (encapsulate () (local (defun g () (c))) (local (in-theory (disable g (g)))) (local (defthm f-g (equal (f (g)) t) :rule-classes nil)) (defthm f-c (equal (f (c)) t) :hints ((\"Goal\" :use f-g :in-theory (e/d (g) (correctness-of-my-cancel)))) :rule-classes nil))) (defthm f-t (equal (f x) t) :hints ((\"Goal\" :by (:functional-instance f-c (c (lambda () x))))) :rule-classes nil)) To see that the term (equal (f x) t) does not follow logically from the axiomatic [events] above, consider following the above definition of my-cancel with the following [events] instead. ; (defun my-cancel (term) ...) as before, then: (defun f (x) (not x)) (defun g () nil) (defevaluator evl evl-list ((f x) (g))) These events imply the axiomatic events above, because we still have the definition of my-cancel, we have a stronger [defevaluator] event, and we can now prove correctness-of-my-cancel exactly as it is stated above. So, the rule f-t is a logical consequence of the chronology of the current session. However, in the current session we can also prove the following rule, which contradicts f-t. (defthm f-not-t (equal (f t) nil) :rule-classes nil) It follows that the current session logically yields a contradiction! Erik Reeber has taken the above example and modified it to prove nil in ACL2 Version_3.1, as follows. (in-package \"ACL2\") (defun my-cancel (term) (case-match term (('f ('g)) *t*) (('f2 ('g2)) *t*) (& term))) (defun f2 (x) (not x)) (defun g2 () nil) (encapsulate ((f (x) t)) (local (defun f (x) (declare (ignore x)) t)) (defevaluator evl evl-list ((f x) (f2 x) (g2))) (defthm correctness-of-my-cancel (equal (evl x a) (evl (my-cancel x) a)) :rule-classes ((:meta :trigger-fns (f))))) (encapsulate () (local (defstub c () t)) (local (encapsulate () (local (defun g () (c))) (local (in-theory (disable g (g)))) (local (defthm f-g (equal (f (g)) t) :rule-classes nil)) (defthm f-c (equal (f (c)) t) :hints ((\"Goal\" :use f-g :in-theory (e/d (g) (correctness-of-my-cancel)))) :rule-classes nil))) (defthm f-t (equal (f x) t) :hints ((\"Goal\" :by (:functional-instance f-c (c (lambda () x))))) :rule-classes nil)) (defun g () nil) ; Below is the expansion of the following defevaluator, changed slightly as ; indicated by comments. ; (defevaluator evl2 evl2-list ((f x) (f2 x) (g) (g2))) (ENCAPSULATE (((EVL2 * *) => *) ((EVL2-LIST * *) => *)) (SET-INHIBIT-WARNINGS \"theory\") (LOCAL (IN-THEORY *DEFEVALUATOR-FORM-BASE-THEORY*)) (LOCAL (MUTUAL-RECURSION (DEFUN EVL2 (X A) (DECLARE (XARGS :VERIFY-GUARDS NIL :MEASURE (ACL2-COUNT X) :WELL-FOUNDED-RELATION O< :MODE :LOGIC)) (COND ((SYMBOLP X) (CDR (ASSOC-EQ X A))) ((ATOM X) NIL) ((EQ (CAR X) 'QUOTE) (CAR (CDR X))) ((CONSP (CAR X)) (EVL2 (CAR (CDR (CDR (CAR X)))) (PAIRLIS$ (CAR (CDR (CAR X))) (EVL2-LIST (CDR X) A)))) ((EQUAL (CAR X) 'F) ; changed f to f2 just below (F2 (EVL2 (CAR (CDR X)) A))) ((EQUAL (CAR X) 'F2) (F2 (EVL2 (CAR (CDR X)) A))) ((EQUAL (CAR X) 'G) (G)) ((EQUAL (CAR X) 'G2) (G2)) (T NIL))) (DEFUN EVL2-LIST (X-LST A) (DECLARE (XARGS :MEASURE (ACL2-COUNT X-LST) :WELL-FOUNDED-RELATION O<)) (COND ((ENDP X-LST) NIL) (T (CONS (EVL2 (CAR X-LST) A) (EVL2-LIST (CDR X-LST) A))))))) (DEFTHM EVL2-CONSTRAINT-1 (IMPLIES (SYMBOLP X) (EQUAL (EVL2 X A) (CDR (ASSOC-EQ X A))))) (DEFTHM EVL2-CONSTRAINT-2 (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'QUOTE)) (EQUAL (EVL2 X A) (CADR X)))) (DEFTHM EVL2-CONSTRAINT-3 (IMPLIES (AND (CONSP X) (CONSP (CAR X))) (EQUAL (EVL2 X A) (EVL2 (CADDAR X) (PAIRLIS$ (CADAR X) (EVL2-LIST (CDR X) A)))))) (DEFTHM EVL2-CONSTRAINT-4 (IMPLIES (NOT (CONSP X-LST)) (EQUAL (EVL2-LIST X-LST A) NIL))) (DEFTHM EVL2-CONSTRAINT-5 (IMPLIES (CONSP X-LST) (EQUAL (EVL2-LIST X-LST A) (CONS (EVL2 (CAR X-LST) A) (EVL2-LIST (CDR X-LST) A))))) (DEFTHM EVL2-CONSTRAINT-6 (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'F)) (EQUAL (EVL2 X A) ; changed f to f2 just below (F2 (EVL2 (CADR X) A))))) (DEFTHM EVL2-CONSTRAINT-7 (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'F2)) (EQUAL (EVL2 X A) (F2 (EVL2 (CADR X) A))))) (DEFTHM EVL2-CONSTRAINT-8 (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'G)) (EQUAL (EVL2 X A) (G)))) (DEFTHM EVL2-CONSTRAINT-9 (IMPLIES (AND (CONSP X) (EQUAL (CAR X) 'G2)) (EQUAL (EVL2 X A) (G2))))) (defthm f2-t (equal (f2 x) t) :hints ((\"Goal\" :by (:functional-instance f-t (f f2) (evl evl2) (evl-list evl2-list))))) (defthm bug-implies-nil nil :hints ((\"Goal\" :use ((:instance f2-t (x t))))) :rule-classes nil) Finally, we also require that no function has an attachment (see [defattach]) that is both ancestral in the evaluator and also ancestral in the meta or clause-processor functions. (If you don't use [defattach] then you can ignore this condition.) Without this restriction, the following events prove nil. (in-package \"ACL2\") (defstub f () t) (defevaluator evl evl-list ((f))) (defun my-meta-fn (x) (if (equal x '(f)) (list 'quote (f)) x)) (defthm my-meta-fn-correct (equal (evl x a) (evl (my-meta-fn x) a)) :rule-classes ((:meta :trigger-fns (f)))) (defun constant-nil () (declare (xargs :guard t)) nil) (defattach f constant-nil) (defthm f-is-nil ; proved using my-meta-fn-correct (equal (f) nil) :rule-classes nil) (defthm contradiction nil :hints ((\"Goal\" :use ((:functional-instance f-is-nil (f (lambda () t)))))) :rule-classes nil) To see why this restriction is sufficient, see a comment in the ACL2 source code entitled ``; Essay on Correctness of Meta Reasoning.''") (EVENP (NUMBERS ACL2-BUILT-INS) "Test whether an integer is even (evenp x) is true if and only if the integer x is even. Actually, in the ACL2 logic (evenp x) is defined to be true when x/2 is an integer. The [guard] for evenp requires its argument to be an integer. Evenp is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun evenp (x) (declare (xargs :guard (integerp x))) (integerp (* x (/ 2))))") (EVENTS (ACL2) "Functions that extend the logic Any extension of the syntax of ACL2 (i.e., the definition of a new constant or macro), the axioms (i.e., the definition of a function), or the rule database (i.e., the proof of a theorem), constitutes a logical ``event.'' Events change the ACL2 logical world (see [world]). Indeed, the only way to change the ACL2 [world] is via the successful evaluation of an event function. Every time the [world] is changed by an event, a landmark is left on the [world] and it is thus possible to identify the [world] ``as of'' the evaluation of a given event. An event may introduce new logical names. Some events introduce no new names (e.g., [verify-guards]), some introduce exactly one (e.g., [defmacro] and [defthm]), and some may introduce many (e.g., [encapsulate] ). ACL2 typically completes processing of an event by printing a summary. Unless proofs are skipped (see [ld-skip-proofsp]) or summary output is inhibited (see [set-inhibit-output-lst]), information about the proof attempt (if any) is printed that includes a list of rules used, a summary of warnings, and the number of ``prover steps'' (if any; see [with-prover-step-limit]). A breakdown of the time used is also printed, which by default is runtime (cpu time), but can be changed to realtime (wall clock time); see [get-internal-time]. See [embedded-event-form] for a discussion of events permitted in [books]. Subtopics [Add-custom-keyword-hint] Add a new custom keyword hint [Assert-event] Assert that a given form returns a non-nil value [Comp] Compile some ACL2 functions [Defabbrev] A convenient form of macro definition for simple expansions [Defabsstobj] Define a new abstract single-threaded object [Defabsstobj-missing-events] Obtain the [events] needed to admit a [defabsstobj] event [Defattach] Execute constrained functions using corresponding attached functions [Defaxiom] Add an axiom [Defchoose] Define a Skolem (witnessing) function [Defcong] Prove [congruence] rule [Defconst] Define a constant [Defdoc] Deprecated event (formerly for adding documentation) [Defequiv] Prove that a function is an [equivalence] relation [Defevaluator] Introduce an evaluator function [Defexec] Attach a terminating executable function to a definition [Define-trusted-clause-processor] Define a trusted (unverified) goal-level simplifier [Deflabel] Build a landmark and/or add a [documentation] topic [Defmacro] Define a macro [Defmacro-last] Define a macro that returns its last argument, but with side effects [Defn] Definition with [guard] t [Defnd] [disable]d definition with [guard] t [Defpkg] Define a new symbol package [Defproxy] Define a non-executable :[program]-mode function for attachment [Defpun] Define a tail-recursive function symbol [Defrec] Introduce a record structure, like a struct in C. [Defrefinement] Prove that equiv1 refines equiv2 [Defstobj] Define a new single-threaded object [Defstub] Stub-out a function symbol [Deftheory] Define a theory (to [enable] or [disable] a set of rules) [Deftheory-static] Define a `static' theory (to [enable] or [disable] a set of rules) [Defthm] Prove and name a theorem [Defthmd] Prove and name a theorem and then disable it [Defttag] Introduce a trust tag (ttag) [Defun] Define a function symbol [Defun-inline] Define a potentially inlined function symbol and associated macro [Defun-notinline] Define a not-to-be-inlined function symbol and associated macro [Defun-nx] Define a non-executable function symbol [Defun-sk] Define a function whose body has an outermost quantifier [Defund] Define a function symbol and then disable it [Defund-inline] Define a potentially disabled, inlined function symbol and associated macro [Defund-notinline] Define a disabled, not-to-be-inlined function symbol and associated macro [Embedded-event-form] Forms that may be embedded in other [events] [Encapsulate] Hide some [events] and/or constrain some functions [Evisc-table] Support for abbreviated output [In-arithmetic-theory] Designate theory for some rewriting done for non-linear arithmetic [In-theory] Designate ``current'' theory (enabling its rules) [Include-book] Load the [events] in a file [Local] Hiding an event in an encapsulation or book [Logical-name] A name created by a logical event [Make-event] Evaluate (expand) a given form and then evaluate the result [Memoize] Turn on memoization for a specified function [Mutual-recursion] Define some mutually recursive functions [Name] Syntactic rules on logical names [Profile] Turn on profiling for one function [Progn] Evaluate some [events] [Progn!] Evaluate some forms, not necessarily [events] [Redundant-events] Allowing a name to be introduced ``twice'' [Regenerate-tau-database] Regenerate the tau database relative to the current enabled theory [Remove-custom-keyword-hint] Remove a custom keyword hint [Set-body] Set the definition body [Skip-proofs] Skip proofs for a given form --- a quick way to introduce unsoundness [Table] User-managed tables [Theory-invariant] User-specified invariants on [theories] [Unmemoize] Turn off memoization for the specified function [Value-triple] Compute a value, optionally checking that it is not nil [Verify-guards] Verify the [guard]s of a function [Verify-guards+] Verify the [guard]s of a function [Verify-termination] Convert a function from :program mode to :logic mode") (EVISC-TABLE (EVENTS) "Support for abbreviated output The evisc-table is an ACL2 table (see [table]) whose purpose is to modify the print representations of specified non-nil objects. When a key (some object) is associated with a string value, then that string is printed instead of that key (as an abbreviation). For example, the following log shows how to abbreviate the key (a b c) with the token . ACL2 !>(table evisc-table '(a b c) \"\") Summary Form: ( TABLE EVISC-TABLE ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) EVISC-TABLE ACL2 !>'(a b c) ACL2 !>'(4 5 a b c) (4 5 . ) ACL2 !> Every value in this [table] must be either a string or nil, where nil eliminates any association of the key with an abbreviation. Continuing with the log above: ACL2 !>(table evisc-table '(a b c) nil) Summary Form: ( TABLE EVISC-TABLE ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) EVISC-TABLE ACL2 !>'(a b c) (A B C) ACL2 !>'(4 5 a b c) (4 5 A B C) ACL2 !> It can be particularly helpful to use this table to abbreviate a constant introduced by [defconst] by prefixing the constant name with \"#,\", as we now describe. Consider first the following example. (defconst *abc* '(1 2 3 4 5 6 7 8)) (table evisc-table *abc* (concatenate 'string \"#,\" (symbol-name '*abc*))) Then the constant *abc* is printed as follows --- very helpful if its associated structure is significantly larger than the 8-element list of numbers shown above! ACL2 !>*abc* #,*ABC* ACL2 !> What's more, the ACL2 reader will replace #,*C*, where *C* is defined by [defconst], by its value, regardless of evisc-table; see [sharp-dot-reader]. Continuing with the example above, we have: ACL2 !>(cdr (quote #,*ABC*)) (2 3 4 5 6 7 8) ACL2 !> Of course, more care needs to be taken if packages are involved (see [defpkg]), as we now illustrate. ACL2 !>(defpkg \"FOO\" nil) Summary Form: ( DEFPKG \"FOO\" ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) \"FOO\" ACL2 !>(defconst foo::*a* '(1 2 3)) Summary Form: ( DEFCONST FOO::*A* ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FOO::*A* ACL2 !>(table evisc-table foo::*a* \"#,foo::*a*\") Summary Form: ( TABLE EVISC-TABLE ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) EVISC-TABLE ACL2 !>foo::*a* #,foo::*a* ACL2 !>'#,foo::*a* #,foo::*a* ACL2 !>(cdr '#,foo::*a*) (2 3) ACL2 !> We conclude by an example showing some extra care that may be important to consider taking. We start with: (defconst |*BaR*| '(3 4)) Then the following works just fine; but try it without the extra code for the may-need-slashes case and you'll see that the sharp-dot printing is missing. First: (table evisc-table |*BaR*| (let ((x (symbol-name '|*BaR*|))) (if (may-need-slashes x) (concatenate 'string \"#.|\" x \"|\") (concatenate 'string \"#.\" x)))) Then: ACL2 !>|*BaR*| #,|*BaR*| ACL2 !>") (EVISC-TUPLE (IO) "Control suppression of details when printing ACL2 output is generally printed in full. However, ACL2 can be directed to abbreviate, or ``eviscerate'', objects before printing them. To ``eviscerate'' an object we replace certain substructures within it by strings that are printed in their stead. Such replacement is made relative to a so-called ``evisc-tuple'', which has four components: (evisc-tuple print-level print-length alist hiding-cars) is the same as the value of (list alist print-level print-length hiding-cars), and the components are used as follows (with priority order as discussed below). The alist component is used to replace any substructure occurring as a key by the corresponding string. The print-level and print-length are analogous to Common Lisp variables *print-level* and *print-length*, respectively, and cause replacement of substructures deeper than print-level by `#' and those longer than print-length by `...'. Finally, any [consp] x that starts with one of the symbols in hiding-cars is printed as . The following example illustrates the use of an evisc-tuple that limits the print-level to 3 --- only three descents into list structures are permitted before replacing a subexpression by `#' --- and limits the print-length to 4 --- only the first four elements of any list structure will be printed before replacing its tail by `...'. ACL2 !>(fms \"~x0~%\" (list (cons #\\0 '((a b ((c d)) e f g) u v w x y))) *standard-co* state (evisc-tuple 3 4 nil nil)) ((A B (#) E ...) U V W ...) ACL2 !> Notice that it is impossible to read the printed value back into ACL2, since there is no way for the ACL2 reader to interpret `#' or `...'. To solve this problem, see [set-iprint]. In the above example we pass an evisc-tuple explicitly to a printing function, in this case, [fms] (see [fmt]). But ACL2 also does its own printing, for example during a proof attempt. There are global evisc-tuples that control ACL2's printing; see [set-evisc-tuple] and see [without-evisc].") (EVISCERATE-HIDE-TERMS (IO) "To print (hide ...) as Example: (assign eviscerate-hide-terms t) (assign eviscerate-hide-terms nil) Eviscerate-hide-terms is a [state] global variable whose value is either t or nil. The variable affects how terms are displayed by default (but not if you have set the term-evisc-tuple to other than its default; see [set-evisc-tuple]). If t, terms of the form (hide ...) are printed as . Otherwise, they are printed normally.") (EXAMPLE-INDUCTION-SCHEME-BINARY-TREES (INTRODUCTION-TO-THE-THEOREM-PROVER) "Induction on binary trees See [logic-knowledge-taken-for-granted-inductive-proof] for an explanation of what we mean by the induction suggested by a recursive function or a term. Classical Induction on Binary Trees: To prove (p x), for all x, by classical induction on binary tree structures, prove each of the following: Base Case: (implies (atom x) (p x)) Induction Step: (implies (and (not (atom x)) (p (car x)) (p (cdr x))) (p x)) An argument analogous to that given in [example-induction-scheme-on-lists] should convince you that (p x) holds for every object. A function that suggests this induction is: (defun flatten (x) (if (atom x) (list x) (app (flatten (car x)) (flatten (cdr x))))).") (EXAMPLE-INDUCTION-SCHEME-DOWN-BY-2 (INTRODUCTION-TO-THE-THEOREM-PROVER) "Induction downwards 2 steps at a time See [logic-knowledge-taken-for-granted-inductive-proof] for an explanation of what we mean by the induction suggested by a recursive function or a term. Classical Induction on Natural Numbers Preserving Parity: Here is another way to decompose natural numbers. To prove (p n), for all n, prove each of the following: Base Case 1: (implies (zp n) (p n)) Base Case 2: (implies (equal n 1) (p n)) Induction Step: (implies (and (not (zp n)) (not (equal n 1)) (p (- n 2))) (p n)) Base Case 1 establishes that p holds for 0 (and all objects other than positive naturals). Base Case 2 establishes that p holds for 1. The Induction Step establishes that if n is a natural number greater than 1, and if p holds for n-2, then p holds for n. Note that we have thus proved that (p n) holds, for all n. For example, (p -7), (p 'abc), and (p 0) are all established by Base Case 1. (p 1) is established by Base Case 2. (p 2) is established from (p 0) and the Induction Step. Think about it! (p 3) is established form (p 1) and the Induction Step, etc. A function that suggests this induction is: (defun parity (n) (if (zp n) 'even (if (equal n 1) 'odd (parity (- n 2))))).") (EXAMPLE-INDUCTION-SCHEME-NAT-RECURSION (INTRODUCTION-TO-THE-THEOREM-PROVER) "Induction on natural numbers See [logic-knowledge-taken-for-granted-inductive-proof] for an explanation of what we mean by the induction suggested by a recursive function or a term. Classical Induction on Natural Numbers: Induction is familiar in the arithmetic setting. To prove (p n), for all n, by classical induction on the construction of the natural numbers, prove each of the following: Base Case: (implies (zp n) (p n)) Induction Step: (implies (and (not (zp n)) (p (- n 1))) (p n)) The Base Case establishes that p holds for 0. In fact, because of the definition of [zp] [{ICON}], it establishes that (p n) holds when n is 0 and it holds when n is not a natural number. The Induction Step establishes that if n is a natural number other than 0, and if p holds for n-1, then p holds for n. The hypothesis (p (- n 1)) above is called the induction hypothesis. A function that suggests this induction is (defun nat-recursion (n) (if (zp n) n (nat-recursion (- n 1)))) Similarly, the term (fact n) suggests this induction if fact is defined: (defun fact (k) (if (zp k) 1 (* k (fact (- k 1))))). even though the formal parameter of this definition of fact is k, not n.") (EXAMPLE-INDUCTION-SCHEME-ON-LISTS (INTRODUCTION-TO-THE-THEOREM-PROVER) "Induction on lists See [logic-knowledge-taken-for-granted-inductive-proof] for an explanation of what we mean by the induction suggested by a recursive function or a term. Classical Induction on Lists: To prove (p x), for all x, by classical induction on the linear list structure, prove each of the following: Base Case: (implies (endp x) (p x)) Induction Step: (implies (and (not (endp x)) (p (cdr x))) (p x)) An argument analogous to that given for natural numbers, [example-induction-scheme-nat-recursion], establishes (p x) for every x. For example, (p -7), (p 'abc), and (p nil) are all established by the Base Case. (p '(Friday)) follows from (p nil), given the Induction Step. That sentence bears thinking about! Think about it! Similarly, (p '(Yellow)) holds for the same reason. (p '(Thursday Friday)) follows from (p '(Friday)) and the Induction Step, etc. A function that suggests this induction is (defun app (x y) (if (endp x) y (cons (car x) (app (cdr x) y)))).") (EXAMPLE-INDUCTION-SCHEME-ON-SEVERAL-VARIABLES (INTRODUCTION-TO-THE-THEOREM-PROVER) "Induction on several variables See [logic-knowledge-taken-for-granted-inductive-proof] for an explanation of what we mean by the induction suggested by a recursive function or a term. Induction on Several Variables To (p n x) for all n and all x, prove each of the following: Base Case 1: (implies (endp x) (p n x)) Base Case 2: (implies (and (not (endp x)) (zp n)) (p n x)) Induction Step: (implies (and (not (endp x)) (not (zp n)) (p (- n 1) (cdr x))) (p n x)) A function that suggests this induction is (defun nth (n x) (if (endp x) nil (if (zp n) (car x) (nth (- n 1) (cdr x))))).") (EXAMPLE-INDUCTION-SCHEME-UPWARDS (INTRODUCTION-TO-THE-THEOREM-PROVER) "Induction upwards See [logic-knowledge-taken-for-granted-inductive-proof] for an explanation of what we mean by the induction suggested by a recursive function or a term. Induction Upwards: To (p i max) for all i and all max, prove each of the following: Base Case: (implies (not (and (natp i) (natp max) (< i max))) (p i max)) Induction Step: (implies (and (natp i) (natp max) (< i max) (p (+ i 1) max)) (p i max)) Note that the induction hypothesis is about an i that is bigger than the i in in the conclusion. In induction, as in recursion, the sense of one thing being ``smaller'' than another is determined by an arbitrary measure of all the variables, not the magnitude or extent of some particular variable. A function that suggests this induction is shown below. ACL2 has to be told the measure, namely the difference between max and i (coerced to a natural number to insure that the measure is an ordinal). (defun count-up (i max) (declare (xargs :measure (nfix (- max i)))) (if (and (natp i) (natp max) (< i max)) (cons i (count-up (+ 1 i) max)) nil)).") (EXAMPLE-INDUCTION-SCHEME-WITH-ACCUMULATORS (INTRODUCTION-TO-THE-THEOREM-PROVER) "Induction scheme with accumulators See [logic-knowledge-taken-for-granted-inductive-proof] for an explanation of what we mean by the induction suggested by a recursive function or a term. To prove (p x a) for all x and all a, prove each of the following: Base Case: (implies (endp x) (p x a)) Induction Step: (implies (and (not (endp x)) (p (cdr x) (cons (car x) a))) (p x a)) Note that in the induction hypothesis we assume p for a smaller x but a larger a. In fact, we could include as many induction hypotheses as we want and use any terms we want in the a position as long as the x position is occupied by a smaller term. A function that suggests this particular induction is shown below. (defun rev1 (x a) (if (endp x) a (rev1 (cdr x) (cons (car x) a)))). A function that suggests a similar induction in which three induction hypotheses are provided, one in which the a position is occupied by (cons (car x) a), another in which the a position is occupied by some arbitrary term b, and a third in which the a position is occupied by a, is suggested by the term (rev1-modified x a b) where (defun rev1-modified (x a b) (if (endp x) (list x a b) (list (rev1-modified (cdr x) (cons (car x) a) b) (rev1-modified (cdr x) b b) (rev1-modified (cdr x) a b)))) Remember that the value of this term or function is irrelevant to the induction suggested. Because ACL2's definitional principle insists that all the formal parameters play a role in the computation (at least syntactically), it is common practice when defining functions for their induction schemes to return the list of all the formals (to insure all variables are involved) and to combine recursive calls on a given branch with list (to avoid introducing additional case analysis as would happen if and or or or other propositional functions are used). If you tried to prove (p x a) and suggested the induct hint (rev1-modified x a (fact k)), as by (thm (p x a) :hints ((\"Goal\" :induct (rev1-modified x a (fact k))))) the inductive argument would be: Base Case: (implies (endp x) (p x a)) Inductive Step: (implies (and (not (endp x)) (p (cdr x) (cons (car x) a)) (p (cdr x) (fact k)) (p (cdr x) a)) (p x a))") (EXAMPLE-INDUCTION-SCHEME-WITH-MULTIPLE-INDUCTION-STEPS (INTRODUCTION-TO-THE-THEOREM-PROVER) "Induction scheme with more than one induction step See [logic-knowledge-taken-for-granted-inductive-proof] for an explanation of what we mean by the induction suggested by a recursive function or a term. Several Induction Steps: To (p x i a) for all x, i, and a, prove each of the following: Base Case 1: (implies (zp i) (p x i a)) Induction Step 1: (implies (and (not (zp i)) (equal (parity i) 'even) (p (* x x) (floor i 2) a)) (p x i a)) Induction Step 2: (implies (and (not (zp i)) (not (equal (parity i) 'even)) (p x (- i 1) (* x a))) (p x i a)) A function that suggests this induction is the binary exponentiation function for natural numbers. (defun bexpt (x i a) (cond ((zp i) a) ((equal (parity i) 'even) (bexpt (* x x) (floor i 2) a)) (t (bexpt x (- i 1) (* x a) )))). In order to admit this function it is necessary to know that (floor i 2) is smaller than i in the case above. This can be proved if the community book \"arithmetic-5/top\" has been included from the ACL2 system directory, i.e., (include-book \"arithmetic-5/top\" :dir :system) should be executed before defining bexpt.") (EXAMPLE-INDUCTIONS (INTRODUCTION-TO-THE-THEOREM-PROVER) "Some examples of induction schemes in ACL2 Here are some pages illustrating various induction schemes suggested by recursive functions. Classical Induction on Natural Numbers: see [example-induction-scheme-nat-recursion]. Induction Preserving Even/Odd Parity or Induction Downwards by 2 or Induction with Multiple Base Cases: see [example-induction-scheme-down-by-2] for an induction in which the induction hypothesis decreases the induction variable by an amount other than 1. This illustrates that the induction hypothesis can be about whatever term or terms are needed to explain how the formula recurs. The example also illustrates an induction with more than one Base Case. Classical Induction on Lists: see [example-induction-scheme-on-lists] for an induction over linear lists, in which we inductively assume the conjecture for (cdr x) and prove it for x. It doesn't matter whether the list is nil-terminated or not; the Base Case addresses all the possibilities. Classical Induction on Binary (Cons) Trees: see [example-induction-scheme-binary-trees] for an induction over the simplest form of binary tree. Here the Induction Step provides two hypotheses, one about the left subtree and one about the right subtree. Induction on Several Variables: see [example-induction-scheme-on-several-variables] for an induction in which several variables participate in the case analysis and induction hypotheses. Induction Upwards: see [example-induction-scheme-upwards] for an induction scheme in which the induction hypothesis is about something ``bigger than'' the induction conclusion. This illustrates that the sense in which the hypothesis is about something ``smaller'' than the conclusion is determined by a measure of all the variables, not the magnitude or extent of some single variable. Induction with Auxiliary Variables or Induction with Accumulators: see [example-induction-scheme-with-accumulators] for an induction scheme in which one variable ``gets smaller'' but another is completely arbitrary. Such schemes are common when dealing with tail-recursive functions that accumulate partial results in auxiliary variables. This example also shows how to provide several arbitrary terms in a non-inductive variable of a scheme. Induction with Multiple Induction Steps: see [example-induction-scheme-with-multiple-induction-steps] for an induction in which we make different inductive hypotheses depending on which case we're in. This example also illustrates the handling of auxiliary variables or accumulators.") (EXECUTABLE-COUNTERPART (RULE-CLASSES) "A rule for computing the value of a function Examples: (:executable-counterpart length) which may be abbreviated in [theories] as (length) Every [defun] introduces at least two rules used by the theorem prover. Suppose fn is the name of a [defun]'d function. Then (:definition fn) is the rune (see [rune]) naming the rule that allows the simplifier to replace calls of fn by its instantiated body. (:executable-counterpart fn) is the [rune] for the rule for how to evaluate the function on known constants. When typing [theories] it is convenient to know that (fn) is a runic designator that denotes (:executable-counterpart fn). See [theories]. If (:executable-counterpart fn) is [enable]d, then when applications of fn to known constants are seen by the simplifier they are computed out by executing the Common Lisp code for fn (with the appropriate handling of [guard]s). Suppose fact is defined as the factorial function. If the executable counterpart [rune] of fact, (:executable-counterpart fact), is [enable]d when the simplifier encounters (fact 12), then that term will be ``immediately'' expanded to 479001600. Note that even if subroutines of fn have disabled executable counterparts, fn will call their Lisp code nonetheless: once an executable counterpart function is applied, no subsidiary enable checks are made. Such one-step expansions are sometimes counterproductive because they prevent the anticipated application of certain lemmas about the subroutines of the expanded function. Such computed expansions can be prevented by disabling the executable counterpart [rune] of the relevant function. For example, if (:executable-counterpart fact) is [disable]d, (fact 12) will not be expanded by computation. In this situation, (fact 12) may be rewritten to (* 12 (fact 11)), using the rule named (:definition fact), provided the system's heuristics permit the introduction of the term (fact 11). Note that lemmas about multiplication may then be applicable (while such lemmas would be inapplicable to 479001600). In many proofs it is desirable to [disable] the executable counterpart [rune]s of certain functions to prevent their expansion by computation. See [executable-counterpart-theory]. Finally: What do we do about functions that are ``constrained'' rather than defined, such as the following? (See [encapsulate].) (encapsulate (((foo *) => *)) (local (defun foo (x) x))) Does foo have an executable counterpart? Yes: since the vast majority of functions have sensible executable counterparts, it was decided that all functions, even such ``constrained'' ones, have executable counterparts. We essentially ``trap'' when such calls are inappropriate. Thus, consider for example: (defun bar (x) (if (rationalp x) (+ x 1) (foo x))) If the term (bar '3) is encountered by the ACL2 rewriter during a proof, and if the :executable-counterpart of bar is [enable]d, then it will be invoked to reduce this term to '4. However, if the term (bar 'a) is encountered during a proof, then since 'a is not a [rationalp] and since the :executable-counterpart of foo is only a ``trap,'' then this call of the :executable-counterpart of bar will result in a ``trap.'' In that case, the rewriter will return the term (hide (bar 'a)) so that it never has to go through this process again. See [hide].") (EXECUTABLE-COUNTERPART-THEORY (THEORIES THEORY-FUNCTIONS) "Executable counterpart rules as of logical name Examples: (executable-counterpart-theory :here) (executable-counterpart-theory 'lemma3) See [logical-name]. General Form: (executable-counterpart-theory logical-name) Returns the theory containing all the :[executable-counterpart] [rune]s, whether [enable]d or not, that existed immediately after [logical-name] was introduced. See the documentation for [theories], [logical-name], [executable-counterpart] and [function-theory]. You may experience a fencepost problem in deciding which logical name to use. [Deflabel] can always be used to mark unambiguously for future reference a particular point in the development of your theory. The order of [events] in the vicinity of an [encapsulate] is confusing. See [encapsulate]. This ``function'' is actually a macro that expands to a term mentioning the single free variable [world]. When theory expressions are evaluated by [in-theory] or the :[in-theory] hint, [world] is bound to the current ACL2 [world].") (EXISTS (DEFUN-SK) "Existential quantifier The symbol exists (in the ACL2 package) represents existential quantification in the context of a [defun-sk] form. See [defun-sk] and see [forall]. See [quantifiers] for an example illustrating how the use of recursion, rather than explicit quantification with [defun-sk], may be preferable.") (EXIT (GOOD-BYE) "Quit entirely out of Lisp Same as [good-bye].") (EXIT-BOOT-STRAP-MODE (HISTORY) "The end of pre-history Exit-boot-strap-mode is the last step in creating the ACL2 [world] in which the user lives. It has [command] number 0. [Command]s before it are part of the system initialization and extend all the way back to :[min]. [Command]s after it are those of the user. Exit-boot-strap-mode is a Common Lisp function but not an ACL2 function. It is called when every [defconst], [defun], etc., in our source code has been processed under ACL2 and the [world] is all but complete. exit-boot-strap-mode has only one job: to signal the completion of the boot-strapping.") (EXPAND (POINTERS) "See [hints] for keyword :expand.") (EXPLODE-ATOM (CHARACTERS ACL2-BUILT-INS) "Convert any [atom] into a [character-listp] that contains its printed representation, rendering numbers in your choice of print base. (explode-atom x print-base) prints the atom x as a list of characters, using some [print-base-p] to decide what base to print numbers in. Examples: (explode-atom 15 10) --> (#\\1 #\\5) ; 15 in decimal (explode-atom 15 16) --> (#\\F) ; 15 in hex (explode-atom \"foo\" 10) --> (#\\f #\\o #\\o) (explode-atom 'acl2::foo 10) --> (#\\F #\\O #\\O) ; note: no package See also [explode-nonnegative-integer], [str::numbers], and [printing-to-strings]. Function: (defun explode-atom (x print-base) (declare (xargs :guard (and (or (acl2-numberp x) (characterp x) (stringp x) (symbolp x)) (print-base-p print-base)))) (cond ((rationalp x) (cond ((integerp x) (cond ((< x 0) (cons #\\- (explode-nonnegative-integer (- x) print-base nil))) (t (explode-nonnegative-integer x print-base nil)))) (t (append (explode-atom (numerator x) print-base) (cons #\\/ (explode-nonnegative-integer (denominator x) print-base nil)))))) ((complex-rationalp x) (list* #\\# #\\C #\\( (append (explode-atom (realpart x) print-base) (cons #\\Space (append (explode-atom (imagpart x) print-base) '(#\\))))))) ((characterp x) (list x)) ((stringp x) (coerce x 'list)) (t (coerce (symbol-name x) 'list))))") (EXPLODE-NONNEGATIVE-INTEGER (CHARACTERS NUMBERS ACL2-BUILT-INS) "The list of [characters] in the radix-r form of a number Examples: ACL2 !>(explode-nonnegative-integer 925 10 nil) (#9 #2 #5) ACL2 !>(explode-nonnegative-integer 325 16 nil) (#3 #9 #D) For a non-negative integer n, (explode-nonnegative-integer n r nil) is the list of [characters] in the radix-r (base-r) representation of n. The [guard] for explode-nonnegative-integer requires the first argument to be a nonnegative integer and second argument to be a valid radix for ACL2 (2, 8, 10, or 16). See also [explode-atom], [str::numbers], and [printing-to-strings]. Function: (defun explode-nonnegative-integer (n print-base ans) (declare (xargs :guard (and (integerp n) (>= n 0) (print-base-p print-base)))) (cond ((or (zp n) (not (print-base-p print-base))) (cond ((null ans) '(#\\0)) (t ans))) (t (explode-nonnegative-integer (floor n print-base) print-base (cons (digit-to-char (mod n print-base)) ans)))))") (EXPT (NUMBERS ACL2-BUILT-INS) "Exponential function (Expt r i) is the result of raising the number r to the integer power i. The [guard] for (expt r i) is that r is a number and i is an integer, and furthermore, if r is 0 then i is nonnegative. When the type requirements of the [guard] aren't met, (expt r i) first coerces r to a number and i to an integer. Expt is a Common Lisp function. See any Common Lisp documentation for more information. Note that r can be a complex number; this is consistent with Common lisp. Function: (defun expt (r i) (declare (xargs :guard (and (acl2-numberp r) (integerp i) (not (and (eql r 0) (< i 0)))))) (cond ((zip i) 1) ((= (fix r) 0) 0) ((> i 0) (* r (expt r (+ i -1)))) (t (* (/ r) (expt r (+ i 1))))))") (EXTENDED-METAFUNCTIONS (META) "State and context sensitive metafunctions General Form of an Extended :Meta theorem: (implies (and (pseudo-termp x) ; this hyp is optional (alistp a) ; this hyp is optional (ev (hyp-fn x mfc state) a) ; this hyp is optional ; meta-extract hyps may also be included (see below) ) (equiv (ev x a) (ev (fn x mfc state) a))) where the restrictions are as described in the [documentation] for [meta] where state is literally the symbol STATE, and x, a, mfc, and state are distinct variable symbols. A :meta theorem of the above form installs fn as a metatheoretic simplifier with hypothesis function hyp-fn, exactly as for vanilla metafunctions. The only difference is that when the metafunctions are applied, some contextual information is passed in via the mfc argument and the ACL2 [state] is made available. See [meta] for a discussion of vanilla flavored metafunctions. This documentation assumes you are familiar with the simpler situation, in particular, how to define a vanilla flavored metafunction, fn, and its associated hypothesis metafunction, hyp-fn, and how to state and prove metatheorems installing such functions. Defining extended metafunctions requires that you also be familiar with many ACL2 implementation details. This documentation is sketchy on these details; see the ACL2 source code or email the [ACL2-help] list if you need more help. Additional hypotheses are supported, called ``meta-extract hypotheses'', that allow metafunctions to depend on the validity of certain terms extracted from the context or the logical [world]. These hypotheses provide an even more advanced form of metatheorem so we explain them elsewhere; see [meta-extract]. The metafunction context, mfc, is a list containing many different data structures used by various internal ACL2 functions. We do not document the form of mfc. Your extended metafunction should just take mfc as its second formal and pass it into the functions mentioned below. The ACL2 state is well-documented (see [state]). Below we present expressions below that can be useful in defining extended metafunctions. Some of these expressions involve keyword arguments, :forcep and :ttree, which are optional and in most cases are fine to omit, and which we explain after we present the useful expressions. (mfc-clause mfc): returns the current goal, in clausal form. A clause is a list of ACL2 terms, implicitly denoting the disjunction of the listed terms. The clause returned by mfc-clause is the clausal form of the translation (see [trans]) of the goal or subgoal on which the rewriter is working. When a metafunction calls mfc-clause, the term being rewritten by the metafunction either occurs somewhere in this clause or, perhaps more commonly, is being rewritten on behalf of some lemma to which the rewriter has backchained while trying to rewrite a term in the clause. (mfc-ancestors mfc): returns an alist whose keys are the negations of the backchaining hypotheses being pursued. In particular, (null (mfc-ancestors mfc)) will be true exactly when rewriting is on part of the current goal. Exception: An element of this alist whose key is of the form (:binding-hyp hyp unify-subst) indicates that hyp has been encountered as a hypothesis of the form (equal var term) or (equiv var (double-rewrite-term)), in each case binding variable var to the result of rewriting term under unify-subst. (mfc-rdepth mfc): returns the remaining stack depth for calls of the rewriter (by default, *default-rewrite-stack-limit* at the top level; see [rewrite-stack-limit]). When this is 0, no further calls of the rewriter can be made without error. (mfc-type-alist mfc): returns the type-alist governing the occurrence of the term, x, being rewritten by the metafunction. A type-alist is an association list, each element of which is of the form (term ts . ttree). Such an element means that the term term has the [type-set] ts; see [type-alist]. The ttree component is probably irrelevant here. All the terms in the type-alist are in translated form (see [trans]). The ts are numbers denoting finite Boolean combinations of ACL2's primitive types (see [type-set]). The type-alist includes not only information gleaned from the conditions governing the term being rewritten but also that gleaned from forward chaining from the (negations of the) other literals in the clause returned by mfc-clause. (mfc-unify-subst mfc): returns nil except when evaluating a [syntaxp] or [bind-free] hypothesis, in which case, returns the unifying substitution present at the start of that evaluation. (mfc-world mfc): returns the ACL2 logical [world]. (mfc-ts term mfc state :forcep forcep :ttreep ttreep): returns the type-set of term in the current context; see [type-set]. (mfc-rw term obj equiv-info mfc state): returns the result of rewriting term in the current context, mfc, with objective obj and the equivalence relation described by equiv-info. Obj should be t, nil, or ?, and describes your objective: try to show that term is true, false, or anything. Equiv-info is either nil, t, a function symbol fn naming a known equivalence relation, or a list of congruence rules. Nil means return a term that is equal to term. T means return a term that is propositionally equivalent (i.e., in the iff sense) to term, while fn means return a term fn-equivalent to term. The final case, which is intended only for advanced users, allows the specification of generated equivalence relations, as supplied to the geneqv argument of rewrite. Generally, if you wish to establish that term is true in the current context, use the idiom (equal (mfc-rw term t t mfc state) *t*) The constant *t* is set to the internal form of the constant term t, i.e., 't. (mfc-rw+ term alist obj equiv-info mfc state): if alist is nil then this is equivalent to (mfc-rw term obj equiv-info mfc state). However, the former takes an argument, alist, that binds variables to terms, and returns the result of rewriting term under that alist, where this rewriting is as described for mfc-rw above. The function mfc-rw+ can be more efficient than mfc-rw, because the terms in the binding alist have generally already been rewritten, and it can be inefficient to rewrite them again. For example, consider a rewrite rule of the following form. (implies (and ... (syntaxp (... (mfc-rw `(bar ,x) ...) ...)) ...) (equal (... x ...) ...)) Here, x is bound in the conclusion to the result of rewriting some term, say, tm. Then the above call of mfc-rw will rewrite tm, which is probably unnecessary. So a preferable form of the rule above may be as follows, so that tm is not further rewritten by mfc-rw+. (implies (and ... (syntaxp (... (mfc-rw+ '(bar v) `((v . ,x)) ...) ...)) ...) (equal (... x ...) ...)) However, you may find that the additional rewriting done by mfc-rw is useful in some cases. (mfc-ap term mfc state): returns t or nil according to whether linear arithmetic can determine that term is false. To the cognoscenti: returns the contradiction flag produced by linearizing term and adding it to the linear-pot-lst. (mfc-relieve-hyp hyp alist rune target bkptr mfc state): returns t or nil according to whether the indicated hypothesis term, hyp, can be relieved (proved) under the giving variable bindings, alist. Note that this function returns nil if hyp has free variables (see [free-variables]). Here, hyp is the hypothesis of the indicated [rune] at (one-based) position bkptr, and target is an instantiated term to which rune is being applied. Note that no indication is returned for whether any assumptions have been generated by [force] or [case-split]. (If you need such a feature, feel free to request it of the ACL2 implementors.) We explain the :forcep and :ttreep keyword arguments provided in some expressions, as promised above. Their defaults are :same and nil, respectively. A value of :same for :forcep means that forcing will be allowed if and only if it is allowed in the current rewriting environment; see [force]. A value of t or nil for :forcep overrides this default and allows or disallows forcing, respectively. By default these functions return a single value, val, but if :ttreep is t then they return (mv val ttree), where ttree is the tag-tree (see [ttree]) returned by the indicated operation, with an input tag-tree of nil). During the execution of a metafunction by the theorem prover, the expressions above compute the results specified. Typically, you should imagine that there are no axioms about the mfc- function symbols: treat them as uninterpreted function symbols. There is an advanced feature, meta-extract hypotheses, that can avoid this logical weakness in some cases when proving :[meta] rules; see [meta-extract]. But we assume for the rest of the present [documentation] topic that you do not use meta-extract hypotheses. Thus, in the proof of the correctness of a metafunction, no information is available about the results of these functions: you should use these functions for heuristic purposes only. For example, your metafunction may use these functions to decide whether to perform a given transformation, but the transformation must be sound regardless of the value that your metafunction returns. We illustrate this below. It is sometimes possible to use the hypothesis metafunction, hyp-fn, to generate a sufficient hypothesis to justify the transformation. The generated hypothesis might have already been ``proved'' internally by your use of mfc-ts or mfc-rw, but the system will have to prove it ``officially'' by relieving it. We illustrate this below also. We conclude with a script that defines, verifies, and uses several extended metafunctions. This script is based on one provided by Robert Krug, who was instrumental in the development of this style of metafunction and whose help we gratefully acknowledge. ; Here is an example. I will define (foo i j) simply to be (+ i j). ; But I will keep its definition disabled so the theorem prover ; doesn't know that. Then I will define an extended metafunction ; that reduces (foo i (- i)) to 0 provided i has integer type and the ; expression (< 10 i) occurs as a hypothesis in the clause. ; Note that (foo i (- i)) is 0 in any case. (defun foo (i j) (+ i j)) (defevaluator eva eva-lst ((foo i j) (unary-- i) ; I won't need these two cases until the last example below, but I ; include them now. (if x y z) (integerp x))) (set-state-ok t) (defun metafn (x mfc state) (cond ((and (consp x) (equal (car x) 'foo) (equal (caddr x) (list 'unary-- (cadr x)))) ; So x is of the form (foo i (- i)). Now I want to check some other ; conditions. (cond ((and (ts-subsetp (mfc-ts (cadr x) mfc state) *ts-integer*) (member-equal `(NOT (< '10 ,(cadr x))) (mfc-clause mfc))) (quote (quote 0))) (t x))) (t x))) (defthm metafn-correct (equal (eva x a) (eva (metafn x mfc state) a)) :rule-classes ((:meta :trigger-fns (foo)))) (in-theory (disable foo)) ; The following will fail because the metafunction won't fire. ; We don't know enough about i. (thm (equal (foo i (- i)) 0)) ; Same here. (thm (implies (and (integerp i) (< 0 i)) (equal (foo i (- i)) 0))) ; But this will work. (thm (implies (and (integerp i) (< 10 i)) (equal (foo i (- i)) 0))) ; This won't, because the metafunction looks for (< 10 i) literally, ; not just something that implies it. (thm (implies (and (integerp i) (< 11 i)) (equal (foo i (- i)) 0))) ; Now I will undo the defun of metafn and repeat the exercise, but ; this time check the weaker condition that (< 10 i) is provable ; (by rewriting it) rather than explicitly present. (ubt 'metafn) (defun metafn (x mfc state) (cond ((and (consp x) (equal (car x) 'foo) (equal (caddr x) (list 'unary-- (cadr x)))) (cond ((and (ts-subsetp (mfc-ts (cadr x) mfc state) *ts-integer*) (equal (mfc-rw `(< '10 ,(cadr x)) t t mfc state) *t*)) ; The mfc-rw above rewrites (< 10 i) with objective t and iffp t. The ; objective means the theorem prover will try to establish it. The ; iffp means the theorem prover can rewrite maintaining propositional ; equivalence instead of strict equality. (quote (quote 0))) (t x))) (t x))) (defthm metafn-correct (equal (eva x a) (eva (metafn x mfc state) a)) :rule-classes ((:meta :trigger-fns (foo)))) (in-theory (disable foo)) ; Now it will prove both: (thm (implies (and (integerp i) (< 10 i)) (equal (foo i (- i)) 0))) (thm (implies (and (integerp i) (< 11 i)) (equal (foo i (- i)) 0))) ; Now I undo the defun of metafn and change the problem entirely. ; This time I will rewrite (integerp (foo i j)) to t. Note that ; this is true if i and j are integers. I can check this ; internally, but have to generate a hyp-fn to make it official. (ubt 'metafn) (defun metafn (x mfc state) (cond ((and (consp x) (equal (car x) 'integerp) (consp (cadr x)) (equal (car (cadr x)) 'foo)) ; So x is (integerp (foo i j)). Now check that i and j are ; ``probably'' integers. (cond ((and (ts-subsetp (mfc-ts (cadr (cadr x)) mfc state) *ts-integer*) (ts-subsetp (mfc-ts (caddr (cadr x)) mfc state) *ts-integer*)) *t*) (t x))) (t x))) ; To justify this transformation, I generate the appropriate hyps. (defun hyp-fn (x mfc state) (declare (ignore mfc state)) ; The hyp-fn is run only if the metafn produces an answer different ; from its input. Thus, we know at execution time that x is of the ; form (integerp (foo i j)) and we know that metafn rewrote ; (integerp i) and (integerp j) both to t. So we just produce their ; conjunction. Note that we must produce a translated term; we ; cannot use the macro AND and must quote constants! Sometimes you ; must do tests in the hyp-fn to figure out which case the metafn ; produced, but not in this example. `(if (integerp ,(cadr (cadr x))) (integerp ,(caddr (cadr x))) 'nil)) (defthm metafn-correct (implies (eva (hyp-fn x mfc state) a) (equal (eva x a) (eva (metafn x mfc state) a))) :rule-classes ((:meta :trigger-fns (integerp)))) (in-theory (disable foo)) ; This will not be proved. (thm (implies (and (rationalp x) (integerp i)) (integerp (foo i j)))) ; But this will be. (thm (implies (and (rationalp x) (integerp i) (integerp j)) (integerp (foo i j))))") (EXTERNAL-FORMAT (POINTERS) "See [character-encoding].") (EXTRA-INFO (GUARD) "Sources of measure or guard proof obligations (Extra-info x y) always returns t by definition. See [guard-debug] and see [measure-debug] for a discussion of this function, which is useful for debugging failures from attempts to prove measure conjectures or to verify [guard]s.") (F-GET-GLOBAL (PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "Get the value of a global variable in [state] Examples: (+ (f-get-global 'y state) 1) (f-put-global 'a (aset1 'ascii-map-array (f-get-global 'a state) 66 'Upper-case-B) state) General Form: (f-get-global 'symbol state) where symbol is any symbol to which you have [assign]ed a global value. The macro [@] is closely related to f-get-global: (@ var) macroexpands to (f-get-global 'var state). The macro [f-put-global] makes it convenient to set the value of a symbol. The :[ubt] operation has no effect on the global-table of [state]. Thus, you may use these globals to hang onto useful data structures even though you may undo back past where you computed and saved them.") (F-PUT-GLOBAL (PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "Assign to a global variable in [state] Examples: (f-put-global 'x (expt 2 10) state) (f-put-global 'a (aset1 'ascii-map-array (@ a) 66 'Upper-case-B) state) General Form: (f-put-global (quote symbol) term state) where symbol is any symbol (with certain enforced exclusions to avoid overwriting ACL2 system ``globals'') and term is any ACL2 term that could be evaluated at the top-level. F-put-global evaluates the term, stores the result as the value of the given symbol in the global-table of [state], and returns the new state. (Note: the actual implementation of the storage of this value is much more efficient than this discussion of the logic might suggest.) The macro [assign] is closely related to f-put-global: (assign var val) macroexpands to (f-put-global 'var val state). The macros [@] and [f-get-global] give convenient access to the value of such globals. The :[ubt] operation has no effect on the global-table of [state]. Thus, you may use these globals to hang onto useful data structures even though you may undo back past where you computed and saved them.") (FAILED-FORCING (FORCE DEBUGGING) "How to deal with a proof [failure] in a forcing round See [forcing-round] for a background discussion of the notion of forcing rounds. When a proof fails during a forcing round it means that the ``gist'' of the proof succeeded but some ``technical detail'' failed. The first question you must ask yourself is whether the [force]d goals are indeed theorems. We discuss the possibilities below. If you believe the [force]d goals are theorems, you should follow the usual methodology for ``fixing'' failed ACL2 proofs, e.g., the identification of key lemmas and their timely and proper use as rules. See [failure], see [gag-mode], and see [proof-tree]. The rules designed for the goals of forcing rounds are often just what is needed to prove the [force]d hypothesis at the time it is [force]d. Thus, you may find that when the system has been ``taught'' how to prove the goals of the forcing round no forcing round is needed. This is intended as a feature to help structure the discovery of the necessary rules. If a hint must be provided to prove a goal in a forcing round, the appropriate ``goal specifier'' (the string used to identify the goal to which the hint is to be applied) is just the text printed on the line above the formula, e.g., \"[1]Subgoal *1/3''\". See [goal-spec]. If you solve a forcing problem by giving explicit [hints] for the goals of forcing rounds, you might consider whether you could avoid forcing the assumption in the first place by giving those [hints] in the appropriate places of the main proof. This is one reason that we print out the origins of each [force]d assumption. An argument against this style, however, is that an assumption might be [force]d in hundreds of places in the main goal and proved only once in the forcing round, so that by delaying the proof you actually save time. We now turn to the possibility that some goal in the forcing round is not a theorem. There are two possibilities to consider. The first is that the original theorem has insufficient hypotheses to ensure that all the [force]d hypotheses are in fact always true. The ``fix'' in this case is to amend the original conjecture so that it has adequate hypotheses. A more difficult situation can arise and that is when the conjecture has sufficient hypotheses but they are not present in the forcing round goal. This can be caused by what we call ``premature'' forcing. Because ACL2 rewrites from the inside out, it is possible that it will [force] hypotheses while the context is insufficient to establish them. Consider trying to prove (p x (foo x)). We first rewrite the formula in an empty context, i.e., assuming nothing. Thus, we rewrite (foo x) in an empty context. If rewriting (foo x) [force]s anything, that [force]d assumption will have to be proved in an empty context. This will likely be impossible. On the other hand, suppose we did not attack (foo x) until after we had expanded p. We might find that the value of its second argument, (foo x), is relevant only in some cases and in those cases we might be able to establish the hypotheses [force]d by (foo x). Our premature forcing is thus seen to be a consequence of our ``over eager'' rewriting. Here, just for concreteness, is an example you can try. In this example, (foo x) rewrites to x but has a [force]d hypothesis of (rationalp x). P does a case split on that very hypothesis and uses its second argument only when x is known to be rational. Thus, the hypothesis for the (foo x) rewrite is satisfied. On the false branch of its case split, p simplies to (p1 x) which can be proved under the assumption that x is not rational. (defun p1 (x) (not (rationalp x))) (defun p (x y)(if (rationalp x) (equal x y) (p1 x))) (defun foo (x) x) (defthm foo-rewrite (implies (force (rationalp x)) (equal (foo x) x))) (in-theory (disable foo)) The attempt then to do (thm (p x (foo x))) [force]s the unprovable goal (rationalp x). Since all ``formulas'' are presented to the theorem prover as single terms with no hypotheses (e.g., since [implies] is a function), this problem would occur routinely were it not for the fact that the theorem prover expands certain ``simple'' definitions immediately without doing anything that can cause a hypothesis to be [force]d. See [simple]. This does not solve the problem, since it is possible to hide the propositional structure arbitrarily deeply. For example, one could define p, above, recursively so that the test that x is rational and the subsequent first ``real'' use of y occurred arbitrarily deeply. Therefore, the problem remains: what do you do if an impossible goal is [force]d and yet you know that the original conjecture was adequately protected by hypotheses? One alternative is to disable forcing entirely. See [disable-forcing]. Another is to [disable] the rule that caused the [force]. A third alternative is to prove that the negation of the main goal implies the [force]d hypothesis. For example, (defthm not-p-implies-rationalp (implies (not (p x (foo x))) (rationalp x)) :rule-classes nil) Observe that we make no rules from this formula. Instead, we merely :use it in the subgoal where we must establish (rationalp x). (thm (p x (foo x)) :hints ((\"Goal\" :use not-p-implies-rationalp))) When we said, above, that (p x (foo x)) is first rewritten in an empty context we were misrepresenting the situation slightly. When we rewrite a literal we know what literal we are rewriting and we implicitly assume it false. This assumption is ``dangerous'' in that it can lead us to simplify our goal to nil and give up --- we have even seen people make the mistake of assuming the negation of what they wished to prove and then via a very complicated series of transformations convince themselves that the formula is false. Because of this ``tail biting'' we make very weak use of the negation of our goal. But the use we make of it is sufficient to establish the [force]d hypothesis above. A fourth alternative is to weaken your desired theorem so as to make explicit the required hypotheses, e.g., to prove (defthm rationalp-implies-main (implies (rationalp x) (p x (foo x))) :rule-classes nil) This of course is unsatisfying because it is not what you originally intended. But all is not lost. You can now prove your main theorem from this one, letting the [implies] here provide the necessary case split. (thm (p x (foo x)) :hints ((\"Goal\" :use rationalp-implies-main)))") (FAILURE (DEBUGGING) "How to deal with a proof failure When ACL2 gives up it does not mean that the submitted conjecture is invalid, even if the last formula ACL2 printed in its proof attempt is manifestly false. Since ACL2 sometimes [generalize]s the goal being proved, it is possible it adopted an invalid subgoal as a legitimate (but doomed) strategy for proving a valid goal. Nevertheless, conjectures submitted to ACL2 are often invalid and the proof attempt often leads the careful reader to the realization that a hypothesis has been omitted or that some special case has been forgotten. It is good practice to ask yourself, when you see a proof attempt fail, whether the conjecture submitted is actually a theorem. If you think the conjecture is a theorem, then you must figure out from ACL2's output what you know that ACL2 doesn't about the functions in the conjecture and how to impart that knowledge to ACL2 in the form of rules. The ``key checkpoint'' information printed at the end of the summary provides a fine place to start. See [the-method] for a general discussion of how to prove theorems with ACL2, and see [introduction-to-the-theorem-prover] for a more detailed tutorial. Also see [set-gag-mode] for discussion of key checkpoints and an abbreviated output mode that focuses attention on them. You may find it most useful to start by focusing on key checkpoints that are not under a proof by induction, if any, both because these are more likely to suggest useful lemmas and because they are more likely to be theorems; for example, generalization may have occurred before a proof by induction has begun. If you need more information than is provided by the key checkpoints --- although this should rarely be necessary --- then you can look at the full proof, perhaps with the aid of certain utilities: see [proof-tree], see [set-gag-mode], and see [set-saved-output]. For information on a tool to help debug failures of [encapsulate] and [progn] events, as well as [certify-book] failures, see [redo-flat]. Again, see [the-method] for a general discussion of how to prove theorems with ACL2, and see [introduction-to-the-theorem-prover] for a more detailed tutorial. See also the book ``Computer-Aided Reasoning: An Approach'' (Kaufmann, Manolios, Moore), as well as the discussion of how to read Nqthm proofs and how to use Nqthm rules in ``A Computational Logic Handbook'' by Boyer and Moore (Academic Press, 1988). If the failure occurred during a forcing round, see [failed-forcing].") (FAKE-RUNE (POINTERS) "See [rune].") (FANCY-STRING-READER (READER) "A friendly syntax for strings literals that have backslashes and quotes. Examples: ACL2 !> #{\"\"\"Hello, World!\"\"\"} \"Hello, World!\" ACL2 !> #{\"\"\"\"\"\"} \"\" ACL2 !> #{\"\"\"C:\\ACL2\\axioms.lisp\"\"\"} \"C:\\\\ACL2\\\\axioms.lisp\" String literals in ACL2 and Common Lisp source code files are usually written as text strings within quote marks. For instance, the 5-character string whose contents are Hello is normally written as \"Hello\". Usually this syntax is fine, but things can get tricky when you want to write a string whose contents include \" marks. For example, if you wanted to write down a string whose contents were: then you would need to escape the quote marks within it using backslash characters, e.g., as follows: \"\" But using \\ as a special character means we also need a special way to write backslashes. For instance, if we want to write a string literal whose contents are: C:\\ACL2\\axioms.lisp Then we would need to write something a string literal such as: \"C:\\\\ACL2\\\\axioms.lisp\" In certain cases, such as when writing long [documentation] strings, the extra escaping can be tedious and error-prone. To simplify this, ACL2 provides an alternate #{\"\"\"...\"\"\"} syntax for string literals. This syntax has no special characters, so nothing needs to be escaped. The end of the string is recognized by the unusual character sequence \"\"\"}. Of course, a string that needs to contain the sequence \"\"\"} cannot be represented using this fancy string literal syntax, but in practice that's rarely ever a problem.") (FAST-ALIST-CLEAN (FAST-ALISTS ACL2-BUILT-INS) "(fast-alist-clean alist) can be used to eliminate \"shadowed pairs\" from a fast alist. This [documentation] topic assumes familiarity with fast alists; see [fast-alists]. See [fast-alist-clean!], [fast-alist-fork], and [fast-alist-fork!] for related utilities. Logically, (fast-alist-clean alist) is defined as follows: Function: (defun fast-alist-clean (alist) (declare (xargs :guard t)) (fast-alist-fork alist (if (consp alist) (cdr (last alist)) alist))) The result is thus a corresponding fast alist, with the order reversed and with atoms and shadowed pairs removed, as per the definition above; see [fast-alist-fork] for details. Moreover, if alist is not a fast alist, then (fast-alist-clean alist) is executed in raw Lisp by calling fast-alist-fork as indicated above. However, if alist is a fast alist, then a special definition under the hood provides a different handling of associated hash tables. After running (fast-alist-clean alist) to obtain a result, cleaned-alist, the hash table that had been associated with alist will now be associated with cleaned-alist instead. This saves the expense of creating a new hash table, but there is still the expense of copying the alist, as for [fast-alist-fork]. However, unlike fast-alist-fork, there is no need to free the input alist. Note that the final cdr is preserved, so that the name is preserved for use by [fast-alist-summary] (also see [hons-acons]).") (FAST-ALIST-CLEAN! (FAST-ALISTS ACL2-BUILT-INS) "(fast-alist-clean! alist) is an alternative to [fast-alist-clean] that produces a [normed] result. Logically this function is just fast-alist-clean; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, this is the same as fast-alist-clean except that it uses something like [hons-acons!] instead of [hons-acons]. You generally should not use this function unless you really know what you're doing and understand the drawbacks discussed in [hons-acons!].") (FAST-ALIST-FORK (FAST-ALISTS ACL2-BUILT-INS) "(fast-alist-fork alist ans) can be used to eliminate \"shadowed pairs\" from an alist or to copy [fast-alists]. This [documentation] topic assumes familiarity with fast alists; see [fast-alists]. See [fast-alist-fork!], [fast-alist-clean], and [fast-alist-clean!] for related utilities. Logically, (fast-alist-fork alist ans) is defined as follows: Function: (defun fast-alist-fork (alist ans) (declare (xargs :guard t)) (cond ((atom alist) ans) ((atom (car alist)) (fast-alist-fork (cdr alist) ans)) ((hons-assoc-equal (car (car alist)) ans) (fast-alist-fork (cdr alist) ans)) (t (fast-alist-fork (cdr alist) (cons (car alist) ans))))) The alist argument need not be a fast alist. Typically ans is set to nil or some other atom. In this case, shrinking produces a new, fast alist which is like alist except that (1) any \"malformed,\" atomic entries have been removed, (2) all \"shadowed pairs\" have been removed, and (3) incidentally, the surviving elements have been reversed. This can be useful as a way to clean up any unnecessary bindings in alist, or as a way to obtain a \"deep copy\" of a fast alist that can extended independently from the original while maintaining discipline. Note that fast-alist-fork is potentially expensive, for the following two reasons. * The alist is copied, dropping any shadowed pairs. This process will require a hash table lookup for each entry in the alist; and it will require creating a new alist, which uses additional memory. * Unless ans is a fast alist that is stolen (see below), a new hash table is created, which uses additional memory. This hash table is populated in time that is linear in the number of unique keys in the alist. When ans is not an atom, good discipline requires that it is a fast alist. In this case, fast-alist-fork steals the hash table for ans and extends it with all of the bindings in alist that are not in ans. From the perspective of [hons-assoc-equal], you can think of the resulting alist as being basically similar to (append ans alist), but in a different order. Note that when ans is not a fast alist (e.g., ans is an atom) then such stealing does not take place. A common idiom is to replace an alist by the result of shrinking it, in which case it is best to free the input alist, for example as follows. (let ((alist (fast-alist-free-on-exit alist (fast-alist-fork alist nil)))) ...) See [fast-alist-free-on-exit] and see [fast-alist-free]. Subtopics [Hons-shrink-alist] Deprecated feature") (FAST-ALIST-FORK! (FAST-ALISTS ACL2-BUILT-INS) "(fast-alist-fork! alist ans) is an alternative to [fast-alist-fork] that produces a [normed] result. Logically this function is just fast-alist-fork; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, this is the same as fast-alist-fork except that it uses something like [hons-acons!] instead of [hons-acons]. You generally should not use this function unless you really know what you're doing and understand the drawbacks discussed in [hons-acons!]. Subtopics [Hons-shrink-alist!] Deprecated feature") (FAST-ALIST-FREE (FAST-ALISTS ACL2-BUILT-INS) "(fast-alist-free alist) throws away the hash table associated with a fast alist. Logically, this function is the identity; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, fast-alist-free removes the hash table associated with this alist, if one exists. This effectively converts the alist into an ordinary alist. Also see [fast-alist-free-on-exit]. Because there is no automatic mechanism for freeing the hash tables used in fast alists, to avoid memory leaks you should manually free any alists that will no longer be used. You may find [fast-alist-summary] useful in tracking down alists that were not properly freed. It is safe to call fast-alist-free on any argument, including fast alists that have already been freed and objects which are not alists at all. Function: (defun fast-alist-free (alist) (declare (xargs :guard t)) alist) Subtopics [Flush-hons-get-hash-table-link] Deprecated feature") (FAST-ALIST-FREE-ON-EXIT (FAST-ALISTS ACL2-BUILT-INS) "Free a fast alist after the completion of some form. Logically, (fast-alist-free-on-exit alist form) is the identity and returns form. Also see [fast-alist-free]. Under the hood, this essentially expands to: (prog1 form (fast-alist-free alist)) In other words, alist is not freed immediately, but instead remains a fast alist until the form completes. This may be useful when you are writing code that uses a fast alist but has many return points. See also the macro fast-alists-free-on-exit defined in the community book \"books/centaur/misc/hons-extra.lisp\", which can be used to free several alists. The community book \"books/centaur/misc/hons-extra.lisp\" extends the [b*] macro with the free-on-exit pattern binder. That is, after executing (include-book \"centaur/misc/hons-extra.lisp\" :dir :system), the form (b* (... ((free-on-exit a b c)) ...) ...) causes a, b, and c to be freed when the b* completes, but they remain fast alists until then.") (FAST-ALIST-LEN (FAST-ALISTS ACL2-BUILT-INS) "(fast-alist-len alist) counts the number of unique keys in a fast alist. Logically this function counts how many elements would remain in the alist were we to shrink it with [fast-alist-fork]. Good discipline requires that the alist is a fast alist. Under the hood, when the alist is a fast alist we can simply call the underlying Common Lisp function hash-table-count on the associated hash table, which is very fast and doesn't require us to actually shrink the alist. Function: (defun fast-alist-len (alist) (declare (xargs :guard t)) (len (fast-alist-fork alist nil)))") (FAST-ALIST-SUMMARY (FAST-ALISTS ACL2-BUILT-INS) "(fast-alist-summary) prints some basic statistics about any current fast alists. Logically, fast-alist-summary just returns nil; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, this function gathers and prints some basic statistics about the current fast alists. It may be useful for identifying fast alists that should have been freed with [fast-alist-free]. Function: (defun fast-alist-summary nil (declare (xargs :guard t)) nil)") (FAST-ALISTS (ALISTS PROGRAMMING HONS-AND-MEMOIZATION) "Alists with hidden hash tables for faster execution The implementation of fast alists is, in many ways, similar to that of ACL2 arrays. Logically, [hons-acons] is just like acons, and [hons-get] is similar to [assoc-equal]. But under the hood, hash tables are associated with these alists, and, when a certain discipline is followed, these functions execute with hash table speeds. What is this discipline? Each hons-acons operation \"steals\" the hash table associated with the alist that is being extended. Because of this, one must be very conscious of which object is the most recent extension of an alist and use that extension exclusively. The only penalty for a failure to keep track of the most recent extension is a loss of execution speed, not of correctness, and perhaps the annoyance of some [slow-alist-warning]s. Maintaining discipline may require careful passing of a fast alist up and down through function calls, as with any single threaded object in an applicative setting, but there is no syntactic enforcement that insists you only use the most recent extension of an alist as there is for single threaded objects ([stobj]s). Also, even with perfectly proper code, discipline can sometimes be lost due to user interrupts and aborts. Performance Notes See [hons-acons] for how the final [cdr] of a fast alist can be used as a size hint or as a name for reports printed by calling [fast-alist-summary]. The keys of fast alists are always [normed]. Why? In Common Lisp, equal-based hashing is relatively slow, so to allow the use of eql-based hash tables, [hons-acons] and [hons-get] always [hons-copy] the keys involved. Since alist keys are frequently atoms, this norming activity may often be so fast that you do not need to think about it. But if you are going to use large structures as the keys for your fast alist, this overhead can be significant, and you may want to ensure that your keys are normed ahead of time. There is no automatic mechanism for reclaiming the hash tables that are associated with alists. Because of this, to avoid memory leaks, you should call [fast-alist-free] to remove the hash table associated with alists that will no longer be used. Subtopics [Cons-subtrees] Build a fast alist whose keys are the subtrees of X [Fast-alist-clean] ([fast-alist-clean] alist) can be used to eliminate \"shadowed pairs\" from a fast alist. [Fast-alist-clean!] ([fast-alist-clean!] alist) is an alternative to [fast-alist-clean] that produces a [normed] result. [Fast-alist-fork] ([fast-alist-fork] alist ans) can be used to eliminate \"shadowed pairs\" from an alist or to copy [fast-alists]. [Fast-alist-fork!] ([fast-alist-fork!] alist ans) is an alternative to [fast-alist-fork] that produces a [normed] result. [Fast-alist-free] ([fast-alist-free] alist) throws away the hash table associated with a fast alist. [Fast-alist-free-on-exit] Free a fast alist after the completion of some form. [Fast-alist-len] ([fast-alist-len] alist) counts the number of unique keys in a fast alist. [Fast-alist-summary] ([fast-alist-summary]) prints some basic statistics about any current fast alists. [Hons-acons] ([hons-acons] key val alist) is the main way to create or extend [fast-alists]. [Hons-acons!] ([hons-acons!] key val alist) is an alternative to [hons-acons] that produces [normed], fast alists. [Hons-assoc-equal] ([hons-assoc-equal] key alist) is not fast; it serves as the logical definition for [hons-get]. [Hons-get] ([hons-get] key alist) is the efficient lookup operation for [fast-alists]. [Make-fast-alist] ([make-fast-alist] alist) creates a fast-alist from the input alist, returning alist itself or, in some cases, a new object equal to it. [Slow-alist-warning] Warnings issued when [fast-alists] are used inefficiently [With-fast-alist] ([with-fast-alist] name form) causes name to be a fast alist for the execution of form.") (FC-REPORT (FORWARD-CHAINING-REPORTS) "To report on the forward chaining activity in the most recent proof Example: (fc-report 15) General Form: (fc-report k) where k is the number of some forward chaining report printed in the most recent event. See [forward-chaining-reports] for details.") (FIFTH (NTH ACL2-BUILT-INS) "Fifth member of the list See any Common Lisp documentation for details.") (FILE-READING-EXAMPLE (TUTORIAL5-MISCELLANEOUS-EXAMPLES) "Example of reading files in ACL2 This example illustrates the use of ACL2's [io] primitives to read the forms in a file. See [io]. This example provides a solution to the following problem. Let's say that you have a file that contains s-expressions. Suppose that you want to build a list by starting with nil, and updating it ``appropriately'' upon encountering each successive s-expression in the file. That is, suppose that you have written a function update-list such that (update-list obj current-list) returns the list obtained by ``updating'' current-list with the next object, obj, encountered in the file. The top-level function for processing such a file, returning the final list, could be defined as follows. Notice that because it opens a channel to the given file, this function modifies [state] and hence must return [state]. Thus it actually returns two values: the final list and the new [state]. (defun process-file (filename state) (mv-let (channel state) (open-input-channel filename :object state) (mv-let (result state) (process-file1 nil channel state) ;see below (let ((state (close-input-channel channel state))) (mv result state))))) The function process-file1 referred to above takes the currently constructed list (initially, nil), together with a channel to the file being read and the [state], and returns the final updated list. Notice that this function is tail recursive. This is important because many Lisp compilers will remove tail recursion, thus avoiding the potential for stack overflows when the file contains a large number of forms. (defun process-file1 (current-list channel state) (mv-let (eofp obj state) (read-object channel state) (cond (eofp (mv current-list state)) (t (process-file1 (update-list obj current-list) channel state))))) As an exercise, you might want to add [guard]s to the functions above and verify the guards (see [verify-guards]). See [args] or make a call of the form (guard 'your-function nil (w state)) to see the guard of an existing function.") (FINALIZE-EVENT-USER (PROVER-OUTPUT) "User-supplied code to complete [events], e.g., with extra summary output This utility is intended for system hackers, not standard ACL2 users. ACL2 prints summaries at the conclusions of processing [events] (unless summaries are inhibited; see [set-inhibit-output-lst] and also see [set-inhibited-summary-types]). You may arrange for processing to take place just after the summary, by defining a function with argument list (ctx body state) that returns one value, namely state. We describe ctx and body at the end below, but you may simply prefer to ignore these arguments.) Your function should normally be a [guard]-verified :[logic] mode function with no guard other than that provided by the input requirement on [state], that is, (state-p state); but later below we discuss how to avoid this requirement. You then attach (see [defattach]) your function to the function finalize-event-user. The following example illustrates how this all works. (defun finalize-event-user-test (ctx body state) (declare (xargs :stobjs state) (ignore ctx body)) (cond ((and (boundp-global 'abbrev-evisc-tuple state) (open-output-channel-p *standard-co* :character state)) (pprogn (if (eq (f-get-global 'abbrev-evisc-tuple state) :DEFAULT) (princ$ \"Abbrev-evisc-tuple has its default value.~%\" *standard-co* state) (princ$ \"Abbrev-evisc-tuple has been modified.~%\" *standard-co* state)))) (t state))) (defattach finalize-event-user finalize-event-user-test) After admission of the two events above, an event summary will conclude with extra printout, for example: Note: Abbrev-evisc-tuple has its default value. If the attachment function (above, finalize-event-user-test) does not meet all the requirements stated above, then you can use the :skip-checks argument of [defattach] to get around the requirement, as illustrated by the following example. (defun finalize-event-user-test2 (state) (declare (xargs :stobjs state :mode :program) (ignore ctx body)) (observation 'my-test \"~|Value of term-evisc-tuple: ~x0~|\" (f-get-global 'term-evisc-tuple state))) (defttag t) ; needed for :skip-checks t (defattach (finalize-event-user finalize-event-user-test2) :skip-checks t) So for example: ACL2 !>(set-term-evisc-tuple (evisc-tuple 2 7 nil nil) state) (:TERM) ACL2 !>(defconst *foo6* '(a b c)) Summary Form: ( DEFCONST *FOO6* ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) ACL2 Observation in MY-TEST: Value of term-evisc-tuple: (NIL 2 7 NIL) *FOO6* ACL2 !> Note that (as of this writing) the macro [observation] expands to a call of a :[program]-mode function. Thus, the trick shown above involving :skip-checks allows the use of :program-mode functions; for example, you can print with [fmt]. See community book books/misc/defattach-bang.lisp for a variant of [defattach] that uses [ec-call] to avoid issues of [guard] verification. Also see [initialize-event-user], which discusses the handling of [state] globals by that utility as well as by finalize-event-user. Finally, as promised above, we briefly describe the arguments ctx and body. These are the arguments passed to the call of macro with-ctx-summarized under which finalize-event-user (or initialize-event-user) was called. Thus, they are unevaluated expressions. For example, system function defthm-fn1 has a body of the following form. (with-ctx-summarized (if (output-in-infixp state) event-form (cons 'defthm name)) (let ((wrld (w state)) (ens (ens state)) ..... Thus, when initialize-event-user and finalize-event-user are called on behalf of [defthm], ctx is the s-expression (if (output-in-infixp state) event-form (cons 'defthm name)) while body is the following s-expression (with most code elided). (let ((wrld (w state)) (ens (ens state)) ..... You might find it helpful to use [trace$] to get a sense of ctx and body, for example, (trace$ finalize-event-user).") (FIND-RULES-OF-RUNE (RUNE) "Find the rules named rune General Form: (find-rules-of-rune rune wrld) This function finds all the rules in wrld with :[rune] rune. It returns a list of rules in their internal form (generally as described by the corresponding defrec). Decyphering these rules is difficult since one cannot always look at a rule object and decide what kind of record it is without exploiting many system invariants (e.g., that :[rewrite] runes only name rewrite-rules). At the moment this function returns nil if the rune in question is a :[refinement] rune, because there is no object representing :[refinement] rules. (:[refinement] rules cause changes in the 'coarsenings properties.) In addition, if the rune is an :[equivalence] rune, then congruence rules with that rune will be returned --- because :[equivalence] lemmas generate some congruence rules --- but the fact that a certain function is now known to be an equivalence relation is not represented by any rule object and so no such rule is returned. (The fact that the function is an equivalence relation is encoded entirely in its presence as a 'coarsening of [equal].)") (FINDING-DOCUMENTATION (DOCUMENTATION) "Searching the documentation The :[doc] command will display, at the terminal, [documentation] topics defined in ACL2 or in [books] that have already been included. But how can you find documentation for books that are not included in the current ACL2 session? The [xdoc] {ACL2+Books Manual | http://www.cs.utexas.edu/users/moore/acl2/v7-1/combined-manual/index.html} includes documentation for both the ACL2 system and the [community-books]. For more information on this manual and how to view it, see [documentation].") (FIRST (NTH ACL2-BUILT-INS) "First member of the list See any Common Lisp documentation for details.") (FIX (NUMBERS ACL2-BUILT-INS) "Coerce to a number Fix simply returns any numeric argument unchanged, returning 0 on a non-numeric argument. Also see [nfix], see [ifix], and see [rfix] for analogous functions that coerce to a natural number, an integer, and a rational number, respectively. Fix has a [guard] of t. Function: (defun fix (x) (declare (xargs :guard t)) (if (acl2-numberp x) x 0))") (FIX-TRUE-LIST (LISTS ACL2-BUILT-INS) "Coerce to a true list Fix-true-list is the identity function on [true-listp] objects. It converts every list to a true list by dropping the final [cdr], and it converts every [atom] to nil. Function: (defun fix-true-list (x) (declare (xargs :guard t)) (if (consp x) (cons (car x) (fix-true-list (cdr x))) nil))") (FLAWED_INDUCTION_CANDIDATES_IN_APP_EXAMPLE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Flawed Induction Candidates in App Example Induction on a is unflawed: every occurrence of a in the conjecture (equal (app (app a b) c) (app a (app b c))) is in a position being recursively decomposed! Now look at the occurrences of b. The first (shown in bold below) is in a position that is held constant in the recursion of (app a b). It would be ``bad'' to induct on b here. (equal (app (app a b) c) (app a (app b c)))") (FLET (BASICS ACL2-BUILT-INS) "Local binding of function symbols Example Form: ; The following evaluates to (mv 7 10): (flet ((f (x) (+ x 3)) (g (x) (declare (type integer x)) (* x 2))) (mv (f 4) (g 5))) General Forms: (flet (def1 ... defk) body) (flet (def1 ... defk) declare-form1 .. declare-formk body) where body is a term, and each defi is a definition as in [defun] but with the leading defun symbol omitted. See [defun]. If any declare-formi are supplied, then each must be of the form (declare decl1 ... decln), where each decli is of the form (inline g1 ... gm) or (notinline g1 ... gm), and each gi is defined by some defi. The only effect of the declarations is to provide advice to the host Lisp compiler. The declarations are otherwise ignored by ACL2, so we mainly ignore them in the discussion below. The innermost flet-binding of a function symbol, f, above a call of f, is the one that provides the definition of f for that call. Note that flet does not provide recursion. Consider the following example. ; Give a global definition of f: (defun f (x) (+ x 3)) ; Evaluate an expression using a local binding of f: (flet ((f (x) (cons x (f (1+ x))))) (f 4)) In the above term (cons x (f (1+ x))), f refers to the global definition of f above the flet expression. However, (f 4) refers to the flet-binding of f, (f (x) (cons x (f x))). The result of the flet expression is thus obtained by evaluating (f 4) where (f 4) is (cons 4 (f (1+ 4))), where the latter call of f refers to the global definition; thus we have (cons 4 (f 5)), which evaluates to (4 . 8). Although flet behaves in ACL2 essentially as it does in Common Lisp, ACL2 imposes the following restrictions and qualifications. * Every [declare] form for a local definition (def1 through defk, above) must be an ignore, ignorable, or type expression. * Each defi must bind a different function symbol. * Each defi must bind a symbol that is a legal name for an ACL2 function symbol. In particular, the symbol may not be in the keyword package or the main Lisp package. Moreover, the symbol may not be a built-in ACL2 function or macro. * Every variable occurring in the body of a defi must be a formal parameter of that defi. (This restriction is not enforced in Common Lisp.) * If the flet-binding defi is in the body of a function f, then the [stobj] inputs for defi are implicitly those of its inputs that are declared [stobj] inputs of f. Flet bindings are evaluated in parallel. Consider the following example. (defun f (x) x) (flet ((f (x) (cons x x)) (g (x) (f x))) (g 3)) The binding of g refers to the global value of f, not the flet-binding of f. Thus, the flet expression evaluates to 3. Compare the flet expression above to the following one, which instead evaluates to (3 . 3). (defun f (x) x) (flet ((f (x) (cons x x))) (flet ((g (x) (f x))) (g 3))) Under the hood, ACL2 translates flet bindings to [lambda] expressions (see [term]), throwing away the inline and notinline declarations (if any). The following example illustrates this point. ACL2 !>:trans (flet ((f (x) (cons x x)) (g (x y) (+ x y))) (declare (inline f)) (f (g 3 4))) ((LAMBDA (X) (CONS X X)) ((LAMBDA (X Y) (BINARY-+ X Y)) '3 '4)) => * ACL2 !> Flet is part of Common Lisp. See any Common Lisp documentation for more information. We conclude by pointing out an important aspect of flet shared by ACL2 and Common Lisp: The binding is lexical, not dynamic. That is, the flet binding of a function symbol only applies to calls of that function symbol in the body of the flet, not other calls made in the course of evaluation. Consider the following example. Suppose we define: (defun f (x) x) (defun g (x) (f x)) (defun h (x) (flet ((f (x) (cons x x))) (g x))) Then evaluation of (h 3) results in 3, not in the cons pair (3 . 3), because the flet binding of f only applies to calls of f that appear in the body of that flet. In this case, only g is called in the body of that flet.") (FLOOR (NUMBERS ACL2-BUILT-INS) "Division returning an integer by truncating toward negative infinity Example Forms: ACL2 !>(floor 14 3) 4 ACL2 !>(floor -14 3) -5 ACL2 !>(floor 14 -3) -5 ACL2 !>(floor -14 -3) 4 ACL2 !>(floor -15 -3) 5 (Floor i j) returns the result of taking the quotient of i and j and returning the greatest integer not exceeding that quotient. For example, the quotient of -14 by 3 is -4 2/3, and the largest integer not exceeding that rational number is -5. The [guard] for (floor i j) requires that i and j are rational ([real], in ACL2(r)) numbers and j is non-zero. Floor is a Common Lisp function. See any Common Lisp documentation for more information. However, note that unlike Common Lisp, the ACL2 floor function returns only a single value, Function: (defun floor (i j) (declare (xargs :guard (and (real/rationalp i) (real/rationalp j) (not (eql j 0))))) (let* ((q (* i (/ j))) (n (numerator q)) (d (denominator q))) (cond ((= d 1) n) ((>= n 0) (nonnegative-integer-quotient n d)) (t (+ (- (nonnegative-integer-quotient (- n) d)) -1)))))") (FLUSH-COMPRESS (ARRAYS ACL2-BUILT-INS) "Flush the under-the-hood array for the given name Example Form: (flush-compress 'my-array) General Form: (flush-compress name) where name is a symbol. Recall that (compress1 nm alist) associates an under-the-hood raw Lisp one-dimensional array of name nm with the given association list, alist, while (compress2 nm alist) is the analogous function for two-dimensional arrays; see [compress1] and see [compress2]. The only purpose of flush-compress, which always returns nil, is to remove the association of any under-the-hood array with the given name, thus eliminating slow array accesses (see [slow-array-warning]). It is not necessary if the return values of [compress1] and [compress2] are always used as the ``current'' copy of the named array, and thus flush-compress should rarely, if ever, be needed in user applications. Nevertheless, we provide the following contrived example to show how flush-compress can be used to good effect. Comments have been added to this log to provide explanation. ACL2 !>(assign a (compress1 'demo '((:header :dimensions (5) :maximum-length 15 :default uninitialized :name demo) (0 . zero) (1 . one)))) ((:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 15 :DEFAULT UNINITIALIZED :NAME DEMO) (0 . ZERO) (1 . ONE)) ACL2 !>(aref1 'demo (@ a) 0) ZERO ; As expected, the above evaluation did not cause a slow array warning. Now ; we associate a different under-the-hood array with the name 'demo. ACL2 !>(compress1 'demo '((:header :dimensions (5) :maximum-length 15 :default uninitialized :name demo) (0 . zero))) ((:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 15 :DEFAULT UNINITIALIZED :NAME DEMO) (0 . ZERO)) ; The following array access produces a slow array warning because (@ a) is ; no longer associated under-the-hood with the array name 'demo. ACL2 !>(aref1 'demo (@ a) 0) ********************************************************** Slow Array Access! A call of AREF1 on an array named DEMO is being executed slowly. See :DOC slow-array-warning ********************************************************** ZERO ; Now we associate under-the-hood, with array name 'demo, an alist equal to ; (@ a). ACL2 !>(compress1 'demo '((:header :dimensions (5) :maximum-length 15 :default uninitialized :name demo) (0 . zero) (1 . one))) ((:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 15 :DEFAULT UNINITIALIZED :NAME DEMO) (0 . ZERO) (1 . ONE)) ; The following array access is still slow, because the under-the-hood array ; is merely associated with a copy of (@ a), not with the actual object ; (@ a). ACL2 !>(aref1 'demo (@ a) 0) ********************************************************** Slow Array Access! A call of AREF1 on an array named DEMO is being executed slowly. See :DOC slow-array-warning ********************************************************** ZERO ; So we might try to fix the problem by recompressing. But this doesn't ; work. It would work, by the way, if we re-assign a: ; (assign a (compress1 'demo (@ a))). That is why we usually will not need ; flush-compress. ACL2 !>(compress1 'demo (@ a)) ((:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 15 :DEFAULT UNINITIALIZED :NAME DEMO) (0 . ZERO) (1 . ONE)) ACL2 !>(aref1 'demo (@ a) 0) ********************************************************** Slow Array Access! A call of AREF1 on an array named DEMO is being executed slowly. See :DOC slow-array-warning ********************************************************** ZERO ; Finally, we eliminate the warning by calling flush-compress before we call ; compress1. The call of flush-compress removes any under-the-hood ; association of an array with the name 'demo. Then the subsequent call of ; compress1 associates the object (@ a) with that name. (Technical point: ; compress1 always associates the indicated name with the value that it ; returns. in this case, what compress1 returns is (@ a), because (@ a) is ; already, logically speaking, a compressed array1p (starts with a :header ; and the natural number keys are ordered). ACL2 !>(flush-compress 'demo) NIL ACL2 !>(compress1 'demo (@ a)) ((:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 15 :DEFAULT UNINITIALIZED :NAME DEMO) (0 . ZERO) (1 . ONE)) ACL2 !>(aref1 'demo (@ a) 0) ZERO ACL2 !> Function: (defun flush-compress (name) (declare (xargs :guard t)) (declare (ignore name)) nil)") (FLUSH-HONS-GET-HASH-TABLE-LINK (FAST-ALIST-FREE ACL2-BUILT-INS) "Deprecated feature Deprecated. Alias for [fast-alist-free].") (FMS (IO ACL2-BUILT-INS) "(fms str alist co-channel state evisc) => state See [fmt] for further explanation, including documentation of the tilde-directives.") (FMS! (IO ACL2-BUILT-INS) "(fms! str alist co-channel state evisc) => state This function is nearly identical to fms; see [fms]. The only difference is that fms may insert backslash (\\) characters when forced to print past the right margin in order to make the output a bit clearer in that case. Use fms! instead if you want to be able to read the forms back in.") (FMS!-TO-STRING (POINTERS) "See [printing-to-strings].") (FMS-TO-STRING (POINTERS) "See [printing-to-strings].") (FMT (IO ACL2-BUILT-INS) "Formatted printing ACL2 provides the functions fmt, [fmt1], and [fms] as substitutes for Common Lisp's format function. Also see [fmt!], see [fmt1!], and see [fms!] for versions of these functions that write forms to files in a manner that allows them to be read, by avoiding using backslash (\\) to break long lines. There are also analogues of these functions that return a string without taking [state] as an argument; see [printing-to-strings]. All three print a given string under an alist pairing character objects with values, interpreting certain ``tilde-directives'' in the string. Channel must be a character output channel (e.g., [*standard-co*]). General Forms: result (fms string alist channel state evisc-tuple) ; state (fmt string alist channel state evisc-tuple) ; (mv col state) (fmt1 string alist column channel state evisc-tuple) ; (mv col state) [Fms] and fmt print an initial newline to put channel in column 0; [Fmt1] requires the current column as input. Columns are numbered from 0. The current column is the column into which the next character will be printed. (Thus, the current column number is also the number of [characters] printed since the last newline.) The col returned by fmt and [fmt1] is the current column at the conclusion of the formatting. Evisc-tuple must be either nil (meaning no abbreviations are used when objects are printed) or an ``evisceration tuple''; see [evisc-tuple]. We list the tilde-directives below. The notation is explained after the chart. ~xx pretty print vx (maybe after printing a newline) ~yx pretty print vx starting in current column; end with newline ~Xxy like ~xx but use vy as the evisceration tuple ~Yxy like ~yx but use vy as the evisceration tuple ~@x if vx is a string, \"str\", recursively format \"str\" if vx is (\"str\" . a), recursively format \"str\" under a+ ~#x~[...~/...~/ ... ~/...~] cases on vx ^ ^ ... ^ if 0<=vx<=k, choose vxth alternative 0 1 ... k if vx is a list of length 1, case 0; else 1 ~*x iterator: vx must be of the form (\"str0\" \"str1\" \"str2\" \"str3\" lst . a); if lst is initially empty, format \"str0\" under a+; otherwise, bind #\\* successively to the elements of lst and then recursively format \"stri\" under a+, where i=1 if there is one element left to process, i=2 if there are two left, and i=3 otherwise. ~&x print elements of vx with ~x, separated by commas and a final ``and'' ~vx print elements of vx with ~x, separated by commas and a final ``or'' ~nx if vx is a small positive integer, print it as a word, e.g., seven; if vx is a singleton containing a small positive integer, print the corresponding ordinal as a word, e.g., seventh ~Nx like ~nx but the word is capitalized, e.g., Seven or Seventh ~tx tab out to column vx; newline first if at or past column vx ~cx vx is (n . w), print integer n right justified in field of width w ~fx print object vx flat over as many lines as necessary ~Fx same as ~f, except that subsequent lines are indented to start one character to the right of the first character printed ~sx if vx is a symbol, print vx, breaking on hyphens (unless the symbol would normally be printed with surrounding vertical bar characters (|), in which case print as with ~fx); if vx is a string, print the characters in it, breaking on hyphens; else vx is a number, to be printed using the current print-base and print-radix ~ tilde space: print a space ~_x print vx spaces ~ tilde newline: skip following whitespace ~% output a newline ~| output a newline unless already on left margin ~~ print a tilde ~- if close to rightmargin, output a hyphen and newline; else skip this char If x is a character, then vx is the value of #\\x under the current alist. Consider for example the discussion above for ~y, ``~yx pretty print vx'', applied to the following expression: (fmt \"HELLO ~y7\" (list (cons #\\7 'world)) *standard-co* state nil). Then in this example: #\\x is 7; and vx is the value of character #\\7 under the given alist, which is the symbol, WORLD. Thus, ACL2 will print HELLO WORLD. When we say ``format str under a+'' we mean: process the given string under an alist obtained by appending a to the current alist. The following example illustrates how this works. ACL2 !>(fms \"~@0\" (list (cons #\\0 (cons \"~x0 ~@1\" (list (cons #\\0 'abc)))) (cons #\\1 \"-- and now: ~x0 again~%\")) *standard-co* state nil) ABC -- and now: ABC again ACL2 !> Note: ~p, ~q, ~P, and ~Q are also currently supported, but are deprecated. These are respectively the same as ~x, ~y, ~X, and ~Y, except that their arguments are expected to be terms, preferably untranslated (user-level) terms, that could be printed using infix notation in certain environments. Infix printing is not currently supported but may be if there is sufficient need for it. ACL2's formatting functions print to the indicated channel, keeping track of which column they are in. [Fmt1] can be used if the caller knows which column the channel is in (i.e., how many [characters] have been printed since the last newline). Otherwise, fmt or [fms] must be used, both of which output a newline so as to establish the column position at 0. Unlike Common Lisp's format routine, fmt and its relatives break the output into lines so that, by default, an attempt is made to avoid printing past column 77 (the value of constant *fmt-hard-right-margin-default*). See [set-fmt-hard-right-margin] for a discussion of how linebreaks are inserted and how to change the relevant default settings. The formatting functions scan the string from left to right, printing each successive character unless it is a tilde (~). Upon encountering tildes the formatters take action determined by the character or [characters] immediately following the tilde. The typical tilde-directive is a group of three successive [characters] from the string being printed. For example, ~x0 is a 3 character tilde-directive. The first character in a tilde-directive is always the tilde character itself. The next character is called the ``command'' character. The character after that is usually taken as the name of a ``format variable'' that is bound in the alist under which the string is being printed. Format variables are, by necessity, [characters]. The objects actually printed by a tilde-directive are the objects obtained by looking up the command's format variables in the alist. Typical format variable names are 0, 1, 2, ..., 9, a, b, c, etc., and if a tilde-directive uses the format variable 0, as in ~x0, then the character #\\0 must be bound in the alist. Some tilde commands take no arguments and others take more than one, so some directives are of length two and others are longer. It should be noted that this use of [characters] in the string to denote arguments is another break from Common Lisp's format routine. In Common Lisp, the directives refer implicitly to the ``next item to be printed.'' But in ACL2 the directives name each item explicitly with our format variables. The following text contains examples that can be evaluated. To make this process easier, we use a macro which is defined as part of ACL2 just for this [documentation]. The macro is named fmx and it takes up to eleven arguments, the first of which is a format string, str, and the others of which are taken as the values of format variables. The variables used are #\\0 through #\\9. The macro constructs an appropriate alist, a, and then evaluates (fmt str a *standard-co* state nil). Thus, (fmx \"Here is v0, ~x0, and here is v1, ~x1.\" (cons 'value 0) (cons 'value 1)) is just an abbreviation for (fmt \"Here is v0, ~x0, and here is v1, ~x1.\" (list (cons #\\0 (cons 'value 0)) (cons #\\1 (cons 'value 1))) *standard-co* state nil) which returns (mv 53 state) after printing the line Here is v0, (VALUE . 0), and here is v1, (VALUE . 1). We now devote special attention to three of the tilde-directives whose use is non-obvious. The Case Statement ~#x is essentially a ``case statement'' in the language of fmt. The proper form of the statement is ~#x~[case-0~/case-1~/ ... ~/case-k~], where each of the case-i is a format string. In the most common use, the variable x has an integer value, vx, between 0 and k, inclusive. The effect of formatting the directive is to format case-vx. For example (fmx \"Go ~#0~[North~/East~/South~/West~].~%\" 1) will print ``Go East.'' followed by a newline and will return (mv 0 state), while if you change the 1 above to 3 (the maximum legal value), it will print ``Go West.'' In order to make it easier to print such phrases as ``there are seven cases'' requiring agreement between subject and verb based on the number of elements of a list, the case statement allows its variable to take a list as its value and selects case-0 if the list has length 1 and case-1 otherwise. (let ((cases '(a b c))) (fmx \"There ~#0~[is ~n1 case~/are ~n1 cases~].\" cases (length cases))) will print ``There are three cases.'' but if you change the '(a b c) above simply to '(a) it will print ``There is one case.'' and if you change it to nil it will print ``There are zero cases.'' Indirection Roughly speaking, ~@ will act as though the value of its argument is a format string and splice it into the current string at the current position. It is often used when the phrase to be printed must be computed. For example, (let ((ev 'DEFUN)) (fmx \"~x0 is an event~@1.\" 'foo (if (member-eq ev '(defun defstub encapsulate)) \" that may introduce a function symbol\" \"\"))) will print ``foo is an event that may introduce a function symbol,'' but if the value of ev is changed from '[defun] to '[defthm], it prints ``foo is an event.'' The ~@ directive ``splices'' in the computed phrase (which might be empty). Of course, this particular example could be done with the case statement ~#1~[~/ that may introduce a function symbol~] where the value of #\\1 is appropriately computed to be 0 or 1. If the argument to ~@ is a pair, it is taken to be a format string [cons]ed onto an alist, i.e., (\"str\" . a), and the alist, a, is used to extend the current one before \"str\" is recursively processed. This feature of fmt can be used to pass around ``phrases'' that contain computed contextual information in a. The most typical use is as ``error messages.'' For example, suppose you are writing a function which does not have access to [state] and so cannot print an error message. It may nevertheless be necessary for it to signal an error to its caller, say by returning two results, the first of which is interpreted as an error message if non-nil. Our convention is to use a ~@ pair to represent such messages. For example, the error value might be produced by the code: (cons \"Error: The instruction ~x0 is illegal when the stack is ~x1.~%\" (list (cons #\\0 (current-instruction st)) (cons #\\1 (i-stack st)))) If the current-instruction and i-stack (whatever they are) are '(popi 3) and '(a b) when the [cons] above is evaluated, then it produces '(\"Error: The instruction ~x0 is illegal when the stack is ~x1.~%\" (#\\0 POPI 3) (#\\1 A B)) and if this pair is made the value of the fmt variable 0, then ~@0 will print Error: The instruction (POPI 3) is illegal when the stack is (A B). For example, evaluate (let ((pair '(\"Error: The instruction ~x0 is illegal when the stack is ~x1.~%\" (#\\0 POPI 3) (#\\1 A B)))) (fmx \"~@0\" pair)). Thus, even though the function that produced the ``error'' could not print it, it could specify exactly what error message and data are to be printed. This example raises another issue. Sometimes it is desirable to break lines in your format strings so as to make your source code more attractive. That is the purpose of the tilde-newline directive. The following code produces exactly the same output as described above. (let ((pair '(\"Error: The instruction ~x0 ~ is illegal when the stack is ~ ~x1.~%\" (#\\0 POPI 3) (#\\1 A B)))) (fmx \"~@0\" pair)). Finally, observe that when ~@0 extends the current alist, alist, with the one, a, in its argument, the bindings from a are added to the front of alist, overriding the current values of any shared variables. This ensures that the variable values seen by the recursively processed string, \"str\", are those from a, but if \"str\" uses variables not bound in a, their values are as specified in the original alist. Intuitively, variables bound in a are local to the processing of (\"str\" . a) but \"str\" may use ``global variables.'' The example above illustrates this because when the ~@0 is processed, #\\0 is bound to the error message pair. But when the ~x0 in the error string is processed, #\\0 is bound to the illegal instruction. Iteration The ~* directive is used to process each element of a list. For example, (let ((lst '(a b c d e f g h))) ; a true-list whose elements we exhibit (fmx \"~*0\" `(\"Whoa!\" ; what to print if there's nothing to print \"~x*!\" ; how to print the last element \"~x* and \" ; how to print the 2nd to last element \"~x*, \" ; how to print all other elements ,lst))) ; the list of elements to print will print ``A, B, C, D, E, F, G and H!''. Try this example with other true list values of lst, such as '(a b), '(a), and nil. The tilde-directives ~&0 and ~v0, which take a true list argument and display its elements separated by commas and a final ``and'' or ``or,'' are implemented in terms of the more general ~*. The ~* directive allows the 5-tuple to specify in its final [cdr] an alist with which to extend the current one before processing the individual elements. We often use ~* to print a series of phrases, separated by suitable punctuation, whitespace and noise words. In such use, the ~* handles the separation of the phrases and each phrase is generally printed by ~@. Here is a complex example. In the [let*], below, we bind phrases to a list of ~@ pairs and then we create a ~* 5-tuple to print out the conjunction of the phrases with a parenthetical ``finally!'' if the series is longer than 3. (let* ((phrases (list (list \"simplifying with the replacement rules ~&0\" (cons #\\0 '(rewrite-rule1 rewrite-rule2 rewrite-rule3))) (list \"destructor elimination using ~x0\" (cons #\\0 'elim-rule)) (list \"generalizing the terms ~&0\" (cons #\\0 '((rev x) (app u v)))) (list \"inducting on ~x0\" (cons #\\0 'I)))) (5-tuple (list \"magic\" ; no phrases \"~@*\" ; last phrase \"~@*, and~#f~[~/ (finally!)~] \" ; second to last phrase \"~@*, \" ; other phrases phrases ; the phrases themselves (cons #\\f (if (>(length phrases) 3) 1 0))))) ;print ``finally''? (fmx \"We did it by ~*0.\" 5-tuple)) This [let*] prints We did it by simplifying with the replacement rules REWRITE-RULE1, REWRITE-RULE2 and REWRITE-RULE3, destructor elimination using ELIM- RULE, generalizing the terms (REV X) and (APP U V), and (finally!) inducting on I. You might wish to try evaluating the [let*] after removing elements of phrases. Most of the output produced by ACL2 is produced via fmt statements. Thus, inspection of the source code will yield many examples. A complicated example is the code that explains the simplifier's work. See :[pc] simplify-clause-msg1. An ad hoc example is provided by the function fmt-doc-example, which takes two arguments: an arbitrary true list and [state]. To see how fmt-doc-example works, :[pe] fmt-doc-example. (fmt-doc-example '(a b c d e f g h i j k l m n o p) state) will produce the output Here is a true list: (A B C D E F G H I J K L M N O P). It has 16 elements, the third of which is C. We could print each element in square brackets: ([A], [B], [C], [D], [E], [F], [G], [H], [I], [J], [K], [L], [M], [N], [almost there: O], [the end: P]). And if we wished to itemize them into column 15 we could do it like this 0123456789012345 0 (zeroth) A 1 (first) B 2 (second) C 3 (third) D 4 (fourth) E 5 (fifth) F 6 (sixth) G 7 (seventh) H 8 (eighth) I 9 (ninth) J 10 (tenth) K 11 (eleventh) L 12 (twelfth) M 13 (thirteenth) N 14 (14th) O 15 (15th) P End of example. and return (mv 15 state). Finally, we should remind the reader that fmt and its subfunctions, most importantly fmt0, are written entirely in ACL2. We make this comment for two reasons. First, it illustrates the fact that quite low level code can be efficiently written in the language. Second, it means that as a last resort for documentation purposes you can read the source code without changing languages.") (FMT! (IO ACL2-BUILT-INS) "(fmt! str alist co-channel state evisc) => state This function is nearly identical to fmt; see [fmt]. The only difference is that fmt may insert backslash (\\) characters when forced to print past the right margin in order to make the output a bit clearer in that case. Use fmt! instead if you want to be able to read the forms back in.") (FMT!-TO-STRING (POINTERS) "See [printing-to-strings].") (FMT-TO-COMMENT-WINDOW (IO ACL2-BUILT-INS) "Print to the comment window See [cw] for an introduction to the comment window and the usual way to print it. Function fmt-to-comment-window is identical to fmt1 (see [fmt]), except that the channel is [*standard-co*] and the ACL2 [state] is neither an input nor an output. An analogous function, fmt-to-comment-window!, prints with [fmt!] instead of [fmt], in order to avoid insertion of backslash (\\) characters for margins; also see [cw!]. Note that even if you change the value of [ld] special standard-co (see [standard-co]), fmt-to-comment-window will print to [*standard-co*], which is the original value of [standard-co]. General Form: (fmt-to-comment-window fmt-string alist col evisc-tuple) where these arguments are as desribed for [fmt1]; see [fmt].") (FMT-TO-STRING (POINTERS) "See [printing-to-strings].") (FMT1 (IO ACL2-BUILT-INS) "(fmt1 str alist col co-channel state evisc) => (mv col state) See [fmt] for further explanation, including documentation of the tilde-directives.") (FMT1! (IO ACL2-BUILT-INS) "(fmt1! str alist col channel state evisc) => (mv col state) This function is nearly identical to fmt1; see [fmt1]. The only difference is that fmt1 may insert backslash (\\) characters when forced to print past the right margin in order to make the output a bit clearer in that case. Use fmt1! instead if you want to be able to read the forms back in.") (FMT1!-TO-STRING (POINTERS) "See [printing-to-strings].") (FMT1-TO-STRING (POINTERS) "See [printing-to-strings].") (FNCALL-TERM (POINTERS) "See [meta-extract].") (FORALL (DEFUN-SK) "Universal quantifier The symbol forall (in the ACL2 package) represents universal quantification in the context of a [defun-sk] form. See [defun-sk] and see [exists]. See [quantifiers] for an example illustrating how the use of recursion, rather than explicit quantification with [defun-sk], may be preferable.") (FORCE (REWRITE LINEAR TYPE-PRESCRIPTION DEFINITION META) "Identity function used to force a hypothesis Force is the identity function: (force x) is equal to x. However, for rules of many classes (see [rule-classes]), a hypothesis of the form (force term) is given special treatment, as described below. This treatment takes place for rule classes :[rewrite], :[linear], :[type-prescription], :[definition], :[meta] (actually in that case, the result of evaluating the hypothesis metafunction call), and :[forward-chaining]. When a hypothesis of a conditional rule (of one of the classes listed above) has the form (force hyp), it is logically equivalent to hyp but has a pragmatic effect. In particular, when the rule is considered, the needed instance of the hypothesis, hyp', may be assumed if the usual process fails to prove it or its negation. In that situation, if the rule is eventually applied, then a special case is generated, requiring the system to prove that hyp' is true in the current context. The proofs of all such ``forced assumptions'' are, by default, delayed until the successful completion of the main goal. See [forcing-round] and see [immediate-force-modep]. Note that the only time that ACL2 gives special treatment to calls of force is when it is considering the hypotheses of a conditional rule, as discussed above. In particular, when the rewriter encounters a subterm of the goal currently being simplified, a call of force is not treated specially. For example, if you provide a :use hint (see [hints]) that replaces a goal G by the goal (implies (implies (and ... (force HYP) ...) concl) G) then the rewriter will not give any special treatment to (force HYP). Instead, it will first rewrite HYP to, say, HYP'; and then, using the fact that force is the identity function, the rewriter will return HYP' as the rewritten value for (force HYP). Forcing is generally used on hypotheses that are always expected to be true, as is commonly the case for [guard]s of functions. All the power of the theorem prover is brought to bear on a forced hypothesis and no backtracking is possible. Forced goals can be attacked immediately (see [immediate-force-modep]) or in a subsequent forcing round (see [forcing-round]). Also see [case-split] for a related utility. If the :[executable-counterpart] of the function force is [disable]d, then no hypothesis is forced. For more on enabling and disabling forcing, see [enable-forcing] and see [disable-forcing]. It sometimes happens that a conditional rule is not applied because some hypothesis, hyp, could not be relieved, even though the required instance of hyp, hyp', can be shown true in the context. This happens when insufficient resources are brought to bear on hyp' at the time we try to relieve it. A sometimes desirable alternative behavior is for the system to assume hyp', apply the rule, and to generate explicitly a special case to show that hyp' is true in the context. This is called ``forcing'' hyp. It can be arranged by restating the rule so that the offending hypothesis, hyp, is embedded in a call of force, as in (force hyp). By using the :[corollary] field of the [rule-classes] entry, a hypothesis can be forced without changing the statement of the theorem from which the rule is derived. Technically, force is just a function of one argument that returns that argument. It is generally [enable]d and hence evaporates during simplification. But its presence among the hypotheses of a conditional rule causes case splitting to occur if the hypothesis cannot be conventionally relieved. Since a forced hypothesis must be provable whenever the rule is otherwise applicable, forcing should be used only on hypotheses that are expected always to be true. A particularly common situation in which some hypotheses should be forced is in ``most general'' [type-prescription] lemmas. If a single lemma describes the ``expected'' type of a function, for all ``expected'' arguments, then it is probably a good idea to force the hypotheses of the lemma. Thus, every time a term involving the function arises, the term will be given the expected type and its arguments will be required to be of the expected type. In applying this advice it might be wise to avoid forcing those hypotheses that are in fact just type predicates on the arguments, since the routine that applies [type-prescription] lemmas has fairly thorough knowledge of the types of all terms. Force can have the additional benefit of causing the ACL2 typing mechanism to interact with the ACL2 rewriter to establish the hypotheses of [type-prescription] rules. To understand this remark, think of the ACL2 type reasoning system as a rather primitive rule-based theorem prover for questions about Common Lisp types, e.g., ``does this expression produce a [consp]?'' ``does this expression produce some kind of ACL2 number, e.g., an [integerp], a [rationalp], or a [complex-rationalp]?'' etc. It is driven by [type-prescription] rules. To relieve the hypotheses of such rules, the type system recursively invokes itself. This can be done for any hypothesis, whether it is ``type-like'' or not, since any proposition, p, can be phrased as the type-like question ``does p produce an object of type nil?'' However, as you might expect, the type system is not very good at establishing hypotheses that are not type-like, unless they happen to be assumed explicitly in the context in which the question is posed, e.g., ``If p produces a [consp] then does p produce nil?'' If type reasoning alone is insufficient to prove some instance of a hypothesis, then the instance will not be proved by the type system and a [type-prescription] rule with that hypothesis will be inapplicable in that case. But by embedding such hypotheses in force expressions you can effectively cause the type system to ``punt'' them to the rest of the theorem prover. Of course, as already noted, this should only be done on hypotheses that are ``always true.'' In particular, if rewriting is required to establish some hypothesis of a [type-prescription] rule, then the rule will be found inapplicable because the hypothesis will not be established by type reasoning alone. The ACL2 rewriter uses the type reasoning system as a subsystem. It is therefore possible that the type system will force a hypothesis that the rewriter could establish. Before a forced hypothesis is reported out of the rewriter, we try to establish it by rewriting. This makes the following surprising behavior possible: A [type-prescription] rule fails to apply because some true hypothesis is not being relieved. The user changes the rule so as to force the hypothesis. The system then applies the rule but reports no forcing. How can this happen? The type system ``punted'' the forced hypothesis to the rewriter, which established it. Finally, we should mention that the rewriter is never willing to force when there is an [if] term present in the goal being simplified. Since [and] terms and [or] terms are merely abbreviations for [if] terms, they also prevent forcing. Note that [if] terms are ultimately eliminated using the ordinary flow of the proof (but see [set-case-split-limitations]), allowing force ultimately to function as intended. Moreover, forcing can be disabled, as described above; also see [disable-forcing]. Function: (defun force (x) (declare (xargs :guard t)) x) Subtopics [Disable-forcing] To disallow forced case-splits [Disable-immediate-force-modep] [force]d hypotheses are not attacked immediately [Enable-forcing] To allow forced case splits [Enable-immediate-force-modep] [force]d hypotheses are attacked immediately [Failed-forcing] How to deal with a proof [failure] in a forcing round [Forcing-round] A section of a proof dealing with [force]d assumptions [Immediate-force-modep] When executable counterpart is [enable]d, [force]d hypotheses are attacked immediately") (FORCED (POINTERS) "See [force].") (FORCING-ROUND (FORCE) "A section of a proof dealing with [force]d assumptions If ACL2 ``[force]s'' some hypothesis of some rule to be true, it is obliged later to prove the hypothesis. See [force]. ACL2 delays the consideration of [force]d hypotheses until the main goal has been proved. It then undertakes a new round of proofs in which the main goal is essentially the conjunction of all hypotheses [force]d in the preceding proof. Call this round of proofs the ``Forcing Round.'' Additional hypotheses may be [force]d by the proofs in the Forcing Round. The attempt to prove these hypotheses is delayed until the Forcing Round has been successfully completed. Then a new Forcing Round is undertaken to prove the recently [force]d hypotheses and this continues until no hypotheses are [force]d. Thus, there is a succession of Forcing Rounds. The Forcing Rounds are enumerated starting from 1. The Goals and Subgoals of a Forcing Round are printed with the round's number displayed in square brackets. Thus, \"[1]Subgoal 1.3\" means that the goal in question is Subgoal 1.3 of the 1st forcing round. To supply a hint for use in the proof of that subgoal, you should use the goal specifier \"[1]Subgoal 1.3\". See [goal-spec]. When a round is successfully completed --- and for these purposes you may think of the proof of the main goal as being the 0th forcing round --- the system collects all of the assumptions [force]d by the just-completed round. Here, an assumption should be thought of as an implication, (implies context hyp), where context describes the context in which hyp was assumed true. Before undertaking the proofs of these assumptions, we try to ``clean them up'' in an effort to reduce the amount of work required. This is often possible because the [force]d assumptions are generated by the same rule being applied repeatedly in a given context. By delaying and collecting the forced assumptions until the completion of the ``main goal'' we gain two advantages. First, the user gets confirmation that the ``gist'' of the proof is complete and that all that remains are ``technical details.'' Second, by delaying the proofs of the [force]d assumptions ACL2 can undertake the proof of each assumption only once, no matter how many times it was [force]d in the main goal. In order to indicate which proof steps of the previous round were responsible for which [force]d assumptions, we print a sentence explaining the origins of each newly [force]d goal. For example, [1]Subgoal 1, below, will focus on (GOOD-INPUTP (XTRANS I)), which was forced in Subgoal 14, above, by applying (:REWRITE PRED-CRUNCHER) to (PRED (XTRANS I) I), and Subgoal 28, above, by applying (:REWRITE PRED-CRUNCHER) to (PRED (XTRANS I) I). In this entry, ``[1]Subgoal 1'' is the name of a goal which will be proved in the next forcing round. On the next line we display the [force]d hypothesis, call it x, which is (good-inputp (xtrans i)) in this example. This term will be the conclusion of the new subgoal. Since the new subgoal will be printed in its entirety when its proof is undertaken, we do not here exhibit the context in which x was [force]d. The sentence then lists (possibly a succession of) a goal name from the just-completed round and some step in the proof of that goal that [force]d x. In the example above we see that Subgoals 14 and 28 of the just-completed proof [force]d (good-inputp (xtrans i)) by applying (:rewrite pred-cruncher) to the term (pred (xtrans i) i). If one were to inspect the theorem prover's description of the proof steps applied to Subgoals 14 and 28 one would find the word ``[force]d'' (or sometimes ``forcibly'') occurring in the commentary. Whenever you see that word in the output, you know you will get a subsequent forcing round to deal with the hypotheses [force]d. Similarly, if at the beginning of a forcing round a [rune] is blamed for causing a [force] in some subgoal, inspection of the commentary for that subgoal will reveal the word ``[force]d'' after the rule name blamed. Most [force]d hypotheses come from within the prover's simplifier. When the simplifier encounters a hypothesis of the form (force hyp) it first attempts to establish it by rewriting hyp to, say, hyp'. If the truth or falsity of hyp' is known, forcing is not required. Otherwise, the simplifier actually [force]s hyp'. That is, the x mentioned above is hyp', not hyp, when the [force]d subgoal was generated by the simplifier. Once the system has printed out the origins of the newly [force]d goals, it proceeds to the next forcing round, where those goals are individually displayed and attacked. At the beginning of a forcing round, the [enable]d structure defaults to the global [enable]d structure. For example, suppose some [rune], rune, is globally [enable]d. Suppose in some event you [disable] the [rune] at \"Goal\" and successfully prove the goal but [force] \"[1]Goal\". Then during the proof of \"[1]Goal\", [rune] is [enable]d ``again.'' The right way to think about this is that the [rune] is ``still'' [enable]d. That is, it is [enable]d globally and each forcing round resumes with the global [enable]d structure.") (FORMULA (HISTORY WORLD ACL2-BUILT-INS) "The formula of a name or [rune] The ACL2 system function, formula, returns the [term] associated with a given [rune] or symbolic name, returning nil if there is no such term. Note that a non-nil result will be an ACL2 ``translated'' term (see [term]). Most ACL2 users probably will have no reason to know about this function. But here we document this function for those who write system-level tools, since they might find this interface to the ACL2 logical world to be useful. When ACL2 is given a :use or :by hint, it looks for the [term] stored in the ACL2 logical [world] that is associated with the name given in the hint, which is a symbol or a [rune]. (See (@see lemma-instance).) The utility used to find that term is formula, which ACL2 invokes as follows. (formula x t wrld) ; for :use hints (formula x nil wrld) ; for :by hints The second argument can affect whether or not to use a ``normalized'' version of the term associated with x. The value is t for :use [hints] because normalizing a term simplifies it, which is often desirable. But for a :by hint, the non-normalized version of the term is used in order to increase the chance that the necessary subsumption test will succeed. Even if the second argument is t, normalization might not take place. In the unlikely case that you really need to know the effect of supplying t, see the source code for formula. Here are some examples. Note that (w state) returns the current ACL2 logical world. First let us submit a few [events]. (defun f1 (x) (cons 3 x)) (defun f2 (x y) (implies x y)) (defthm one-rule (and (equal (* 2 y) (+ y y)) (equal (* 3 y) (+ y y y)))) (defthm two-rules t :rule-classes ((:rewrite :corollary (equal (* 2 y) (+ y y))) (:rewrite :corollary (equal (* 3 y) (+ y y y))))) Then: ACL2 !>(formula 'f1 nil (w state)) (EQUAL (F1 X) (CONS '3 X)) ACL2 !>(formula 'f1 t (w state)) (EQUAL (F1 X) (CONS '3 X)) ACL2 !>(formula 'f2 nil (w state)) (EQUAL (F2 X Y) (IMPLIES X Y)) ACL2 !>(formula 'f2 t (w state)) (EQUAL (F2 X Y) (IF X (IF Y 'T 'NIL) 'T)) ACL2 !>(formula 'one-rule nil (w state)) (IF (EQUAL (BINARY-* '2 Y) (BINARY-+ Y Y)) (EQUAL (BINARY-* '3 Y) (BINARY-+ Y (BINARY-+ Y Y))) 'NIL) ACL2 !>(equal (formula 'one-rule nil (w state)) (formula 'one-rule t (w state))) T ACL2 !>(formula 'two-rules nil (w state)) 'T ACL2 !>(formula 'two-rules t (w state)) 'T ACL2 !>(formula '(:rewrite two-rules . 1) nil (w state)) (EQUAL (BINARY-* '2 Y) (BINARY-+ Y Y)) ACL2 !>(formula '(:rewrite two-rules . 2) nil (w state)) (EQUAL (BINARY-* '3 Y) (BINARY-+ Y (BINARY-+ Y Y))) ACL2 !>(formula 'no-such-rule nil (w state)) NIL ACL2 !>") (FORWARD-CHAINING (RULE-CLASSES) "Make a rule to forward chain when a certain trigger arises See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. Examples: (defthm p-and-r-forward ; When (p a) appears in a formula to be (implies (and (p x) (r x)) ; simplified, try to establish (p a) and (q (f x))) ; (r a) and, if successful, add (q (f a)) :rule-classes :forward-chaining) ; to the known assumptions. (defthm p-and-r-forward ; as above with most defaults filled in (implies (and (p x) (r x)) (q (f x))) :rule-classes ((:forward-chaining :trigger-terms ((p x)) :corollary (implies (and (p x) (r x)) (q (f x))) :match-free :all))) To specify the triggering terms provide a non-empty list of terms as the value of the :trigger-terms field of the rule class object. General Form: Any theorem, provided an acceptable triggering term exists. The structure of this documentation is as follows. First we give a brief overview of forward chaining and contrast it to backchaining (rewriting). Then we lay out the syntactic restrictions on :forward-chaining rules. Then we give more details about the process and point to a tool to assist you in debugging your :forward-chaining rules. Overview and When to Use Forward Chaining Forward chaining is performed as part of the simplification process: before the goal is rewritten a context is established. The context tells the theorem prover what may be assumed during rewriting, in particular, to establish hypotheses of rewrite rules. Forward chaining is used to extend the context before rewriting begins. For example, the :forward-chaining rule (implies (p x) (p1 x)) would add (p1 A) to the context, where A is some term, if (p A) is already in the context. Forward chaining and backchaining are duals. If a rewrite rule requires that (p1 A) be established and (p A) is known, it could be done either by making (implies (p x) (p1 x)) a :forward-chaining rule or a :rewrite rule. Which should you choose? As a rule of thumb, if a conclusion like (p1 A) is expected to be widely needed, it is better to derive it via forward chaining because then it is available ``for free'' during the rewriting after paying the one-time cost of forward chaining. Alternatively, if (p1 A) is a rather special hypothesis of key importance to only a few rewrite rules, it is best to derive it only when needed. Thus forward chaining is pro-active and backward chaining (rewriting) is reactive. Syntactic Restrictions Forward chaining rules are generated from the corollary term (see [rule-classes]) as follows. First, every [let] expression is expanded away (hence, so is every [let*] and [lambda] expression), and trivial ``guard holders'' are removed; see [guard-holders]. If the resulting term has the form (implies hyp concl), then concl is treated as a conjunction, with one forward chaining rule with hypothesis hyp created for each conjunct. In the other case, where the corollary term is not an [implies], we process it as we process the conclusion in the first case. Note that unlike rewrite rules, a nested implication is not folded into a single implication. Consider for example the following term. (implies (p1 x) (implies (p2 x) (p3 x))) Although this term is parsed for a rewrite rule as (implies (and (p1 x) (p2 x)) (p3 x)), that is not the case when this term is parsed for a forward-chaining rule, in which case (p1 x) is treated as the hypothesis and (implies (p2 x) (p3 x)) is treated as the conclusion. The :trigger-terms field of a :forward-chaining rule class object should be a non-empty list of terms, if provided, and should have certain properties described below. If the :trigger-terms field is not provided, it defaults to the singleton list containing the ``atom'' of the first hypothesis of the formula. (The atom of (not x) is x; the atom of any other term is the term itself.) If there are no hypotheses and no :trigger-terms were provided, an error is caused. A triggering term is acceptable if it is not a variable, a quoted constant, a lambda application, a [let]- (or [let*]-) expression, or a [not]-expression, and every variable symbol in the conclusion of the theorem either occurs in the hypotheses or occurs in the trigger. More Details about Forward Chaining :Forward-chaining rules are used by the simplifier before it begins to rewrite the literals of the goal. (Forward chaining is thus carried out from scratch for each goal.) If any term in the goal is an instance of a trigger of some forward chaining rule, we try to establish the hypotheses of that forward chaining theorem (from the negation of the goal). To relieve a hypothesis we only use type reasoning, evaluation of ground terms, and presence among our known assumptions. We do not use rewriting. So-called free variables in hypotheses are treated specially; see [free-variables]. If all hypotheses are relieved, and certain heuristics approve of the newly derived conclusion, we add the instantiated conclusion to our known assumptions. Since this might introduce new terms into the assumptions, forward chaining is repeated. Heuristic approval of each new addition is necessary to avoid infinite looping as would happen with the rule (implies (p x) (p (f x))), which might otherwise forward chain from (p A) to (p (f A)) to (p (f (f A))), etc. Caution. Forward chaining does not actually add terms to the goals displayed during proof attempts. Instead, it extends an associated context, called ``assumptions'' in the preceding paragraph, that ACL2 builds from the goal currently being proved. (For insiders: forward chaining extends the [type-alist].) The context starts out with ``obvious'' consequences of the negation of the goal. For example, if the goal is (implies (and (p A) (q (f A))) (c A)) then the context notes that (p A) and (q (f A)) are non-nil and (c A) is nil. Forward chaining is then used to expand the context. For example, if a forward chaining rule has (f x) as a trigger term and has body (implies (p x) (r (f x))), then the context is extended by binding (r (f A)) to non-nil, provided the heuristics approve of this extension. Note however that since (r (f A)) is put into the context, not the goal, you will not see it in the goal formula. Furthermore, the assumption added to the context is just the instantiation of the conclusion of the rule, with no simplification or rewriting applied. Thus, for example, if it contains an enabled non-recursive function symbol it is unlikely ever to match a (rewritten) term arising during subsequent simplification of the goal. However, forward-chaining does support the linear arithmetic reasoning package. For example, suppose that forward-chaining puts (< (f x) (g x)) into the context. Then this inequality also goes into the linear arithmetic database, together with suitable instances of linear lemmas whose trigger term is a call of g. See [linear]. Debugging :forward-chaining rules can be difficult since their effects are not directly visible on the goal being simplified. Tools are available to help you discover what forward chaining has occurred see [forward-chaining-reports]. Subtopics [Case-split] Like force but immediately splits the top-level goal on the hypothesis [Forward-chaining-reports] To see reports about the forward chaining process") (FORWARD-CHAINING-REPORTS (FORWARD-CHAINING DEBUGGING) "To see reports about the forward chaining process Debugging forward-chaining rules can be hard because their effects are not directly visible on the goal. In this documentation we tell you how to get reports on the forward chaining activity occurring in your proof attempts. This documentation is written in several parts. The first part is an introduction for the first-time user of forward chaining reports. The next two parts describe how to read reports. The last part describes how to monitor forward chaining activity only for selected runes, etc. We recommend the new user of these reports read everything! A Quick Introduction to Forward Chaining Reports Caution: The reporting mechanism maintains some state, and if you have already used forward chaining reporting in a session, the directions below may not work as advertised! To return to the default forward chaining reporting state, execute this form at the top level: (reset-fc-reporting) You can get a report about all forward chaining activity in subsequent proofs by doing: (set-fc-criteria t) Options will be discussed later that allow you to monitor the activity caused by particular :forward-chaining rules or terms. Then do a proof that is expected to cause some forward chaining. In the proof output you will see lines like this: (Forward Chaining on behalf of PREPROCESS-CLAUSE: (FC-Report 1)) This is the only difference you should see in the proof output. After the proof attempt has terminated, you can execute: (fc-report k) for any k printed during the immediately preceding proof attempt. That will print a much longer report describing the activity that occurred during the kth use of forward chaining in that proof attempt. If you want to see these reports in real time (embedded in the proof output), do this before invoking the prover: (set-fc-report-on-the-fly t) Collecting the data used to generate these reports slows down the prover. If you no longer wish to see such reports, do (set-fc-criteria nil) How To Read FC Reports The report printed by (fc-report k) is of the form: Forward Chaining Report k: Caller: token Clause: (lit1 lit2 ... litn) Number of Rounds: m Contradictionp: bool Activations: (act1 act2 ...) This report means that the kth use of forward chaining in the most recent proof attempt was done on behalf of token (see below). The initial context (set of assumptions) consisted of the negations of the literals listed in the clause shown and the initial candidate trigger terms are all those appearing in that clause. This invocation of forward chaining proceeded to do m rounds of successive extensions of the initial context and ultimately either reached a contradiction (bool = T) or returned an extended context (bool = NIL). Note that reaching a contradiction from the negations of all the literals in a clause is ``good'' because it means the clause is true. The report concludes with the final status of all the forward chaining rules fired during the process. We explain how to read one of these activation reports in the next section. Forward chaining is done on behalf of many proof techniques in the system. Each is associated with a token. The main proof technique that uses forward chaining is SIMPLIFY-CLAUSE. This is the call of forward chaining that sets up the context used by the rewriter to relieve hypotheses during backchaining. Another common caller of forward chaining is PREPROCESS-CLAUSE, the first process in the ACL2 waterfall (see [hints-and-the-waterfall]). Forward chaining often proves ``near propositional'' goals (those depending just on boolean implications between basic predicates). Other tokens you may see include INDUCT, which uses forward chaining to set up a context for applying :[induction] rules, and the definitional principle (and related utilities such as [verify-termination] and [verify-guards]) which uses forward chaining during the construction of both measure conjectures and guard conjectures. When used this way, the token is defun-or-guard-verification. How to Read Activation Reports The forward chaining report concludes with a list of activation reports. Activations: (act1 act2 ...) Each acti is of the form: (rune (:TRIGGER inst-trig) ((:UNIFY-SUBST subst) (:DISPOSITION outcome-part1 outcome-part2 inst-term)) ...) where the ... indicates that the rest of the report consists of more of those tuples listing a :UNIFY-SUBST and :DISPOSITION. We call each tuple a disposition of the activation and each disposition describes a substitution subst identifying the final instantiation of the rule and how the activation fared. Suppose there are n dispositions. (If the rule in question contains no free variables, n will be 1.) This activation report means that during the forward chaining process in question, the :[forward-chaining] [rune] rune was fired due to the presence in the evolving context of the trigger term inst-trig. (Note that inst-trig is an instantiation of the trigger term of the named rule. That is, the variable symbols you see in inst-trig are those of the clause printed in the forward chaining report.) The activation of rune by inst-trig proceeded to split n ways as different choices were made for the [free-variables] occuring among the hypotheses. Each of those n choices gave rise to a different substitution subst, and each succeeded or failed as described by the corresponding :DISPOSITION. The :DISPOSITION of an activation is described in three parts, outcome-part1, outcome-part2, and inst-term. Outcome-part1 is either SUCCESS or BLOCKED, meaning that the instance given by subst either succeeded in the sense that all of its instantiated hypotheses were found in the context, or failed because some instantiated hypothesis was not found. If outcome-part1 is SUCCESS then inst-term is the instantiated conclusion produced by the rule. Outcome-part2 is APPROVED if the instantiated conclusion was acceptable to our heuristics designed to prevent looping and not already known in the evolving context. Outcome-part2 is REJECTED if the instantiated conclusion was not approved by our heuristics. Outcome-part2 is REDUNDANT if the instantiated conclusion was approved by the heuristics but already known true in the current evolving context. If APPROVED, the truth of the instantiated conclusion is added to the evolving context. Otherwise, it is not. If outcome-part1 is BLOCKED then outcome-part2 is one of three possible things: FALSE, in which case inst-term is an instantiated hypothesis of the rule that is assumed false in the current context, UNRELIEVED-HYP, in which case inst-term is an instantiated hypothesis whose truthvalue is not determined by the context, or UNRELIEVED-HYP-FREE, in which case inst-term is an oddly instantiated hypothesis whose truthvalue is not determined by the context and which also contains free variables. In the last case, the ``odd'' instantiation was by the substitution subst but extended so that free variables in the hypothesis are renamed to start with the prefix UNBOUND-FREE- to draw your attention to them. Note: All of the terms printed in the report are instantiated with the relevant unifying substitution (possibly extended to bind free variables). Specifying the Tracking Criteria During a proof attempt, the forward chaining module stores information about the activations satisfying certain criteria. The criteria is a list of triples. Each triple consists of a forward chaining rune, an instantiated trigger term, and an instantiated conclusion to watch for. However, any or all of the components of such a triple may be t and that is given special significance. An activation satisfies a criteria if it satisfies at least one of the triples. An activation satisfies a triple if it satisfies all three of the components. Every activation satisfies the component t. An activation satisfies a rune if the activation describes a firing of the named rule. An activation satisfies an instantiated trigger term if the activation was created by that trigger being present in the context. An activation satisfies an instantiated conclusion if the activation could produce the instantiated conclusion (with the right choice of any free variables). Thus, the criteria is interpreted as a disjunction of conjunctions, making it possible to track a specific set of runes, triggers, and conclusions. For example, here is a triple that might appear in the criteria: ((:FORWARD-CHAINING ALISTP-FORWARD-TO-TRUE-LISTP) t t). This triple would cause every activation of the given rule to be tracked. However, the triple ((:FORWARD-CHAINING ALISTP-FORWARD-TO-TRUE-LISTP) (ALISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S)))) t) would only track activations of that rule fired by the specific term shown as the second element of the triple. Futhermore (t (ALISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S)))) t) would track any forward chaining rule triggered by that term, and (t t (TRUE-LISTP (MAKE-BINDINGS VARS (TOP-N (OP1 INST) (STACK S))))) would track any rule fired by any trigger that might lead to the specific term given as the third component above. Note: The condition on how an activation satisfies an instantiated conclusion is a little subtle. Consider the activation of the forward chaining rule (implies (and (symbol-listp x) (equal (len x) (len y))) (true-listp (make-bindings x y))) triggered by (SYMBOL-LISTP VARS) arising in the current context. This activation could produce the specific conclusion shown in the last triple above, if it just happened that (TOP-N (OP1 INST) (STACK S)) were chosen as the binding of the free variable y. Thus, the activation of this rule triggered by (SYMBOL-LISTP VARS) satisfies the last triple above. Observe that the triple (t t t) is satisfied by every activation of any rule by any trigger term producing any conclusion. The function set-fc-criteria sets the criteria describing which activations are to be tracked. For example, if you execute: (set-fc-criteria ((:FORWARD-CHAINING LEMMA1) t t) ((:FORWARD-CHAINING LEMMA2) (ALISTP (BASIC-MAPPER A B)) t) (t t (TRUE-LISTP (DLT D)))), the system would track all activations of the forward-chaining rule LEMMA1, plus those activations of forward-chaining rule LEMMA2 triggered by the term given in the second triple, plus any activation of any rule that might derive (TRUE-LISTP (DLT D)). Because criteria generally mention variable symbols used in a specific conjecture, it is probably best to reconsider your criteria every time you want to track forward chaining. If the criteria is nil, then nothing is tracked. Setting the criteria to nil is the way you turn off tracking and reporting of forward chaining activity. You may do this either by (set-fc-criteria) or by (set-fc-criteria nil). (Technically the second form is an odd use of set-fc-criteria, which expects any supplied arguments to be triples; if the ``triple'' nil is the only one supplied, we take it to mean that the entire criteria should be nil.) To track every forward chaining activation you may set the criteria with either (set-fc-criteria (t t t)) or use the abbreviation (set-fc-criteria t). If, when you read a forward chaining report, you see no mention of an activation you have in mind, e.g., of a certain rune or deriving a certain conclusion, and you have set the criteria correctly, then the activation never happened. (This is akin to using :[brr] and :[monitor] to monitor the application of a rewrite rule and then seeing no interactive break.) For some relevant functions to help you manage criteria and when the full reports are printed see [fc-report], [show-fc-criteria], [set-fc-criteria], [reset-fc-reporting], and [set-fc-report-on-the-fly]. Subtopics [Fc-report] To report on the forward chaining activity in the most recent proof [Reset-fc-reporting] Reset the forward-chaining tracking state to its initial configuration [Set-fc-criteria] To set the tracking criteria for forward chaining reports [Set-fc-report-on-the-fly] To determine when forward-chaining reports are printed [Show-fc-criteria] Print the forward-chaining tracking criteria") (FOURTH (NTH ACL2-BUILT-INS) "Fourth member of the list See any Common Lisp documentation for details.") (FREE-VARIABLES (RULE-CLASSES REWRITE) "Free variables in rules As described elsewhere (see [rule-classes]), ACL2 rules are treated as implications for which there are zero or more hypotheses hj to prove. In particular, rules of class :[rewrite] may look like this: (implies (and h1 ... hn) (fn lhs rhs)) Variables of hi are said to occur free in the above :rewrite rule if they do not occur in lhs or in any hj with j *)) (local (defun op (x y) (< x y))) (defthm transitivity-of-op (implies (and (op x y) (op y z)) (op x z)) :rule-classes :forward-chaining)) ; The following theorem is proved by forward chaining, using the above rule. (thm (implies (and (op u v) (op v w) (op v a)) (op u w))) ; The proof of the theorem just above succeeds because the term (op u v) ; triggers the application of forward-chaining rule transitivity-of-op, ; binding x to u and y to v. Free variable z of that rule is bound to both w ; and to a, resulting in the addition of both (op u w) and (op u a) to the ; context. However, (op v a) happens to be at the front of the context, so ; if only one free-variable binding had been allowed, then z would have only ; been bound to a, not to w, as we now illustrate. (add-match-free-override :once (:forward-chaining transitivity-of-op)) (thm ; FAILS! (implies (and (op u v) (op v w) (op v a)) (op u w))) :ubt! 1 ; Starting over, this time we prove transitivity-of-op as a :match-free :once ; forward-chaining rule. Note that the presence of :match-free eliminates ; the free-variables warning that we got the first time. (encapsulate (((op * *) => *)) (local (defun op (x y) (< x y))) (defthm transitivity-of-op (implies (and (op x y) (op y z)) (op x z)) :rule-classes ((:forward-chaining :match-free :once)))) (thm ; FAILS! (implies (and (op u v) (op v w) (op v a)) (op u w))) ; Notice that if we swap the order of the last two hypotheses the theorem ; goes through, because this time (op v w) is first in the context. (thm ; SUCCEEDS! (implies (and (op u v) (op v a) (op v w)) (op u w))) :u ; Now let's try setting the default to :once. (set-match-free-default :once) ; We still get a free-variables warning when we admit this forward-chaining rule. (encapsulate (((op * *) => *)) (local (defun op (x y) (< x y))) (defthm transitivity-of-op (implies (and (op x y) (op y z)) (op x z)) :rule-classes ((:forward-chaining)))) ; This theorem fails--as it should. (thm ; FAILS! (implies (and (op u v) (op v w) (op v a)) (op u w))) ; But if we convert this rule (or here, all possible rules) to :all rules, ; then the proof succeeds. (add-match-free-override :all t) (thm ; SUCCEEDS! (implies (and (op u v) (op v w) (op v a)) (op u w))) ; Now let's test a relatively slow :all case (the next thm below). :ubt! 1 (encapsulate (((op1 *) => *) ((op3 * * *) => *)) (local (defun op1 (x) (declare (ignore x)) t)) (local (defun op3 (x0 x1 x2) (declare (ignore x0 x1 x2)) t)) (defthm op1-op3-property (implies (and (op1 x0) (op1 x1) (op1 x2)) (op3 x0 x1 x2)) :rule-classes ((:forward-chaining :match-free :all)))) ; The following succeeds, but takes a little time (about a second in one run). (thm (implies (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5) (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11) (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16) (op1 a17) (op1 a18) (op1 a19) (op1 a20)) (op3 a5 a6 a0))) (add-match-free-override :once t) ; The same theorem now fails because of the add-match-free-override, but is ; more than an order of magnitude faster. (thm (implies (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5) (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11) (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16) (op1 a17) (op1 a18) (op1 a19) (op1 a20)) (op3 a5 a6 a0))) ; A slight variant succeeds in a negligible amount of time (still with the ; :once override above). (thm (implies (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5) (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11) (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16) (op1 a17) (op1 a18) (op1 a19) (op1 a20)) (op3 a5 a20 a20))) ; Reality check: This shouldn't give a free-variables warning, and everything ; should work great since there are no free variables with this trigger term. :ubt! 1 (encapsulate (((op1 *) => *) ((op7 * * * * * * *) => *)) (local (defun op1 (x) (declare (ignore x)) t)) (local (defun op7 (x0 x1 x2 x3 x4 x5 x6) (declare (ignore x0 x1 x2 x3 x4 x5 x6)) t)) (defthm op1-op7-property (implies (and (op1 x0) (op1 x1) (op1 x2) (op1 x3) (op1 x4) (op1 x5) (op1 x6)) (op7 x0 x1 x2 x3 x4 x5 x6)) :rule-classes ((:forward-chaining :trigger-terms ((op7 x0 x1 x2 x3 x4 x5 x6)))))) ; The following then succeeds, and very quickly. (thm (implies (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5) (op1 a6)) (op7 a4 a6 a5 a6 a6 a6 a6)))") (FREE-VARIABLES-EXAMPLES-REWRITE (FREE-VARIABLES-EXAMPLES) "Examples pertaining to free variables in [rewrite] rules The following examples illustrate ACL2's handling of free variables in [rewrite] rules, as well as user control over how such free variables are handled. See [free-variables] for a background discussion. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Example 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defstub p2 (x y) t) ; introduce unconstrained function ; Get warning because of free variable. This would be an error if you had ; first executed (set-match-free-error t) in order to force yourself to ; specify :match-free (illustrated later, below). (defaxiom p2-trans (implies (and (p2 x y) (p2 y z)) (p2 x z))) ; Succeeds. (thm (implies (and (p2 a c) (p2 a b) (p2 c d)) (p2 a d))) ; The following causes an error because p2-trans is not a rune. (add-match-free-override :once p2-trans) ; After the following, the rewrite rule p2-trans will only allow one ; attempt per hypothesis to bind free variables. (add-match-free-override :once (:rewrite p2-trans)) ; Now this same theorem fails to be proved. Here's why. The ; context for proving (p2 a d) happens to include the hypotheses in ; reverse order. So when the first hypothesis of p2-trans, namely ; (p2 x y), is relieved, where x is bound to a (as we are attempting ; to rewrite the current literal (p2 a d)), we find (p2 a b) in the ; context before (p2 a c) and hence y is bound to b. The ; instantiated second hypothesis of p2-trans is thus (p2 b d), and ; the proof fails. Before the add-match-free-override form above, ; the proof succeeded because the rewriter was allowed to backtrack ; and find the other binding for the first hypothesis of p2-trans, ; namely, y bound to c. Then the instantiated second hypothesis of ; p2-trans is (p2 c d), which is known to be true in the current ; context. (thm (implies (and (p2 a c) (p2 a b) (p2 c d)) (p2 a d))) ; Return to original behavior for binding free variables. (add-match-free-override :all t) ; Succeeds once again. (thm (implies (and (p2 a c) (p2 a b) (p2 c d)) (p2 a d))) (u) ; undo (add-match-free-override :all t) ; This is an error, since no further arguments should appear after ; :clear. (add-match-free-override :clear t) ; Return all rules to original behavior for binding free variables, ; regardless of which previous add-match-free-override forms have ; been executed. (add-match-free-override :clear) ; This succeeds just as it did originally. (thm (implies (and (p2 a c) (p2 a b) (p2 c d)) (p2 a d))) (ubt! 'p2-trans) ; back to the start, except retain the defstub ; Require that :match-free be specified for :linear and :rewrite rules with ; free variables. (set-match-free-error t) ; Fails because :match-free is missing. (defaxiom p2-trans (implies (and (p2 x y) (p2 y z)) (p2 x z))) ; Fails because :match-free must be followed by :once or :all. (defaxiom p2-trans (implies (and (p2 x y) (p2 y z)) (p2 x z)) :rule-classes ((:rewrite :match-free nil))) ; Succeeds, this time with no warning at all. (defaxiom p2-trans (implies (and (p2 x y) (p2 y z)) (p2 x z)) :rule-classes ((:rewrite :match-free :once))) ; Fails because we only bind once (see earlier long comment). (thm (implies (and (p2 a c) (p2 a b) (p2 c d)) (p2 a d))) ; Treat p2-trans as though `:match-free :all' had been specified. (add-match-free-override :all (:rewrite p2-trans)) ; Succeeds since more than one binding is allowed for p2-trans. (thm (implies (and (p2 a c) (p2 a b) (p2 c d)) (p2 a d))) (u) (u) ; Specify that future :linear and :rewrite rules with free variables ; that do not have :match-free specified are treated as though ; `:match-free :once' were specified. (set-match-free-default :once) ; Succeeds without error since `:match-free' is specified, as described ; above. But there is a warning, since :match-free is not specified for this ; :rewrite rule. (defaxiom p2-trans (implies (and (p2 x y) (p2 y z)) (p2 x z))) ; Fails since only single bindings are allowed for p2-trans. (thm (implies (and (p2 a c) (p2 a b) (p2 c d)) (p2 a d))) ; Treat p2-trans as though `:match-free :all' had been specified. (add-match-free-override :all t) ; Succeeds. (thm (implies (and (p2 a c) (p2 a b) (p2 c d)) (p2 a d))) ; Test searching of ground units, i.e. rewrite rules without variables on the ; left side of the conclusion, for use in relieving hypotheses with free ; variables. This is a very contrived example. (ubt! 1) ; back to the start (encapsulate (((p1 *) => *) ((p2 * *) => *) ((p3 *) => *) ((a) => *) ((b) => *)) (local (defun p1 (x) x)) (local (defun p2 (x y) (list x y))) (local (defun p3 (x) x)) (local (defun a () 0)) (local (defun b () 0))) ; Allow default of :match-free :all (form may be omitted). (set-match-free-error nil) (defaxiom ax1 (implies (and (p2 x y) (p1 y)) (p3 x))) (defaxiom p2-a-b (p2 (a) (b))) (defaxiom p2-a-a (p2 (a) (a))) (defaxiom p1-b (p1 (b))) ; Succeeds; see long comment below on next attempt to prove this ; theorem. (thm (implies (p2 (a) y) (p3 (a)))) ; Now ax1 will only relieve hypothesis (p2 x y) for one binding of y: (add-match-free-override :once t) ; Fails when ax1 attempts to rewrite the conclusion to true, because ; the most recent ground unit for hypothesis (p2 x y) with x bound ; to (a) is rule p2-a-a, which binds y to (a). If more than one ground ; unit could be used then we would backtrack and apply rule p2-a-b, ; which binds y to (b) and hence hypothesis (p1 y) of ax1 is ; relieved by rule p1-b. (thm (implies (p2 (a) y) (p3 (a)))) ; Return rules to original :match-free behavior. (add-match-free-override :clear) ; Succeeds once again. (thm (implies (p2 (a) y) (p3 (a)))) ; Just for kicks, change the behavior of a built-in rule irrelevant ; to the proof at hand. (add-match-free-override :once (:rewrite string<-l-trichotomy)) ; Still succeeds. (thm (implies (p2 (a) y) (p3 (a)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Example 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; The next example illustrates the use of the [break-rewrite] facility to get information about handling of free variables by the rewriter. Explanation is given after this (edited) transcript. Input begins on lines with a prompt (search for ``ACL2''); the rest is output. ACL2 !>(encapsulate ((p1 (u x) t) (bad (x) t) (p2 (x y z) t) (bar (x y) t) (foo (x y) t) (poo (x y) t) (prop (u) t)) (local (defun p1 (u x) (declare (ignore u x)) nil)) (local (defun bad (x) (declare (ignore x)) nil)) (local (defun p2 (x y z) (declare (ignore x y z)) nil)) (local (defun bar (x y) (declare (ignore x y)) nil)) (local (defun foo (x y) (declare (ignore x y)) nil)) (local (defun poo (x y) (declare (ignore x y)) nil)) (local (defun prop (u) (declare (ignore u)) t)) (defthm foo-poo (implies (syntaxp (equal y 'y3)) (equal (foo x y) (poo x y)))) (defthm lemma-1 (implies (and (p1 u x) (bad x) (p2 x y z) (bar x y) (equal x x) ; admittedly silly! (foo x y)) (prop u)) :rule-classes ((:rewrite :match-free :all)))) ; [[ output omitted ]] Summary Form: ( ENCAPSULATE ((P1 ...) ...) ...) Rules: NIL Warnings: Subsume and Non-rec Time: 0.08 seconds (prove: 0.00, print: 0.01, other: 0.06) T ACL2 !>:brr t The monitored runes are: NIL T ACL2 !>:monitor (:rewrite lemma-1) t (((:REWRITE LEMMA-1) 'T)) ACL2 !>(thm (implies (and (p1 u0 x1) (bad x1) (bad x3) (bar x3 y1) (bar x3 y3) (p1 u0 x2) (p1 u0 x3) (p2 x3 y1 z1) (p2 x3 y3 z1)) (prop u0))) (1 Breaking (:REWRITE LEMMA-1) on (PROP U0): 1 ACL2 >:eval 1x (:REWRITE LEMMA-1) failed because :HYP 1 contains free variables. The following display summarizes the attempts to relieve hypotheses by binding free variables; see :DOC free-variables. [1] X : X1 Failed because :HYP 3 contains free variables Y and Z, for which no suitable bindings were found. [1] X : X2 Failed because :HYP 2 rewrote to (BAD X2). [1] X : X3 [3] Z : Z1 Y : Y1 Failed because :HYP 6 rewrote to (FOO X3 Y1). [3] Z : Z1 Y : Y3 Failed because :HYP 6 rewrote to (POO X3 Y3). 1 ACL2 >:unify-subst U : U0 1 ACL2 > The :eval command above asks the rewriter to attempt to apply the rewrite rule lemma-1 to the term (prop u0), shown just above the line with :eval. As we can see at the end, the variable u in the conclusion of lemma-1 is being bound to the variable u0 in the conjecture. The first hypothesis of lemma-1 is (p1 u x), so the rewriter looks for some x for which (p1 u0 x) is known to be true. It finds x1, and then goes on to consider the second hypothesis, (bad x). Since the theorem we are proving has (bad x1) in the hypothesis and x is currently bound to x1, the rewriter is satisfied and moves on to the third hypothesis of lemma-1, (p2 x y z). However, x is bound to x1 and there are no instances of y and z for which (p2 x1 y z) is known in the current context. All of the above analysis is summarized in the first part of the output from :eval above: [1] X : X1 Failed because :HYP 3 contains free variables Y and Z, for which no suitable bindings were found. Thus, the binding of x to x1 on behalf of the first hypothesis has failed. The rewriter now backs up to look for other values of x that satisfy the first hypothesis, and finds x2 because our current theorem has a hypothesis of (p1 u0 x2). But this time, the second hypothesis of lemma-1, (bad x), is not known to be true for x; that is, (bad x2) does not rewrite to t; in fact, it rewrites to itself. That explains the next part of the output from :eval above: [1] X : X2 Failed because :HYP 2 rewrote to (BAD X2). The rewriter now backs up again to look for other values of x that satisfy the first hypothesis, and finds x3 because our current theorem has a hypothesis of (p1 u0 x3). This time, the second hypothesis of lemma-1 is not a problem, and moreover, the rewriter is able to bind y and z to y1 and z1, respectively, in order to satisfy the third hypothesis, (p2 x y z): that is, (p2 x2 y1 z1) is known in the current context. That explains more of the above output from :eval: [1] X : X3 [3] Z : Z1 Y : Y1 Unfortunately, the sixth hypothesis, (foo x y), rewrites to itself under the above bindings: Failed because :HYP 6 rewrote to (FOO X3 Y1). So the rewriter looks for other bindings to satisfy the third hypothesis and finds these. [3] Z : Z1 Y : Y3 This time, the sixth hypothesis can be rewritten under the above bindings, from (foo x3 y3) to (poo x3 y3) by lemma foo-poo, but still not to t. Failed because :HYP 6 rewrote to (POO X3 Y3). There are no more free variable bindings to try, so this concludes the output from :eval. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Example 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; The next pair of examples illustrates so-called ``binding hypotheses'' (see [free-variables]) and explores some of their subtleties. The first shows binding hypotheses in action on a simple example. The second shows how binding hypotheses interact with equivalence relations and explains the role of [double-rewrite]. Our first example sets up a theory with two user-supplied rewrite rules, one of which has a binding hypothesis. Below we explain how that binding hypothesis contributes to the proof. ; Define some unary functions. (defun f (x) (declare (ignore x)) t) (defun g (x) x) (defun h (x) x) (defun k (x) x) ; Prove some simple lemmas. Note the binding hypothesis in g-rewrite. (defthm f-k-h (f (k (h x)))) (defthm g-rewrite (implies (and (equal y (k x)) ; binding hypothesis (f y)) (equal (g x) y))) ; Restrict to a theory that includes the above lemmas but avoids the above ; definitions. (in-theory (union-theories (theory 'minimal-theory) '(f-k-h g-rewrite))) ; Prove a theorem. (thm (equal (g (h a)) (k (h a)))) Let us look at how ACL2 uses the above binding hypothesis in the proof of the preceding thm form. The rewriter considers the term (g (h a)) and finds a match with the left-hand side of the rule g-rewrite, binding x to (h a). The first hypothesis binds y to the result of rewriting (k x) in the current context, where the variable x is bound to the term (h a); thus y is bound to (k (h a)). The second hypothesis, (f y), is then rewritten under this binding, and the result is t by application of the rewrite rule f-k-h. The rule g-rewrite is then applied under the already-mentioned binding of x to (h a). This rule application triggers a recursive rewrite of the right-hand side of g-rewrite, which is y, in a context where y is bound (as discussed above) to (k (h a)). The result of this rewrite is that same term, (k (h a)). The original call of equal then trivially rewrites to t. We move on now to our second example, which is similar but involves a user-defined equivalence relation. You may find it helpful to review :equivalence rules; see [equivalence]. Recall that when a hypothesis is a call of an equivalence relation other than equal, the second argument must be a call of [double-rewrite] in order for the hypothesis to be treated as a binding hypothesis. That is indeed the case below; an explanation follows. ; Define an equivalence relation. (defun my-equiv (x y) (equal x y)) (defequiv my-equiv) ; introduces rule MY-EQUIV-IS-AN-EQUIVALENCE ; Define some unary functions (defun f (x) (declare (ignore x)) t) (defun g (x) x) (defun h1 (x) x) (defun h2 (x) x) ; Prove some simple lemmas. Note the binding hypothesis in lemma-3. (defthm lemma-1 (my-equiv (h1 x) (h2 x))) (defthm lemma-2 (f (h2 x))) (defthm lemma-3 (implies (and (my-equiv y (double-rewrite x)) ; binding hypothesis (f y)) (equal (g x) y))) ; Restrict to a theory that includes the above lemmas but avoids the above ; definitions. (in-theory (union-theories (theory 'minimal-theory) '(lemma-1 lemma-2 lemma-3 my-equiv-is-an-equivalence))) ; Prove a theorem. (thm (equal (g (h1 a)) (h2 a))) The proof succeeds much as in the first example, but the following observation is key: when ACL2 binds y upon considering the first hypothesis of lemma-3, it rewrites the term (double-rewrite x) in a context where it need only preserve the equivalence relation my-equiv. At this point, x is bound by applying lemma-3 to the term (g (h1 a)); so, x is bound to (h1 a). The rule lemma-1 then applies to rewrite this occurrence of x to (h2 a), but only because it suffices to preserve my-equiv. Thus y is ultimately bound to (h2 a), and the proof succeeds as one would expect. If we tweak the above example slightly by disabling the user's [equivalence] [rune], then the proof of the [thm] form fails because the above rewrite of (double-rewrite x) is done in a context where it no longer suffices to preserve my-equiv as we dive into the second argument of my-equiv in the first hypothesis of lemma-3; so, lemma-1 does not apply this time. (in-theory (union-theories (theory 'minimal-theory) '(lemma-1 lemma-2 lemma-3))) ; Proof fails in this case! (thm (equal (g (h1 a)) (h2 a)))") (FREE-VARIABLES-TYPE-PRESCRIPTION (FREE-VARIABLES) "Matching for free variable in [type-prescription] rules We assume familiarity with the issue of dealing with free variables in hypotheses; see [free-variables]. By default, starting with Version 4.3, ACL2 attempts all possible matches for free variables. Consider the following example. (defstub f1 (x) t) (defstub f2 (x y) t) (defstub f3 (y) t) (defaxiom f1-prop (implies (and (f2 x y) ; <-- y is free in this hypothesis (f3 y)) (f1 x)) ; <-- (f1 x) is the type-term (type is `non-nil') :rule-classes :type-prescription) ; Succeeds: (thm (implies (and (f2 a b) (f3 b)) (f1 a))) ; The following fails unless we try more than one match for free variables in ; hypotheses. (thm (implies (and (f2 a b) (f2 a c) (f2 a d) (f3 b)) (f1 a))) There may be times when you want to match only the first free variable. In that case, you can write a function of two arguments, the type-prescription [rune] being applied and the current ACL2 world, that prohibits multiple matching for those times. Your function is then `attached' to the built-in constrained function, oncep-ts. The following examples are intended to explain how this works. First, let us disallow all mutliple matching of free variables (i.e., implement the behavior often referred to as ``:match-free :once''; see [free-variables]). (defun oncep-tp-always (rune wrld) (declare (ignore rune wrld) (xargs :mode :logic :guard t)) t) (defattach oncep-tp oncep-tp-always) The second thm form above will now fail, because only one free-variable match is permitted for the first hypothesis of rule f1-prop above. Now suppose that instead, we want to disallow multiple matches for free variables in hypotheses of type-prescription rules except for the rule f1-prop above. With the following events, the second thm form above once again succeeds. (defun oncep-tp-always-except-f1-prop (rune wrld) (declare (ignore wrld) (xargs :mode :logic :guard (and (consp rune) (consp (cdr rune)) (symbolp (cadr rune))))) (not (eq (base-symbol rune) 'f1-prop))) (defattach oncep-tp oncep-tp-always-except-f1-prop) In general, your [defattach] event will attach a function symbol to oncep-tp. The [guard] of that function symbol must be implied by the guard of oncep-tp: ACL2 !>:args oncep-tp Function ONCEP-TP Formals: (RUNE WRLD) Signature: (ONCEP-TP * *) => * Guard: (AND (PLIST-WORLDP WRLD) (CONSP RUNE) (CONSP (CDR RUNE)) (SYMBOLP (CADR RUNE))) Guards Verified: T Defun-Mode: :logic Type: built-in (or unrestricted) ONCEP-TP ACL2 !>") (FREE_VARIABLES_IN_TOP-LEVEL_INPUT (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Free Variables in Top-Level Input ACL2 !>(equal (app (app a b) c) (app a (app b c)))) ACL2 Error in TOP-LEVEL: Global variables, such as C, B, and A, are not allowed. See :DOC ASSIGN and :DOC @. ACL2 does not allow ``global variables'' in top-level input. There is no ``top-level binding environment'' to give meaning to these variables. Thus, expressions involving no variables can generally be evaluated, ACL2 !>(equal (app (app '(1 2) '(3 4)) '(5 6)) (app '(1 2) (app '(3 4) '(5 6)))) (1 2 3 4 5 6) but expressions containing variables cannot. There is an exception to this rule. References to ``single-threaded objects'' may appear in top-level forms. See [stobj] [{ICON}]. A single-threaded object is an ACL2 object, usually containing many fields, whose use is syntactically restricted so that it may be given as input only to certain functions and must be returned as output by certain functions. These restrictions allow single- threaded objects to be efficiently manipulated. For example, only a single copy of the object actually exists, even though from a logical perspective one might expect the object to be ``copied on write.'' The most commonly used single-threaded object in ACL2 is the ACL2 system state, whose current value is always held in the variable [state] [{ICON}]. ACL2 provides a way for you to use state to save values of computations at the top-level and refer to them later. See [assign] [{ICON}] and [@] [{ICON}].") (FREQUENTLY-ASKED-QUESTIONS-BY-NEWCOMERS (INTRODUCTION-TO-THE-THEOREM-PROVER) "Some questions newcomers frequently ask This FAQ is for people who've read through all the other sections of the tutorial introduction to the theorem prover (see [introduction-to-the-theorem-prover] and all the links from it that are not marked with the little warning sign (``[{ICON}]''). Do not expect to understand our answers if you haven't taken the time to read through the tutorial. In the answers below you will see more links into the hypertext reference manual. While such links were marked ``[{ICON}]'' in the tutorial, they are not marked that way here. When you enter the reference manual be prepared to explore and assemble a mini-course on the topic of interest, not a quick fix. Q. How do I find something in the ACL2 documentation? A. Try going to the Search link on the ACL2 home page. Q. How does the theorem prover work? A. We really don't think you need to know much about the inner workings of the prover to become an effective user. That doesn't mean the system is self-explanatory! It means that stuff you need to learn is not how the theorem prover works but how to interact with it! That is what [introduction-to-the-theorem-prover] is about. However, if you want the most basic overview of the prover, see [architecture-of-the-prover]. Q. How do I define a new function? A. See [defun]. Q. How do I define a new predicate? A. See [defun]. Q. How do I define a new relation? A. See [defun]. Q. How do I define a function or predicate that takes a varying number of arguments? A. You can't. However, see [defmacro] to learn how to define a macro that takes a varying number of arguments and expands into an arbitrary term that you compute. Q. How do I define a macro that is sensitive to the state? A. You can't. However, advanced users should consider [make-event]. Q. How do I define mutually recursive functions? A. See [mutual-recursion]. However, you should realize that when two functions, say f and g, are mutually recursive, properties of f generally have to be stated simultaneously with properties of g, since inductive proofs about one function require inductive hypotheses about the other. Furthermore, ACL2 does not know how to do inductions for mutually recursive functions and must be told. See [mutual-recursion-proof-example]. Q. How do I declare the type signature of a function? A. You can't. ACL2 is a syntactically untyped language and all functions are defined on all objects in the ACL2 universe. We recommend that the new user get used to this and only then explore the use of ACL2 to express and enforce a type regime. In ACL2, the guard of a function is akin to the type signature of a function in typed languages. However, ACL2 guards may be arbitrary terms, not just type conditions, they only concern the inputs to the function (not its result), and do not affect the axiom defining the function -- all functions are defined on every combination of objects. You may, of course, prove theorems that establish that every function called in a definition or theorem is supplied with input satisfying its guards (which necessarily involves describe the outputs too). These formulas are called guard conjectures and the process of proving them is called guard verification. Since guards are arbitrary ACL2 formulas, the ``type regimes'' one tends to enforce in ACL2 can be much for flexible and expressive than those in most programming languages. However, that expressibility also means guard verification can be challenging (indeed undecidable). On the other hand, if one limits oneself to simple type-like guards, lemmas can be proved that make most guard verification fully automatic and one can configure ACL2 to do guard verification automatically at defun-time. One may also delay guard verification until ``the right'' lemmas have been proved. By doing guard verification one can make functions execute faster by allowing the code to avoid runtime checks. This is especially valuable to industrial users who have large models used both in verification and as simulation engines for designed artifacts. In addition, guard verification can give you the assurance that you are using your functions within their intended domains and hence is a form of functional specification and verification. However, all these advantages aside, it is remarkably easy to drift away from the simplest type regimes and write a guard that raises deep mathematical problems. New users should not try to confront these problems until they are comfortable with the theorem prover and with lemma development. Therefore, we strongly recommend that you forget about types and guards and get used to reasoning about total functions. When you do decide to learn about them, be prepared for a complex story involving specification, execution efficiency, and proof management. See [guard]. Q. How do I tell defun what measure to use? A. See [xargs], specifically :measure. Q. I specified a measure that always returns a natural number but ACL2 is acting like it's not a natural number. A. There are two likely problems. The most likely one is that your measure isn't really always a natural! Suppose the formals of your defun are x and y and your measure is (m x y). Suppose the recursive calls of your function are protected by tests that insure that x and y are naturals. Then you might assume x and y are naturals in the measure. But ACL2 has to prove (o-p (m x y)), where [o-p] is the predicate that recognizes ordinals (and naturals are ordinals). Note that the theorem doesn't have any hypotheses! You might intuitively think that your measure has to be an ordinal just under the conditions that lead to recursive calls. That's not what ACL2 enforces. It has to be an ordinal, always. So you must change your specified measure. For example, consider wrapping [nfix] around it or around its uses of x and y to coerce those quantities to naturals. The second most likely explanation is that your measure returns a natural, always, but ACL2 doesn't know that and it takes induction to prove. This might happen if m involves some recursive functions. In this case, prove (natp (m x y)) before your defun. Perhaps you should consider making the natp lemma a :[type-prescription] lemma to make ACL2's typing algorithm aware of it. Q. How do I tell defun what well-founded relation to use? A. See [xargs], specifically :well-founded-relation. Q. How do I show that a relation is well-founded? A. Prove a theorem establishing that there is an order preserving embedding into the ordinals and store it with :rule-classes :[well-founded-relation]. Q. What is an ordinal? What does it mean to be well-founded? A. Ordinals are an extension of the natural numbers used to insure that a process can't go on forever. Like naturals, they can be added, multiplied, and exponentiated. There is a sense of one ordinal being less than another. Unlike the naturals, each of which is finite, the ordinals include infinite objects. Now imagine ``standing'' on an ordinal and ``stepping'' to a smaller one. Like the naturals, this ``walk down the ordinals'' can't go on forever, even if you start on an infinite ordinal. That is because the ordinals are well-founded. See [o-p] for more information about ordinals in ACL2 and about well-foundedness. See [ordinals] for a deeper discussion and a discussion of books that can help configure ACL2 to reason about ordinals. Q. How can provide hints for the termination proofs in defun? A. See [xargs], specifically :hints (for the termination proofs) and :guard-hints (for the guard verification proofs). Q. How do I define a constant (something like a global variable)? A. See [defconst]. But remember that as an applicative programming language, ACL2 does not have global variables! You can define a symbol to have a fixed value and use the symbol sort of like a global variable in function definitions: you may refer to the value of the symbol in your functions without passing the variable in as formal parameter. But you may not ever change the value of the symbol! Q. How do I save the value of a top-level computation for future use? A. See [assign] and see [@]. Q. How do I introduce new syntactic form or abbreviation? A. See [defmacro]. Q. How can create and modify an array? A. ACL2 is a functional language, so it is impossible to destructively modify an existing object; technically, all ``updates'' to objects must be implemented by ``copy-on-write'' semantics. That said, ACL2 provides support for [arrays], provided you use them in a restricted way. They give you constant-time access and change under the use restrictions. Q. How do I read from or write to a file? How do I do IO? A. To manipulate files, your function must have [state] as an argument, so you should read about the restrictions that imposes. For input/output facilities, see [io]. Q. How do I define a structure that can be destructively modified? A. ACL2 is an applicative programming language. You can't modify objects arbitrarily! You basically have to ``copy on write,'' which means you construct new objects from old ones, making the changes you want in the new one. If the car of some object is 1 at one moment and 2 later, then the basic logical axiom (car x) = (car x) is violated! However, if the only reference to the old object, e.g., x, was to pass it to the code that copied and ``changed'' it, then ACL2 can re-use the old object to produce the new one and the axioms would not object. Such syntactic restrictions can make x a modifiable structure but they will impose a heavy burden on you as a programmer: if pass such an x to a function and the function modifies it, then you must pass x only to that function and you must return the modified value and use it henceforth. Such objects are said to be single threaded. See [defstobj]. Q. How do I write a universal quantifier? An existential quantifier? How can I say ``for all'' or ``there exists''? A You can't literally write quantifiers. But ACL2 has the power of full first order logic with quantification. See [quantifiers]. Q. How do I introduce an undefined or uninterpreted function symbol? Can I constrain it to have certain properties? A. See [encapsulate]. Q. How can I hide a lemma? I want to prove a lemma temporarily to use in another proof but I don't want the lemma around thereafter. A. One way to get a similar effect is to prove the lemma and then disable it with an (in-theory (disable ...)) event; see [in-theory]. Another way is to put the lemma and the theorem that needs it into an [encapsulate] and wrap a [local] around the lemma. Q. What is an event? A. An event is a command that adds information to the ACL2 database (the ``logical world''), like defun or defthm. See [events]. Q. How do I say that I do not want a rewrite rule generated from a theorem? A. The command (defthm name formula :rule-classes nil) will attempt to prove formula and, if successful, give formula the name name, which you may use in hints as a theorem, but it will build no rules from the formula. Q. How do I say that I want a formula to be stored as a rewrite rule? A. The command (defthm name formula) will attempt to prove formula and, if successful, it will give formula the name name and generate a rewrite rule from it, with the runic name (:rewrite name)]. It could happen that formula generates more than one rewrite rule, e.g., this happens if the conclusion is an AND. In this case, each conjunctive branch through the conclusion generates a rule named (:rewrite name . i), for i=1,2,... For more details, see [rewrite]. Q. How do I say that I want a formula to be stored as a rewrite rule and some other kinds of rules? A. The command (defthm name formula :rule-classes (:class1 ... classk)) will attempt to prove formula and, if successful, it will give formula the name name and generate a rule of each :classi specified. Each :classi should either be a keyword, like :REWRITE or :GENERALIZE, naming a rule class (see [rule-classes]), or else should be a list that starts with a rule class and then lists the relevant modifiers. Be sure to include :REWRITE among the rule classes if you want the formula to generate a rewrite rule. It doesn't do that automatically if you explicitly specify :rule-classes! Q. How do I rearrange the shape of a formula before generating a rule from it? A. See [rule-classes] and read about the :corollary modifier. Q. What is a type-prescription? A. ACL2 has an algorithm for determining the type of object returned by a term, where a type is one of the Common Lisp primitive datatypes such as natural, integer, Boolean, cons, true-listp, etc. Rules provided by you can influence this algorithm. See [type-prescription]. Q. How do rewrite rules work? A. Re-read the tutorial sections: [introduction-to-rewrite-rules-part-1] and [introduction-to-rewrite-rules-part-2]. Q. How do I see what's in the database? A. You can't look at the entire database with user-friendly tools. You can print the command that introduced a particular name, print the entire sequence of user commands, print the commands in the region between two commands, print all the rewrite rules that apply to a given term or function symbol, and many other options. See [history]. If you have loaded a book from another user, you might wish to read the source file. For example, the source file for (include-book \"arithmetic-5/top\" :dir :system) is the file named arithmetic-5/top.lisp on the acl2-sources/books/ directory where ever your ACL2 sources are installed. Often, books are well-documented by comments by their authors. Some books have Readme or README files on the same directory. Q. How do I undo a command? A. See [history], especially see [u] (``undo'') and see [ubt] (``undo back through''). Q. What rewrite rules match a given term? A. See [pl]. Q. What were those questions to ask when looking at key checkpoints? A. See [introduction-to-key-checkpoints]. Q. How do I figure out why a rewrite rule won't fire? A. If you activate rewrite rule monitoring (see [brr]) and then install a monitor (see [monitor]) on the rule in question, ACL2 will enter an interactive break whenever the pattern of the rule is matched against a target in a proof. So after installing the monitor, re-try the proof and then interact with the rewriter via break commands (see [brr-commands]). Like all trace and break packages, you have to know what you're doing to use the break rewrite facility, so read the material in the reference manual. If no interactive break happens after you've installed the monitor on your rule and re-tried the proof, it means no suitable target ever arose. Don't forget to turn off monitoring when you're done as it slows down the system. Q. Why is a proof taking so long? A. Unexpectedly poor performance on simple problems is usually a sign of cyclic rewriting or combinatoric explosion. See [dmr] and see [accumulated-persistence]. Q. How do I tell ACL2 what induction to do for a particular formula? A. When issuing the defthm command for the formula, supply an :induct hint: (defthm name formula :hints ((\"Goal\" :induct (f x1 ... xn)))) where f is a function that recurs the way you want the induction to unfold and x1 ... xn are the relevant variables in formula. You usually have to define f appropriately for each formula that needs an induct hint, though sometimes you can re-use an earlier f or one of the functions in the formula itself. It doesn't matter what value (f x1 ... xn) returns. All that matters is how it recurs. The termination analysis for f justifies the induction done. See [hints], especially the section on :induct hints; also see [induction]. Q. ACL2 doesn't know simple arithmetic that can simplify the term (+ 1 -1 x). A. You should load an arithmetic book whenever you're dealing with an arithmetic problem. The simplest arithmetic book is typically loaded with the event (include-book \"arithmetic/top-with-meta\" :dir :system). If you're using floor and mod or non-linear arithmetic like (* x y) you should use (include-book \"arithmetic-5/top\" :dir :system). See also the discussion of arithmetic books under the ``Lemma Libraries and Utilities'' link of the ACL2 home page, and see [community-books]. Q. ACL2 is not using an arithmetic lemma that I proved. A. Lemmas concluding with arithmetic inequalities, like (implies (member e x) (< (len (delete e x)) (len x))) are not good rewrite rules because they rarely match targets because of intervening arithmetic operators. For example, the above conclusion doesn't match (< (LEN (DELETE E X)) (+ 1 (LEN X))). You should store such lemmas as :linear rules by using the command: (defthm len-delete (implies (member e x) (< (len (delete e x)) (len x))) :rule-classes :linear) See [linear]. Q. What is a linear rule? A. See [linear]. Q. How do I make ACL2 treat a relation as an equality? A. We assume you mean to treat the relation as an equivalence, i.e., replace one term by another when they are equivalent under your relation. See [equivalence], see [congruence], and see [refinement]. Q. One of my rewrite rules has a hypothesis that doesn't rewrite to true. What do I do? A. Prove a rewrite rule that establishes that hypothesis under the relevant assumptions from the context of the intended target. Alternatively, undo the rule and restate it with a [force] around the problematic hypothesis, making ACL2 assume the hypothesis when the rule is applied and raising the truth of the hypothesis as an explicit subgoal of the proof. See also [case-split]. Of course, you should always state the strongest rewrite rules you can think of, eliminating hypotheses or shifting them to the right-hand side inside of IFs; see [strong-rewrite-rules]. Q. How do I make ACL2 ``guess'' the right instantiation of a free variable? A. You can provide a :restrict hint that names the problematic lemma and provides an instantiation of the free variable. See [hints], specifically :restrict. You could alternatively give a hint that :uses the rule and provides the appropriate instantiation in full. See [hints], specifically :use. Recall that ACL2 guesses free variable instantiations by matching the problematic hypothesis to the assumptions in the context of the target. If the appropriate assumption is present but ACL2 is finding another one, try undoing the problematic rule and proving it again, specifying the :match-free :all modifier of the :rewrite or :linear rule class. See [rule-classes]. Alternatively, undo and prove the problematic rule again and use a [bind-free] form to compute the appropriate instantiation. Q. How can I make ACL2 do a case split to prove a certain subgoal? A. See [hints], specifically :cases. Q. How can I prevent ACL2 from using a rewrite rule? A. See [hints], specifically :in-theory (disable ...). If the use of the rule is problematic in only one subgoal and the lemma is needed in other subgoals, disable the lemma only in the problematic subgoal by specifying the subgoal name (e.g., \"Subgoal 1/3.2.1\") as the goal specifier in the hint. If the rule isn't needed anywhere in the proof, you could use the specifier \"Goal\". If you don't think the rule will ever be needed for a while, you could globally disable it with the event (in-theory (disable ...)) (see [in-theory]) executed before the first problematic proof. If the rule has never been used or must always be disabled, undo it and prove it again with :[rule-classes] nil. Q. How can I prevent ACL2 from running a definition on constants? I tried disabling the function but that didn't work. A. If you have a function named f then disabling f will disable the definitional axiom about f. But ACL2 has another kind of rule about f, telling it how to evaluate f. The [rune] of this rule is (:executable-counterpart f). Try disabling that, as in the :[hints] ((... :in-theory (disable (:executable-counterpart f)) ...c[)). Q. How can I make ACL2 use a rule in a proof? A. See [hints], specifically :use. Q. How can I make ACL2 expand a function call in a proof? A. You can give an :See [expand] hint. Q. ACL2 sometimes aborts the proof attempt before showing me all of the subgoals. How can I make it just keep going instead of aborting early? A. See [otf-flg], which stands for Onward Thru the Fog FLaG. Q. How can I compute when I want a rule to fire? A. See [syntaxp]. Q. How can I add pragmatic advice to a lemma after it has been proved? For example, how can add a forced hypothesis, a backchain limit, or a syntaxp test? A. You can't. You can undo the lemma, restate it appropriately, and prove it again. This produces the cleanest database. Alternatively, you can prove the restated lemma under a new name -- a task that should be easy since the old version is in the database and will presumably make the proof trivial -- and then disable the old name. Q. How can I stop ACL2 from rewriting a term? A. If you need rewriting done but want to prevent some particular terms from being rewritten, see [hints], specifically :hands-off. Alternatively, consider embedding the problematic term in a [hide]. Users sometime develop special theories (see [theory]) containing just the rules they want and then use hints to switch to those theories on the appropriate subgoals. Q. Can I compute which subgoals a hint refers to? A. Yes, see [computed-hints]. This topic is for advanced users but knowing that it is possible might come in handy someday. Q. I want the rewriter to always use one theory and then switch to another so that it doesn't use my most complicated before until doing the simple things. A. This is possible but is something for the advanced user. It can be done using a form of [computed-hints]. See [using-computed-hints-7]. Q. Is there a way to attach the same hint to every defthm? A. See [default-hints]. Q. How can I just tell ACL2 the proof steps? A. See [verify] and see [proof-checker]. Q. How can I write my own simplifier? A. See [meta]. Q. How can I add an axiom or just assume some lemma without proof? A. This is very dangerous but is a good strategy for exploring whether or not a certain set of lemmas (and their rules) is sufficient to prove your goal. See [defaxiom] and see [skip-proofs]. Q. How can redefine a user-defined function? A. This is tricky. What if you've already proved theorems about the old definition and then wish to change it? There are several options. See [ld-redefinition-action] (and note specifically the discussion of updater function for it, set-ld-redefinition-action); also see [redef], see [redef!], see [redef+], and see [redef-]. Q. How do I change a function from :program mode to :logic mode? A. See [verify-termination]. Q. How do I change the guards on a function? A. You can't. Undo it and redefine it. Q. What is program mode? A. See [program]. Q. What does the ACL2 prompt mean? A. See [introduction-to-a-few-system-considerations] or, specifically, see [prompt]. Q. What is logic mode? A. See [logic]. Q. How do I get into or out of :program mode? :Logic mode? A. See [program] and see [logic]. You can enter these modes temporarily for a particular [defun] by using (declare (xargs :mode :program)) or (declare (xargs :mode :logic)) after the list of formal parameters to the definition. Q. How do I quit from ACL2? A. This varies depending on the interface you're using. See [introduction-to-a-few-system-considerations]. Q. How do I load a file of definitions and theorems created by someone else? A. See [include-book]. Q. How do I create my own book of definitions and theorems? A. See [books]. Q. Where are the books referenced by :dir :system on my machine? A. If your ACL2 is installed on the directory dir/acl2-sources and you follow the standard installation instructions, then the books are typically the files under the directory dir/acl2-sources/books/. Q. How can I find out what books are available? A. Go to the ACL2 home page, http://www.cs.utexas.edu/u/moore/acl2/ and look at the link labeled ``Lemma Libraries and Utilities.'' Q. How do I produce my own book? A. See [books]. Q. What is a decision procedure? What decision procedures does ACL2 have? A. A decision procedure is an algorithm that given enough time and space can determine, for all the formulas in a certain syntactic class of formulas, whether the formula is a theorem or not. The most well-known decision procedure is for propositional calculus: by testing a formula under all the combinations Boolean assignments to the variables, one can decide if a propositional formula is a theorem. The syntactic class consists of all formulas you can write using just variables, constants, and compositions of the functions and, or, not, implies, iff, and if. There are, of course, an exponential number of different assignments so the algorithm can be slow. ACL2 contains a propositional decision procedure based on symbolic normalization that can be faster than trying all the combinations of truthvalues -- but is not guaranteed to be faster. ACL2 also contains an optional [bdd] procedure. ACL2 also contains a decision procedure for rational arithmetic involving variables, rational constants, addition, multiplication by rational constants, equality, and the various versions of arithmetic inequality (<, <=, >=, and >). It can be extended with :[linear] lemmas. ACL2 is complete for equality over uninterpreted (e.g., undefined and unconstrained) function symbols using an algorithm based on transitive closure of equivalence classes under functional substitutivity. Finally, you can make ACL2 use other decision procedures, even ones implemented outside of ACL2; see [clause-processor]. Q. ACL2 has the change of variable trick (destructor elimination) that it does to get rid of (CAR X) and (CDR X) by replacing x by (CONS A B). Is there a way to make ACL2 do that for other terms? A. Yes. See [elim]. Q. How can I prevent destructor elimination? A. See [hints], specifically :do-not '(eliminate-destructors). Q. How can I prevent cross-fertilization? A. See [hints], specifically :do-not '(fertilize). Q. How can I prevent generalization? A. See [hints], specifically :do-not '(generalize). Q. How can I make ACL2 impose a restriction on a new variable introduced by destructor elimination or generalization? A. See [generalize]. Q. What rule classes are there? A. See [rule-classes]. Q. What is a theory? A. See [theories]. Q. How are hints inherited by the children of a subgoal? A. See [hints-and-the-waterfall]. Q. How do I use ACL2 under Emacs? A. See [emacs]. Q. How do I use ACL2 under Eclipse? A. See [ACL2-Sedan]. Q. How do I interrupt the prover? A. The keyboard sequence for interrupting a running process depends your operating system, host Common Lisp, and user interface (e.g., Emacs, Eclipse, etc.). But perhaps a few examples will help you discover what you need to know. If your host Common Lisp is GCL or Allegro and you are typing directly to the Common Lisp process, then you can interrupt a computation by typing ``ctrl-c'' (hold down the Control key and hit the ``c'' key once). But other Lisps may require some other control sequence. If you are typing to an Emacs process which is running the GCL or Allegro Common Lisp process in a shell buffer, you should type ctrl-c ctrl-c -- that is, you have to type the previously mentioned sequence twice in succession. If you are running the ACL2 Sedan, you can use the Interrupt Session button on the tool bar. The environment you enter when you interrupt depends on various factors and basically you should endeavor to get back to the top level ACL2 command loop, perhaps by typing some kind of Lisp depenent ``abort'' command like A or :q, or :abort!. You can usually determine what environment you're in by paying attention to the prompt. Q. What is the ACL2 loop? A. That is the name given to the interactive environment ACL2 provides, a ``read-eval-print loop'' in which the user submits successive commands by typing ACL2 expressions and keyword commands. See [introduction-to-a-few-system-considerations]. Q. What is raw lisp? A. That is our name for the host Common Lisp in which ACL2 is implemented. See [introduction-to-a-few-system-considerations]. There is an ACL2 mode named raw mode which is different from ``raw lisp.'' See [set-raw-mode]. Q. Can I get a tree-like view of a proof? A. See [proof-tree] for an Emacs utility that displays proof trees and allows you to navigate through a proof from the proof tree. The ACL2 Sedan also supports proof trees and you should see the ACL2s documention on that topic. Q. I used the earlier Boyer-Moore theorem prover, Nqthm. How is ACL2 different? A. See [nqthm-to-ACL2]. If you are reading this as part of the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-the-theorem-prover].") (FULL-BOOK-NAME (BOOKS-REFERENCE) "Book naming conventions assumed by ACL2 For this discussion we assume that the resident operating system is Unix (trademark of AT&T), but analogous remarks apply to other operating systems supported by ACL2; see [pathname]. ACL2 defines a ``full book name'' to be an ``absolute filename string,'' that may be divided into contiguous sections: a ``directory string'', a ``familiar name'' and an ``extension''. See [pathname] for the definitions of ``absolute,'' ``filename string,'' and other notions pertaining to naming files. Below we exhibit the three sections of one such string: \"/usr/home/smith/project/arith.lisp\" \"/usr/home/smith/project/\" ; directory string \"arith\" ; familiar name \".lisp\" ; extension The sections are marked by the rightmost slash and rightmost dot, as shown below. \"/usr/home/smith/project/arith.lisp\" | | slash dot | | \"/usr/home/smith/project/\" ; directory string \"arith\" ; familiar name \".lisp\" ; extension The directory string includes (and terminates with) the rightmost slash. The extension includes (and starts with) the rightmost dot. The dot must be strictly to the right of the slash so that the familiar name is well-defined and nonempty. If you are using ACL2 on a system in which file names do not have this form, please contact the authors and we'll see what we can do about generalizing ACL2's conventions. We conclude with a remark about a representation of full book names that is used in [certificate] files and [make-event] expansions. When the system books directory is a prefix of a full book name, ACL2 may choose to write a full book name as (:system . \"suffix\"), where \"suffix\" is the result of removing the system books directory from the front of the full book name. Here is an example. ; full book name: \"/Users/smith/acl2/acl2/books/std/portcullis.lisp\" ; alternate representation ; (where \"/Users/smith/acl2/acl2/books/\" is the system books directory): (:SYSTEM . \"std/portcullis.lisp\") Conversely, in some contexts ACL2 will convert :system . \"suffix\" to an absolute pathname. Generally \"suffix\" will be a relative pathname, such as \"dir/filename.lisp\"; in that case, the system books directory will be concatenated with \"suffix\" to form a corresponding full book name. However, if \"suffix\" is an absolute pathname, such as \"/u/smith/foo.lisp\", then the corresponding full book name is simply that absolute pathname; essentially, the :system prefix is dropped.") (FUNCTION-THEORY (THEORIES THEORY-FUNCTIONS) "Function symbol rules as of logical name Examples: (function-theory :here) (function-theory 'lemma3) See [logical-name]. General Form: (function-theory logical-name) Returns the theory containing all the :[definition] [rune]s, whether [enable]d or not, that existed immediately after [logical-name] was introduced. See the documentation for [theories], [logical-name] and [executable-counterpart-theory]. You may experience a fencepost problem in deciding which logical name to use. [Deflabel] can always be used to mark unambiguously for future reference a particular point in the development of your theory. The order of [events] in the vicinity of an [encapsulate] is confusing. See [encapsulate]. This ``function'' is actually a macro that expands to a term mentioning the single free variable [world]. When theory expressions are evaluated by [in-theory] or the :[in-theory] hint, [world] is bound to the current ACL2 [world].") (FUNCTIONAL-INSTANTIATION (ENCAPSULATE) "An analogue in ACL2 of higher-order logical reasoning. Functional instantiation allows you to prove theorems ``by analogy'' with previous theorems. See [hints] and see [lemma-instance]. Subtopics [Functional-instantiation-example] A small proof demonstrating functional instantiation [Functional-instantiation-in-ACL2r] Additional requirements for :functional-instance hints in ACL2(r) [Lemma-instance] An object denoting an instance of a theorem") (FUNCTIONAL-INSTANTIATION-EXAMPLE (FUNCTIONAL-INSTANTIATION TUTORIAL5-MISCELLANEOUS-EXAMPLES) "A small proof demonstrating functional instantiation The example below demonstrates the use of functional instantiation, that is, the use of a generic result in proving a result about specific functions. In this example we constrain a function to be associative and commutative, with an identity or ``root,'' on a given domain. Next, we define a corresponding function that applies the constrained associative-commutative function to successive elements of a list. We then prove that the latter function gives the same value when we first reverse the elements of the list. Finally, we use functional instantiation to derive the corresponding result for the function that multiplies successive elements of a list. The details of the proof (such as the [in-theory] event and particulars of the lemmas) are not the point here. Rather, the point is to demonstrate the interaction of [encapsulate] [events] and :functional-instance [lemma-instance]s. Of course, if you are interested in details then you may find it helpful to run these [events] through ACL2. Also see [constraint] for more about :functional-instance and see [lemma-instance] for general information about the use of previously-proved lemmas. (in-package \"ACL2\") (encapsulate (((ac-fn * *) => *) ((ac-fn-domain *) => *) ((ac-fn-root) => *)) (local (defun ac-fn (x y) (+ x y))) (local (defun ac-fn-root () 0)) (local (defun ac-fn-domain (x) (acl2-numberp x))) (defthm ac-fn-comm (equal (ac-fn x y) (ac-fn y x))) (defthm ac-fn-assoc (equal (ac-fn (ac-fn x y) z) (ac-fn x (ac-fn y z)))) (defthm ac-fn-id (implies (ac-fn-domain x) (equal (ac-fn (ac-fn-root) x) x))) (defthm ac-fn-closed (and (ac-fn-domain (ac-fn x y)) (ac-fn-domain (ac-fn-root))))) ;;;;;;;;;;;;;;;;;;;;;;; ; End of encapsulate. ; ;;;;;;;;;;;;;;;;;;;;;;; ; Define a ``fold'' function that iteratively applies ac-fn over a list. (defun ac-fn-list (x) (if (atom x) (ac-fn-root) (ac-fn (car x) (ac-fn-list (cdr x))))) ; Recognize lists all of whose elements are in the intended domain. (defun ac-fn-domain-list (x) (if (atom x) t (and (ac-fn-domain (car x)) (ac-fn-domain-list (cdr x))))) ; Define a list reverse function. (defun rev (x) (if (atom x) nil (append (rev (cdr x)) (list (car x))))) ; The following is needed for proving ac-fn-list-append, which is ; needed for proving ac-fn-list-rev. (defthm ac-fn-list-closed (ac-fn-domain (ac-fn-list x))) ; Needed for proving ac-fn-list-rev: (defthm ac-fn-list-append (implies (and (ac-fn-domain-list x) (ac-fn-domain-list y)) (equal (ac-fn-list (append x y)) (ac-fn (ac-fn-list x) (ac-fn-list y))))) ; Needed for proving ac-fn-list-rev: (defthm ac-fn-domain-list-rev (equal (ac-fn-domain-list (rev x)) (ac-fn-domain-list x))) ; The following is a good idea because without it, the proof attempt ; for ac-fn-list-rev (see just below) fails with the term (HIDE ; (AC-FN-LIST NIL)). It is often a good idea to disable ; executable-counterparts of functions that call constrained ; functions. (in-theory (disable (:executable-counterpart ac-fn-list))) (defthm ac-fn-list-rev (implies (ac-fn-domain-list x) (equal (ac-fn-list (rev x)) (ac-fn-list x)))) ; Our goal now is to apply functional instantiation to ac-fn-list-rev ; in order to prove the corresponding theorem, times-list-rev, based ; on * instead of ac-fn. (defun times-list (x) (if (atom x) 1 (* (car x) (times-list (cdr x))))) (defun acl2-number-listp (x) (if (atom x) t (and (acl2-numberp (car x)) (acl2-number-listp (cdr x))))) ; The following relies on the following built-in rules for * (whose ; statements correspond directly to their names): commutativity-of-*, ; associativity-of-*, and unicity-of-1. (defthm times-list-rev (implies (acl2-number-listp x) (equal (times-list (rev x)) (times-list x))) :hints ((\"Goal\" :use ((:functional-instance ac-fn-list-rev ;; Instantiate the generic functions: (ac-fn *) (ac-fn-root (lambda () 1)) (ac-fn-domain acl2-numberp) ;; Instantiate the other relevant functions: (ac-fn-list times-list) (ac-fn-domain-list acl2-number-listp))))))") (FUNCTIONAL-INSTANTIATION-IN-ACL2R (FUNCTIONAL-INSTANTIATION) "Additional requirements for :functional-instance hints in ACL2(r) This documentation topic relates to ACL2(r), the modification of ACL2 that supports the real numbers (see [real]). See [hints] and see [lemma-instance] for a discussion of :use hints that employ the :functional-instance keyword. Here, we document additional requirements for such hints that applies to ACL2(r). We assume familiarity with lemma instances; see [lemma-instance]. (1) When functionally instantiating a non-classical formula, it is illegal to use pseudo-lambda expressions in a lemma instance. (2) A classical function symbol must be bound either to a classical function symbol or to a lambda (or, if allowed, pseudo-lambda) expression with a classical body. Similarly, a non-classical function symbol must be bound either to a non-classical function symbol or to a lambda (or, if allowed, pseudo-lambda) expression with a non-classical body.") (FUNCTIONS_FOR_MANIPULATING_THESE_OBJECTS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Functions for Manipulating these Objects [{IMAGE}] Consider a typical ``stack'' of control frames. {IMAGE} Suppose the model required that we express the idea of ``the most recent frame whose return program counter points into MAIN.'' The natural expression of this notion involves function application --- ``fetch the return-pc of this frame'' case analysis --- ``if the pc is MAIN, then ...'' iteration or recursion --- ``pop this frame off and repeat.'' The designers of ACL2 have taken the position that a programming language is the natural language in which to define such notions, provided the language has a mathematical foundation so that models can be analyzed and properties derived logically. Common Lisp is the language supported by ACL2. To be precise, a small applicative subset of Common Lisp is the language supported by ACL2. [{IMAGE}]") (FURTHER-INFORMATION-ON-REWRITING (INTRODUCTION-TO-THE-THEOREM-PROVER) "A grab bag of advice and information on rewriting In the following paragraphs we give some links to advanced topics, marked with ``[{ICON}]''. If you are reading this topic as part of the tutorial on the theorem prover, do not follow these links upon your first reading. Just take note of the existence of the facilities and ideas mentioned. [Arithmetic]: If your goal theorem involves even trivial arithmetic, such as adding or subtracting 1, we recommend that you do (include-book \"arithmetic/top-with-meta\" :dir :system) which loads into ACL2 all the rules in one of the so-called ACL2 ``community books''. (Books are certified files of definitions, lemmas, etc., usually prepared by other ACL2 users and explicitly shared with the community. The ACL2 installation instructions suggest downloading the community books.) The book \"top-with-meta\" is the most elementary and most widely used arithmetic book. Other community books include \"arithmetic-5/top\" and various hardware and floating-point arithmetic books. Rules Concluding with Arithmetic Inequalities: If you are tempted to create a rewrite rule with an arithmetic inequality as its conclusion or left-hand side, think again. Inequalities such as (<= (len (delete e x)) (len x)) make poor left-hand sides for rewrite rules. For example, the inequality above does not match the target (<= (LEN (DELETE E X)) (+ 1 (LEN X))) even though it is sufficient to prove the target (given some simple arithmetic). We recommend that if you have a theorem that establishes an arithmetic inequality, you make it a linear rule. See [linear] [{ICON}]. Rearranging Formulas Before Making Rules: It is possible to rearrange the propositional structure of a proved formula before processing it as a rule. This allows you to state a theorem one way ``for publication'' and rearrange it to be stored as a more effective rule. See [introduction-to-the-database] (a tutorial topic you'll come to later) and its discussion of the concept of corollary. Also, see the discussion of corollary in [rule-classes] [{ICON}]. Rewriting with New Equivalence Relations: You may introduce new equivalence relations, like ``set-equal'' or ``is-a-permutation'' and cause the rewriter to replace equivalents by equivalents in suitable contexts, where you use congruence rules to inform ACL2 of where these more relaxed notions of equivalence may be used; see [equivalence] [{ICON}] and see [congruence] [{ICON}]. Pragmatic Advice to Control Rules: You may attach various pragmas to a rule that allow you rather fine heuristic control over whether and how the rule is applied. For example, you may mark a hypothesis to be forced (see [force] [{ICON}]) meaning that the rule is to be applied even if that hypothesis is not relieved -- but if the proof is successful the system will turn its attention to all forced subgoals. You may similarly mark a hypothesis so as to cause a case split, allowing the relief of the hypothesis on one branch and spawning another branch explicitly denying the hypothesis; see [case-split] [{ICON}]. You may add a bogus hypothesis that looks at the intended application of the rule and decides whether to apply the rule or not, performing an arbitrary computation on the syntactic context of the application; see [syntaxp] [{ICON}]. By providing a :match-free modifier to the :rewrite rule declaration in your rule-classes, you may tell ACL2 to try all or only the first free variable value it guesses (see [rule-classes] [{ICON}]). You may provide a bogus hypothesis that computes from the syntactic environment the values to guess for the free variables in a rule; see [bind-free] [{ICON}]. You may mark a term so that the rewriter does not dive into it; see [hide] [{ICON}]. Programming Your Own Rewriter: If you cannot find a way to use rewrite rules to make the transformations you desire, you might investigate the use of metafunctions. A metafunction is just a little theorem prover of your own design. It takes as input a list structure representing a term and returns a list structure representing a term. If you can prove that the meaning of the input and output terms are equivalent, you can extend the ACL2 simplifier to call your metafunction. See [meta] [{ICON}]. The Order in which Targets are Rewritten: The rewriter sweeps through terms ``inside-out'' otherwise known as ``left-most innermost first''. Thus, before trying to apply rewrite rules to (f a1 ... an), rules are applied to the ai. This has the good effect of normalizing the ai. This fact might help you understand why sometimes your rules ``don't seem to fire.'' For example, suppose you have a rule for rewriting (len (rev x)) to (len x) and suppose you wish to prove a theorem about (LEN (REV (CONS A B))). Suppose rev is defined in terms of append, as shown in [programming-knowledge-taken-for-granted]. Then you might see a checkpoint in which the (LEN (REV ...)) above has been simplified to (LEN (APPEND (REV B) (LIST A))) instead of to (LEN (CONS A B)). Why wasn't your rule about (len (rev x)) applied? The reason is that (REV (CONS A B)) rewrote to (APPEND (REV B) (LIST A)) before rules were applied to (LEN (REV ...)). You need a rule about (len (append x y)), as you will see from the checkpoint. The Order in which Rules are Tried: The rewriter tries the most recently proved rules first. For example, suppose f, g, and h are functions defined so that the following two theorems are provable and suppose you executed the following two events in the order shown: (defthm rule1 (equal (f (g x)) (h 1 x))) (defthm rule2 (equal (f (g x)) (h 2 X))) Then if rewrite rules are applied to (F (G A)), the result will be (H 2 A), because the latter rule, rule2, is applied first. It is generally best not to have conflicting rules or, at least, to understand how such conflicts are resolved. The system will warn you when you propose a rule that conflicts with an existing one. If you were reading this topic as part of the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-rewrite-rules-part-2].") (FUTURE-WORK-RELATED-TO-THE-TAU-SYSTEM (INTRODUCTION-TO-THE-TAU-SYSTEM) "Some tau system problems that we hope someone will address The tau system is inexpressive compared to modern polymorphic type systems --- something that may be unavoidable in an untyped first-order language. However, we believe its effectiveness could be greatly increased by the development of some additional tools. We also believe that most of these tools could be provided by ACL2 users creating certified community books that exploit the basic tools already provided. It is likely the initial attempts to create such books will show the inadequacy of some of the current algorithms and data structures in the tau system and might point the way to improvements. As implementors of ACL2 our preference is to support the improvement of the core algorithms and data structures and provide customizable hooks allowing users to exploit them by developing effective and convenient interfaces. However, we want the further elaboration and optimization of the tau system to be based on user experience not just speculation. Some tools we think might help are listed below. We invite volunteers and further suggestions. A tau-centric signature notation for use in function definitions, exploited by a macro replacing defun so that input-output relationships phrased in tau terms are proved as :tau-system rules immediately after functions are introduced: We have, for example, experimented with a book defining a macro that allows the definition of the function ap (append) accompanied by a signature rule. Subsequent defsig events can add other signatures in the same notation. (defsig ap (true-listp * true-listp ==> true-listp) (x y) (if (consp x) (cons (car x) (ap (cdr x) y)) y)) (defsig ap (integer-listp * integer-listp ==> integer-listp)) This experimental book provides succinct syntax for all tau signatures. For example, that book parses the signature (NATP (/= 3 5 7) (< 16) * TRUE-LISTP ==> BOOLEANP * INTEGER-LISTP * NATP) to be the signature of a function with two inputs and three outputs. The first input must be a natural number, different from 3, 5, and 7, and less than 16. The second input must be a true list. The first output is a boolean, the second a list of integers, and the third a natural. To express this signature for function fn as a formula requires significantly more typing by the user: (IMPLIES (AND (NATP X) (NOT (EQUAL X 3)) (NOT (EQUAL X 5)) (NOT (EQUAL X 7)) (< X 16) (TRUE-LISTP Y)) (AND (BOOLEANP (MV-NTH 0 (FN X Y))) (INTEGER-LISP (MV-NTH 1 (FN X Y))) (NATP (MV-NTH 2 (FN X Y))))) We suspect that the provision of some succinct tau-centric notation (not necessarily the one above) for signatures at definition-time will mean users get more benefit from the tau system. Some tau inference mechanisms: This phrase suggests two different improvements. One is to implement a mechanism that adds or completes signatures for function definitions by exploiting knowledge of commonly used recursive schemas and the signatures of the subroutines in the body. For example, the definition of ap above rather obviously has the signature (integer-listp * integer-listp ==> integer-listp) and many others just based on the two recursive schemas that (a) collect certain elements from lists and (b) check that all elements have a certain property. The other ``tau inference'' improvement is to implement a mechanism for inferring relations between user-defined Booleans, perhaps by exploiting example generation, testing, and knowledge of recursive schemas. For example, it is fairly obvious that [symbol-alistp] implies [alistp]. Making the user state these relations invites omissions that render the tau system very unpredictable. A tau assistant: It would be useful to have a way to find out what tau rules are missing. Given a term that the user believes should ``obviously'' have some tau (``type'') what rules might be added to make the tau algorithm compute that expected tau? For example, if (g x) is known to satisfy P and (f x) is known to satisfy R when its argument satisfies S: g : T ==> P f : S ==> R then if the user asserts that (f (g x)) ``ought'' to have tau R, one plausible suggestion is the simple tau rule that (P x) implies (S x). Such assistance --- while still confronting an undecidable problem --- might be easier to implement within the tau framework than more generally in ACL2. (Many users have wanted such an assistant to suggest lemmas for the rewriter.)") (GAG-MODE (PROVER-OUTPUT) "Verbosity of proof output Please see [set-gag-mode] for an explanation of gag-mode, which can take any of the following values: (gag-mode) ; generally evaluates to t, nil, or :goals") (GC$ (MISCELLANEOUS ACL2-BUILT-INS) "Invoke the garbage collector This function is provided so that the user can call the garbage collector of the host Lisp from inside the ACL2 loop. Specifically, a call of gc$ is translated into a call of a function below on the same arguments. Allegro CL: excl:gc CCL ccl::gc CLISP ext:gc CMU Common Lisp system::gc GCL si::gbc [default argument list: (t)] LispWorks hcl::gc-generation [default argument list: (7) for 64-bit OS, else (3)] SBCL sb-ext:gc The arguments, if any, are as documented in the underlying Common Lisp. It is up to the user to pass in the right arguments, although we may do some rudimentary checks. Also see [gc-verbose]. Evaluation of a call of this macro always returns nil. To include gc$ in a book, one can use value-triple: (value-triple (gc$)) Subtopics [Gc-verbose] Control printing from the garbage collector") (GC-VERBOSE (GC$) "Control printing from the garbage collector General Form: (gc-verbose arg &optional arg2) Garbage collection (gc) is performed by every Lisp implementation; see [gc$]. However, different ACL2 builds might see more or fewer messages. This macro is intended to provide an interface for controlling the verbosity, which is off if the (first) argument evaluates to nil and otherwise is on. The second (optional) argument is currently ignored except when the host Common Lisp implementation is CCL, where it specifies verbosity for EGC. The above functionality is only supported for the following host Common Lisp implementations: CCL, CMUCL, and GCL. Otherwise, the only effect of this macro is to print a notice that it is not supported. You are welcome to contact the ACL2 developers if you would like to help in adding such support for another host Common Lisp. Evaluation of a call of this macro always returns nil.") (GCL (MISCELLANEOUS) "Tips on building and using ACL2 based on Gnu Common Lisp See the installation instructions for basic information about building ACL2 on top of GCL, including information about where to fetch GCL. Here, we provide some tips that may be useful. 1. You can place forms to evaluate at start-up into file init.lsp in the directory where you are starting ACL2 (GCL), or into file acl2-init.lsp in your home directory. For example, in order to evaluate both of the lisp forms mentioned in 2 below, you could put them both into init.lsp in the current directory or in ~/acl2-init.lsp (either way, without (lp) or :q): (setq si::*optimize-maximum-pages* nil) (si::allocate 'cons 75000 t) Note that if you want to put ACL2 patches in this file, you should precede them with (in-package \"ACL2\"). 2. Suppose you run out of space, for example with an error like this: Error: The storage for CONS is exhausted. Currently, 59470 pages are allocated. Use ALLOCATE to expand the space. The following suggestion from Camm Maguire will minimize the heap size, at the cost of more garbage collection time. :q ; exit the ACL2 loop (setq si::*optimize-maximum-pages* nil) (lp) ; re-enter the ACL2 loop A second thing to try, suggested by several people, is to preallocate more pages before the run, e.g.: :q ; exit the ACL2 loop (si::allocate 'cons 75000 t) (lp) ; re-enter the ACL2 loop Also see [reset-kill-ring] for a suggestion on how to free up space. 3. Windows users have seen this error: cc1.exe: unrecognized option `-fno-zero-initialized-in-bss' Camm Maguire suggests that a solution may be to evaluate the following in GCL before building ACL2. (in-package 'compiler) (let* ((x `-fno-zero-initialized-in-bss') (i (search x *cc*))) (setq *cc* (concatenate 'string (subseq *cc* 0 i) (subseq *cc* (+ i (length x)))))) 4. It is possible to profile using ACL2 built on GCL. See file save-gprof.lsp in the ACL2 source directory. 5. Some versions of GCL may have garbage-collector bugs that, on rare occasions, cause ACL2 (when built on GCL) to break. If you run into this, a solution may be to execute the following: :q (si::sgc-on nil) (lp) Alternatively, put (si::sgc-on nil) in your ~/acl2-init.lsp file. A full regression test and found that this decreased performance by about 10%. But even with that, GCL is probably one of the faster Common Lisp implementations for ACL2 on Linux. Performance figures may often be found by following the ``Recent changes'' link on the ACL2 home page. 6. GCL operations on numbers can sometimes be sped up, perhaps by up to two orders of magnitude, by suitable [declare] forms (also see [type-spec]). The following example, developed with Warren Hunt and Serita Nelesen, illustrates the use of such declarations. ; File iplus.lisp: ; Operations on naturals together with positive infinity (represented as -1). ; After (ld \"iplus.lisp\"), escape to raw Lisp with :q and then eavluate ; (disassemble 'big-test). You should see lots of arithmetic operations ; in C code, but no calls of C functions CMPmake_fixnum or number_plus. (in-package \"ACL2\") (defmacro i-max () (expt 2 (1- 28))) (defmacro i+ (x y) `(the (signed-byte 28) (let ((x ,x) (y ,y)) (declare (type (signed-byte 28) x y)) (cond ((or (< x 0) (< y 0)) -1) (t (let ((result (the (signed-byte 29) (+ x y)))) (declare (type (signed-byte 29) result)) (cond ((>= result (i-max)) -1) (t (the (signed-byte 28) result))))))))) (defmacro imin (x y) `(the (signed-byte 28) (let ((x ,x) (y ,y)) (declare (type (signed-byte 28) x y)) (cond ((< x 0) (cond ((< y 0) -1) (t y))) ((< y 0) x) (t (the (signed-byte 28) (min x y))))))) (defun big-test (x y z) (declare (type (signed-byte 28) x y z)) (imin (i+ x y) (i+ y (imin x z))))") (GCS (POINTERS) "See [get-command-sequence].") (GENERALIZE (RULE-CLASSES) "Make a rule to restrict generalizations See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. Example: (defthm integer-listp-rev (implies (integer-listp x) (integer-listp (rev x))) :rule-classes :generalize) General Form: any theorem To use a :generalize rule, the system waits until it has decided to generalize some term, term, by replacing it with some new variable v. If any :generalize formula can be instantiated so that some non-variable subterm becomes term, then that instance of the formula is added as a hypothesis. Thus for the example above, if the term (rev x2) is generalized to the variable rv during a proof, then the following is added as a hypothesis when generalizing to a new goal. (implies (integer-listp x2) (integer-listp rv)) At the moment, the best description of how ACL2 :generalize rules are used may be found in the discussion of ``Generalize Rules,'' page 248 of A Computational Logic Handbook, or ``Generalization,'' page 132 of ``Computer-Aided Reasoning: An Approach.'' Also see [introduction-to-the-theorem-prover] for detailed tutorial on using ACL2 to prove theorems, which includes some discussion of generalization.") (GENERALIZED-BOOLEANS (COMMON-LISP) "Potential soundness issues related to ACL2 predicates The discussion below outlines a potential source of unsoundness in ACL2. Although to our knowledge there is no existing Lisp implementation in which this problem can arise, nevertheless we feel compelled to explain this situation. Consider for example the question: What is the value of (equal 3 3)? According to the ACL2 axioms, it's t. And as far as we know, based on considerable testing, the value is t in every Common Lisp implementation. However, according the Common Lisp draft proposed ANSI standard, any non-nil value could result. Thus for example, (equal 3 3) is allowed by the standard to be 17. The Common Lisp standard specifies (or soon will) that a number of Common Lisp functions that one might expect to return Boolean values may, in fact, return arbitrary values. Examples of such functions are [equal], [rationalp], and [<]; a much more complete list is given below. Indeed, we dare to say that every Common Lisp function that one may believe returns only Booleans is, nevertheless, not specified by the standard to have that property, with the exceptions of the functions not and null. The standard refers to such arbitrary values as ``generalized Booleans,'' but in fact this terminology makes no restriction on those values. Rather, it merely specifies that they are to be viewed, in an informal sense, as being either nil or not nil. This situation is problematic for ACL2, which axiomatizes these functions to return Booleans. The problem is that because (for efficiency and simplicity) ACL2 makes very direct use of compiled Common Lisp functions to support the execution of its functions, there is in principle a potential for unsoundness due to these ``generalized Booleans.'' For example, ACL2's [equal] function is defined to be Common Lisp's equal. Hence if in Common Lisp the form (equal 3 3) were to evaluate to 17, then in ACL2 we could prove (using the :[executable-counterpart] of [equal]) (equal (equal 3 3) 17). However, ACL2 can also prove (equal (equal x x) t), and these two terms together are contradictory, since they imply (instantiating x in the second term by 3) that (equal 3 3) is both equal to 17 and to t. To make matters worse, the standard allows (equal 3 3) to evaluate to different non-nil values every time. That is: equal need not even be a function! Fortunately, no existing Lisp implementation takes advantage of the flexibility to have (most of) its predicates return generalized Booleans, as far as we know. We may implement appropriate safeguards in future releases of ACL2, in analogy to (indeed, probably extending) the existing safeguards by way of guards (see [guard]). For now, we'll sleep a bit better knowing that we have been up-front about this potential problem. The following list of functions contains all those that are defined in Common Lisp to return generalized Booleans but are assumed by ACL2 to return Booleans. In addition, the functions [ACL2-numberp] and [complex-rationalp] are directly defined in terms of respective Common Lisp functions numberp and complexp. /= < = alpha-char-p atom char-equal char< char<= char> char>= characterp consp digit-char-p endp eq eql equal evenp integerp keywordp listp logbitp logtest lower-case-p minusp oddp plusp rationalp standard-char-p string-equal string< string<= string> string>= stringp subsetp symbolp upper-case-p zerop") (GENERALIZING-KEY-CHECKPOINTS (INTRODUCTION-TO-THE-THEOREM-PROVER) "Getting rid of unnecessary specificity Suppose MEMBER determines whether its first argument is a member of its second, and SUBSETP determines whether every element of its first argument is a member of its second. Suppose that you're trying to prove some Main Theorem and are told the formula below is a key checkpoint. What should you do? Key Checkpoint: (IMPLIES (AND (CONSP A) (INTEGERP (CAR A)) (MEMBER (CAR A) B) (SUBSETP (CDR A) B) (NOT (SUBSETP (CDR A) (APPEND B C)))) (MEMBER (CAR A) C)) The key observation is that the third hypothesis implies the negation of the fourth. Writing it in the contrapositive: (IMPLIES (AND ... (SUBSETP (CDR A) B) ...) (SUBSETP (CDR A) (APPEND B C))) In fact, that is more complicated than it needs to be. A ``correct'' response to the key checkpoint above is to prove (defthm subsetp-append (implies (subsetp a b) (subsetp a (append b c)))). A still better response is to prove this: (defthm subsetp-append-2 (implies (or (subsetp a b) (subsetp a c)) (subsetp a (append b c)))). This version is better because it handles both of the possibilities regarding whether a is a subset of the arguments of the append. It would be nice if we could think of a ``strong'' version, one in which (SUBSETP a (APPEND b c)) is rewritten to some clearly simpler term, but nothing comes to mind. In any case, if you cannot see any obvious simplification of the individual terms in the Key Checkpoint, you should ask yourself whether there are connections beween the various propositional parts (as here, with the third and fourth hypotheses). It is a good heuristic to look for relations between parts with the same top-level function symbol (as here, with SUBSETP). It is also a good heuristic to throw out parts of the formula that seem disconnected (as here, with the terms involving (CAR A)). This discussion suggests several ``modes'' of looking at key checkpoints and the idea of trying the modes in sequence: (1) look for simplifiable combinations of function symbols within propositional components, (2) look for relations between propositional components, and (3) throw out irrelevant or weakly connected components. In all cases you are bringing to bear your intuitions about the semantics of the terms. That is, you're not just slinging symbols. You should be looking out for obvious truths about individual parts of the checkpoints... truths that are obvious to you but not to ACL2! Ultimately the three ``modes'' are the same and we do not really recommend adhering to the given sequence. You're just looking for simpler theorems that, in combination, imply the checkpoint. Keeping the ``modes'' in mind may help focus your attention so you consider all the plausible possibilities. After a little experience you'll find yourself looking for all these things simultaneously as part ``cleaning up'' the checkpoints. When your main goal theorems are harder than these, your main concern will be looking at a Key Checkpoint and asking yourself ``why is this true?'' But you don't want to do that until you've cleaned it up ``locally'' as much as possible and sometimes -- more often than you might think -- local considerations can prove many of your checkpoints. If you have been working your way through the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-key-checkpoints].") (GET-COMMAND-SEQUENCE (HISTORY) "Return list of [command]s that are between two [command] descriptors Examples: (get-command-sequence 4 12) :gcs 4 12 ; same as above (get-command-sequence 4 :x) :gcs 4 :x ; same as above See [pcs] for a utility that prints abbreviated information about the [command]s that are between two command descriptors. The utility get-command-sequence --- or simply gcs, so that you can just type :gcs at the prompt --- has the same syntax but instead of printing, it simply returns the corresponding list of commands. More precisely, it returns an error triple (mv erp val state) (see [error-triples]) such that if erp is not nil, then val is the desired list of commands.") (GET-INTERNAL-TIME (PROGRAMMING ACL2-BUILT-INS) "Runtime vs. realtime in ACL2 timings The ACL2 system provides utilities that deal with elapsed time. The most visible of these is in the time summaries printed when completing evaluation of [events]. For others, see [with-prover-time-limit], see [read-run-time], see [time-tracker], see [time-tracker-tau], and see [pstack]. By default, these utilities all use an underlying notion of run time provided by the host Common Lisp implementation: specifically, the Common Lisp function get-internal-run-time. However, Common Lisp also provides the function get-internal-real-time, which returns the real time (wall clock time). While the latter is specified to measure elapsed time, the former is left to the implementation, which might well only measure time spent in the Lisp process. Consider the following example, which is a bit arcane but basically sleeps for 2 seconds. (defttag t) ; to allow sys-call (make-event (prog2$ (sys-call \"sleep\" '(\"2\")) (value '(value-triple nil)))) A typical time summary might be as follows, drastically under-reporting the elapsed time. Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) However, you can instruct ACL2 to switch to using elapsed time (real time), in summaries and elsewhere, by evaluating the following form. (assign get-internal-time-as-realtime t) To return to using runtime: (assign get-internal-time-as-realtime nil) While the above example is rather silly, the issue becomes significant in time summaries for proofs that call out to external tools (see [sys-call] and see [clause-processor]). Note that a function get-internal-time is defined in raw Lisp but is not available inside the ACL2 loop. However, the expression (read-run-time state) provides an interface to this function that is available inside the ACL2 loop; see [read-run-time]. We are open to changing the default to elapsed wall-clock time (realtime), and may do so in future ACL2 releases. Implementation note (GCL only): If the host Lisp is Gnu Common Lisp, then get-internal-run-time has a multiple value return, and the first two values (runtime and child runtime) are added together to produce a result for get-internal-time.") (GET-OUTPUT-STREAM-STRING$ (POINTERS) "See [io].") (GET-WORMHOLE-STATUS (WORMHOLE) "Make a wormhole's status visible outside the wormhole General Form: (get-wormhole-status name state) Name should be the name of a wormhole (see [wormhole]). This function returns an error triple (see [error-triples]) of the form (mv nil s state), where s is the status of the named wormhole. The status is obtained by reading the oracle in the ACL2 [state]. This function makes the status of a wormhole visible outside the wormhole. But since this function takes [state] and modifies it, the function may only be used in contexts in which you may change [state]. Otherwise, the wormhole status may stay in the wormhole. See [wormhole-eval] and [wormhole].") (GETENV$ (PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "Read an environment variable (Getenv$ str state), where str is a string, reads the value of environment variable str, returning a value of nil if none is found or if the read fails. The logical story is that getenv$ reads its value from the oracle field of the ACL2 [state]. The return value is thus a triple of the form (mv erp val state), where erp will always be nil in practice, and logically, val is the top of the acl2-oracle field of the state (see [read-ACL2-oracle]) and the returned state has the updated (popped) acl2-oracle. Example: (getenv$ \"PWD\" state) ==> (mv nil \"/u/joe/work\" state) Also see [setenv$]. Function: (defun getenv$ (str state) (declare (xargs :stobjs state :guard (stringp str))) (declare (ignore str)) (read-acl2-oracle state))") (GETPROP (WORLD ACL2-BUILT-INS) "Access fast property lists General form: (getprop symb key default world-name world-alist) See community book books/misc/getprop.lisp for an example that illustrates the use of ACL2 utilities [getprop] and putprop to take advantage of under-the-hood Lisp (hashed) property lists. Macro: (defmacro getprop (symb key default world-name world-alist) (if (equal world-name ''current-acl2-world) (cons 'fgetprop (cons symb (cons key (cons default (cons world-alist 'nil))))) (cons 'sgetprop (cons symb (cons key (cons default (cons world-name (cons world-alist 'nil))))))))") (GETTING-STARTED (POINTERS) "See [ACL2-tutorial].") (GIT-QUICK-START (ABOUT-ACL2) "Git quick start guide Each of the two topics [github-commit-code-using-push] and [github-commit-code-using-pull-requests] presents a minimal guide to using the Github repository for ACL2+Books. That {repository | https://github.com/acl2/acl2} exists on the web and contains the ``bleeding edge'' ACL2 source code and [community-books], available between ACL2 releases (see [release-notes]). Those who are familiar with older version control systems, or perhaps with no version control systems, might find this guide to be helpful. For additional information, including the use of branches and links to more information about git, see {the wiki page for git tips | https://github.com/acl2/acl2/wiki/ACL2-repo-git-tips}, [books-certification], and the Internet in general. However, both of the above-mentioned guides are intended to be sufficient for you to obtain the latest ACL2 source code and community-books, and optionally, for you to contribute to the [community-books]. Select the guide that is right for you based upon the headings below. For non-contributors: See sections (A) and (B) in [github-commit-code-using-push]. For infrequent contributors: For those only planning on contributing a few times per year (or less), see [github-commit-code-using-pull-requests]. For frequent contributors: For those contributing on a monthly or weekly basis, see [github-commit-code-using-push]. Subtopics [Github-commit-code-using-pull-requests] How to commit code to the books using pull requests [Github-commit-code-using-push] How to commit code to the books using direct push access") (GITHUB-COMMIT-CODE-USING-PULL-REQUESTS (GIT-QUICK-START) "How to commit code to the books using pull requests This guide is written for contributors who will probably only commit to the repository a few times a year. If you find yourself committing more often, you should see [github-commit-code-using-push]. A nice result of using pull requests is that all changes will be peer-reviewed before being committed. Also, we sometimes call this method theFork and Pullmethod. (A) GETTING STARTED 1. Go to {https://github.com/acl2/acl2 | https://github.com/acl2/acl2} and click on the fork button on the top-right. Fork the repository into your github space. This will create a new repository at https://github.com//acl2. 2. In your working space on your computer, create a clone of your github repository and cd into it: git clone https://github.com//acl2 cd acl2 3. Add the Community ACL2 repository as a git remote: git remote add upstream https://github.com/acl2/acl2 (B) UPDATING The following commands will update your local repository to match the latest contents of the ACL2 Community github repository (on the web). git fetch --all git merge remotes/upstream/master (C) CONTRIBUTING Change and Test 1. Before beginning your edits, update, as in (B) above: git fetch --all git merge remotes/upstream/master 2. Build an executable. (time nice make LISP=) >& make.log 3. Make book changes. If you are creating any new books, tell git that you intend to add them (but the local repository on the web won't change until the commit step below is executed). git add file1 file2 ... 4. Run a regression. Note: Unless your ACL2 is classic (as opposed to the default, [hons-enabled]), this will also test the hons-only books in the regression. (time nice make -j 8 regression-fresh) >& make-regression.log Note that the -j 8 option specifies the use of 8 hardware threads; feel free to omit it or use a more suitable number (especially if your computer has other than 8 hardware threads). 5. Look for failures, as indicated by ** in the log. fgrep -a '**' make-regression.log 6. If there were failures, then go back to Step 1 above to make appropriate changes and re-test, but you can replace the 'make' step by replacing regression-fresh with regression, since 'make' is clever enough to avoid recertifying more than is necessary. For example: (time nice make -j 8 regression) >& make-regression-finish-1.log Update, and Iterate If Necessary Update again as in (B) above: git fetch --all git merge remotes/upstream/master The merge may fail if there have been remote updates, that is updates in the repository on the web. In that case, commit your changes locally and then try the merge again. You might want to use the -F option instead of -m; see the next section for more on those options. git commit -a -m '' git merge remotes/upstream/master If the second command (the git merge) prompts you for a message, the empty message should suffice as a reasonable default (in emacs -- if vi tries to come up, just type :q and . You can now go on to the next step (Contribute Your Changes). But ideally: If the output indicates that anything has changed, then go back to ``Change and Test'' above. Of course, you can skip the build if no ACL2 sources have changed, and you can skip making book changes if you are still happy with your changes. Contribute Your Changes The following commands will update your github repository on the web. The -m ... option is a log message whose first line should be a summary of your changes and other lines may give more details. You are welcome to replace the -m ... option by -F , where is the name of a file that contains your log message. git commit -a -m '' git push You now need to create apull request, where you request that changes from your github repository be accepted into the Community ACL2 repository. To achieve this: 1. Goto https://github.com//acl2. 2. Click the Compare & pull request button (you can search for it with your browser). 3. Put some explanation about what's in the changes in the comments section. It's helpful if you quote (possibly abbreviated) versions of your commit log messages here, as that way the descriptions are easily read when clicking on the Community Repository commits tab, which goes to { https://github.com/acl2/acl2/commits/master | https://github.com/acl2/acl2/commits/master}. 4. Click Create pull request. At this point, the Community ACL2 repository maintainers will be notified, check that things seem to be in order, and then adopt your changes.") (GITHUB-COMMIT-CODE-USING-PUSH (GIT-QUICK-START) "How to commit code to the books using direct push access This guide is written for two groups of people: * Users of the ACL2 System and Books who do not plan to contribute to the books, and * Contributors who commit to the repository on a monthly or weekly basis. In this case, a contributor will typically begin with the [github-commit-code-using-pull-requests] method, and after they are familiar with the process and community, they will move to this method. (A) GETTING STARTED Start by obtaining an up-to-date copy of the web-based github repository. Here, we show how to put it into into a directory called ACL2 (but name it whatever you like). mkdir ACL2 cd ACL2 git clone https://github.com/acl2/acl2 . (B) UPDATING The following commands will update your directory to match the latest contents of the github repository (on the web). git fetch --all git merge remotes/origin/master (C) CONTRIBUTING (optional) To join the {github project | https://github.com/acl2/acl2/}, please send email to one of the following individuals. * Jared Davis (jared.c.davis@gmail.com) * David Rager (ragerdl@gmail.com) * Sol Swords (sswords@gmail.com) After you have joined the project, you can proceed as follows when you are ready to contribute. Change and Test 1. Update as in (B) above: git fetch --all git merge remotes/origin/master 2. Build an executable. (time nice make LISP=) >& make.log 3. Make book changes. If you are creating any new books, tell git that you intend to add them (but the repository on the web won't change until the last step below is executed). git add file1 file2 ... 4. Run a regression. Note: Unless your ACL2 is classic (as opposed to the default, [hons-enabled]), this will also test the hons-only books in the regression. (time nice make -j 8 regression-fresh) >& make-regression.log 5. Look for failures, as indicated by ** in the log. fgrep -a '**' make-regression.log 6. If there were failures, then go back to Step 1 above to make appropriate changes and re-test, but you can replace the 'make' step by replacing regression-fresh with regression, since 'make' is clever enough to avoid recertifying more than is necessary. For example: (time nice make -j 8 regression) >& make-regression-finish-1.log Note that the -j 8 option specifies the use of 8 hardware threads; feel free to omit it or use a more suitable number (especially if your computer has other than 8 hardware threads). Update, and Iterate If Necessary Update again as in (B) above: git fetch --all git merge remotes/origin/master The merge may fail if there have been remote updates, that is updates in the repository on the web. In that case, commit your changes locally and then try the merge again. You might want to use the -F option instead of -m; see the next section for more on those options. git commit -a -m '' git merge remotes/origin/master If the second command prompts you for a message, the empty message should suffice as a reasonable default. (In emacs, if vi tries to come up, just type :q and . You can now go on to the next step (Contribute Your Changes). But ideally: If the output indicates that anything has changed, then go back to ``Change and Test'' above. Of course, you can skip the build if no ACL2 sources have changed, and you can skip making book changes if you are still happy with your changes. Contribute Your Changes The following commands will update the github repository on the web. The -m ... option is a log message whose first line should be a summary of your changes and other lines may give more details. You are welcome to replace the -m ... option by -F , where is the name of a file that contains your log message. git commit -a -m '' git push") (GOAL-SPEC (HINTS) "To indicate where a hint is to be used Examples: \"Goal\" \"goal\" \"Subgoal *1/3''\" \"subgoal *1/3''\" \"[2]Subgoal *1/3''\" When [hints] are given to the theorem prover, a goal-spec is provided to specify the goal to which the [hints] are to be applied. The [hints] provided are carried along innocuously until the named goal arises. When it arises, the [hints] are ``activated'' for that goal and its descendents. A legal goal specification may be extracted from the theorem prover's output. Certain lines clearly label formulas, as in Subgoal *1/3.2' (IMPLIES ... ...) and these lines all give rise to goal specifications. In general, these lines all start either with ``Goal'' or ``Subgoal'' or else with those words preceded by a number in square brackets, as in [1]Subgoal *1/3.2' (IMPLIES ... ...). A goal specification may be obtained by deleting any surrounding whitespace from such a line and embedding the text in string quotation marks. Thus \"[1]Subgoal *1/3.2'\" is the goal specifier for the goal above. As noted, a hint is applied to a goal when the hint's goal specification matches the name ACL2 assigns to the goal. The matching algorithm is case-insensitive. Thus, alternative goal specifications for the goal above are \"[1]subgoal *1/3.2'\" and \"[1]SUBGOAL *1/3.2'\". The matching algorithm does not tolerate non-case discrepancies. Thus, \"[1]Subgoal*1/3.2'\" and \" [1]Subgoal *1/3.2'\" are unacceptable. Sometimes a formula is given two names, e.g., Subgoal *1/14.2' (IMPLIES ... ...) Name the formula above *1.1. It is the first name (the one that starts with ``Goal'' or ``Subgoal'') and not the second which constitutes a legal goal-spec. Roughly speaking, when the system prints the line containing the goal specification, it activates any [hints] that are attached to that goal-spec. Consider the example above. Suppose Subgoal *1/14.2' could be proved by using a certain lemma instance. Then the appropriate entry in the [hints] would be: (\"Subgoal *1/14.2'\" :use ...) This might surprise you because the system appears to do nothing to *1/14.2' besides push it for a subsequent induction. But actually between the time the system printed the goal-spec line and the time it decides to push the goal, you can think of the system as trying everything it has. So a use hint activated when Subgoal *1/14.2' arises is just what you want. But what if you want to give an :induct hint? By the time induction is tried, the formula has been given the name *1.1. Well, this is one you just have to remember: (\"Subgoal *1/14.2'\" :induct ...). When the above hint is activated the :induct directive short-circuits the rest of the processing and sends immediately the formula into the pool of goals to prove by induction. The induct hint is attached to the formula in the pool and when the time comes to turn our attention to that goal, the induct advice is followed. We conclude by emphasizing a point made above, that a hint is applied to a goal when the hint's goal specification matches the name ACL2 assigns to the goal. If there is no such match, then the hint is ignored. Consider the following example. (thm (equal (append (append x y) z) (append x y z)) :hints ((\"Subgoal *1/\" :in-theory nil))) Normally, :in-theory hints are inherited by subgoals (see [hints-and-the-waterfall]), so you might expect that the empty theory is used in Subgoal *1/2 and Subgoal *1/1. But in fact, since there is no subgoal printed that is labeled Subgoal *1/, the above :in-theory hint is ignored. The above example is in contrast to the following, where the hint makes the proof fail, because there really is a Subgoal *1/ in the proof this time. (thm (implies (and (not (endp x)) (not (endp (cdr x)))) (equal (append (append x y) z) (append x y z))) :hints ((\"Subgoal *1/\" :in-theory nil))) Subtopics [Clause-identifier] The internal form of a [goal-spec]") (GOOD-ATOM-LISTP (ATOM LISTS ACL2-BUILT-INS) "Recognizer for a true list of ``good'' [atom]s The predicate good-atom-listp tests whether its argument is a [true-listp] of ``good'' [atom]s, i.e., where each element is a number, a symbol, a character, or a string. Also see [atom-listp]. Function: (defun good-atom-listp (lst) (declare (xargs :guard t)) (cond ((atom lst) (eq lst nil)) (t (and (or (acl2-numberp (car lst)) (symbolp (car lst)) (characterp (car lst)) (stringp (car lst))) (good-atom-listp (cdr lst))))))") (GOOD-BYE (BASICS ACL2-BUILT-INS) "Quit entirely out of Lisp Examples: ACL2 !>(good-bye) ; [ACL2 is exited] ACL2 !>(good-bye 3) ; [ACL2 is exited with Unix exit status 3] Note: Your entire session will disappear forever when you evaluate (good-bye). The command (good-bye) quits not only out of the ACL2 [command] loop, but in fact quits entirely out of the underlying Lisp. Thus, there is no going back! You will not be able to re-enter the [command] loop after typing (good-bye)! All your work will be lost!!! This command may not work in some underlying Common Lisp implementations. In such cases, there is no harm in trying; ACL2 will let you know how to proceed if it cannot exit. In some systems, typing control-d at the top-level ACL2 prompt (control-c control-d if inside emacs) will call this function. If you give good-bye an argument, it should be a natural number, and it indicates the Unix (Linux) exit status. If you merely want to exit the ACL2 [command] loop, use :q instead (see [q]). Subtopics [Exit] Quit entirely out of Lisp [Quit] Quit entirely out of Lisp") (GRANULARITY (PARALLEL-PROGRAMMING) "Limit the amount of parallelism This [documentation] topic relates to the experimental extension of ACL2 supporting parallel execution and proof; see [parallelism]. Some function calls are on arguments whose evaluation time is long enough to warrant parallel execution, while others are not. A granularity form can be used to make appropriate restrictions on the use of parallelism. For example, consider the Fibonacci function. Experiments have suggested that execution time can be reduced if whenever the argument is less than 27, a serial version of the Fibonacci function is called. One way to utilize this information is to write two definitions of the Fibonacci function, one serial and one parallel. (defun fib (x) (declare (xargs :guard (natp x))) (cond ((or (zp x) (<= x 0)) 0) ((= x 1) 1) (t (binary-+ (fib (- x 1)) (fib (- x 2)))))) (defun pfib (x) (declare (xargs :guard (natp x))) (cond ((or (zp x) (<= x 0)) 0) ((= x 1) 1) ((< x 27) (binary-+ (fib (- x 1)) (fib (- x 2)))) (t (pargs (binary-+ (pfib (- x 1)) (pfib (- x 2))))))) We realize quickly that writing both of these function definitions is cumbersome and redundant. This problem can be avoided by using a granularity declaration with a parallelism primitive. This form ensures that a call is parallelized only if resources are available and the granularity form evaluates to a non-nil value at the time of the call. Below is a definition of the Fibonacci function using a granularity form. (defun pfib (x) (declare (xargs :guard (natp x))) (cond ((or (zp x) (<= x 0)) 0) ((= x 1) 1) (t (pargs (declare (granularity (>= x 27))) (binary-+ (pfib (- x 1)) (pfib (- x 2))))))) A granularity form can reference an extra formal parameter that describes the call depth of the function the user is parallelizing. Consider for example the following parallel mergesort function, based on Davis's Ordered Sets library. It splits the data into symmetric chunks for computation, so we increment the depth argument during the recursive call on both the car and cdr. (include-book \"finite-set-theory/osets/sets\" :dir :system) (defun set::pmergesort-exec (x depth) (declare (xargs :mode :program)) (cond ((endp x) nil) ((endp (cdr x)) (set::insert (car x) nil)) (t (mv-let (part1 part2) (set::split-list x nil nil) (pargs (declare (granularity (< depth 2))) (set::union (set::pmergesort-exec part1 (1+ depth)) (set::pmergesort-exec part2 (1+ depth)))))))) A less intrusive method (i.e., not requiring an extra formal parameter like the depth argument just above), which however can be less efficient, involves analyzing the data itself for structural properties. For example: (defun some-depth-exceeds (x n) (declare (xargs :guard (natp n))) (if (atom x) nil (if (zp n) t (or (some-depth-exceeds (car x) (1- n)) (some-depth-exceeds (cdr x) (1- n)))))) (defun valid-tip (x) (declare (xargs :guard t)) (or (eq x 'A) (eq x 'T) (eq x 'C) (eq x 'G))) (defun pvalid-tree (x) (declare (xargs :guard t)) (if (atom x) (valid-tip x) (pand (declare (granularity (some-depth-exceeds x 3))) (pvalid-tree (car x)) (pvalid-tree (cdr x))))) If you experiment with calls of pvalid-tree, you are likely to find that the ``speedup'' it provides over a corresponding serial version is, in fact, a slowdown! The problem is likely that some-depth-exceeds is an expensive function to run repeatedly. Instead of the approach above, it is often handy to add an extra formal parameter in order to allow for more efficient granularity forms, as we have done above in the definition of SET::pmergesort-exec.") (GROUND-ZERO (THEORIES THEORY-FUNCTIONS) "[enable]d rules in the [startup] theory ACL2 concludes its initialization (boot-strapping) procedure by defining the theory ground-zero; see [theories]. In fact, this theory is just the theory defined by (current-theory :here) at the conclusion of initialization; see [current-theory]. Note that by evaluating the event (in-theory (current-theory 'ground-zero)) you can restore the current theory to its value at the time you started up ACL2.") (GUARD (PROGRAMMING XARGS) "Restricting the domain of a function The ACL2 system provides a mechanism for restricting a function to a particular domain. Such restrictions are called ``guards.'' A definition's guard has no effect on the logical axiom added when that definition is accepted by ACL2, and novices are often best served by avoiding guards. However, guards can be useful as a specification device or for increasing execution efficiency. To make such a restriction, use the :guard keyword (see [xargs]) or, especially if you want the host Lisp compiler to use this information, use type declarations (see [declare]; also see [xargs] for a discussion of the split-types keyword). The general issue of guards and guard verification is discussed in the topics listed below. To begin further discussion of guards, see [guard-introduction]. That section directs the reader to further sections for more details. To see just a summary of some [command]s related to guards, see [guard-quick-reference]. For a discussion of the use of proof to verify the absence of guard violations, see [verify-guards]. Subtopics [Ec-call] Execute a call in the ACL2 logic instead of raw Lisp [Extra-info] Sources of measure or guard proof obligations [Guard-debug] Generate markers to indicate sources of [guard] proof obligations [Guard-evaluation-examples-log] Log showing combinations of [defun-mode]s and [guard]-checking [Guard-evaluation-examples-script] A script to show combinations of [defun-mode]s and [guard]-checking [Guard-evaluation-table] A table that shows combinations of [defun-mode]s and [guard]-checking [Guard-example] A brief transcript illustrating [guard]s in ACL2 [Guard-holders] Remove trivial calls from a [term] [Guard-introduction] Introduction to [guard]s in ACL2 [Guard-miscellany] Miscellaneous remarks about guards [Guard-obligation] The guard proof obligation [Guard-quick-reference] Brief summary of guard checking and guard verification [Guards-and-evaluation] The relationship between guards and evaluation [Guards-for-specification] Guards as a specification device [Mbe] Attach code for execution [Non-exec] Mark code as non-executable [Print-gv] Print a form whose evaluation caused a guard violation [Set-guard-checking] Control checking [guard]s during execution of top-level forms [Set-guard-msg] Specify what is printed when a [guard] is violated [Set-verify-guards-eagerness] The eagerness with which [guard] verification is tried. [The] The is a special form that can be used to optimize the execution efficiency of [guard]-verified ACL2 definitions, or (less frequently) to carry out a low-level run-time type checks. (Advanced) [Verify-guards] Verify the [guard]s of a function [Verify-guards-formula] View the guard proof obligation, without proving it [With-guard-checking] Suppressing or enable guard-checking for a form") (GUARD-DEBUG (GUARD DEBUGGING) "Generate markers to indicate sources of [guard] proof obligations ACL2 guard verification (see [guard]) is often best avoided by beginning users of ACL2. When guard verification is employed, it can generate numerous goals, some of which may not be theorems if the definition being processed has bugs. It can be difficult to find such bugs. This [documentation] topic explains a capability provided by ACL2 to help find such bugs. For a similar utility appropriate for proving [measure] conjectures (that is, for termination proofs), see [measure-debug]. We begin with the following example. Although it is contrived and a bit simplistic, it illustrates how the guard-debug utility works. (defun length-repeat (x) (length (append x x))) (verify-guards length-repeat :guard-debug t) The output produces two top-level key checkpoints, as follows. Subgoal 2 (IMPLIES (EXTRA-INFO '(:GUARD (:BODY LENGTH-REPEAT)) '(APPEND X X)) (TRUE-LISTP X)) Subgoal 1 (IMPLIES (AND (EXTRA-INFO '(:GUARD (:BODY LENGTH-REPEAT)) '(LENGTH (APPEND X X))) (NOT (TRUE-LISTP (APPEND X X)))) (STRINGP (APPEND X X))) The upper subgoal (numbered 2) says that the body of the definition of length-repeat contains a call (APPEND X X), which is the source of the goal. In this case, that makes sense: the [guard] for a call (append arg1 arg2) is (true-listp arg1), which in this case is (TRUE-LISTP X). The lower subgoal (numbered 1) says that the same definition contains the call (LENGTH (APPEND X X)), which generates the proof obligation that if (APPEND X X) does not satisfy true-listp, then it must satisfy stringp. That proof obligation comes directly from the [guard] for [length]. Of course, the example above is a bit obvious. But for large definitional bodies such information can be very helpful. Note that guard-debug can be specified not only in [verify-guards] events but also in [xargs] [declare] forms of [defun] events. We now describe the guard-debug utility in some detail. (Extra-info x y) always returns t by definition. However, if [guard] verification takes place with a non-nil setting of guard-debug (see below), then the goals generated for guard verification can include hypotheses that are calls of extra-info. Typically, such a hypothesis is of the following form: (extra-info '(:guard (:body F)) '(G ARG1 ... ARGk)) The above form indicates that the goal in which it occurs was generated to verify that the [guard] of the function F is satisfied by the arguments ARG1 through ARGk, where the term (G ARG1 ... ARGk) occurs in the body of the function F whose guard verification is in progress. If however the above call of G occurs in the guard of F instead of the body of F, then :body is replaced by :guard above: (extra-info '(:guard (:guard F)) '(G ARG1 ... ARGk)) If the same proof obligation (goal clause) arises from more than one occurrence of the same call, then a single goal will be generated, which has several extra-info hypotheses added to show the multiple sources of that proof obligation. All rules (see [rune]) associated with extra-info are [disable]d by default, so that hypotheses of the form described above are not simplified to t. These hypotheses are intended to ride along for free: you can generally expect the proof to have the same structure whether or not the :guard-debug option is supplied, though on rare occasions the proofs may diverge. It remains to explain the notion of a guard-debug setting of t, that is, to explain how to obtain the additional hypotheses described above. If guards are being verified during processing of a [defun] event (whether or not inside a call of [mutual-recursion]), then one specifies :guard-debug t in an [xargs] declaration of a [declare] form; see [xargs]. If however the guard verification is on behalf of a [verify-guards] call, whether for a definition or a theorem, then one specifies the keyword argument :guard-debug t. Also see [print-gv] for a utility for debugging guard violations, in contrast to the above guard-debug mechanism, which is for debugging failed proofs arising from guard verification.") (GUARD-EVALUATION-EXAMPLES-LOG (GUARD) "Log showing combinations of [defun-mode]s and [guard]-checking See [guard-evaluation-examples-script] for a script that shows the interaction of [defun-mode]s with the value set by [set-guard-checking]. Here, we present a log resulting from running this script. See [set-guard-checking] for discussion of the interaction between [defun-mode]s and [guard]-checking that is illustrated by this script. Also see [guard-evaluation-table] for a succinct table, with associated discussion, that covers in detail the interactions illustrated here. ACL2 !>(defun fact (x) (declare (xargs :guard (integerp x) :mode :program)) (if (posp x) (* x (fact (1- x))) 1)) Summary Form: ( DEFUN FACT ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FACT ACL2 !>(trace$ fact) ((FACT)) ACL2 !>:set-guard-checking t Guard-checking-on already has value T. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) ACL2 Error in TOP-LEVEL: The guard for the :program function symbol FACT, which is (INTEGERP X), is violated by the arguments in the call (FACT T). See :DOC trace for a useful debugging utility. See :DOC set-guard-checking for information about suppressing this check with (set-guard-checking :none), as recommended for new users. ACL2 !>:set-guard-checking :all Leaving guard checking on, but changing value to :ALL. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) ACL2 Error in TOP-LEVEL: The guard for the :program function symbol FACT, which is (INTEGERP X), is violated by the arguments in the call (FACT T). See :DOC trace for a useful debugging utility. See :DOC set-guard-checking for information about suppressing this check with (set-guard-checking :none), as recommended for new users. ACL2 !>:set-guard-checking :none Turning off guard checking entirely. To allow execution in raw Lisp for functions with guards other than T, while continuing to mask guard violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:set-guard-checking nil Masking guard violations but still checking guards except for self- recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING :NONE. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) 2> (FACT T) <2 (FACT 1) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:u 0:x(EXIT-BOOT-STRAP-MODE) ACL2 >(defun fact (x) (declare (xargs :guard t :mode :program)) (if (posp x) (* x (fact (1- x))) 1)) Summary Form: ( DEFUN FACT ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FACT ACL2 >(trace$ fact) ((FACT)) ACL2 >:set-guard-checking t Turning guard checking on, value T. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) 2> (FACT T) <2 (FACT 1) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 !>:set-guard-checking :all Leaving guard checking on, but changing value to :ALL. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 !>:set-guard-checking :none Turning off guard checking entirely. To allow execution in raw Lisp for functions with guards other than T, while continuing to mask guard violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:set-guard-checking nil Masking guard violations but still checking guards except for self- recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING :NONE. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) 2> (FACT T) <2 (FACT 1) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:u 0:x(EXIT-BOOT-STRAP-MODE) ACL2 >(defun fact (x) (declare (xargs :guard (integerp x) :verify-guards nil :mode :logic)) (if (posp x) (* x (fact (1- x))) 1)) For the admission of FACT we will use the relation O< (which is known to be well-founded on the domain recognized by O-P) and the measure (ACL2-COUNT X). The non-trivial part of the measure conjecture is [[output omitted here]] Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FACT ACL2 >(trace$ fact) ((FACT)) ACL2 >:set-guard-checking t Turning guard checking on, value T. ACL2 !>(fact 2) [[Comment added to the log: Normally you would get a message about guard-checking being inhibited on recursive calls. However, when a function is traced the guard-checking is done on recursive calls unless the guards have been verified (see :DOC verify-guards). ]] 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which is (INTEGERP X), is violated by the arguments in the call (FACT T). See :DOC trace for a useful debugging utility. See :DOC set-guard- checking for information about suppressing this check with (set-guard- checking :none), as recommended for new users. ACL2 !>:set-guard-checking :all Leaving guard checking on, but changing value to :ALL. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which is (INTEGERP X), is violated by the arguments in the call (FACT T). See :DOC trace for a useful debugging utility. See :DOC set-guard- checking for information about suppressing this check with (set-guard- checking :none), as recommended for new users. ACL2 !>:set-guard-checking :none Turning off guard checking entirely. To allow execution in raw Lisp for functions with guards other than T, while continuing to mask guard violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:set-guard-checking nil Masking guard violations but still checking guards except for self- recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING :NONE. See :DOC set-guard-checking. ACL2 >(fact 2) [[Comment added to the log: In spite of the warning above, guards are checked here on self-recursive calls, because the function is traced. ]] 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >(verify-guards fact) Computing the guard conjecture for FACT.... The guard conjecture for FACT is trivial to prove, given the :compound- recognizer rule POSP-COMPOUND-RECOGNIZER, primitive type reasoning and the :type-prescription rule FACT. FACT is compliant with Common Lisp. Summary Form: ( VERIFY-GUARDS FACT) Rules: ((:COMPOUND-RECOGNIZER POSP-COMPOUND-RECOGNIZER) (:FAKE-RUNE-FOR-TYPE-SET NIL) (:TYPE-PRESCRIPTION FACT)) Warnings: None Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) FACT ACL2 >(trace$ fact) ((FACT)) ACL2 >:set-guard-checking t Turning guard checking on, value T. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which is (INTEGERP X), is violated by the arguments in the call (FACT T). See :DOC trace for a useful debugging utility. See :DOC set-guard- checking for information about suppressing this check with (set-guard- checking :none), as recommended for new users. ACL2 !>:set-guard-checking :all Leaving guard checking on, but changing value to :ALL. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which is (INTEGERP X), is violated by the arguments in the call (FACT T). See :DOC trace for a useful debugging utility. See :DOC set-guard- checking for information about suppressing this check with (set-guard- checking :none), as recommended for new users. ACL2 !>:set-guard-checking :none Turning off guard checking entirely. To allow execution in raw Lisp for functions with guards other than T, while continuing to mask guard violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:set-guard-checking nil Masking guard violations but still checking guards except for self- recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING :NONE. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:u L 1:x(DEFUN FACT (X) ...) ACL2 >:u 0:x(EXIT-BOOT-STRAP-MODE) ACL2 >(defun fact (x) (declare (xargs :guard (integerp x) :mode :logic)) (if (posp x) (* x (fact (1- x))) 1)) For the admission of FACT we will use the relation O< (which is known to be well-founded on the domain recognized by O-P) and the measure (ACL2-COUNT X). The non-trivial part of the measure conjecture is [[output omitted here]] Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FACT ACL2 >(trace$ fact) ((FACT)) ACL2 >:set-guard-checking t Turning guard checking on, value T. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which is (INTEGERP X), is violated by the arguments in the call (FACT T). See :DOC trace for a useful debugging utility. See :DOC set-guard- checking for information about suppressing this check with (set-guard- checking :none), as recommended for new users. ACL2 !>:set-guard-checking :all Leaving guard checking on, but changing value to :ALL. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) ACL2 Error in TOP-LEVEL: The guard for the function symbol FACT, which is (INTEGERP X), is violated by the arguments in the call (FACT T). See :DOC trace for a useful debugging utility. See :DOC set-guard- checking for information about suppressing this check with (set-guard- checking :none), as recommended for new users. ACL2 !>:set-guard-checking :none Turning off guard checking entirely. To allow execution in raw Lisp for functions with guards other than T, while continuing to mask guard violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:set-guard-checking nil Masking guard violations but still checking guards except for self- recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING :NONE. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:u 0:x(EXIT-BOOT-STRAP-MODE) ACL2 >(defun fact (x) (declare (xargs :guard t :verify-guards nil :mode :logic)) (if (posp x) (* x (fact (1- x))) 1)) For the admission of FACT we will use the relation O< (which is known to be well-founded on the domain recognized by O-P) and the measure (ACL2-COUNT X). The non-trivial part of the measure conjecture is [[output omitted here]] Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FACT ACL2 >(trace$ fact) ((FACT)) ACL2 >:set-guard-checking t Turning guard checking on, value T. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 !>:set-guard-checking :all Leaving guard checking on, but changing value to :ALL. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 !>:set-guard-checking :none Turning off guard checking entirely. To allow execution in raw Lisp for functions with guards other than T, while continuing to mask guard violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:set-guard-checking nil Masking guard violations but still checking guards except for self- recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING :NONE. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (ACL2_*1*_ACL2::FACT 1) 3> (ACL2_*1*_ACL2::FACT 0) <3 (ACL2_*1*_ACL2::FACT 1) <2 (ACL2_*1*_ACL2::FACT 1) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >(verify-guards fact) Computing the guard conjecture for FACT.... The guard conjecture for FACT is trivial to prove, given the :compound- recognizer rule POSP-COMPOUND-RECOGNIZER and the :type-prescription rule FACT. FACT is compliant with Common Lisp. Summary Form: ( VERIFY-GUARDS FACT) Rules: ((:COMPOUND-RECOGNIZER POSP-COMPOUND-RECOGNIZER) (:TYPE-PRESCRIPTION FACT)) Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FACT [[Note added to log: No need to trace fact again after verify-guards.]] ACL2 >:set-guard-checking t Turning guard checking on, value T. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) 2> (FACT T) <2 (FACT 1) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 !>:set-guard-checking :all Leaving guard checking on, but changing value to :ALL. ACL2 !>(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 !>(fact t) 1> (ACL2_*1*_ACL2::FACT T) 2> (FACT T) <2 (FACT 1) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 !>:set-guard-checking :none Turning off guard checking entirely. To allow execution in raw Lisp for functions with guards other than T, while continuing to mask guard violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) 2> (FACT T) <2 (FACT 1) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >:set-guard-checking nil Masking guard violations but still checking guards except for self- recursive calls. To avoid guard checking entirely, :SET-GUARD-CHECKING :NONE. See :DOC set-guard-checking. ACL2 >(fact 2) 1> (ACL2_*1*_ACL2::FACT 2) 2> (FACT 2) 3> (FACT 1) 4> (FACT 0) <4 (FACT 1) <3 (FACT 1) <2 (FACT 2) <1 (ACL2_*1*_ACL2::FACT 2) 2 ACL2 >(fact t) 1> (ACL2_*1*_ACL2::FACT T) 2> (FACT T) <2 (FACT 1) <1 (ACL2_*1*_ACL2::FACT 1) 1 ACL2 >") (GUARD-EVALUATION-EXAMPLES-SCRIPT (GUARD) "A script to show combinations of [defun-mode]s and [guard]-checking Below is a script that illustrates the combination of [defun-mode]s --- :[program] mode, :[logic] mode without [guard]s verified, and :[logic] mode with [guard]s verified --- with values from [set-guard-checking] --- t (the default), :all, :none, and nil. (It does not illustrate the value :nowarn, which is the same as t except for inhibiting a warning.) The script also illustrates cases where the guard is not, or is, t. See [guard-evaluation-examples-log] for result of running this script. Before presenting the script below, we give some instructions in case you want to run it yourself. See [set-guard-checking] for discussion of the interaction between [defun-mode]s and [guard]-checking that is illustrated by this script. Also see [guard-evaluation-table] for a succinct table, with associated discussion, that covers in detail the interactions illustrated here. The script mentions the running of ``Tracing Code''. The code is the following sequence of commands. (trace$ fact) :set-guard-checking t (fact 2) (fact t) :set-guard-checking :all (fact 2) (fact t) :set-guard-checking :none (fact 2) (fact t) :set-guard-checking nil (fact 2) (fact t) If you want to run the script yourself, you may find it handy to use the following Emacs keyboard macro for running the tracing code in 2-window mode, with the cursor in the window with the script and ACL2 running in the other window. (fset 'step-guard-script [?C-a ?C- ?C-e ?M-w ?C-a ?C-n ?C-x ?o ?M-> ?C-y return ?C-x ?o]) ; Put it on a key (if you have defined the indicated keymap by using ; emacs/emacs-acl2.el): (define-key ctl-t-keymap \"r\" 'step-guard-script) The script follows. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Program mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun fact (x) (declare (xargs :guard (integerp x) :mode :program)) (if (posp x) (* x (fact (1- x))) 1)) ; Run the Tracing Code here. It shows execution in raw Lisp in the t and nil ; cases of :set-guard-checking, but not in the :all or :none cases. We get a ; guard violation for argument t in the case :set-guard-checking t. :u (defun fact (x) (declare (xargs :guard t :mode :program)) (if (posp x) (* x (fact (1- x))) 1)) ; Run the Tracing Code here. It should give the same results as above, ; except that we no longer get a guard violation in the case ; :set-guard-checking t. :u ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Logic mode, guard other than t ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun fact (x) (declare (xargs :guard (integerp x) :verify-guards nil :mode :logic)) (if (posp x) (* x (fact (1- x))) 1)) ; Run the Tracing Code here. It should give guard violations for (fact t) ; with guard-checking set to t or :all. It should never run in raw Lisp, ; because we have not verified guards. In the t case, we can get a warning ; about avoiding the guard check on recursive calls, but only if we do not ; trace the function, fact. (verify-guards fact) ; Run the Tracing Code here. The results should be as described just above, ; except that now we go into raw Lisp for (fact 2) with guard-checking other ; than :none. :u :u ; The following definition is the same as above, except that guards are ; verified. (defun fact (x) (declare (xargs :guard (integerp x) :mode :logic)) (if (posp x) (* x (fact (1- x))) 1)) ; Run the Tracing Code here. We should get the same traces as in the ; immediately preceding case, since guards had been verified in both cases. :u ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Logic mode, guard t ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun fact (x) (declare (xargs :guard t :verify-guards nil :mode :logic)) (if (posp x) (* x (fact (1- x))) 1)) ; Run the Tracing Code here. We should never go in to raw Lisp, because ; guards have not been verified. We will see the same traces for (fact 2) as ; with the (integerp x) guard above with :verify-guards nil specified, except ; that even without tracing, there is no warning for :set-guard-checking t ; about recursive calls. And, there are no guard violations for (fact t), of ; course, since posp (necessarily, if we are to verify guards) has a guard of ; t. (verify-guards fact) ; Run the Tracing Code here. You shouldn't see any surprises. Note however ; that if we back up to the start (using :u :u) and then define fact as just ; above but without :verify-guards nil, then the :none setting will allow us ; to go into raw Lisp: although :none generally avoids execution of raw Lisp ; counterparts, it allows this when the guard is T and guards have been ; verified.") (GUARD-EVALUATION-TABLE (GUARD) "A table that shows combinations of [defun-mode]s and [guard]-checking See [set-guard-checking] for an introduction to the topic discussed here. Also see [guard] for a general discussion of guards, and see [guard-evaluation-examples-script] for a script that illustrates combinations presented below. Note: The default setting for guard-checking (that is, the initial value for (@ guard-checking-on)) is T. The table below illustrates the interaction of the [defun-mode] with the value supplied to [set-guard-checking]. The first row considers functions defined in :[program] mode; the other two consider functions defined in :[logic] mode. The columns correspond to four values of state global 'guard-checking-on, as supplied to [set-guard-checking]. (A fifth value, :nowarn, is similar to t but suppresses warnings encountered with t (as explained in those warning messages), and is not considered here.) During proofs, 'guard-checking-on is set to nil regardless of how this variable has been set in the top-level loop. Below this table, we make some comments about its entries, ordered by row and then by column. For example, when we refer to ``b2'' we are discussing the execution of a :[logic] mode function whose guards have not been verified, after having executed :[set-guard-checking] :all. guard-checking-on: (1)t (2):all (3):none (4)nil (a) :program a1 a2 a3 a4 (b) guards not verified b1 b2 b3 b4 (c) guards verified c1 c2 c3 c4 a1. Check the [guard] upon entry, then use the raw Lisp code if the guard checks (else cause an error). This is a common setting when one wants a little guard checking but also wants the efficiency of raw Lisp. But note that you can get raw Lisp errors. For example, if you make the definition (defun foo (x) (car x)) in :[program] mode and execute :[set-guard-checking] t, and then execute (foo 3), you will likely get an error from the call (car 3) made in raw Lisp. a2. For built-in (predefined) functions, see a1 instead. Otherwise: Check the [guard], without exception. Thus, we never run the raw Lisp code in this case. This can be useful when testing :[program] mode functions, but you may want to run :[comp] t or at least :[comp] :exec in this case, so that the execution is done using compiled code. a3. For built-in (predefined) functions, see a4 instead. Otherwise: Do not check the [guard]. For :[program] mode functions, we never run the raw Lisp code in this case; so if you care about efficiency, see the comment in a2 above about :[comp]. This combination is useful if you are using ACL2 as a programming language and do not want to prove theorems about your functions or suffer [guard] violations. In this case, you can forget about any connection between ACL2 and Common Lisp. a4. Run the raw Lisp code without checking [guard]s at all. Thus, for :[program] mode functions, the nil setting is often preferable to the :none setting because you get the efficiency of raw Lisp execution. However, with nil you can therefore get hard Lisp errors as in a1 above. b1. Guards are checked at the top-level, though not at self-recursive calls. We never run the raw Lisp code in this case; guards would need to be verified first. b2. Unlike the t setting, guards are checked even on self-recursive calls. But like the t setting, we do not run the raw Lisp code. Use this setting if you want guards checked on each recursive call in spite of the cost of doing so. b3, b4. Execution avoids the raw Lisp code and never checks guards. The nil and :none settings behave the same in this case (i.e., for :[logic] mode functions whose guards have not been verified), except that recursive calls are never inlined for :none and tracing (see [trace]) will show recursive calls for :none but not for nil. c1, c2. Guards are checked. If the checks pass, evaluation takes place using the raw Lisp code. If the checks fail, we get a guard violation. Either way, we do not execute ``in the logic''; we only execute using the raw Lisp code. Note that t and :all behave the same in this case, (i.e. for :[logic] mode functions whose [guard]s have been verified). c3, c4. For the :none and nil settings, :[logic] mode functions whose guards have been verified will never cause guard violations. However, with nil and for built-in functions in :logic mode, guards are still checked: if the check succeeds, then evaluation is done using the raw Lisp code, and if not, it is done by the ``logic'' code, including self-recursive calls (though unlike the t case, we will not see a warning about this). But with :none for user-defined functions, no guard checking is done, and the only time the raw Lisp code will be executed is when the guard is t and guards are verified at the time the executable counterpart of the function is defined (i.e., when the function is admitted unless it is later defined again and compiled using :[comp]). Thus, if you use :none and you want a function (foo x) with guard (g x) to execute using raw Lisp code, you can write a ``wrapper''function with a guard of t: (defun foo-wrap (x) (declare (xargs :guard t)) (if (g x) (foo x) 'do-not-case)) If you want the speed of executing raw Lisp code and you have non-trivial guards on functions that you want to call at the top-level, use nil rather than :none.") (GUARD-EXAMPLE (TUTORIAL5-MISCELLANEOUS-EXAMPLES GUARD) "A brief transcript illustrating [guard]s in ACL2 This note addresses the question: what is the use of [guard]s in ACL2? Although we recommend that beginners try to avoid [guard]s for a while, we hope that the summary here is reasonably self-contained and will provide a reasonable introduction to guards in ACL2. For a more systematic discussion, see [guard]. For a summary of that topic, see [guard-quick-reference]. Before we get into the issue of [guard]s, let us note that there are two important ``modes'': [defun-mode] --- ``Does this [defun] add an axiom (`:logic mode') or not (`:program mode')?'' (See [defun-mode].) Only :[logic] mode functions can have their ``[guard]s verified'' via mechanized proof; see [verify-guards]. [set-guard-checking] --- ``Should runtime [guard] violations signal an error (:all, and usually with t or :nowarn) or go undetected (nil, :none)? Equivalently, are expressions evaluated in Common Lisp or in the logic?'' (See [set-guard-checking].) Prompt examples Here some examples of the relation between the ACL2 [prompt] and the ``modes'' discussed above. Also see [default-print-prompt]. The first examples all have ld-skip-proofsp nil; that is, proofs are not skipped. ACL2 !> ; logic mode with guard checking on ACL2 > ; logic mode with guard checking off ACL2 p!> ; program mode with guard checking on ACL2 p> ; program mode with guard checking off Here are some examples with [default-defun-mode] of :[logic]. ACL2 > ; guard checking off, ld-skip-proofsp nil ACL2 s> ; guard checking off, ld-skip-proofsp t ACL2 !> ; guard checking on, ld-skip-proofsp nil ACL2 !s> ; guard checking on, ld-skip-proofsp t Sample session ACL2 !>(+ 'abc 3) ACL2 Error in TOP-LEVEL: The guard for the function symbol BINARY-+, which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)), is violated by the arguments in the call (+ 'ABC 3). ACL2 !>:set-guard-checking nil ;;;; verbose output omitted here ACL2 >(+ 'abc 3) 3 ACL2 >(< 'abc 3) T ACL2 >(< 3 'abc) NIL ACL2 >(< -3 'abc) T ACL2 >:set-guard-checking t Turning guard checking on, value T. ACL2 !>(defun sum-list (x) (declare (xargs :guard (integer-listp x) :verify-guards nil)) (cond ((endp x) 0) (t (+ (car x) (sum-list (cdr x)))))) The admission of SUM-LIST is trivial, using the relation O< (which is known to be well-founded on the domain recognized by O-P) and the measure (ACL2-COUNT X). We observe that the type of SUM-LIST is described by the theorem (ACL2-NUMBERP (SUM-LIST X)). We used primitive type reasoning. Summary Form: ( DEFUN SUM-LIST ...) Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL)) Warnings: None Time: 0.03 seconds (prove: 0.00, print: 0.00, proof tree: 0.00, other: 0.03) SUM-LIST ACL2 !>(sum-list '(1 2 3)) ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited on recursive calls of the executable counterpart (i.e., in the ACL2 logic) of SUM-LIST. To check guards on all recursive calls: (set-guard-checking :all) To leave behavior unchanged except for inhibiting this message: (set-guard-checking :nowarn) 6 ACL2 !>(sum-list '(1 2 abc 3)) ACL2 Error in TOP-LEVEL: The guard for the function symbol BINARY-+, which is (AND (ACL2-NUMBERP X) (ACL2-NUMBERP Y)), is violated by the arguments in the call (+ 'ABC 3). ACL2 !>:set-guard-checking nil ;;;; verbose output omitted here ACL2 >(sum-list '(1 2 abc 3)) 6 ACL2 >(defthm sum-list-append (equal (sum-list (append a b)) (+ (sum-list a) (sum-list b)))) << Starting proof tree logging >> Name the formula above *1. Perhaps we can prove *1 by induction. Three induction schemes are suggested by this conjecture. Subsumption reduces that number to two. However, one of these is flawed and so we are left with one viable candidate. ... That completes the proof of *1. Q.E.D. Guard verification vs. defun Declare Form Guards Verified? (declare (xargs :mode :program ...)) no (declare (xargs :guard g)) yes (declare (xargs :guard g :verify-guards nil)) no (declare (xargs ......)) no ACL2 >:pe sum-list l 8 (DEFUN SUM-LIST (X) (DECLARE (XARGS :GUARD (INTEGER-LISTP X) :VERIFY-GUARDS NIL)) (COND ((ENDP X) 0) (T (+ (CAR X) (SUM-LIST (CDR X)))))) ACL2 >(verify-guards sum-list) The non-trivial part of the guard conjecture for SUM-LIST, given the :type-prescription rule SUM-LIST, is Goal (AND (IMPLIES (AND (INTEGER-LISTP X) (NOT (CONSP X))) (EQUAL X NIL)) (IMPLIES (AND (INTEGER-LISTP X) (NOT (ENDP X))) (INTEGER-LISTP (CDR X))) (IMPLIES (AND (INTEGER-LISTP X) (NOT (ENDP X))) (ACL2-NUMBERP (CAR X)))). ... ACL2 >:pe sum-list lv 8 (DEFUN SUM-LIST (X) (DECLARE (XARGS :GUARD (INTEGER-LISTP X) :VERIFY-GUARDS NIL)) ACL2 >:set-guard-checking t Turning guard checking on, value T. ACL2 !>(sum-list '(1 2 abc 3)) ACL2 Error in TOP-LEVEL: The guard for the function symbol SUM-LIST, which is (INTEGER-LISTP X), is violated by the arguments in the call (SUM-LIST '(1 2 ABC ...)). See :DOC trace for a useful debugging utility. See :DOC set-guard-checking for information about suppressing this check with (set-guard-checking :none), as recommended for new users. ACL2 !>:set-guard-checking nil ;;;; verbose output omitted here ACL2 >(sum-list '(1 2 abc 3)) 6 ACL2 >:comp sum-list Compiling gazonk0.lsp. End of Pass 1. End of Pass 2. Finished compiling gazonk0.lsp. Loading gazonk0.o start address -T 1bbf0b4 Finished loading gazonk0.o Compiling gazonk0.lsp. End of Pass 1. End of Pass 2. Finished compiling gazonk0.lsp. Loading gazonk0.o start address -T 1bc4408 Finished loading gazonk0.o SUM-LIST ACL2 >:q Exiting the ACL2 read-eval-print loop. ACL2>(trace sum-list) (SUM-LIST) ACL2>(lp) ACL2 Version 1.8. Level 1. Cbd \"/slocal/src/acl2/v1-9/\". Type :help for help. ACL2 >(sum-list '(1 2 abc 3)) 6 ACL2 >(sum-list '(1 2 3)) 1> (SUM-LIST (1 2 3))> 2> (SUM-LIST (2 3))> 3> (SUM-LIST (3))> 4> (SUM-LIST NIL)> <4 (SUM-LIST 0)> <3 (SUM-LIST 3)> <2 (SUM-LIST 5)> <1 (SUM-LIST 6)> 6 ACL2 >:pe sum-list-append 9 (DEFTHM SUM-LIST-APPEND (EQUAL (SUM-LIST (APPEND A B)) (+ (SUM-LIST A) (SUM-LIST B)))) ACL2 >(verify-guards sum-list-append) The non-trivial part of the guard conjecture for SUM-LIST-APPEND, given the :type-prescription rule SUM-LIST, is Goal (AND (TRUE-LISTP A) (INTEGER-LISTP (APPEND A B)) (INTEGER-LISTP A) (INTEGER-LISTP B)). ... ****** FAILED ******* See :DOC failure ****** FAILED ****** ACL2 >(defthm common-lisp-sum-list-append (if (and (integer-listp a) (integer-listp b)) (equal (sum-list (append a b)) (+ (sum-list a) (sum-list b))) t) :rule-classes nil) << Starting proof tree logging >> By the simple :rewrite rule SUM-LIST-APPEND we reduce the conjecture to Goal' (IMPLIES (AND (INTEGER-LISTP A) (INTEGER-LISTP B)) (EQUAL (+ (SUM-LIST A) (SUM-LIST B)) (+ (SUM-LIST A) (SUM-LIST B)))). But we reduce the conjecture to T, by primitive type reasoning. Q.E.D. ;;;; summary omitted here ACL2 >(verify-guards common-lisp-sum-list-append) The non-trivial part of the guard conjecture for COMMON-LISP-SUM-LIST-APPEND, given the :type-prescription rule SUM-LIST, is Goal (AND (IMPLIES (AND (INTEGER-LISTP A) (INTEGER-LISTP B)) (TRUE-LISTP A)) (IMPLIES (AND (INTEGER-LISTP A) (INTEGER-LISTP B)) (INTEGER-LISTP (APPEND A B)))). ... Q.E.D. That completes the proof of the guard theorem for COMMON-LISP-SUM-LIST-APPEND. COMMON-LISP-SUM-LIST-APPEND is compliant with Common Lisp. ;;;; Summary omitted here. ACL2 >(defthm foo (consp (mv x y))) ... Q.E.D. ACL2 >(verify-guards foo) ACL2 Error in (VERIFY-GUARDS FOO): The number of values we need to return is 1 but the number of values returned by the call (MV X Y) is 2. > (CONSP (MV X Y)) ACL2 Error in (VERIFY-GUARDS FOO): The guards for FOO cannot be verified because the theorem has the wrong syntactic form. See :DOC verify-guards.") (GUARD-HINTS (POINTERS) "See [xargs] for keyword :guard-hints.") (GUARD-HOLDERS (RULE-CLASSES TERM GUARD) "Remove trivial calls from a [term] For many [rule-classes], the process of converting terms to rules includes the removal of certain trivial calls from the term. In all such cases, the resulting term is provably equivalent to the input term. A common example is to replace the term (prog2$ term1 term2) by the term term2. But (prog2$ term1 term2) is really an abbreviation for (i.e., macroexpands to) the term (return-last 'progn term1 term2); so a more accurate explanation, at the level of proper ACL2 [term]s, is that the call of function [return-last] is replaced by its last argument. ACL2 identifies certain such transformations, from a term to a trivial simplification of it such that the input and output are provably equal. We historically have refered to the process of making such replacements as ``removing guard holders.'' (For a discussion of the connection to guards, see the ``Essay on the Removal of Guard Holders'' in the ACL2 sources.) As of this writing, the process of removing guard-holders includes the transformations below. That process is also applied to each argument of a function call and to the bodies of [lambda] expressions (see [term]). (return-last term0 term1 term2) ==> term2 (mv-list term0 ... termk) ==> termk ; For replacing a term (the type term) by term: ((lambda (y) (the-check guard x y)) val) ==> val Because of how [mbe] and [ec-call] are defined in terms of [return-last], the expressions (mbe :logic l :exec e) and (ec-call (f t1 ... tk)) are effective transformed by removing guard holders into l and (f t1 ... tk), respectively.") (GUARD-INTRODUCTION (GUARD) "Introduction to [guard]s in ACL2 Most users can probably profit by avoiding dealing with guards most of the time. If they seem to get in the way, they can be ``turned off'' using the command :[set-guard-checking] nil; for more about this, see [set-guard-checking]. For more about guards in general, see [guard]. The guard on a function symbol is a formula about the formals of the function. To see the guard on a function, use the keyword command :[args]. See [args]. To specify the guard on a function at defun-time, use the :[guard] xarg (See [xargs]) or type declarations (see [declare]). The latter may be preferable if you want the host Lisp compiler to use this information. Guards can be seen as having either of two roles: (a) they are a specification device allowing you to characterize the kinds of inputs a function ``should'' have, or (b) they are an efficiency device allowing logically defined functions to be executed directly in Common Lisp. Briefly: If the guards of a function definition are ``verified'' (see [verify-guards]), then the evaluation of a call of that function on arguments satisfying its guard will have the following property: All subsequent function calls during that evaluation will be on arguments satisfying the guard of the called function. The consequence of this fact for (a) is that your specification function is well-formed, in the sense that the values returned by this function on appropriate arguments only depend on the restrictions of the called functions to their intended domains. The consequence of this fact for (b) is that in the ACL2 system, when a function whose guards have been verified is called on arguments that satisfy its guard, then the raw lisp function defined by this function's [defun] event is used to evaluate the call. Note however that even when the user-supplied [defun] is not used, ACL2 uses a corresponding ``executable counterpart'' that generally performs, we expect, nearly as well as the raw lisp function. See [comp] to see how [compilation] can speed up both kinds of execution. Let us turn next to the issue of the relationship between guards and evaluation. See [guards-and-evaluation].") (GUARD-MISCELLANY (GUARD) "Miscellaneous remarks about guards The discussion of guards concludes here with a few miscellaneous remarks. (Presumably you found this documentation by following a link; see [guards-for-specification].) For further information related to guards other than what you find under ``[guard],'' see any of the following documentation topics: [guard-example], [set-verify-guards-eagerness], [set-guard-checking], [verify-guards], and (for a discussion of keyword :SPLIT-TYPES) [xargs]. [Defun] can be made to try to verify the guards on a function. This is controlled by the ``[defun-mode]'' of the [defun]; see [defun-mode]. The [defun-mode] is either as specified with the :mode xarg of the [defun] or else defaults to the default [defun-mode]. See [default-defun-mode]. If the [defun-mode] of the [defun] is :[logic] and either a [guard] is specified explicitly or :[verify-guards] t is specified in the [xargs], then we attempt to verify the guards of the function. Otherwise we do not. (But see [set-verify-guards-eagerness] for how to modify this behavior.) It is sometimes impossible for the system to verify the guards of a recursive function at definition time. For example, the guard conjectures might require the invention and proof of some inductively derived property of the function (as often happens when the value of a recursive call is fed to a guarded subroutine). So sometimes it is necessary to define the function using :verify-guards nil then to state and prove key theorems about the function, and only then have the system attempt guard verification. Post-[defun] guard verification is achieved via the event [verify-guards]. See [verify-guards]. It should be emphasized that guard verification affects only two things: how fast ACL2 can evaluate the function and whether the function is executed correctly by raw Common Lisp, without guard violations. Since ACL2 does not use the raw Common Lisp definition of a function to evaluate its calls unless that function's guards have been verified, the latter effect is felt only if you run functions in raw Common Lisp rather than via ACL2's command loop. Guard verification does not otherwise affect the theorem prover or the semantics of a definition. If you are not planning on running your function on ``big'' inputs and you don't care if your function runs correctly in raw Common Lisp (e.g., you have formalized some abstract mathematical property and just happened to use ACL2 as your language), there is no need to suffer through guard verification. Often users start by not doing guard verification and address that problem later. Sometimes you are driven to it, even in mathematical projects, because you find that you want to run your functions particularly fast or in raw Common Lisp. If [certify-book] is used to compile a file, and the file contains functions with unverified guard conjectures, then you will be warned that the compiled file cannot be loaded into raw Common Lisp with the expectation that the functions will run correctly. This is just the same point we have been making: ACL2 and Common Lisp agree only on the restricted domains specified by our guards. When guards are violated, Common Lisp can do anything. When you call a compiled function on arguments violating its guards, the chances are only increased that Common Lisp will go berserk, because compiled functions generally check fewer things at runtime and tend to be more fragile than interpreted ones. Finally, we note that ACL2 collects up [guard]s from [declare] forms in order of appearance. So for example, the [declare] form (declare (xargs :guard (foo x)) (type string x) will generate the guard (and (foo x) (stringp x)), while the form (declare (type string x) (xargs :guard (foo x)) will generate the guard (and (stringp x) (foo x)). The only exception to this rule is the case that :guard and :stobjs are specified in the same [xargs] form, in which case the :stobjs form will be treated as through it comes before the :guard form.") (GUARD-MSG-TABLE (POINTERS) "See [set-guard-msg].") (GUARD-OBLIGATION (GUARD) "The guard proof obligation See [verify-guards], and see [guard] for a discussion of guards. Also see [verify-guards-formula] for a utility provided for viewing the guard proof obligation, without proof. Guard-obligation is a lower level function for use in system programs, not typically appropriate for most ACL2 users. If you simply want to see the guard proof obligations, see [verify-guards-formula]. Example Form: (guard-obligation 'foo nil 'top-level state) (guard-obligation '(if (consp x) (foo (car x)) t) nil 'my-function state) General Forms: (guard-obligation name guard-debug ctx state) (guard-obligation term guard-debug ctx state) where the first argument is either the name of a function or theorem or is a non-variable term that may be in untranslated form; guard-debug is typically nil but may be t (see [guard-debug]); ctx is a context (typically, a symbol used in error and warning messages); and [state] references the ACL2 [state]. If you want to obtain the formula but you don't care about the so-called ``tag tree'': (mv-let (erp val state) (guard-obligation x guard-debug 'top-level state) (if erp ( .. code for handling error case, e.g., name is undefined .. ) (let ((cl-set (cadr val))) ; to be proved for guard verification ( .. code using cl-set, which is a list of clauses, implicitly conjoined, each of which is viewed as a disjunction .. )))) The form (guard-obligation x guard-debug ctx state) evaluates to a triple (mv erp val state), where erp is nil unless there is an error, and [state] is the ACL2 state. Suppose erp is nil. Then val is the keyword :redundant if the corresponding [verify-guards] event would be redundant; see [redundant-events]. Otherwise, val is a tuple (list* names cl-set ttree), where: names is (cons :term xt) if x is not a variable, where xt is the translated form of x; and otherwise is a list containing x along with, if x is defined in a mutual-recursion, any other functions defined in the same [mutual-recursion] nest; cl-set is a list of lists of terms, viewed as a conjunction of clauses (each viewed (as a disjunction); and ttree is an assumption-free tag-tree that justifies cl-set. (The notion of ``tag-tree'' may probably be ignored except for system developers.) Guard-obligation is typically used for function names or non-variable terms, but as for [verify-guards], it may also be applied to theorem names. See the source code for [verify-guards-formula] for an example of how to use guard-obligation.") (GUARD-QUICK-REFERENCE (GUARD) "Brief summary of guard checking and guard verification For a careful introduction to guards, see [guard]. I. GUARD CHECKING DURING EXECUTION Effect Guards on definitions are checked at execution time (except for guards on subsidiary calls of recursive or mutually recursive functions). When does it happen By default, guards are checked for all forms submitted at the top level. To disable :set-guard-checking nil ; skip raw Lisp if there is a guard violation :set-guard-checking :none ; skip guard checking entirely To (re-)enable :set-guard-checking t See [set-guard-checking] for more options. II. GUARD VERIFICATION Effect A proof is attempted of the obligations arising from the guards of subsidiary functions in a [defun], [defthm], or [defaxiom] event. In the case of a defun, the guard itself is also verified (under an implicit guard of t). When does it happen Only names of defined functions, [defthm]s, and [defaxiom]s are subject to guard verification. Guard verification may occur when functions are defined (using [defun]), but it requires an explicit call of [verify-guards] in order to verify guards for [defthm]s and [defaxiom]s. Constrained functions (see [encapsulate]) may not have their guards verified. (verify-guards foo ...) causes guard verification for the [defun], [defthm], or [defaxiom] named by foo, if it has not already been successfully done. The default [defun-mode] (see [default-defun-mode]) must be :[logic], or else this event is ignored. (defun foo ...) causes guard verification of foo if and only if the following two conditions are both met. First, foo is processed in :[logic] mode (either by setting mode :[logic] globally, or by including :mode :logic in the [xargs] declaration). Second, at least one of the following sub-conditions is met. Also see [xargs], and see [set-verify-guards-eagerness] for how to change this behavior. 1. The [xargs] declaration specifies a :[guard]. 2. There is at least one type declaration (see [declare]). 3. The [xargs] declaration specifies :[stobj]s. 4. The [xargs] declaration specifies :[verify-guards] t. (verify-termination foo ...) causes guard verification of foo if foo is a function currently defined in :[program] mode and the criteria for guard verification of a [defun] form are met, as discussed above. The default [defun-mode] (see [default-defun-mode]) must be :[logic], or else this event is ignored.") (GUARDS (POINTERS) "See [guard].") (GUARDS-AND-EVALUATION (GUARD) "The relationship between guards and evaluation The guard has no effect on the logical axiom added by the definition of a function. It does, however, have consequences for how calls of that function are evaluated in ACL2. We begin by explaining those consequences, when ACL2 is in its default ``mode,'' i.e., as originally brought up. In subsequent discussion we'll consider other ways that guards can interact with evaluation. For more about guards in general, see [guard]. For in-depth discussion of the interaction between the [defun-mode] and guard checking, see [set-guard-checking], see [guard-evaluation-table], see [guard-evaluation-examples-script], and see [guard-evaluation-examples-log]. Also see [generalized-booleans] for discussion about a subtle issue in the evaluation of certain Common Lisp functions. Guards and evaluation I: the default Consider the following very simple definition. (defun foo (x) (cons 1 (cdr x))) First consider how raw Common Lisp behaves when evaluating calls of this function. To evaluate (foo x) for some expression x, first x is evaluated to some value v, and then (cons 1 (cdr x)) is evaluated with x bound to v. For example, if v is (cons 'a 3), then Common Lisp computes (cons 1 3). But if (for example) v is a number, e.g., 7, then there is no way to predict what Common Lisp might do. Some implementations would cause ``sensible'' errors, others might return nonsense, still others might crash the host machine. The results tend toward the catastrophic if the call of foo in question is in compiled code. Now by default, ACL2 evaluates calls of foo exactly as Common Lisp does, except that it uses guards to check the ``legality'' of each function call. So for example, since (cdr x) has a guard of (or (consp x) (equal x nil)), the call (foo 7) would cause a ``guard violation,'' as illustrated below. ACL2 !>(foo 7) ACL2 Error in TOP-LEVEL: The guard for the function symbol CDR, which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the call (CDR 7). ACL2 !> Thus, the relation between evaluation in ACL2 and evaluation in Common Lisp is that the two produce the very same results, provided there is no guard violation. Guards and evaluation II: :[set-guard-checking]. The ACL2 logic is a logic of total functions. That is, every application of a function defined has a completely specified result. See the [documentation] for each individual primitive for the specification of what it returns when its guard is violated; for example, see [cdr]. The presence of guards thus introduces a choice in the sense of evaluation. When you type a form for evaluation do you mean for guards to be checked or not? Put another way, do you mean for the form to be evaluated in Common Lisp (if possible) or in the ACL2 logic? Note: If Common Lisp delivers an answer, it will be the same as in the logic, but it might be erroneous to execute the form in Common Lisp. For example, the ACL2 logic definition of [cdr] implies that the [cdr] of an [atom] is nil; see [cdr]. So: should (cdr 7) cause a guard violation error or return nil? The top-level ACL2 loop has a variable which controls which sense of execution is provided. By default, ``guard checking'' is on, by which we mean that guards are checked at runtime, in the sense already described. To allow execution to proceed in the logic when there is a guard violation, do :[set-guard-checking] nil; or evaluate :[set-guard-checking] :none to skip guard checking entirely. To turn ``guard checking'' back on, execute the top-level form :[set-guard-checking] t. The status of guard checking reflected in the [prompt]; guard-checking is ``on'' when the [prompt] contains an exclamation mark (also see [default-print-prompt]). For example, ACL2 !> means guard checking is on and ACL2 > means guard checking is off. The exclamation mark can be thought of as ``barring'' certain computations. The absence of the mark suggests the absence of error messages or unbarred access to the logical axioms. Thus, for example ACL2 !>(car 'abc) will signal an error, while ACL2 >(car 'abc) will return nil. To return to our previous example: with guard checking off, (foo 7) evaluates to (cons 1 nil). Also see [set-guard-checking]. Guards and evaluation III: guard verification Consider the defininition of foo given above, but modified so that a reasonable guard of (consp x) is specified, as shown below. (defun foo (x) (declare (xargs :guard (consp x))) (cons 1 (cdr x))) We say ``reasonable guard'' above because if x is such that (consp x) holds, then the call of [cdr] in the evaluation of (foo x) will not cause a guard violation. Thus, it ``should'' be legal to evaluate (foo x), for any such x, simply by evaluating this form in raw Common Lisp. The [verify-guards] event has been provided for this purpose. Details may be found elsewhere; see [verify-guards]. Briefly, for any defined function fn, the event (verify-guards fn) attempts to check the condition discussed above, that whenever fn is called on arguments that satisfy its guard, the evaluation of this call will proceed without any guard violation. (Moreover, the guard itself should be evaluable without any guard violation.) If this check is successful, then future calls of this sort will be evaluated in raw Common Lisp. Returning to our example above, the (verify-guards foo) will succeed because the guard (consp x) of foo implies the guard generated from the call (cdr x) in the body of the definition, namely, (or (consp x) (equal x nil)) (see [cdr]). Then the evaluation of (foo (cons 'a 3)) will take place in raw Common Lisp, because (cons 'a 3) satisfies the guard of foo. This ability to dive into raw Common Lisp hinges on the proof that the guards you attach to your own functions are sufficient to ensure that the guards encountered in the body are satisfied. This is called ``guard verification.'' Once a function has had its guards verified, then ACL2 can evaluate the function somewhat faster (but see ``Guards and evaluation V: efficiency issues'' below). Perhaps more importantly, ACL2 can also guarantee that the function will be evaluated correctly by any implementation of Common Lisp (provided the guard of the function is satisfied on the input). That is, if you have verified the guards of a system of functions and you have determined that they work as you wish in your host ACL2 (perhaps by proving it, perhaps by testing), then they will work identically in any Common Lisp. There is a subtlety to our treatment of evaluation of calls of functions whose guards have been verified. If the function's guard is not satisfied by such a call, then no further attempt is made to evaluate any call of that function in raw lisp during the course of evaluation of that call. This is obvious if guard checking is on, because an error is signalled the first time its guard is violated; but in fact it is also true when guard checking is off. See [guard-example] for an example. Guards and evaluation IV: functions having :program mode Strictly speaking, functions in :[program] mode (see [defun-mode]) do not have definitions in the ACL2 logic. So what does it mean to evaluate calls of such functions in ACL2? In general we treat :[program] functions much as we treat :[logic] functions whose guards have been verified, except that when no error occurs then the corresponding raw Lisp function is always called. (We say ``in general'' because there are exceptions, discussed in the ``Aside'' just below.) Note that when the guard of a function in :[logic] mode is violated, there is still a value that the ACL2 logic proves is equal to the given call. But the same cannot be said for a function in :[program] mode. Nevertheless, for the sake of convenience we go ahead and evaluate the corresponding raw Lisp function except in the situation where the guard is violated and guard-checking is on, aside from the following: Aside. There are exceptions to the use of raw Lisp, discussed just above, to evaluate calls of :[program] mode functions. The primary one is that after :[set-guard-checking] :none, evaluation of user-defined :[program] mode function calls is done in the ACL2 logic, not in raw Lisp. The more obscure exception is that during expansion of macros and [make-event] forms, and during evaluation of [defconst] forms, ACL2 enters a ``safe mode'' in which this escape to raw Lisp is prevented. The following example illustrates how the user can experiment directly with safe mode, though it is preferred to use :[set-guard-checking] :none if you are happy to skip all guard checking and evaluate forms in the logic. ACL2 !>(defun foo (x) (declare (xargs :mode :program :guard t)) (car x)) Summary Form: ( DEFUN FOO ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FOO ACL2 !>(foo 3) Error: Attempt to take the car of 3 which is not listp. [condition type: SIMPLE-ERROR] Restart actions (select using :continue): 0: Return to Top Level (an \"abort\" restart). 1: Abort entirely from this process. [1] ACL2(2): :pop ACL2 !>(assign safe-mode t) T ACL2 !>(foo 3) ACL2 Error in TOP-LEVEL: The guard for the function symbol CAR, which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the call (CAR 3). See :DOC trace for a useful debugging utility. See :DOC set-guard-checking for information about suppressing this check with (set-guard-checking :none), as recommended for new users. ACL2 !>(assign safe-mode nil) NIL ACL2 !>(foo 3) Error: Attempt to take the car of 3 which is not listp. [condition type: SIMPLE-ERROR] Restart actions (select using :continue): 0: Return to Top Level (an \"abort\" restart). 1: Abort entirely from this process. [1] ACL2(2): The other exception occurs after [set-guard-checking] can be called with a value of :all; see [set-guard-checking]. End of aside. Thus, as with :[logic] functions: when a guard has been satisfied on a call of a function with :[program] mode, no subsidiary guard checking will be done. Notice that by treating functions in :[program] mode like functions whose guards have been verified, we are using raw lisp to compute their values when their guards are met. We do not check guards any further once raw lisp is invoked. This can lead to hard lisp errors if the guards are not appropriate, as illustrated below. ACL2 >:program ACL2 p>(defun foo (x) (declare (xargs :guard t)) (cons 1 (cdr x))) Summary Form: ( DEFUN FOO ...) Rules: NIL Warnings: None Time: 0.02 seconds (prove: 0.00, print: 0.00, proof tree: 0.00, other: 0.02) FOO ACL2 p>(foo 3) Error: 3 is not of type LIST. Fast links are on: do (use-fast-links nil) for debugging Error signalled by CDR. Broken at COND. Type :H for Help. ACL2>> See [defun-mode-caveat]. However, here is a way to get ACL2 to do run-time guard checking for user-defined :[program] mode functions. With this method, ACL2 will evaluate calls of user-defined :program mode functions in a manner that follows their ACL2 definitions. Simply execute the following in the ACL2 loop to put ACL2 into a ``safe mode.'' (f-put-global 'safe-mode t state) Let us revisit the example above, using safe mode. Notice that the guard of [cdr] is now being checked, because the executable counterpart of foo is being called even though the [guard] is t. ACL2 !>(f-put-global 'safe-mode t state) ACL2 !>:program ACL2 p!>(defun foo (x) (declare (xargs :guard t)) (cons 1 (cdr x))) Summary Form: ( DEFUN FOO ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FOO ACL2 p!>(foo 3) ACL2 Error in TOP-LEVEL: The guard for the function symbol CDR, which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the call (CDR 3). See :DOC trace for a useful debugging utility. See :DOC set-guard-checking for information about suppressing this check with (set-guard-checking :none), as recommended for new users. ACL2 p!> If we go back into ``unsafe'' mode, then we once again see a raw Lisp error, as we now illustrate. ACL2 p!>(f-put-global 'safe-mode nil state) ACL2 p!>(foo 3) Error: 3 is not of type LIST. Fast links are on: do (si::use-fast-links nil) for debugging Error signalled by CDR. Broken at COND. Type :H for Help. ACL2>> Guards and evaluation V: efficiency issues We have seen that by verifying the guards for a :[logic] function, we arrange that raw lisp is used for evaluation of calls of such functions when the arguments satisfy its guard. This has several apparent advantages over the checking of guards as we go. First, the savings is magnified as your system of functions gets deeper: the guard is checked upon the top-level entry to your system and then raw Common Lisp does all the computing. Second, if the raw Common Lisp is compiled (see [compilation]), enormous speed-ups are possible. Third, if your Common Lisp or its compiler does such optimizations as tail-recursion removal, raw Common Lisp may be able to compute your functions on input much ``bigger'' than ACL2 can. The first of these advantages is quite important if you have complicated guards. However, the other two advantages are probably not very important, as we now explain. When a function is defined in :[logic] mode, its [defun] is executed in raw Common Lisp. (We might call this the ``primary'' raw lisp definition of the function.) However, a corresponding ``logic definition'' is also executed. The ``logic definition'' is a [defun] in raw lisp that checks guards at runtime and escapes to the primary raw lisp definition if the guard holds of the arguments and the function has already had its guards verified. Otherwise the logic definition executes the body of the function by calling the logic definitions of each subroutine. Now it is true that [compilation] generally speeds up execution enormously. However, the :[comp] command (see [comp]) compiles both of the raw lisp definitions associated with a :[logic] function. Also, we have attempted to arrange that for every tail recursion removal done on the actual [defun], a corresponding tail recursion removal is done on the ``logic definition.'' We believe that in most cases, the logic definition executes almost as fast as the primary raw lisp definition, at least if the evaluation of the guards is fast. So, the main advantage of guard verification is probably that it lets you know that the function may be executed safely in raw lisp, returning the value predicted by the ACL2 logic, whenever its arguments satisfy its guard. We envision the development of systems of applicative lisp functions that have been developed and reasoned about using ACL2 but which are intended for evaluation in raw Common Lisp (perhaps with only a small ``core'' of ACL2 loaded), so this advantage of guard verification is important. Nevertheless, guard verification might be important for optimal efficiency when the functions make use of type declarations. For example, at this writing, the GCL implementation of Common Lisp can often take great advantage of [declare] forms that assign small integer types to formal parameters. Note that while type declarations contributed to the guard by default, they can be proved from the guard instead; see [xargs] for a discussion of the :SPLIT-TYPES keyword. To continue the discussion of guards, see [guards-for-specification] to read about the use of guards as a specification device.") (GUARDS-FOR-SPECIFICATION (GUARD) "Guards as a specification device A use of guard verification that has nothing to do with efficiency is as a way to gain confidence in specifications. This use has the feel of ``types'' in many traditional [programming] languages, though guards allow much greater expressiveness than most systems of types (and unfortunately, as a result they are not syntactically checkable). For more discussion of guards in general, see [guard]. Suppose you have written a collection of function definitions that are intended to specify the behavior of some system. Perhaps certain functions are only intended to be called on certain sorts of inputs, so you attach guards to those functions in order to ``enforce'' that requirement. And then, you verify the guards for all those functions. Then what have you gained, other than somewhat increased efficiency of execution (as explained above), which quite possibly isn't your main concern? You have gained the confidence that when evaluating any call of a (specification) function whose arguments satisfy that function's guard, all subsequent function calls during the course of evaluation will have this same property, that the arguments satisfy the guard of the calling function. The rest of this topic addresses those who wish to understand [guard]s from a proof-theoretic perspective instead of (or in addition to) the evaluation perspective given above. In logical terms, we can say that the equality of the original call with the returned value is provable from weakened versions of the definitions, where each definitional axiom is replaced by an implication whose antecedent is the requirement that the arguments satisfy the guard and whose consequent is the original axiom. For example, (defun foo (x) (declare (xargs :guard (consp x))) (cons 1 (cdr x))) originally generates the axiom (equal (foo x) (cons 1 (cdr x))) but in fact, when evaluation involves no guard violation then the following weaker axiom suffices in the justification of the evaluation. (implies (consp x) (equal (foo x) (cons 1 (cdr x)))) So for example, suppose we evaluate (foo '(a b c)) and get '(1 b c). Then of course the equality of these two terms is provable from the original axiom. The point here is that it's even provable from the weaker axiom. If you are following links to read this documentation as a hypertext style document, then please see [guard-miscellany]. This concludes our discussion of guards with miscellaneous remarks, and also contains pointers to related topics.") (GUARDS_IN_ACL2 (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Guards Common Lisp functions are partial; they are not defined for all possible inputs. But ACL2 functions are total. Roughly speaking, the logical function of a given name in ACL2 is a completion of the Common Lisp function of the same name obtained by adding some arbitrary but ``natural'' values on arguments outside the ``intended domain'' of the Common Lisp function. ACL2 requires that every ACL2 function symbol have a ``guard,'' which may be thought of as a predicate on the formals of the function describing the intended domain. The guard on the primitive function [car] [{ICON}], for example, is (or (consp x) (equal x nil)), which requires the argument to be either an ordered pair or nil. We will discuss later how to specify a guard for a defined function; when one is not specified, the guard is t which is just to say all arguments are allowed. But guards are entirely extra-logical: they are not involved in the axioms defining functions. If you put a guard on a defined function, the defining axiom added to the logic defines the function on all arguments, not just on the guarded domain. So what is the purpose of guards? The key to the utility of guards is that we provide a mechanism, called ``guard verification,'' for checking that all the guards in a formula are true. See [verify-guards]. This mechanism will attempt to prove that all the guards encountered in the evaluation of a guarded function are true every time they are encountered. For a thorough discussion of guards, see the paper [km97] in the ACL2 [bibliography].") (GUESSING_THE_TYPE_OF_A_NEWLY_ADMITTED_FUNCTION (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Guessing the Type of a Newly Admitted Function When a function is admitted to the logic, ACL2 tries to ``guess'' what type of object it returns. This guess is codified as a term that expresses a property of the value of the function. For app the term is (OR (CONSP (APP X Y)) (EQUAL (APP X Y) Y)) which says that app returns either a cons or its second argument. This formula is added to ACL2's rule base as a [type-prescription] [{ICON}] rule. Later we will discuss how rules are used by the ACL2 theorem prover. The point here is just that when you add a definition, the database of rules is updated, not just by the addition of the definitional axiom, but by several new rules. You should now return to [the Walking Tour].") (GUIDING_THE_ACL2_THEOREM_PROVER (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Guiding the ACL2 Theorem Prover [{IMAGE}] Now that you have seen the theorem prover in action you might be curious as to how you guide it. {IMAGE} Look at the picture above. It is meant to suggest that Q is an important lemma needed for the proof of P. Note that to lead the prover to the proof of P the user first proves Q. In a way, the formulation and proof of Q is a hint to the prover about how to prove P. The user usually doesn't think of Q or recognize the need to prove it separately until he or she sees the theorem prover fail to prove P without it ``knowing'' Q. The way the user typically discovers the need for Q is to look at failed proofs. [{IMAGE}]") (HANDS-OFF (POINTERS) "See [hints] for keyword :hands-off.") (HARD-ERROR (ERRORS ACL2-BUILT-INS) "Print an error message and stop execution (Hard-error ctx str alist) causes evaluation to halt with a short message using the ``context'' ctx. An error message is first printed using the string str and alist alist that are of the same kind as expected by [fmt]. See [fmt]. Also see [er] for a macro that provides a unified way of signaling errors. Hard-error has a guard of t. Also see [illegal] for a similar capability which however has a guard of nil that supports static checking using [guard] verification, rather than using dynamic (run-time) checking. This distinction is illustrated elsewhere: see [prog2$] for examples. Semantically, hard-error ignores its arguments and always returns nil. But if a call (hard-error ctx str alist) is encountered during evaluation, then the string str is printed using the association list alist (as in [fmt]), after which evaluation halts immediately. Here is a trivial, contrived example. ACL2 !>(cons 3 (hard-error 'my-context \"Printing 4: ~n0\" (list (cons #\\0 4)))) HARD ACL2 ERROR in MY-CONTEXT: Printing 4: four ACL2 Error in TOP-LEVEL: Evaluation aborted. ACL2 !> Technical note for raw Lisp programmers only. It is possible to cause hard errors to signal actual raw Lisp errors, simply by evaluating the following form in raw Lisp: (setq *hard-error-is-error* t). Indeed, any non-nil value for *hard-error-is-error* will cause hard-error or [illegal] --- or indeed (er hard ...), (er hard! ...), or (er hard? ...) --- to produce a Lisp error whose condition, when printed with format directive ~a, is the same error message that ACL2 would otherwise print. Below is a sample log, closely based on an example provided by Jared Davis. ACL2 !>(defun f (x) (er hard 'f \"F got bad input ~x0.~%\" x)) Since F is non-recursive, its admission is trivial. We observe that the type of F is described by the theorem (EQUAL (F X) NIL). We used the :type-prescription rule ILLEGAL. Summary Form: ( DEFUN F ...) Rules: ((:TYPE-PRESCRIPTION ILLEGAL)) Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) F ACL2 !>:q Exiting the ACL2 read-eval-print loop. To re-enter, execute (LP). ? (defun run-f () (let ((*hard-error-is-error* t)) (handler-case (f 3) (error (condition) (format t \"Got the following error: ~a~%\" condition))))) RUN-F ? (run-f) Got the following error: HARD ACL2 ERROR in F: F got bad input 3. NIL ? Function: (defun hard-error (ctx str alist) (declare (xargs :guard t)) (declare (ignore ctx str alist)) nil)") (HEADER (ARRAYS ACL2-BUILT-INS) "Return the header of a 1- or 2-dimensional array Example Form: (header 'delta1 a) General Form: (header name alist) where name is arbitrary and alist is a 1- or 2-dimensional array. This function returns the header of the array alist. The function operates in virtually constant time if alist is the semantic value of name. See [arrays]. Function:
(defun header (name l) (declare (xargs :guard (or (array1p name l) (array2p name l)))) (prog2$ name (assoc-eq :header l)))") (HEY_WAIT!__IS_ACL2_TYPED_OR_UNTYPED{Q} (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Hey Wait! Is ACL2 Typed or Untyped? The example ACL2 !>(app 7 27) ACL2 Error in TOP-LEVEL: The guard for the function symbol ENDP, which is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the call (ENDP 7). illustrates the fact that while ACL2 is an untyped language the ACL2 evaluator can be configured so as to check ``types'' at runtime. We should not say ``types'' here but ``guards.'' Click [here] for a discussion of guards. The guard on [endp] [{ICON}] requires its argument to be a true list. Since 7 is not a true list, and since ACL2 is checking guards in this example, an error is signaled by ACL2. How do you know ACL2 is checking guards? Because the prompt tells us (click [here]) with its ``!''.") (HIDDEN-DEATH-PACKAGE (PACKAGES DEFPKG) "Handling [defpkg] [events] that are [local] This documentation topic explains a little bit about certain errors users may see when attempting to evaluate a [defpkg] event. In brief, if you see an error that refers you to this topic, you are probably trying to admit a [defpkg] event, and you should change the name of the package to be introduced by that event. Recall that defpkg events introduce axioms, for example as follows. ACL2 !>(defpkg \"PKG0\" '(a b)) Summary Form: ( DEFPKG \"PKG0\" ...) Rules: NIL Warnings: None Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) \"PKG0\" ACL2 !>:pr! \"PKG0\" Rune: (:REWRITE PKG0-PACKAGE) Status: Enabled Lhs: (SYMBOL-PACKAGE-NAME (INTERN-IN-PACKAGE-OF-SYMBOL X Y)) Rhs: \"PKG0\" Hyps: (AND (STRINGP X) (NOT (MEMBER-SYMBOL-NAME X '(A B))) (SYMBOLP Y) (EQUAL (SYMBOL-PACKAGE-NAME Y) \"PKG0\")) Equiv: EQUAL Backchain-limit-lst: NIL Subclass: BACKCHAIN Loop-stopper: NIL ACL2 !> Now, a [defpkg] event may be executed underneath an [encapsulate] or [include-book] form that is marked [local]. In that case, traces of the added axiom will disappear after the surrounding [encapsulate] or [include-book] form is admitted. This can cause inconsistencies. (You can take our word for it, or you can look at the example shown in the ``Essay on Hidden Packages'' in source file axioms.lisp.) In order to prevent unsoundness, then, ACL2 maintains the following invariant. Let us say that a defpkg event is ``hidden'' if it is in support of the current logical [world] but is not present in that world as an event, because it is [local] as indicated above. We maintain the invariant that all [defpkg] [events], even if ``hidden'', are tracked under-the-hood in the current logical [world]. Sometimes this property causes [defpkg] events to be written to the [portcullis] of a book's [certificate] (see [books]). At any rate, if you then try to define the package in a manner inconsistent with the earlier such definition, that is, with a different imports list, you will see an error because of the above-mentioned tracking. (By the way, this topic's name comes from Holly Bell, who heard \"hidden death package\" instead of \"hidden defpkg\". The description seemed to fit. Thanks, Holly!)") (HIDDEN-DEFPKG (PACKAGES DEFPKG) "Handling defpkg events that are local See [hidden-death-package]") (HIDE (REWRITE) "Hide a term from the rewriter Hide is actually the [identity] function: (hide x) = x for all x. However, terms of the form (hide x) are ignored by the ACL2 rewriter, except when explicit :expand [hints] are given for such terms (see [hints]) or when rewrite rules explicitly about hide are available. An :expand hint that removes all calls of hide is: :expand ((:free (x) (hide x))) The above hint can be particularly useful when ACL2's equality heuristics apply hide to an equality after substituting it into the rest of the goal, if that goal (or a subgoal of it) fails to be proved. Hide terms are also ignored by the induction heuristics. Sometimes the ACL2 simplifier inserts hide terms into a proof attempt out of the blue, as it were. Why and what can you do about it? Suppose you have a constrained function, say constrained-fn, and you define another function, say another-fn, in terms of it, as in: (defun another-fn (x y z) (if (big-hairy-test x y z) (constrained-fn x y z) t)) Suppose the term (another-fn 'a 'b 'c) arises in a proof. Since the arguments are all constants, ACL2 will try to reduce such a term to a constant by executing the definition of another-fn. However, after a possibly extensive computation (because of big-hairy-test) the execution fails because of the unevaluable call of constrained-fn. To avoid subsequent attempts to evaluate the term, ACL2 embeds it in a hide expression, i.e., rewrites it to (hide (another-fn 'a 'b 'c)). You might think this rarely occurs since all the arguments of another-fn must be constants. You would be right except for one special case: if another-fn takes no arguments, i.e., is a constant function, then every call of it fits this case. Thus, if you define a function of no arguments in terms of a constrained function, you will often see (another-fn) rewrite to (hide (another-fn)). We do not hide the term if the executable counterpart of the function is disabled -- because we do not try to evaluate it in the first place. Thus, to prevent the insertion of a hide term into the proof attempt, you can globally disable the executable counterpart of the offending defined function, e.g., (in-theory (disable (:executable-counterpart another-fn))). It is conceivable that you cannot afford to do this: perhaps some calls of the offending function must be computed while others cannot be. One way to handle this situation is to leave the executable counterpart enabled, so that hide terms are introduced on the calls that cannot be computed, but prove explicit :[rewrite] rules for each of those hide terms. For example, suppose that in the proof of some theorem, thm, it is necessary to leave the executable counterpart of another-fn enabled but that the call (another-fn 1 2 3) arises in the proof and cannot be computed. Thus the proof attempt will introduce the term (hide (another-fn 1 2 3)). Suppose that you can show that (another-fn 1 2 3) is (constrained-fn 1 2 3) and that such a step is necessary to the proof. Unfortunately, proving the rewrite rule (defthm thm-helper (equal (another-fn 1 2 3) (constrained-fn 1 2 3))) would not help the proof of thm because the target term is hidden inside the hide. However, (defthm thm-helper (equal (hide (another-fn 1 2 3)) (constrained-fn 1 2 3))) would be applied in the proof of thm and is the rule you should prove. Now to prove thm-helper you need to use the two ``tricks'' which have already been discussed. First, to eliminate the hide term in the proof of thm-helper you should include the hint :expand (hide (another-fn 1 2 3)). Second, to prevent the hide term from being reintroduced when the system tries and fails to evaluate (another-fn 1 2 3) you should include the hint :in-theory (disable (:executable-counterpart another-fn)). Thus, thm-helper will actually be: (defthm thm-helper (equal (hide (another-fn 1 2 3)) (constrained-fn 1 2 3)) :hints ((\"Goal\" :expand (hide (another-fn 1 2 3)) :in-theory (disable (:executable-counterpart another-fn))))) See [eviscerate-hide-terms] for how to affect the printing of hide terms. Function: (defun hide (x) (declare (xargs :guard t)) x)") (HINTS (MISCELLANEOUS) "Advice to the theorem proving process Examples: The following :hints value is nonsensical. Nevertheless, it illustrates all of the available hint keywords except the ``custom keywords'' (see [custom-keyword-hints]) definable by the user. :hints ((\"Goal\" :do-not-induct t :do-not '(generalize fertilize) :expand ((assoc x a) :lambdas (:free (y) (:with member (member y z)))) :restrict ((<-trans ((x x) (y (foo x))))) :hands-off (length binary-append) :in-theory (set-difference-theories (current-theory :here) '(assoc)) :induct (and (nth n a) (nth n b)) :use ((:instance assoc-of-append (x a) (y b) (z c)) (:functional-instance (:instance p-f (x a) (y b)) (p consp) (f assoc))) :bdd (:vars (c a0 b0 a1 b1) :prove nil :bdd-constructors (cons)) :clause-processor (:function cl-proc :hint (my-hint clause)) :instructions (:x :prove) :cases ((true-listp a) (consp a)) :by (:instance rev-rev (x (cdr z))) :nonlinearp t :backchain-limit-rw 3 :reorder (4 7 2) :case-split-limitations (20 10) :no-op t :no-thanks t :error (\"Bad value ~x0.\" 123) :or (hint-kwd-alist-1 ... hint-kwd-alist-k) :rw-cache-state nil :backtrack (my-computed-hint clause processor clause-list))) A very common hint is the :use hint, which in general takes as its value a list of ``lemma instances'' (see [lemma-instance]) but which allows a single lemma name as a special case. Here are two examples, one using a single lemma name and one using a lemma instance: ; Attach :use hint to the top-level goal, which is named \"Goal\": :hints ((\"Goal\" :use lemma23)) ; Equivalent to the above: use the trivial instance (i.e., with the empty ; substitution of lemma23: :hints ((\"Goal\" :use ((:instance lemma23)))) ; Attach :use hint to the named subgoal, where the indicated lemma is used ; with the substitution that maps x to 17 and y to (foo z): :hints ((\"[1]Subgoal *1/1.2'\" :use ((:instance lemma23 (x 17) (y (foo z)))))) ; Equivalent to the above: ACL2 allows you to omit the outer parentheses if ; there is only one lemma used. :hints ((\"[1]Subgoal *1/1.2'\" :use (:instance lemma23 (x 17) (y (foo z))))) ACL2 also provides ``custom keyword'' hints (see [custom-keyword-hints]) and even more general ``computed hints'' for the advanced user (see [computed-hints]). Only the first hint applicable to a goal, as specified in the user-supplied list of :hints followed by the default hints (see [default-hints-table]), will be applied to that goal. For an advanced exception, see [override-hints]. For a detailed discussion of how hints fit into the ACL2 waterfall, see [hints-and-the-waterfall]. For examples of the sophisticated use of hints, primarily for experts, see community book books/hints/basic-tests.lisp. Background: Hints are allowed in all [events] that use the theorem prover. During [defun] [events] there are two different uses of the theorem prover: one to prove termination and another to verify the [guard]s. To pass a hint to the theorem prover during termination proofs, use the :hints keyword in the [defun]'s [xargs] declaration. To pass a hint to the theorem prover during the [guard] verification portion of admitting a [defun], use the :guard-hints keyword in the [defun]'s [xargs] declaration. The [verify-guards] event and the [defthm] event also use the theorem prover. To pass hints to them, use the :hints keyword argument to the event. General Form of Common :hints: ((goal-spec :key1 val1 ... :keyn valn) ... (goal-spec :key1 val1 ... :keyn valn)) where [goal-spec] is as described elsewhere (see [goal-spec]) and the keys and their respective values are shown below with their interpretations. We also provide ``computed hints'' but discuss them separately; see [computed-hints]. The hint keywords below are considered in alphabetical order. :backchain-limit-rw Value is a natural number or nil, indicating the level of backchaining for [rewrite], [meta], and [linear] rules. This overrides, for the current goal and (as with :[in-theory] hints) descendent goals, the default [backchain-limit] (see [set-backchain-limit]). :backtrack This is an advanced hint. You can probably accomplish its effect by the use of ordinary computed hints; see [computed-hints]. But if you are an expert, read on. (See [hints-and-the-waterfall] for some relevant background.) Value is a computed hint, which is an expression that evaluates either to nil --- indicating that the :backtrack hint is to have no effect --- or to a non-empty alternating list of :keyi :vali pairs, as expected for a hint. However, unlike ordinary computed hints, :backtrack hints are evaluated after a goal has been processed to yield zero or more subgoals, not before. Moreover, variables PROCESSOR and CLAUSE-LIST are allowed, but variable STABLE-UNDER-SIMPLIFICATIONP is not. We explain in more detail below, but first consider the following simple example. First we define a standard list reversal function: (defun rev (x) (if (consp x) (append (rev (cdr x)) (cons (car x) nil)) nil)) Now we prove: (thm (true-listp (rev x))) The successful proof includes the following output. Subgoal *1/1' (IMPLIES (AND (CONSP X) (TRUE-LISTP (REV (CDR X)))) (TRUE-LISTP (APPEND (REV (CDR X)) (LIST (CAR X))))). The destructor terms (CAR X) and (CDR X) can be eliminated by using CAR-CDR-ELIM to replace X by (CONS X1 X2), (CAR X) by X1 and (CDR X) by X2. This produces the following goal. Subgoal *1/1'' (IMPLIES (AND (CONSP (CONS X1 X2)) (TRUE-LISTP (REV X2))) (TRUE-LISTP (APPEND (REV X2) (LIST X1)))). But suppose that we attach a :backtrack hint to the goal above at which destructor elimination was applied: (thm (true-listp (rev x)) :hints ((\"Subgoal *1/1'\" :backtrack (quote (:do-not '(eliminate-destructors)))))) Then when ACL2 applies destructor elimination as displayed above, this time the :backtrack hint applies, evaluating to (:do-not '(eliminate-destructors)). Since this list is not nil, the prover decides not to keep the new subgoal, and instead supplies this :do-not hint before attacking the goal again. In this example, ACL2 happens to use a technique later in its ``waterfall'' arsenal than destructor elimination, namely, generalization: Subgoal *1/1' (IMPLIES (AND (CONSP X) (TRUE-LISTP (REV (CDR X)))) (TRUE-LISTP (APPEND (REV (CDR X)) (LIST (CAR X))))). [Note: A hint was supplied for our processing of the goal above, because of a :backtrack hint that is preventing destructor elimination. Thanks!] We generalize this conjecture, replacing (REV (CDR X)) by RV. This produces Subgoal *1/1'' (IMPLIES (AND (CONSP X) (TRUE-LISTP RV)) (TRUE-LISTP (APPEND RV (LIST (CAR X))))). We now provide a careful explanation of how :backtrack hints work, but we suggest that you keep the example above in mind. If ``:backtrack form'' is part of the hint that has been selected for a goal, then form is evaluated when one of ACL2's clause processors successfully applies to the current goal to produce a list of subgoals. This evaluation takes place in an environment just like that for any computed hint (see [computed-hints]), with the following exceptions. First, the variable STABLE-UNDER-SIMPLIFICATIONP is not allowed to occur free in form, but instead the following new variables are allowed to occur free and are bound for this evaluation as follows: PROCESSOR is bound to the processor in the list *preprocess-clause-ledge* that has applied to the goal, and CLAUSE-LIST is bound to the list of clauses (each a list of literals that is implicitly disjoined) returned by that clause processor. Second, the variables HIST and PSPV are bound to the history and pspv returned by the clause processor, not the ones that were passed to the clause processor. If this evaluation returns an error, then the proof aborts, as for any computed hint whose evaluation returns an error. If this evaluation returns nil, then the :backtrack hint has no effect, and the goal is replaced by the list of goals (the value of CLAUSE-LIST described above), as usual. Otherwise, the clause processor is deemed to have failed, and the goal clause is tried again starting at the top of the waterfall after selecting the hint returned by the above evaluation. That hint will normally be an alternating list of hint keywords and their values, but if it is a custom keyword hint (see [custom-keyword-hints]), then it will be handled in the usual manner but with the first three variables above bound to the symbol :OMITTED. Of course, if the new hint includes a value for :BACKTRACK then this process can loop; care should be taken to keep that from happening. A final note about :BACKTRACK hints: since these are a form of computed hints, [override-hints] (if any) are applied to their evaluation result just as with any computed hint. That is, the backtrack hint is successively modified with each override-hint, to produce a final hint that is actually used (or, ignored if that final hint is nil). See [override-hints]. :[bdd] This hint indicates that ACL2's built-in ordered binary decision diagrams (BDDs) with rewriting are to be used to prove or simplify the goal. See [bdd] for an introduction to the ACL2 BDD algorithm. Value is a list of even length, such that every other element, starting with the first, is one of the keywords :vars, :bdd-constructors, :prove, or :literal. Each keyword that is supplied should be followed by a value of the appropriate form, as shown below; for others, a default is used. Although :vars must always be supplied, we expect that most users will be content with the defaults used for the other values. :vars --- A list of ACL2 variables, which are to be treated as Boolean variables. The prover must be able to check, using trivial reasoning (see [type-set]), that each of these variables is Boolean in the context of the current goal. Note that the prover will use very simple heuristics to order any variables that do not occur in :vars (so that they are ``greater than'' the variables that do occur in :vars), and these heuristics are often far from optimal. In addition, any variables not listed may fail to be assumed Boolean by the prover, which is likely to seriously impede the effectiveness of ACL2's BDD algorithm. Thus, users are encouraged not to rely on the default order, but to supply a list of variables instead. Finally, it is allowed to use a value of t for vars. This means the same as a nil value, except that the BDD algorithm is directed to fail unless it can guarantee that all variables in the input term are known to be Boolean (in a sense discussed elsewhere; see [bdd-algorithm]). :literal --- An indication of which part of the current goal should receive BDD processing. Possible values are: :all treat entire goal as a single literal (the default) :conc process the conclusion n process the hypothesis with index n (1, 2, ...) :bdd-constructors --- When supplied, this value should be a list of function symbols in the current ACL2 [world]; it is (cons) by default, unless :bdd-constructors has a value in the [ACL2-defaults-table] by default, in which case that value is the default. We expect that most users will be content with the default. See [bdd-algorithm] for information about how this value is used. :prove --- When supplied, this value should be t or nil; it is t by default. When the goal is not proved and this value is t, the entire proof will abort. Use the value nil if you are happy to the proof to go on with the simplified term. :by Value is a [lemma-instance], nil, or a new event name. If the value is a [lemma-instance] (see [lemma-instance]), then it indicates that the goal (when viewed as a clause) is either equal to the proposition denoted by the instance, or is subsumed by that proposition when both are viewed as clauses. To view a formula as a clause, union together the negations of the hypotheses and add the conclusion. For example, (IMPLIES (AND (h1 t1) (h2 t2)) (c t1)) may be viewed as the clause {~(h1 t1) ~(h2 t2) (c t1)}. Clause c1 is ``subsumed'' by clause c2 iff some instance of c2 is a subset of c1. For example, the clause above is subsumed by {~(h1 x) (c x)}, which when viewed as a formula is (implies (h1 x) (c x)). Note that if the value is the name of a function symbol introduced by [defun], then the original form of the body of that definition is used. This behavior differs from that provided by a :use hint, where the so-called ``normalized'' body, for which ACL2 has propagated IF tests upward. If the value is nil or a new name, the prover does not even attempt to prove the goal to which this hint is attached. Instead the goal is given a ``bye'', i.e., it is skipped and the proof attempt continues as though the goal had been proved. If the prover terminates without error then it reports that the proof would have succeeded had the indicated goals been proved and it prints an appropriate [defthm] form to define each of the :by names. The ``name'' nil means ``make up a name.'' Here is an example (admittedly contrived for illustration purposes). ACL2 !>(thm (equal (append (append x y) z) (append x y z)) :hints ((\"Subgoal *1/2'\" :by nil))) Name the formula above *1. [[... output omitted here ...]] [Note: A hint was supplied for our processing of the goal below. Thanks!] Subgoal *1/2' (IMPLIES (AND (CONSP X) (EQUAL (APPEND (APPEND (CDR X) Y) Z) (APPEND (CDR X) Y Z))) (EQUAL (APPEND (APPEND X Y) Z) (APPEND X Y Z))). But we have been asked to pretend that this goal is subsumed by the yet-to-be-proved |THM Subgoal *1/2'|. Subgoal *1/1 [[... proof goes on; further output omitted here ...]] The system does not attempt to check the uniqueness of the :by names (supplied or made up), since by the time those goals are proved the namespace will be cluttered still further. Therefore, the final list of ``appropriate'' [defthm] forms may be impossible to admit without some renaming by the user. If you must invent new names, remember to substitute the new ones for the old ones in the :by hints themselves. :[case-split-limitations] Value is the same as for [set-case-split-limitations]. The simplifier will behave as though the value had instead been supplied to set-case-split-limitations; see [set-case-split-limitations]. This behavior will persist through subgoals unless overridden by another :CASE-SPLIT-LIMITATIONS hint. :cases Value is a non-empty list of terms. For each term in the list, a new goal is created from the current goal by assuming that term; and also, in essence, one additional new goal is created by assuming all the terms in the list false. We say ``in essence'' because if the disjunction of the terms supplied is a tautology, then that final goal will be a tautology and hence will in fact never actually be created. :[clause-processor] Value specifies the application of a user-defined simplifier to the current goal. See [clause-processor], which provides necessary background and hint syntax. Also see [define-trusted-clause-processor] for a discussion of ``trusted clause-processors'': goal-level simplifiers that may be external to ACL2 and do not need to be proved correct in ACL2. You can see all current :clause-processor rules by issuing the command (print-clause-processor-rules), and you can see the names of all trusted clause-processors by issuing the command (table trusted-clause-processor-table). :do-not Value is a term having at most the single free variable [world], which when evaluated (with [world] bound to the current ACL2 logical [world]) produces a list of symbols that is a subset of the list (preprocess ;propositional logic, simple rules simplify ;as above plus rewriting, linear arithmetic eliminate-destructors fertilize ;use of equalities generalize eliminate-irrelevance). The hint indicates that the ``processes'' named should not be used at or below the goal in question. Thus, to prevent generalization and fertilization, say, include the hint :do-not '(generalize fertilize) If value is a single symbol, as in :do-not generalize, it is taken to be '(value). See also [do-not-hint] for a way to automatically provide :do-not hints across several theorems. :do-not-induct Value is t, :otf-flg-override, :otf, name or nil, indicating whether [induction] is permitted under the specified goal. If value is t or :otf-flg-override, then the attempt to apply [induction] to the indicated goal or any subgoal under the indicated goal will immediately cause the theorem prover to report [failure], except that if :otf-flg t is specified (see [otf-flg]) and value is t, then the proof will continue until the time at which the goal pushed for induction is finally considered. The latter behavior is also what occurs if value is :otf. Thus, any non-nil value requires the indicated goal to be proved entirely by simplification, destructor elimination, and the other ``waterfall'' processes. [Induction] to prove the indicated goal (or any subgoal) is not permitted. See however the :induct hint below. If value is a symbol other than t, :otf-flg-override, :otf or nil, the theorem prover will give a ``bye'' to any subgoal that would otherwise be attacked with induction. This will cause the theorem prover to fail eventually but will collect the necessary subgoals. If value is nil, this hint means [induction] is permitted. Since that is the default, there is no reason to use the value nil. Note that a :do-not-induct hint is ignored for any goal on which an :induct hint is supplied. For an advanced example of the use of value :otf with [override-hints], see community book books/hints/basic-tests.lisp. :error Value is typically a ``fmt message'' to be printed by the [fmt] tilde-directive ~@ but may be any object. The effect of this hint is to cause an error when the hint is translated. There is no reason to include an :ERROR hint in any user-typein, since it will only cause an error when the form is evaluated. :ERROR hints are useful in the definition of functions that generate custom keyword hints ([custom-keyword-hints]) and computed hints ([computed-hints]). For example, if you wish to define a custom keyword hint :my-hint val and you wish the hint to signal an error if there is something inappropriate about val in the context of the hint, use the following code to generate the hint (list :ERROR (cons \"Your specified value, ~x0, is inappropriate\" (list (cons #0 val)))) which is equivalent to (list :ERROR (msg \"Your specified value, ~x0, is inappropriate\" val)) which, if val has the value 123, would evaluate to the hint (:ERROR (\"Your specified value, ~x0, is inappropriate\" (#0 . 123))). Note that any time an :ERROR keyword is produced during hint processing, including iterations of the expansions of custom keyword hints or of [override-hints], an error will occur. :expand Value is a true list of terms, each of which is of one of the forms (let ((v1 t1)...) b) or (fn t1 ... tn), where fn is a defined function symbol with formals v1, ..., vn, and body b. Such a term is said to be ``expandable:'' it can be replaced by the result of substituting the ti's for the vi's in b. The terms listed in the :expand hint are expanded when they are encountered by the simplifier while working on the specified goal or any of its subgoals. We permit value to be a single such term instead of a singleton list. Remarks: (1) Allowed are ``terms'' of the form (:free (var1 var2 ... varn) pattern) where the indicated variables are distinct and pattern is a term. Such ``terms'' indicate that we consider the indicated variables to be instantiatable, in the following sense: whenever the simplifier encounters a term that can be obtained from pattern by instantiating the variables (var1 var2 ... varn), then it expands that term. (2) Also allowed are ``terms'' of the form (:with name term), where name is a function symbol, a macro name that denotes a function symbol (see [macro-aliases-table]), or a [rune]. The corresponding rule of class :rewrite, which is often a [definition] rule but need not be, is then used in place of the current body for the function symbol of term; see [show-bodies] and see [set-body]. If the rule is of the form (implies hyp (equiv lhs rhs)), then after matching lhs to the current term in a context that is maintaining equivalence relation equiv, ACL2 will replace the current term with (if hyp rhs (hide term)), or just rhs if the rule is just (equal lhs rhs). (3) A combination of both :free and :with, as described above, is legal. (4) The term :LAMBDAS is treated specially. It denotes the list of all lambda applications (i.e., [let] expressions) encountered during the proof. Conceptually, this use of :LAMBDAS tells ACL2 to treat lambda applications as a notation for substitutions, rather than as function calls whose opening is subject to the ACL2 rewriter's heuristics (specifically, not allowing lambda applications to open when they introduce ``too many'' if terms). :hands-off Value is a true list of function symbols or lambda expressions, indicating that under the specified goal applications of these functions are not to be rewritten. Note however that subterms will still be rewritten; see [hide] if that is not what is intended. (The community book books/clause-processors/autohide.lisp from Jared Davis may also be helpful in that case.) Value may also be a single function symbol or lambda expression instead of a list. :[in-theory] Value is a ``theory expression,'' i.e., a term having at most the single free variable [world] which when evaluated (with [world] bound to the current ACL2 logical world (see [world])) will produce a theory to use as the current theory for the goal specified. See [theories]. Note that an :[in-theory] hint will always be evaluated relative to the current ACL2 logical [world], not relative to the theory of a previous goal. Consider the following example. (defthm prop (p (f (g x))) :hints ((\"Goal\" :in-theory (disable f)) (\"Subgoal 3\" :in-theory (enable g)))) Consider in particular the theory in effect at Subgoal 3. This call of the [enable] macro enables g relative to the [current-theory] of the current logical [world], not relative to the theory produced by the hint at Goal. Thus, the [disable] of f on behalf of the hint at Goal will be lost at Subgoal 3, and f will be enabled at Subgoal 3 if was enabled globally when prop was submitted. :induct Value is either t or a term containing at least one recursively defined function symbol; if t, this hint indicates that the system should proceed to apply its induction heuristic to the specified goal produced (without trying simplification, etc.); if value is a term other than t, then not only should the system apply induction immediately, but it should analyze value rather than the goal to generate its [induction] scheme. Merging and the other [induction] heuristics are applied. Thus, if value contains several mergeable [induction]s, the ``best'' will be created and chosen. E.g., the :induct hint (and (nth i a) (nth j a)) suggests simultaneous [induction] on i, j, and a. If both an :induct and a :do-not-induct hint are supplied for a given goal then the indicated [induction] is applied to the goal and the :do-not-induct hint is inherited by all subgoals generated. :[instructions] Value is a list of [proof-checker] instructions; see [instructions]. Unlike other hint keywords described here, this one is actually a custom keyword hint (see [custom-keyword-hints]) that generates a suitable :[clause-processor] hint. :no-op Value is any object and is irrelevant. This hint does nothing. But empty hints, such as (\"Goal\"), are illegal and there are occasions, especially when writing custom keyword hints (see [custom-keyword-hints]) and computed hints (see [computed-hints]) where it is convenient to be able to generate a non-empty no-op hint. The standard idiom is (\"Goal\" :NO-OP T) but the T is completely ignored. Unlike other hint keywords, multiple occurrences of the keyword :NO-OP are tolerated. :no-thanks Value is any object. This hint does nothing, except that if value is non-nil then the usual ``[Note: A hint was supplied... Thanks!]'' is not printed. :nonlinearp Value is t or nil, indicating whether [non-linear-arithmetic] is active. The default value is nil. See [non-linear-arithmetic]. :or Value is a list (kwd-val-listp-1 ... kwd-val-listp-k), where each kwd-val-listp-i is a list satisfying [keyword-value-listp], i.e., an alternating list of keywords and values. This hint causes an attempt to prove the specified goal using hints kwd-val-listp-i in sequence (first kwd-val-listp-1, then kwd-val-listp-2, and so on), until the first of these succeeds. If none succeeds, then the prover proceeds after heuristically choosing the ``best'' result, taking into account the goals pushed in each case for proof by induction. The following (contrived but illustrative example illustrates how :or hints work. ACL2 !>(thm (f x) :hints ((\"Goal\" :expand ((nth x 3)) :or ((:in-theory (disable car-cons)) (:use cdr-cons :in-theory (enable append))) :do-not '(generalize)))) [Note: A hint was supplied for our processing of the goal above. Thanks!] The :OR hint for Goal gives rise to two disjunctive branches. Proving any one of these branches would suffice to prove Goal. We explore them in turn, describing their derivations as we go. --- Subgoal D2 ( same formula as Goal ). The first disjunctive branch (of 2) for Goal can be created by applying the hint: (\"Subgoal D2\" :EXPAND ((NTH X 3)) :IN-THEORY (DISABLE CAR-CONS) :DO-NOT '(GENERALIZE)). [Note: A hint was supplied for our processing of the goal above. Thanks!] Normally we would attempt to prove this formula by induction. However, we prefer in this instance to focus on the original input conjecture rather than this simplified special case. We therefore abandon our previous work on this conjecture and reassign the name *1 to the original conjecture. (See :DOC otf-flg.) [Note: Thanks again for the hint.] --- Subgoal D1 ( same formula as Goal ). The second disjunctive branch (of 2) for Goal can be created by applying the hint: (\"Subgoal D1\" :EXPAND ((NTH X 3)) :USE CDR-CONS :IN-THEORY (ENABLE APPEND) :DO-NOT '(GENERALIZE)). [Note: A hint was supplied for our processing of the goal above. Thanks!] ACL2 Warning [Use] in ( THM ...): It is unusual to :USE an enabled :REWRITE or :DEFINITION rule, so you may want to consider disabling (:REWRITE CDR-CONS). We augment the goal with the hypothesis provided by the :USE hint. The hypothesis can be obtained from CDR-CONS. We are left with the following subgoal. Subgoal D1' (IMPLIES (EQUAL (CDR (CONS X Y)) Y) (F X)). By the simple :rewrite rule CDR-CONS we reduce the conjecture to Subgoal D1'' (F X). ... and so on. This example illustrates how ACL2 processes :or hints in general. For each i from 1 to k, a so-called ``disjunctive'' subgoal is created by splicing kwd-val-listp-i into the other hint values (if any) supplied for the given goal, in order. A corresponding subgoal is created for each i, numbered in the usual manner (hence, counting down) except that the ``D'' is prefixed to each resulting goal. :reorder Value is a list of positive integers without duplicates, corresponding to the numbering of subgoals generated for the [goal-spec] \"G\", say \"G.k\" down to \"G.1\". Those subgoals are reordered so that if value is (n1 n2 ... nk), then the goal now numbered \"G.k\" will be the goal originally numbered \"G.n1\"; the goal now numbered \"G.k-1\" will be the goal formerly numbered \"G.n2\"; and so on, down the list of ni, after which the goals not yet printed are printed in their original order. Note that reordering for subgoals of a goal to be proved by induction, such as *1, is not supported. :restrict Warning: This is a sophisticated hint, suggested by Bishop Brock, that is intended for advanced users. In particular, :restrict hints are ignored by the preprocessor, so you might find it useful to give the hint :do-not '(preprocess) when using any :restrict hints, at least if the rules in question are abbreviations (see [simple]). Value is an association list. Its members are of the form (x subst1 subst2 ...), where: x is either (1) a [rune] whose [car] is :[rewrite] or :[definition] or (2) an event name corresponding to one or more such [rune]s; and (subst1 subst2 ...) is a non-empty list of substitutions, i.e., of association lists pairing variables with terms. First consider the case that x is a :[rewrite] or :[definition] [rune]. Recall that without this hint, the rule named x is used by matching its left-hand side (call it lhs) against the term currently being considered by the rewriter, that is, by attempting to find a substitution s such that the instantiation of lhs using s is equal to that term. If however the :restrict hint contains (x subst1 subst2 ...), then this behavior will be modified by restricting s so that it must extend subst1; and if there is no such s, then s is restricted so that it must extend subst2; and so on, until the list of substitutions is exhausted. If no such s is found, then the rewrite or definition rule named x is not applied to that term. Finally, if x is an event name corresponding to one or more :[rewrite] or :[definition] [rune]s (that is, x is the ``base symbol'' of such [rune]s; see [rune]), say [rune]s r1, ... rn, then the meaning is the same except that (x subst1 subst2 ...) is replaced by (ri subst1 subst2 ...) for each i. Once this replacement is complete, the hint may not contain two members whose [car] is the same [rune]. Note that the substitutions in :restrict hints refer to the variables actually appearing in the goals, not to the variables appearing in the rule being restricted. Here is an example, supplied by Bishop Brock. Suppose that the database includes the following rewrite rule, which is probably kept [disable]d. (We ignore the question of how to prove this rule.) cancel-<-*$free: (implies (and (rationalp x) (rationalp y) (rationalp z)) (equal (< y z) (if (< x 0) (> (* x y) (* x z)) (if (> x 0) (< (* x y) (* x z)) (hide (< y z)))))) Then ACL2 can prove the following theorem (unless other rules get in the way), essentially by multiplying both sides by x. (thm (implies (and (rationalp x) (< 1 x)) (< (/ x) 1)) :hints ((\"Goal\" :in-theory (enable cancel-<-*$free) :restrict ((cancel-<-*$free ((x x) (y (/ x)) (z 1))))))) The :restrict hint above says that the variables x, y, and z in the rewrite rule cancel-<-*$free above should be instantiated respectively by x, (/ x), and 1. Thus (< y z) becomes (< (/ x) 1), and this inequality is replaced by the corresponding instance of the right-hand-side of cancel-<-*$free. Since the current conjecture assumes (< 1 x), that instance of the right-hand side simplifies to (< (* x (/ x)) (* x 1)) which in turn simplifies to (< 1 x), a hypothesis in the present theorem. :rw-cache-state Value is an element of the list constant *legal-rw-cache-states*: :atom (the default), nil, t, or :disabled. This hint applies to the indicated goal and all its descendents, to set the so-called ``rw-cache-state'' to the indicated value; see [set-rw-cache-state]. :use Examples of :USE hints are shown near the top of this documentation topic. Value is a [lemma-instance] or a true list of [lemma-instance]s, indicating that the propositions denoted by the instances be added as hypotheses to the specified goal. See [lemma-instance]. Note that :use makes the given instances available as ordinary hypotheses of the formula to be proved. The :instance form of a [lemma-instance] permits you to instantiate the free variables of previously proved theorems any way you wish; but it is up to you to provide the appropriate instantiations because once the instances are added as hypotheses their variables are no longer instantiable. These new hypotheses participate fully in all subsequent rewriting, etc. If the goal in question is in fact an instance of a previously proved theorem, you may wish to use :by below. Note that [theories] may be helpful when employing :use hints; see [minimal-theory]. Note that if the value is the name of a function symbol introduced by [defun], then the ``normalized'' body of that definition is used, for which ACL2 has propagated IF tests upward. This behavior differs from that provided by a :by hint, where the original body of the definition is used. Subtopics [Computed-hints] Computing advice to the theorem proving process [Custom-keyword-hints] User-defined hints [Default-hints] A list of hints added to every proof attempt [Do-not] Instruct the theorem prover not to do certain things. [Goal-spec] To indicate where a hint is to be used [Hints-and-the-waterfall] How [hints] fit into the ACL2 proof waterfall [Lemma-instance] An object denoting an instance of a theorem [Override-hints] A list of hints given priority in every proof attempt [Using-computed-hints] How to use computed hints") (HINTS-AND-THE-WATERFALL (HINTS) "How [hints] fit into the ACL2 proof waterfall Below we describe the flow of an ACL2 proof attempt, with special attention to how [hints] are applied during a proof. For most ACL2 users, only one point is important to take away from this [documentation] topic: you may specify hints during a proof (see [hints]; perhaps also see [computed-hints] and see [default-hints]), and they can be expected to behave intuitively. See [the-method] for a summary of how to interact with the ACL2 prover; see [introduction-to-the-theorem-prover] for a more detailed tutorial; and see [hints] for an introduction to ACL2 hints, including detailed [documentation] for specific hint types. The remainder of this topic serves as a reference in case one needs a deeper understanding of the workings of ACL2's handling of hints. Also, for examples of the sophisticated use of hints, primarily for experts, see community book books/hints/basic-tests.lisp. First, we describe the ACL2 ``waterfall'', which handles each goal either by replacing it with a list (possibly empty) of child goals, or else by putting the goal into a ``pool'' for later proof by induction. Then, we describe how hints are handled by the waterfall. The Waterfall. Each goal considered by the ACL2 prover passes through a series of proof processes, called the ``waterfall processes'', as stored in the constant *preprocess-clause-ledge*. The top process applies top-level hints, including :use hints; the next is a lightweight ``preprocess'' simplifier for ``simple'' rules (see [simple]); the next is the main ACL2 simplifier; and finally ACL2 attempts (in this order) destructor elimination, fertilization (heuristic use of equalities), generalization, and elimination of irrelevance. See [architecture-of-the-prover] for more information on these processes. Each process may ``hit'', creating zero or more child goals that are each then handled at the top of the waterfall; or it may ``miss'', in which case the next process in the above sequence is considered. If all processes miss, then a ``push'' process defers the goal until it is later considered for proof by induction. When all goals have been thus handled, the goal most recently pushed for proof by induction is considered, and the process repeats. We next describe the two additional ways in which control can be returned to the top of the waterfall. When the simplification process is attempted unsuccessfully for a goal, the goal is deemed to have ``settled down''. In this case, and if no ancestor of the goal has settled down, then the ``settled-down'' process is deemed to have ``hit'' on the goal, the effect being that the goal makes a new pass through all the waterfall processes. (Other processes can then notice that settling down has occurred and modify their heuristics accordingly.) For example, if \"Goal\" simplifies to \"Subgoal 2\" (among others), and \"Subgoal 2\" simplifies to \"Subgoal 2.3\" (among others), which in turn is not further simplified, then the ``settled-down'' process hits on \"Subgoal 2.3\" but not on any of its children, their children, and so on. When simplification has missed (and thus the goal has settled down), the next proof process is normally destructor elimination. However, if a computed hint is suitable (in a sense described below; also see [computed-hints], especially the discussion of stable-under-simplificationp), then that hint is selected as control is returned to the top of the waterfall. A subtlety is that in this case, if the most recent hit had been from settling down, then the prover ``changes its mind'' and considers that the goal has not yet settled down after all as it continues through the waterfall. Each time a goal is considered at the top of the waterfall, then before passing through the proof processes as described above, ACL2 searches for a relevant hint to select unless it has already been provided a hint in the ``stable-under-simplificationp'' case mentioned above. We turn now to a more thorough discussion of how hints are selected and applied. The handling of hints. In the discussion below we will ignore forcing rounds, as each forcing round is simply treated as a new proof attempt that uses the list of hints provided at the start of the proof. When the theorem prover is called by [thm] or [events] such as [defthm], [defun], and [verify-guards], it gathers up the hints that have been supplied, often provided as a :[hints] argument, but for example using a :guard-hints argument for [guard] verification proofs. (ACL2(r) users (see [real]) may also employ :std-hints.) It then appends these to the front of the list of default hints (see [default-hints]). The resulting list becomes the initial value of the list of ``pending hints'', one of two critical lists maintained by the theorem prover to manage hints. The other critical list is a list of ``hint settings''; the two lists are maintained as follows. When a goal is first considered, a hint is selected from the list of pending hints if any is found to apply, as described below. If a hint is selected, then it takes effect and is removed from the pending hints. Except: if the selected hint is a computed hint with value t specified for :computed-hint-replacement, then it is not removed; and if that value is a list of hints, then that list is appended to the front of the list of pending hints after the selected hint is removed (also see [computed-hints]). The selected hint is also used to update the hint settings, as described below. The list of hint settings associates hint keywords with values. It is passed from the current goal to its children (and hence the children's children, and so on), though modified by hints selected from pending hints, as described below. This list is maintained so that when a goal is pushed for proof by induction, the hint settings are applied at the start of the proof by induction. Note that the list of hint settings is not re-applied to descendents of a goal in the current waterfall; a hint is applied only when it is selected (and also perhaps later as just described, through the stored hint settings at the start of a proof by induction). For example, if the hint selected for \"Subgoal 3\" includes :in-theory (enable foo), then the hint settings are correspondingly updated when processing \"Subgoal 3\", and they persist at subgoals such as \"Subgoal 3.2\" and \"Subgoal 3.2.1\" (unless overriden by hints on those goals); but the theory specifying foo is not re-installed at every such subgoal. When a hint is selected, the list of hint settings is updated so that for each keyword :kwd and associated value val from the hint, :kwd is associated with val in the hint settings, discarding any previous association of :kwd with a value in the hint settings. Except, certain ``top-level'' hints are never saved in the hint settings: :use, :cases, :by, :bdd, :or, and :clause-processor. For example, suppose that we specify the following hints, with no default hints. ((\"Goal\" :expand ((bar x y))) (\"Subgoal 3\" :in-theory (enable foo))) These hints then become the initial list of pending hints. When the proof attempt begins, the prover encounters the top-level goal (\"Goal\") and pulls the \"Goal\" hint from the pending hints, so that the list of hint settings contains a value only for keyword :expand. This hint setting will remain for all children of the top-level goal as well, and their children, and so on, and will be inherited by induction --- in other words, it will remain throughout the entire proof. Now consider what happens when the proof reaches \"Subgoal 3\". At this point there is only one pending hint, which is in fact attached to that subgoal. Therefore, this hint is pulled from the pending hints (leaving that list empty), and the hint settings are extended by associating the :in-theory keyword with the theory represented by (enable foo). That theory is immediately installed until the prover finishes addressing \"Subgoal 3\", its children, their children, and so on; and until that completion is reached, the :in-theory keyword remains associated with the (enable foo) in the hint settings, although of course there is no re-installation of the theory at any ensuing child goal. When finally \"Subgoal 3\" and its descendents have been completed and the prover is about to consider \"Subgoal 2\", the :in-theory association is removed from the hint settings and the global theory is re-installed. However, the list of pending hints remains empty. It remains to describe how a hint is selected for a goal. When a goal is first considered (hence at the top of the waterfall), the list of pending hints is scanned, in order, until one of the hints is suitable for the goal. An explicit hint (goal-name :kwd1 val1 ... :kwdn valn) is suitable if goal-name is the name of the current goal and there is at least one keyword. A computed hint is suitable if it evaluates to a non-nil value. As indicated earlier in this documentation topic, an exception occurs when a computed hint is selected after simplification fails (the ``stable-under-simplificationp'' case): in that case, the goal returns to the top of the waterfall with that hint as the selected hint, and no additional search for a hint to select is made at that time. The following slightly tricky example illustrates handling of hints. ACL2 !>(set-default-hints '((\"Goal\" :do-not '(preprocess)))) ((\"Goal\" :DO-NOT '(PREPROCESS))) ACL2 !>(thm (equal (append (append x y) z) (append x y z)) :hints ((\"Goal\" :in-theory (disable car-cons)))) ACL2 Warning [Hints] in ( THM ...): The goal-spec \"Goal\" is explicitly associated with more than one hint. All but the first of these hints may be ignored. If you intended to give all of these hints, combine them into a single hint of the form (\"Goal\" :kwd1 val1 :kwd2 val2 ...). See :DOC hints-and-the-waterfall. [Note: A hint was supplied for our processing of the goal above. Thanks!] [Note: A hint was supplied for our processing of the goal above. Thanks!] Name the formula above *1. The warning above is printed because \"Goal\" is associated with two pending hints: one given by the [set-default-hints] call and one supplied by the :[hints] keyword of the [thm] form. The :in-theory hint is selected because user-supplied hints are ahead of default hints in the list of pending hints; we then get the first ``Note'' above. The goal progresses through the waterfall without any proof process applying to the goal; in particular, it cannot be further simplified. After the simplification process, a ``settled-down'' process applies, as discussed above, immediately causing another trip through the waterfall. Since the :in-theory hint was earlier removed from the list of pending hints when it was applied, the default (:do-not) hint is now the only pending hint. That hint is applied, resulting in the second ``Note'' above. Again, more examples may be found in the community book books/hints/basic-tests.lisp. A particularly tricky but informative example in that book is the one related to nonlinearp-default-hint. Also see [override-hints] for an advanced feature that allows modification of the hint selected for a goal.") (HISTORY (ACL2) "Functions that display or change history ACL2 keeps track of the [command]s that you have executed that have extended the logic or the rule database, as by the definition of macros, functions, etc. Using the facilities in this section you can review the sequence of [command]s executed so far. For example, you can ask to see the most recently executed [command], or the [command] 10 before that, or the [command] that introduced a given function symbol. You can also undo back through some previous [command], restoring the logical [world] to what it was before the given [command]. The annotations printed in the margin in response to some of these commands (such as `P', `L', and `V') are explained in the documentation for :[pc]. Several technical terms are used in the documentation of the history [command]s. You must understand these terms to use the [command]s. These terms are documented via :[doc] entries of their own. See [command], see [events], see [command-descriptor], and see [logical-name]. Subtopics [Command] Forms you type at the top-level, but... [Command-descriptor] An object describing a particular [command] typed by the user [Enter-boot-strap-mode] The first millisecond of the Big Bang [Exit-boot-strap-mode] The end of pre-history [Formula] The formula of a name or [rune] [Get-command-sequence] Return list of [command]s that are between two [command] descriptors [Oops] Undo a :u or :[ubt] [Pbt] Print the [command]s back through a [command] descriptor [Pc] Print the [command] described by a [command] descriptor [Pcb] Print the [command] block described by a [command] descriptor [Pcb!] Print in full the [command] block described by a [command] descriptor [Pcs] Print the sequence of [command]s between two [command] descriptors [Pe] Print the events named by a logical name [Pe!] Deprecated (see [pe]) [Pf] Print the formula corresponding to the given name [Pl] Print the rules for the given name or term [Pl2] Print rule(s) for the given form [Pr] Print the rules stored by the event with the given name [Pr!] Print rules stored by the command with a given command descriptor [Puff] Replace a compound [command] by its immediate subevents [Puff*] Replace a compound [command] by its subevents [Reset-kill-ring] Save memory by resetting and perhaps resizing the kill ring used by [oops] [Reset-prehistory] Reset the prehistory [Tau-database] To see the tau database as a (very large) object [U] Undo last [command], without a query [Ubt] Undo the [command]s back through a [command] descriptor [Ubt!] Undo [command]s, without a query or an error [Ubt-prehistory] Undo the [command]s back through the last [reset-prehistory] event [Ubu] Undo the [command]s back up to (not including) a [command] descriptor [Ubu!] Undo [command]s, without a query or an error") (HONS (PROGRAMMING HONS-AND-MEMOIZATION ACL2-BUILT-INS) "(hons x y) returns a [normed] object equal to (cons x y). In the logic, hons is just [cons]; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, hons does whatever is necessary to ensure that its result is [normed]. What might this involve? Since the car and cdr of any normed cons must be normed, we need to [hons-copy] x and y. This requires little work if x and y are already normed, but can be expensive if x or y contain large, un-normed cons structures. After that, we need to check whether any normed cons equal to (x . y) already exists. If so, we return it; otherwise, we need to construct a new cons for (x . y) and install it as the normed version of (x . y). Generally speaking, these extra operations make hons much slower than cons, even when given normed arguments. Function: (defun hons (x y) (declare (xargs :guard t)) (cons x y)) Subtopics [Hons-clear] ([hons-clear] gc) is a drastic garbage collection mechanism that clears out the underlying Hons Space. [Hons-clear!] A version of [hons-clear] for [parallel] execution [Hons-copy] ([hons-copy] x) returns a [normed] object that is equal to X. [Hons-copy-persistent] ([hons-copy-persistent] x) returns a [normed] object that is equal to X and which will be re-normed after any calls to [hons-clear]. [Hons-equal] ([hons-equal] x y) is a recursive equality check that optimizes when parts of its arguments are [normed]. [Hons-equal-lite] ([hons-equal-lite] x y) is a non-recursive equality check that optimizes if its arguments are [normed]. [Hons-note] Notes about [hons], especially pertaining to expensive resizing operations [Hons-resize] ([hons-resize] ...) can be used to manually adjust the sizes of the hash tables that govern which ACL2 Objects are considered [normed]. [Hons-summary] ([hons-summary]) prints basic information about the sizes of the tables in the current Hons Space. [Hons-wash] ([hons-wash]) is like [gc$] but can also garbage collect [normed] objects (CCL and GCL Only). [Hons-wash!] A version of [hons-wash] for [parallel] execution [Normed] Normed objects are ACL2 Objects that are \"canonical\" or \"unique\" in a certain sense.") (HONS-ACONS (FAST-ALISTS ACL2-BUILT-INS) "(hons-acons key val alist) is the main way to create or extend [fast-alists]. Logically, hons-acons is like [acons] except that its guard does not require [alistp]; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, two things are done differently. First, the key is copied with [hons-copy]; this lets us use EQL-based hash tables instead of EQUAL-based hash tables for better performance. Second, assuming there is a valid hash table associated with this alist, we destructively update the hash table by binding key to val. The hash table will no longer be associated with alist, but will instead be associated with the new alist returned by hons-acons. Hash Table Creation A new hash table is created by hons-acons whenever alist is an atom. Unlike ordinary acons, we do not require that alist be nil, and in fact you may wish to use a non-nil value for one of two reasons. 1. As a size hint By default, the new hash table will be given a quite modest default capacity of 60 elements. As more elements are added, the table may need to be resized to accommodate them, and this resizing has some runtime cost. When a natural number is used as a fast alist's name, we interpret it as a size hint. For example, (hons-acons 'foo 'bar 1000) instructs us to use 1000 as the initial size for this hash table and binds 'foo to 'bar. The resulting table should not need to be resized until more than 1000 elements are added. We ignore size hints that request fewer than 60 elements. Because of hash collisions, hash tables typically need to have a larger size than the actual number of elements they contain. The hash tables for fast alists are told to grow when they reach 70% full. So, an easy rule of thumb might be: multiply the expected number of elements you need by 1.5 to keep your hash tables about 2/3 full. 2. As an alist name We also frequently use a symbol for alist, and think of this symbol as the name of the new alist. We have found that naming alists can be valuable for two reasons: First, the name can be helpful in identifying fast alists that should have been freed, see [fast-alist-summary]. Second, names can sometimes be used to avoid a subtle and insidious table-stealing phenomenon that occurs when using fast-alists that are themselves normed; see [hons-acons!]. At the moment, there is no way to simultaneously name a fast alist and also give it a size hint. We may eventually allow strings to include embedded name and size components, but for now we have not implemented this capability. Function: (defun hons-acons (key val alist) (declare (xargs :guard t)) (cons (cons key val) alist))") (HONS-ACONS! (FAST-ALISTS ACL2-BUILT-INS) "(hons-acons! key val alist) is an alternative to [hons-acons] that produces [normed], fast alists. Logically, hons-acons! is like [acons] except that its guard does not require [alistp]; we leave it enabled and would think it odd to ever prove a theorem about it. Ordinarily, [fast-alists] are constructed with [hons-acons] instead of hons-acons!. In such alists, the keys are honsed, but the conses that make up the \"spine\" of the alist itself are ordinary conses. In other words, it is basically correct to say: (hons-acons key val alist) == (cons (cons (hons-copy key) val) alist) In contrast, when hons-acons! is used, the conses making up the alist itself are also normed. That is, (hons-acons! key val alist) == (hons (hons key val) alist) Generally, you should not use hons-acons! unless you really know what you're doing. Drawback 1. hons-acons! requires you to [hons-copy] all of the values that are being stored in the fast alist. If you are storing large values, this may be expensive. Drawback 2. It can be more difficult to maintain the proper discipline when using hons-acons!. For instance, consider the following: (let ((al1 (hons-acons 1 'one (hons-acons 2 'two nil))) (al2 (hons-acons 1 'one (hons-acons 2 'two nil)))) ...) Here, both al1 and al2 are valid fast alists and they can be extended independently without any trouble. But if these alists had instead been constructed with hons-acons!, then since both al1 and al2 are equal, normed conses, they will literally be [eq] and hence will refer to precisely the same hash table. In other words, hons-acons! makes it relatively easy to inadvertently steal the hash table associated with some other fast alist. This problem can be alleviated somewhat by uniquely naming alists; see the discussion in [hons-acons] for details. Despite these drawbacks, hons-acons! is the typical way to generate a fast alist that is normed (but also, for example, see [fast-alist-fork!]). It is not adequate to [hons-copy] a fast alist that was generated by ordinary [hons-acons] calls, because this would produce an EQUAL-but-not-EQ object, and this new object would not be associated with the fast alist's hash table. Function: (defun hons-acons! (key val alist) (declare (xargs :guard t)) (cons (cons key val) alist))") (HONS-AND-MEMOIZATION (ACL2) "Hash cons, function memoization, and applicative hash tables This topic describes the hash cons, function memoization, and applicative hash tables features available in so-called [hons-enabled] ACL2 executables, which are built by default. Bob Boyer and Warren Hunt, and later Jared Davis and Sol Swords, have developed a canonical representation for ACL2 data objects and a function memoization mechanism to facilitate reuse of previously computed results. This facility includes procedures to read and print ACL2 expressions in such a way that repetition of some ACL2 objects is eliminated, thereby permitting a kind of on-the-fly file compression. The implementation does not alter the semantics of ACL2 except to add a handful of definitions. We historically gave the name ``ACL2(h)'' to the experimental extension of the ACL2 system including hash cons, function memoization, and fast association lists (applicative hash tables). These features, which we call the ``[hons-enabled]'' features, are now present in default builds of ACL2; thus ``ACL2(h)'' and ``ACL2'' are now synonymous. It is however possible to build ACL2 without these features; see [hons-enabled]. The hons-enabled features are optimized for Clozure Common Lisp (CCL) and, more recently (but not as thoroughly exercised), GNU Common Lisp (GCL ANSI); but they are supported by other ANSI-compliant host Lisp implementations. Power users who want to take advantage of the [hons-enabled] features of ACL2 might find it helpful to consult the document centaur/README.html in the ACL2 community books. Much of the documentation for the remainder of this topic is taken from the paper ``Function Memoization and Unique Object Representation for ACL2 Functions'' by Robert S. Boyer and Warren A. Hunt, Jr., which has appeared in the Sixth International Workshop on the ACL2 Theorem Prover and Its Applications, ACM Digital Library, 2006. In the implementation of the ACL2 logic, ACL2 data objects are represented by Common Lisp objects of the same type, and the ACL2 pairing operation is internally implemented by the Common Lisp [cons] function. In Common Lisp, cons is guaranteed to provide a new pair, distinct from any previously created pair. We have defined a new ACL2 function [hons] that is logically identical to the ACL2 cons function, but whose implementation usually reuses an existing pair if its components are identical to the components of an existing pair. A record of ACL2 HONS objects is kept, and when an ACL2 function calls hons ACL2 searches for an existing identical pair before allocating a new pair; this operation been called ``hash consing''. It appears that hash consing was first conceived by A. P. Ershov in 1957, to speed up the recognition of common subexpressions. Ershov showed how to collapse trees to minimal DAGs by traversing trees bottom up, and he used hashing to eliminate the re-evaluation of common subexpressions. In his 1973 PhD dissertation L. Peter Deutsch describes a program verifier that uses hash cons to represent terms and his rewriter operated on hash consed terms. Later, Eiichi Goto implemented a Lisp system with a built-in hash consing operation: his h-CONS cells were rewrite protected and free of duplicate copies, and Goto used this hash consing operation to facilitate the implementation of a symbolic algebra system he developed. Memoizing functions also has a long history. In 1967, Donald Michie proposed using memoized functions to improve the performance of machine learning. Rote learning was improved by a learning function not forgetting what it had previously learned; this information was stored as memoized function values. The use of hash consing has appeared many times. For instance, Henry Baker used hash consing to improve the performance of the well-known Boyer rewriting benchmark. Baker used both hash consing and function memoization to improve the speed of the Takeuchi function, exactly in the spirit of our implementation, but without the automated, system-wide integration we report here. The ACL2 implementation permits memoization of user-defined functions. During execution a user may enable or disable function memoization on an individual function basis, may clear memoization tables, and may even keep a stack of memoization tables. This facility takes advantage of our implementation where we keep one copy of each distinct ACL2 data object. Due to the functional nature of ACL2, it is sufficient to have at most one copy of any data structure; thus, a user may arrange to keep data canonicalized. This implementation extends to the entire ACL2 system the benefits enjoyed by BDDs: canonicalization, memoization, and fast equality check. We have defined various algorithms using these features, and we have observed, in some cases, substantial performance increases. For instance, we have implemented unordered set intersection and union operations that operate in time roughly linear in the size of the sets. Without using arrays, we defined a canonical representation for Boolean functions using ACL2 objects. We have investigated the performance of rewriting and tree consensus algorithms to good effect, and we believe function memoization offers interesting opportunities to simplify algorithm definition while simultaneously providing performance improvements. We recommend that users focus at first on the logical definitions of [hons] and other primitives rather than their underlying Common Lisp implementations. Integrated with this memoization system is a performance monitoring system, which can provide real-time feedback on the operation and usefulness of [hons] and function memoization. For a more detailed description of these tools, please see the ACL2 2006 workshop paper mentioned above. The Fibonacci function is a small example that demonstrates the utility of function memoization. The following definition exhibits a runtime that is exponential in its input argument. (defun fib (x) (declare (xargs :guard (natp x))) (mbe :logic (cond ((zp x) 0) ((= x 1) 1) (t (+ (fib (- x 1)) (fib (- x 2))))) :exec (if (< x 2) x (+ (fib (- x 1)) (fib (- x 2)))))) Below we show how the ACL2 [time$] utility can measure the time to execute a call to the fib function (with some editing to avoid noise from the underlying Common Lisp implementation). [Memoize] is actually an ACL2 macro that expands to a call of the ACL2 function used to identify a function for memoization; see [memoize]. This function also accepts a well-formed term that must be true in order for the system to memoize a call of the memoized function; to ensure that an instance of the term is safe for evaluation in Common Lisp, a check is performed that if the [guard] of the memoized function is satisfied, then this instance will execute without error. ACL2 !>(time$ (fib 40)) ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 0.99 seconds realtime, 0.98 seconds runtime ; (1,296 bytes allocated). 102334155 ACL2 !>(memoize 'fib) Summary Form: ( TABLE MEMOIZE-TABLE ...) Rules: NIL Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) Summary Form: ( PROGN (TABLE MEMOIZE-TABLE ...) ...) Rules: NIL Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) FIB ACL2 !>(time$ (fib 40)) ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 0.00 seconds realtime, 0.00 seconds runtime ; (2,864 bytes allocated). 102334155 ACL2 !>(time$ (fib 100)) ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 0.00 seconds realtime, 0.00 seconds runtime ; (7,024 bytes allocated). 354224848179261915075 ACL2 !>(unmemoize 'fib) We see that once the function fib is identified as a function for which function calls should be memoized, the execution times are substantially reduced. Finally, we can prevent fib from being further memoized; in fact, [unmemoize] erases the previously memoized values. The implementation of hash consing, memoization, and applicative hash tables involves several facets: canonical representation of ACL2 data, function memoization, and the use of Lisp hash tables to improve the performance of association list operations. We discuss each of these in turn, and we mention some subtle interrelationships. Although it is not necessary to understand the discussion in this section, it may permit some users to better use this implementation. This discussion may be confusing for some ACL2 users as it makes references to Lisp implementation features. The ACL2 system is actually implemented as a Lisp program that is layered on top of a Common Lisp system implementation. ACL2 data constants are implemented with their corresponding counterparts in Common Lisp; that is, ACL2 cons pairs, strings, characters, numbers, and symbols are implemented with their specific Common Lisp counterparts. This choice permits a number of ACL2 primitive functions to be implemented with their corresponding Common Lisp functions, but there are indeed differences. ACL2 is a logic, and as such, it does not specify anything to do with physical storage or execution performance. When ACL2 is used, the knowledgeable user can write functions to facilitate the reuse of some previously computed values. Recall the three mechanisms under discussion: hash consing, function memoization, and fast association list operations. The function memoization mechanism takes advantage of the canonical representation of data objects provided by the [hons] operation as does the fast association list operation mechanism. Each time hons is invoked, its arguments are themselves converted, if necessary, to uniquely represented objects. The ACL2 universe is recursively closed under the cons pairing operation and the atoms. Hash consing ([hons]) is logically identical to cons, but a set of tables is used to record each hons pair. When a hons pair is requested, the implementation checks, in the current set of tables, whether the requested pair already exists. If not, a new pair is created and a record of that pair is made; otherwise, a reference to the previously created pair is returned. Thus, any data object created with hons has a unique representation, as does every subcomponent. We also arrange for strings to have a unique representation --- only one copy of each different string is kept --- and when any previously unseen string is an argument to hons, we add the string to a unique table of strings. A system-wide benefit of having a canonical representation for data is that equality comparisons between any two data objects can be done in constant time. The definition of [hons] in no way changes the operation of cons --- hons creates a cons pair. When asked to create a hons, the implementation checks to see if there is a cons with the same [car] and [cdr] as the hons being requested. Thus, the only difference between the results of a hons call and a corresponding cons call is a notation in some invisible (to the ACL2 logic) tables where we record which cons elements are also hons elements. Since a hons is nothing but a cons, the operation of car and cdr is unchanged. In fact, the implementation is designed so that at any time it is safe to clear the table identifying which cons elements are also considered hons elements. User-defined functions with defined and verified guards can be memoized. When a function is memoized, a user-supplied condition restricts the domain when memoization is attempted. When the condition is satisfied, memoization is attempted (assuming that memoization for the function is presently enabled); otherwise, the function is just evaluated. Each memoized function has a hash table that is used to keep track of a unique list of function arguments paired with their values. If appropriate, for each function the corresponding table is checked to see if a previous call with exactly the same arguments already exists in the table: if so, then the associated value is returned; if not, then the function is evaluated and a new key-value pair is added to the table of memoized values so that some future call will benefit from the memoization. With ACL2 user functions memoization can be dynamically enabled and disabled. There is an ACL2 function that clears a specific memoization table. And finally, just as with the hons table, a stack of these function memoization tables is maintained; that is, it is possible to memoize a function, use it a bit, set the memoized values aside, start a new table, use it, and then return to the original table. We next discuss the fast lookup operation for association lists. When a pair is added to an association list using the functions [hons-acons] or [hons-acons!], the system also records the key-value pair in an associated hash table. As long as a user only used these two functions when placing key-value pairs on an association list, the key-value pairs in the corresponding hash table will be synchronized with the key-value pairs in the association list. Later, if [hons-get] is used to look up a key, then instead of performing a linear search of the association list we consult the associated hash table. If a user does not strictly follow this discipline, then a linear search may be required. In some sense, these association lists are much like ACL2 arrays, but without the burden of explicitly naming the arrays. The ACL2 array [compress1] function is analogous to the functions [fast-alist-clean] and [fast-alist-clean!]. There are user-level ACL2 functions that allow the associated hash tables to be cleared and removed. As mentioned above, the [hons-enabled] features are optimized for CCL and GCL. See [ccl-updates] for easy instructions for obtaining the latest version of CCL. REFERENCES Baker, Henry G., The Boyer Benchmark at Warp Speed. ACM Lisp Pointers V,3 (Jul-Sep 1992), pages 13-14. Baker, Henry G., A Tachy 'TAK'. ACM Lisp Pointers Volume 3, July-September, 1992, pages 22-23. Robert S. Boyer and Warren A. Hunt, Jr., Function Memoization and Unique Object Representation for ACL2 Functions, in the Sixth International Workshop on the ACL2 Theorem Prover and Its Applications, ACM Digital Library, 2006. L.P. Deutsch. An Interactive Program Verifier. Tech. Rept. CSL-73-1, Xerox Palo Alto Research Center, May, 1973. A. P. Ershov. On Programming of Arithmetic Operations. In the Communications of the ACM, Volume 118, Number 3, August, 1958, pages 427-430. Eiichi Goto, Monocopy and Associative Algorithms in Extended Lisp, TR-74-03, University of Toyko, 1974. Richard P. Gabriel. Performance and Evaluation of Lisp Systems. MIT Press, 1985. Donald Michie. Memo functions: a Language Feature with Rote Learning Properties. Technical Report MIP-R-29, Department of Artificial Intelligence, University of Edinburgh, Scotland, 1967. Donald Michie. Memo Functions and Machine Learning. In Nature, Volumne 218, 1968, pages 19-22. Subtopics [Ccl-updates] Updating Clozure Common Lisp (CCL) [Fast-alists] Alists with hidden hash tables for faster execution [Hons] ([hons] x y) returns a [normed] object equal to ([cons] x y). [Hons-enabled] An ACL2 build that supports hash cons, function memoization, and applicative hash tables [Memoize] Turn on memoization for a specified function [Number-subtrees] ([number-subtrees] x) returns the number of distinct subtrees of X, in the sense of [equal] [Unmemoize] Turn off memoization for the specified function [With-stolen-alist] ([with-stolen-alist] name form) ensures that name is a fast alist at the start of the execution of form. At the end of execution, it ensures that name is a fast alist if and only if it was originally. That is, if name was not a fast alist originally, its hash table link is freed, and if it was a fast alist originally but its table was modified during the execution of form, that table is restored. Note that any extended table created from the original fast alist during form must be manually freed.") (HONS-ASSOC-EQUAL (FAST-ALISTS ACL2-BUILT-INS) "(hons-assoc-equal key alist) is not fast; it serves as the logical definition for [hons-get]. The definition of hons-assoc-equal is similar to that of [assoc-equal], except that (1) it does not require [alistp] as a guard, and (2) it \"skips over\" any non-conses when its alist argument is malformed. We typically leave hons-get enabled and reason about hons-assoc-equal instead. One benefit of this approach is that it avoids certain \"false\" discipline warnings that might arise from execution during theorem proving. Function: (defun hons-assoc-equal (key alist) (declare (xargs :guard t)) (cond ((atom alist) nil) ((and (consp (car alist)) (hons-equal key (caar alist))) (car alist)) (t (hons-assoc-equal key (cdr alist)))))") (HONS-CLEAR (HONS ACL2-BUILT-INS) "(hons-clear gc) is a drastic garbage collection mechanism that clears out the underlying Hons Space. Logically, hons-clear just returns nil; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, hons-clear brutally (1) clears all the tables that govern which conses are [normed], then (2) optionally garbage collects, per the gc argument, then finally (3) re-norms the keys of [fast-alists] and persistently normed conses; see [hons-copy-persistent]. Notes. * The hash tables making up the Hons Space retain their sizes after being cleared. If you want to shrink them, see [hons-resize]. * CCL and GCL users might prefer [hons-wash], which is relatively efficient and allows for the garbage collection of normed conses without impacting their normed status. * It is not recommended to interrupt this function. Doing so may cause persistently normed conses and fast alist keys to become un-normed, which might lead to less efficient re-norming and/or violations of the fast-alist discipline. * (For ACL2(p) users only; see [parallelism]) If parallel execution is enabled (see (@see set-parallel-execution)), as it is by default in ACL2(p), then hons-clear may be a no-op (other than to print a warning), in order to avoid thread-unsafe behavior. (However, In CCL you are unlikely to see this restriction unless you are running more than one thread.) To get around this restriction, you can instead use [hons-clear!], which however requires a [trust-tag]. Function: (defun hons-clear (gc) (declare (xargs :guard t)) (declare (ignore gc)) nil)") (HONS-CLEAR! (HONS ACL2-BUILT-INS) "A version of [hons-clear] for [parallel] execution This function is only of interest to ACL2(p) users; see [parallelism], because for ACL2 it suffices to use [hons-clear]. However, if parallel execution is enabled (see (@see set-parallel-execution)), as it is by default in ACL2(p), then hons-clear may be a no-op (other than to print a warning), in order to avoid thread-unsafe behavior. If you are not concerned about thread safety, for example when you want to call hons-clear directly in the top-level loop, you can use hons-clear!, which does not check for parallelism violations. However, hons-clear! requires a trust tag; see [defttag].") (HONS-COPY (HONS ACL2-BUILT-INS) "(hons-copy x) returns a [normed] object that is equal to X. In the logic, hons-copy is just the identity function; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, hons-copy does whatever is necessary to produce a [normed] version of X. What might this involve? If X is a symbol, character, or number, then it is already normed and nothing is done. If X is a string, we check if any normed version of X already exists. If so, we return the already-normed version; otherwise, we install X as the normed version for all strings that are [equal] to X. If X is a cons, we must determine if there is a normed version of X, or recursively construct and install one. Norming large cons trees can become expensive, but there are a couple of cheap cases. In particular, if X is already normed, or if large subtrees of X are already normed, then not much needs to be done. The slowest case is norming some large ACL2 cons structure that has no subtrees which are already normed. Note that running hons-copy on an object that was created with [cons] is often slower than just using [hons] directly when constructing the object. Function: (defun hons-copy (x) (declare (xargs :guard t)) x)") (HONS-COPY-PERSISTENT (HONS ACL2-BUILT-INS) "(hons-copy-persistent x) returns a [normed] object that is equal to X and which will be re-normed after any calls to [hons-clear]. Logically hons-copy-persistent is the identity; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, hons-copy-persistent is virtually identical to [hons-copy]. The only difference is that when [hons-clear] is used, any persistently normed conses are automatically re-normed, and this re-norming can be carried out more efficiently than, say, an ordinary [hons-copy]. Function: (defun hons-copy-persistent (x) (declare (xargs :guard t)) x)") (HONS-ENABLED (HONS-AND-MEMOIZATION) "An ACL2 build that supports hash cons, function memoization, and applicative hash tables ACL2 can support hash cons, function memoization, and applicative hash tables; see [hons-and-memoization]. That support is provided by any default build of an ACL2 executable, for example an executable created by issuing the following shell command, where invokes your Lisp executable (default: ccl). make LISP= Such an executable is said to be ``hons-enabled''. A hons-enabled executable is sometimes called ``ACL2(h)'', while one that is not hons-enabled is called ``ACL2(c)'' --- ``c'' for ``classic'' --- because ACL2 builds before Version 7.0 were not hons-enabled. To build an ACL2 executable saved_acl2c that is not hons-enabled, set the shell variable ACL2_HONS to the empty string, for example: make ACL2_HONS=") (HONS-EQUAL (HONS EQUAL ACL2-BUILT-INS) "(hons-equal x y) is a recursive equality check that optimizes when parts of its arguments are [normed]. In the logic, hons-equal is just [equal]; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, when hons-equal encounters two arguments that are both normed, it becomes a mere [eql] check, and hence avoids the overhead of recursively checking large cons structures for equality. Note. If hons-equal is given arguments that do not contain many normed objects, it can actually be much slower than [equal]! This is because it checks to see whether its arguments are normed at each recursive step, and so you are repeatedly paying the price of such checks. Also see [hons-equal-lite], which only checks at the top level whether its arguments are normed. Function: (defun hons-equal (x y) (declare (xargs :guard t)) (equal x y)) Subtopics [Hons-equal-lite] ([hons-equal-lite] x y) is a non-recursive equality check that optimizes if its arguments are [normed].") (HONS-EQUAL-LITE (HONS HONS-EQUAL) "(hons-equal-lite x y) is a non-recursive equality check that optimizes if its arguments are [normed]. In the logic, hons-equal-lite is just [equal]; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, hons-equal-lite checks whether its arguments are normed, and if so it effectively becomes a [eql] check. Otherwise, it immediately calls [equal] to determine if its arguments are equal. The idea here is to strike a useful balance between equal and [hons-equal]. If both arguments happen to be normed, we get to use a very fast equality comparison. Otherwise, we just get out of the way and let equal do its work, without the extra overhead of recursively checking whether the subtrees of x and y are normed. Function: (defun hons-equal-lite (x y) (declare (xargs :guard t)) (equal x y))") (HONS-GET (FAST-ALISTS ACL2-BUILT-INS) "(hons-get key alist) is the efficient lookup operation for [fast-alists]. Logically, hons-get is just an alias for [hons-assoc-equal]; we typically leave it enabled and prefer to reason about hons-assoc-equal instead. One benefit of this approach is that it helps to avoids \"false\" discipline warnings that might arise from execution during theorem proving. Under the hood, when alist is a fast alist that is associated with a valid hash table, hons-get first norms key using [hons-copy], then becomes a gethash operation on the hidden hash table. Function: (defun hons-get (key alist) (declare (xargs :guard t)) (hons-assoc-equal key alist))") (HONS-NOTE (HONS) "Notes about [hons], especially pertaining to expensive resizing operations Certain ``Hons-Notes'' are printed to the terminal to report implementation-level information about the management of [hons] structures. Some of these may be low-level and of interest mainly to system developers. But below we discuss what users can learn from a particular hons-note, ``ADDR-LIMIT reached''. In short: If you are seeing a lot of such hons-notes, then you may be using a lot of memory. (Maybe you can reduce that memory; for certain BDD operations, for example (as defined in community books books/centaur/ubdds/), variable ordering can make a big difference.) By way of background: The ADDR-HT is the main hash table that lets us look up [normed] conses, i.e., [hons]es. It is an ordinary Common Lisp hash table, so when it starts to get too full the Lisp will grow it. It can get really big. (It has been seen to take more than 10 GB of memory just for the hash table's array, not to mention the actual conses!) Hons-Notes may be printed when the ADDR-HT is getting really full. This growth can be expensive and can lead to memory problems. Think about what it takes to resize a hash table: (1) allocate a new, bigger array (2) rehash elements, copying them into the new array (3) free the old array Until you reach step (3) and a garbage collection takes place, you have to have enough memory to have both the old and new arrays allocated. If the old array was 10 GB and we want to allocate a new one that's 15 GB, this can get pretty bad. Also, rehashing the elements is expensive time-wise when there are lots of elements. Since resizing a hash table is expensive, we want to avoid it. There's a [hons-resize] command for this. You may want your books to start with something like the following. (value-triple (set-max-mem (* 30 (expt 2 30)))) ; 30 GB heap (value-triple (hons-resize :addr-ht #u_100_000_000)) ; 100M honses Basically, if you roughly know how many honses your book will need, you can just get them up front and then never to resize. The Hons-Notes about ``ADDR-LIMIT reached'' are basically there to warn you that the ADDR-HT is being resized. This can help you realize that your [hons-resize] command had too small of an ADDR-HT size, or might suggest that your book should have a [hons-resize] command. There are also commands like ([hons-summary]), [set-max-mem], and defined in community book books/centaur/misc/memory-mgmt-logic.lisp, (hons-analyze-memory nil). These can show you how many honses you currently have, how much space they are taking, and that sort of thing. (A nice trick is to call [hons-summary] at the end of a book, to get an idea of how many honses you should ask for in your [hons-resize] command).") (HONS-RESIZE (HONS ACL2-BUILT-INS) "(hons-resize ...) can be used to manually adjust the sizes of the hash tables that govern which ACL2 Objects are considered [normed]. General form: (hons-resize [:str-ht size] [:nil-ht size] [:cdr-ht size] [:cdr-ht-eql size] [:addr-ht size] [:other-ht size] [:sbits size] [:fal-ht size] [:persist-ht size]) Example: (hons-resize :str-ht 100000 :addr-ht (expt 2 27)) Logically, hons-resize just returns nil; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, hons-resize can be used to change the sizes of certain hash tables in the Hons Space. All arguments are optional. The size given to each argument should either be nil (the default) or a natural number. A natural number indicates the newly desired size for the hash table, whereas nil means \"don't resize this table.\" Any non-natural argument is regarded as nil. You may wish to call this function for two reasons. 1. Improving Performance by Resizing Up Since the hash tables in the Hons Space automatically grow as new objects are normed, hons-resize is unnecessary. But automatic growth can be slow because it is incremental: a particular hash table might be grown dozens of times over the course of your application. Using hons-resize to pick a more appropriate initial size may help to reduce this overhead. 2. Reducing Memory Usage by Resizing Down Resizing can also be used to shrink the hash tables. This might possibly be useful immediately after a [hons-clear] to free up memory taken by the hash tables themselves. (Of course, the tables will grow again as you create new normed objects.) Advice for using hons-resize. Note that hash tables that are already close to the desired size, or which have too many elements to fit into the desired size, will not actually be resized. This makes resizing relatively \"safe.\" Note that the [hons-summary] function can be used to see how large and how full your hash tables are. This may be useful in deciding what sizes you want to give to hons-resize. Note that hons-resize operates by (1) allocating new hash tables, then (2) copying everything from the old hash table into the new table. Because of this, for best performance you should ideally call it when the hash tables involved are minimally populated, i.e., at the start of your application, or soon after a [hons-clear].") (HONS-SHRINK-ALIST (FAST-ALIST-FORK ACL2-BUILT-INS) "Deprecated feature Deprecated. Alias for [fast-alist-fork].") (HONS-SHRINK-ALIST! (FAST-ALIST-FORK! ACL2-BUILT-INS) "Deprecated feature Deprecated. Alias for [fast-alist-fork!].") (HONS-SUMMARY (HONS ACL2-BUILT-INS) "(hons-summary) prints basic information about the sizes of the tables in the current Hons Space. Logically, hons-summary just returns nil; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, this function gathers and prints some basic information about the sizes of the tables in the Hons Space. This information may be useful for deciding if you want to garbage collect using functions such as [hons-clear] or [hons-wash]. It may also be useful for determining good initial sizes for the Hons Space hash tables for your particular computation; see [hons-resize]. For information about [fast-alists], see [fast-alist-summary]. Function: (defun hons-summary nil (declare (xargs :guard t)) nil)") (HONS-WASH (HONS ACL2-BUILT-INS) "(hons-wash) is like [gc$] but can also garbage collect [normed] objects (CCL and GCL Only). Logically, hons-wash just returns nil; we leave it enabled and would think it odd to ever prove a theorem about it. Under the hood, in CCL and GCL, hons-wash runs a garbage collection after taking special measures to allow normed conses to be collected. In Lisps other than CCL, hons-wash does nothing. This is because the efficient implementation of hons-wash is specific to the \"static honsing\" scheme which requires CCL-specific features. Why is this function needed? Ordinarily, it is not possible to garbage collect any normed conses. This is because the Hons Space includes pointers to any normed conses, and hence Lisp's garbage collector thinks these objects are live. To correct for this, hons-wash (1) clears out these pointers, (2) runs a garbage collection, then (3) re-norms any previously-normed conses which have survived the garbage collection. Notes. * It is not recommended to interrupt this function. Doing so may cause persistently normed conses and fast alist keys to become un-normed, which might lead to less efficient re-norming and/or violations of the fast-alist discipline. * (For ACL2(p) users only; see [parallelism]) If parallel execution is enabled (see (@see set-parallel-execution)), as it is by default in ACL2(p), then hons-wash may be a no-op (other than to print a warning), in order to avoid thread-unsafe behavior. (However, In CCL you are unlikely to see this restriction unless you are running more than one thread.) To get around this restriction, you can instead use [hons-wash!], which however requires a [trust-tag]. Function: (defun hons-wash nil (declare (xargs :guard t)) nil)") (HONS-WASH! (HONS ACL2-BUILT-INS) "A version of [hons-wash] for [parallel] execution This function is only of interest to ACL2(p) users; see [parallelism], because for ACL2 it suffices to use [hons-wash]. However, if parallel execution is enabled (see (@see set-parallel-execution)), as it is by default in ACL2(p), then hons-wash may be a no-op (other than to print a warning), in order to avoid thread-unsafe behavior. If you are not concerned about thread safety, for example when you want to call hons-wash directly in the top-level loop, you can use hons-wash!, which does not check for parallelism violations. However, hons-wash! requires a trust tag; see [defttag].") (HOW_LONG_DOES_IT_TAKE_TO_BECOME_AN_EFFECTIVE_USER{Q} (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "How Long Does It Take to Become an Effective User? [{IMAGE}] We expect that a talented undergraduate majoring in computer science (or perhaps mathematics) will probably take several weeks to become an effective ACL2 user. The time will depend, of course, on that student's familiarity with logic (or formal methods) and Lisp programming, as well as willingness to read and study the ACL2 User's Manual. Of course, it is critical to do some projects in order to gain proficiency. (Hence access to an ACL2 implementation is also a requirement, for example by downloading and installing following links from the ACL2 home page.) But it is critical to start with ``toy'' projects before tackling a ``grand challenge.'' [{IMAGE}]") (HOW_TO_FIND_OUT_ABOUT_ACL2_FUNCTIONS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "How To Find Out about ACL2 Functions [{IMAGE}] Most ACL2 primitives are documented. Here is the definition of app again, with the documented topics highlighted. [{ICON}] All of the links below lead into the ACL2 User's Manual. So follow these links if you wish, but use your Back Button to return here! ([defun] app (x y) ([cond] (([endp] x) y) (t ([cons] ([car] x) (app ([cdr] x) y))))) By following the link on [endp] [{ICON}] we see that it is a Common Lisp function and is defined to be the same as [atom] [{ICON}], which recognizes non-conses. But endp has a guard. Since we are ignorning guards for now, we'll ignore the guard issue on endp. So this definition reads ``to app x and y: if x is an atom, return y; otherwise, app (cdr x) and y and then cons (car x) onto that.'' [{IMAGE}]") (HOW_TO_FIND_OUT_ABOUT_ACL2_FUNCTIONS_{CONT} (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "How To Find Out about ACL2 Functions (cont) [{IMAGE}] You can always use the Index [{ICON}] icon below to find the documentation of functions. Try it. Click on the Index icon below. Then use the Find command of your browser to find ``endp'' in that document and follow the link. But remember to come back here. The ACL2 documentation is also available in Emacs, via the ACL2-Doc browser (see [ACL2-Doc]) [{ICON}], allowing you to explore the hyperlinked documentation in the comfort of a text editor that can also interact with ACL2. In addition, runtime images of ACL2 have the hyperlinked text as a large ACL2 data structure that can be explored with ACL2's :doc command. If you have ACL2 running, try the command :doc endp. Another way to find out about ACL2 functions, if you have an ACL2 image available, is to use the command :[args] [{ICON}] which prints the formals, type, and guard of a function symbol. Of course, the ACL2 documentation can also be printed out as a very long book but we do not recommend that! See the ACL2 Home Page to download the Postscript. Now let's continue with app. [{IMAGE}]") (I-AM-HERE (LD) "A convenient marker for use with [rebuild] or [ld] Example Input File for Rebuild: (defun fn1 (x y) ...) (defthm lemma1 ...) (defthm lemma2 ...) (i-am-here) The following lemma won't go through. I started typing the hint but realized I need to prove a lemma first. See the failed proof attempt in foo.bar. I'm going to quit for the night now and resume tomorrow from home. (defthm lemma3 ... :hints ((\"Goal\" :use (:instance ??? ... By putting an (i-am-here) form at the ``frontier'' of an evolving file of [command]s, you can use [rebuild] to load the file up to the (i-am-here). I-am-here simply returns an error triple (see [error-triples]) that indicates an error, and any form that ``causes an error'' will do the same job. Note that the text of the file after the (i-am-here) need not be machine readable.") (I-CLOSE (REAL) "ACL2(r) test for whether two numbers are infinitesimally close (I-close x y) is true if and only if x-y is an infinitesimal number. This predicate is only defined in ACL2(r) (see [real]).") (I-LARGE (REAL) "ACL2(r) recognizer for infinitely large numbers (I-large x) is true if and only if x is non-zero and 1/x is an infinitesimal number. This predicate is only defined in ACL2(r) (see [real]).") (I-LIMITED (REAL) "ACL2(r) recognizer for limited numbers (I-limited x) is true if and only if x is a number that is not infinitely large. This predicate is only defined in ACL2(r) (see [real]).") (I-SMALL (REAL) "ACL2(r) recognizer for infinitesimal numbers (I-small x) is true if and only if x is an infinitesimal number (possibly 0). This predicate is only defined in ACL2(r) (see [real]).") (IDENTITY (BASICS ACL2-BUILT-INS) "The identity function (Identity x) equals x; what else can we say? Identity is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun identity (x) (declare (xargs :guard t)) x)") (IF (BASICS ACL2-BUILT-INS) "If-then-else function (if x y z) is equal to y if x is any value other than nil, and is equal to z if x is nil. Only one of y, z is evaluated when (if x y z) is evaluated. If has a [guard] of t. If is part of Common Lisp. See any Common Lisp documentation for more information.") (IF* (BDD) "For conditional rewriting with BDDs The function IF* is defined to be [if], but it is used in a special way by ACL2's [bdd] package. Function: (defun if* (x y z) (if x y z)) As explained elsewhere (see [bdd-algorithm]), ACL2's [bdd] algorithm gives special treatment to [term]s of the form (IF* TEST TBR FBR). In such cases, the algorithm simplifies TEST first, and the result of that simplification must be a constant (normally t or nil, but any non-nil explicit value is treated like t here). Otherwise, the algorithm aborts. Thus, IF* may be used to implement a sort of conditional rewriting for ACL2's [bdd] package, even though this package only nominally supports unconditional rewriting. The following contrived example should make this point clear. Suppose that we want to prove that (nthcdr (length x) (append x y)) is equal to y, but that we would be happy to prove this only for lists having length 4. We can state such a theorem as follows. (let ((x (list x0 x1 x2 x3))) (equal (nthcdr (length x) (append x y)) y)) If we want to prove this formula with a :[bdd] hint, then we need to have appropriate rewrite rules around. First, note that LENGTH is defined as follows (try :[pe] [length]): (length x) = (if (stringp x) (len (coerce x 'list)) (len x)) Since [bdd]-based rewriting is merely very simple unconditional rewriting (see [bdd-algorithm]), we expect to have to prove a rule reducing [stringp] of a [cons]: (defthm stringp-cons (equal (stringp (cons x y)) nil)) Now we need a rule to compute the LEN of X, because the definition of LEN is recursive and hence not used by the [bdd] package. (defthm len-cons (equal (len (cons a x)) (1+ (len x)))) We imagine this rule simplifying (LEN (LIST X0 X1 X2 X3)) in terms of (LEN (LIST X1 X2 X3)), and so on, and then finally (LEN nil) should be computed by execution (see [bdd-algorithm]). We also need to imagine simplifying (APPEND X Y), where still X is bound to (LIST X0 X1 X2 X3). The following two rules suffice for this purpose (but are needed, since [append], actually [binary-append], is recursive). (defthm append-cons (equal (append (cons a x) y) (cons a (append x y)))) (defthm append-nil (equal (append nil x) x)) Finally, we imagine needing to simplify calls of [nthcdr], where the first argument is a number (initially, the length of (LIST X0 X1 X2 X3), which is 4). The second lemma below is the traditional way to accomplish that goal (when not using BDDs), by proving a conditional rewrite rule. (The first lemma is only proved in order to assist in the proof of the second lemma.) (defthm fold-constants-in-+ (implies (and (syntaxp (quotep x)) (syntaxp (quotep y))) (equal (+ x y z) (+ (+ x y) z)))) (defthm nthcdr-add1-conditional (implies (not (zp (1+ n))) (equal (nthcdr (1+ n) x) (nthcdr n (cdr x))))) The problem with this rule is that its hypothesis makes it a conditional [rewrite] rule, and conditional rewrite rules are not used by the [bdd] package. (See [bdd-algorithm] for a discussion of ``BDD rules.'') (Note that the hypothesis cannot simply be removed; the resulting formula would be false for n = -1 and x = '(a), for example.) We can solve this problem by using IF*, as follows; comments follow. (defthm nthcdr-add1 (equal (nthcdr (+ 1 n) x) (if* (zp (1+ n)) x (nthcdr n (cdr x))))) How is nthcdr-add1 applied by the [bdd] package? Suppose that the [bdd] computation encounters a [term] of the form (NTHCDR (+ 1 N) X). Then the [bdd] package will apply the [rewrite] rule nthcdr-add1. The first thing it will do when attempting to simplify the right hand side of that rule is to attempt to simplify the term (ZP (1+ N)). If N is an explicit number (which is the case in the scenario we envision), this test will reduce (assuming the executable counterparts of [zp] and [binary-+] are [enable]d) to t or to nil. In fact, the lemmas above (not including the lemma nthcdr-add1-conditional) suffice to prove our goal: (thm (let ((x (list x0 x1 x2 x3))) (equal (nthcdr (length x) (append x y)) y)) :hints ((\"Goal\" :bdd (:vars nil)))) If we execute the following form that disables the definition and executable counterpart of the function [zp] (in-theory (disable zp (zp))) before attempting the proof of the theorem above, we can see more clearly the point of using IF*. In this case, the prover makes the following report. ACL2 Error in ( THM ...): Unable to resolve test of IF* for term (IF* (ZP (+ 1 N)) X (NTHCDR N (CDR X))) under the bindings ((X (CONS X0 (CONS X1 (CONS X2 #)))) (N '3)) -- use SHOW-BDD to see a backtrace. If we follow the advice above, we can see rather clearly what happened. See [show-bdd]. ACL2 !>(show-bdd) BDD computation on Goal yielded 21 nodes. ------------------------------ BDD computation was aborted on Goal, and hence there is no falsifying assignment that can be constructed. Here is a backtrace of calls, starting with the top-level call and ending with the one that led to the abort. See :DOC show-bdd. (LET ((X (LIST X0 X1 X2 X3))) (EQUAL (NTHCDR (LENGTH X) (APPEND X Y)) Y)) alist: ((Y Y) (X3 X3) (X2 X2) (X1 X1) (X0 X0)) (NTHCDR (LENGTH X) (APPEND X Y)) alist: ((X (LIST X0 X1 X2 X3)) (Y Y)) (IF* (ZP (+ 1 N)) X (NTHCDR N (CDR X))) alist: ((X (LIST* X0 X1 X2 X3 Y)) (N 3)) ACL2 !> Each of these term-alist pairs led to the next, and the test of the last one, namely (ZP (+ 1 N)) where N is bound to 3, was not simplified to t or to nil. What would have happened if we had used [if] in place of IF* in the rule nthcdr-add1? In that case, if ZP and its executable counterpart were disabled then we would be put into an infinite loop! For, each time a term of the form (NTHCDR k V) is encountered by the BDD package (where k is an explicit number), it will be rewritten in terms of (NTHCDR k-1 (CDR V)). We would prefer that if for some reason the term (ZP (+ 1 N)) cannot be decided to be t or to be nil, then the BDD computation should simply abort. Even if there were no infinite loop, this kind of use of IF* is useful in order to provide feedback of the form shown above whenever the test of an IF term fails to simplify to t or to nil.") (IF-INTRO (POINTERS) "See [splitter].") (IFF (BASICS ACL2-BUILT-INS) "Logical ``if and only if'' Iff is the ACL2 biconditional, ``if and only if''. (iff P Q) means that either P and Q are both false (i.e., nil) or both true (i.e., not nil). Function: (defun iff (p q) (declare (xargs :guard t)) (if p (if q t nil) (if q nil t)))") (IFIX (NUMBERS ACL2-BUILT-INS) "Coerce to an integer Ifix simply returns any integer argument unchanged, returning 0 on a non-integer argument. Also see [nfix], see [rfix], see [realfix] and see [fix] for analogous functions that coerce to a natural number, a rational number, a real, and a number, respectively. Ifix has a [guard] of t. Function: (defun ifix (x) (declare (xargs :guard t)) (if (integerp x) x 0))") (IGNORABLE (POINTERS) "See [declare].") (IGNORE (POINTERS) "See [declare].") (IGNORED-ATTACHMENT (DEFATTACH) "Why attachments are sometimes not used Attachments provide a way to execute constrained functions. But in some cases, ACL2 will not permit such execution. We discuss this issue briefly here. For more information about attachments, see [defattach]. We illustrate this issue with the following example, discussed below. (encapsulate () (defstub foo () t) (defn foo-impl-1 () t) (defattach foo foo-impl-1) (defn foo-impl-2 () nil) (local (defattach foo foo-impl-2)) (defmacro mac () (foo)) ; nil in the first pass, t in the second pass (defun bar () (mac)) ; nil in the first pass, t in the second pass (defthm bar-is-nil (equal (bar) nil)) ) Here, a non-executable function foo is introduced with no constraints, and is provided two contradictory implementations, foo-impl-1 and foo-impl-2. A function, bar, is defined using a macro, mac, whose expansion depends on which of foo-impl-1 or foo-impl-2 is attached to foo. If ACL2 were to allow this, then as indicated by the comments above, (bar) would be defined to be nil on the first pass of the [encapsulate] form, where foo is attached to foo-impl-2; but (bar) would be defined to be t on the second pass, where foo is attached to foo-impl-1 because the second [defattach] call is [local]. Thus, after execution of the encapsulate form, (bar) would be provably equal to t even though there would be a theorem, bar-is-nil --- proved during the first pass of the encapsulate --- saying that (bar) is nil! Fortunately, ACL2 does not permit this to happen. The example above produces the following output. ACL2 !>>(DEFUN BAR NIL (MAC)) ACL2 Error in ( DEFUN BAR ...): In the attempt to macroexpand the form (MAC), evaluation of the macro body caused the following error: ACL2 cannot ev the call of undefined function FOO on argument list: NIL Note that because of logical considerations, attachments (including FOO-IMPL-2) must not be called in this context. We see, then, the importance of disallowing evaluation using attachments during macroexpansion. ACL2 is careful to avoid attachments in situations, like this one, where using attachments could be unsound. We conclude with an example illustrating how [make-event] can be used to work around the refusal of ACL2 to use attachments during macroexpansion. The idea is that [make-event] expansions are stored, and this avoids the issue of [local] attachments. In particular, for the example below, the second [defattach] affects the body of f2 even though that [defattach] is [local], because the expansion of the corresponding [make-event] is saved during the first pass of [certify-book], when full admissibility checks are done. Then even after including the book, the definition of f2 will be based on the second ([local]) [defattach] form below. (in-package \"ACL2\") (defun body-1 (name formals body) (declare (ignore name)) `(if (consp ,(car formals)) ,body nil)) (defun body-2 (name formals body) (declare (ignore name)) `(if (acl2-numberp ,(car formals)) ,body t)) (defmacro defun+ (name formals body) `(make-event (if (foo) ; attachable stub '(defun ,name ,formals ,(body-1 name formals body)) '(defun ,name ,formals ,(body-2 name formals body))))) ;;; (defun+ f1 (x y) (cons x y)) ; fails because foo has no attachment (defstub foo () t) (defn foo-true () t) (defn foo-false () nil) (defattach foo foo-true) (defun+ f1 (x y) (cons x y)) (local (defattach foo foo-false)) (defun+ f2 (x y) (cons x y)) (assert-event (equal (f1 3 t) nil)) (assert-event (equal (f2 3 t) (cons 3 t)))") (ILLEGAL (ERRORS ACL2-BUILT-INS) "Print an error message and stop execution (Illegal ctx str alist) causes evaluation to halt with a short message using the ``context'' ctx. An error message is first printed using the string str and alist alist that are of the same kind as expected by [fmt]. See [fmt], and see [prog2$] for an example of how to use a related function, [hard-error] (see [hard-error]). Also see [er] for a macro that provides a unified way of signaling errors. The difference between illegal and [hard-error] is that the former has a guard of nil while the latter has a [guard] of t. Thus, you may want to use illegal rather than hard-error when you intend to do [guard] verification at some point, and you expect the guard to guarantee that the illegal call is never executed. See [prog2$] for an example. Technical note for raw Lisp programmers only: It is possible to cause hard errors to signal actual raw Lisp errors. See [hard-error]. Function: (defun illegal (ctx str alist) (declare (xargs :guard (hard-error ctx str alist))) (hard-error ctx str alist))") (IMAGPART (NUMBERS ACL2-BUILT-INS) "Imaginary part of a complex number Completion Axiom (completion-of-imagpart): (equal (imagpart x) (if (acl2-numberp x) (imagpart x) 0)) [Guard] for (imagpart x): (acl2-numberp x)") (IMMED-FORCED (POINTERS) "See [splitter].") (IMMEDIATE-FORCE-MODEP (FORCE) "When executable counterpart is [enable]d, [force]d hypotheses are attacked immediately Also see [disable-immediate-force-modep] and see [enable-immediate-force-modep]. This function symbol is defined simply to provide a [rune] which can be [enable]d and [disable]d. Enabling (:executable-counterpart immediate-force-modep) causes ACL2 to attack [force]d hypotheses immediately instead of delaying them to the next forcing round. Example Hints :in-theory (disable (:executable-counterpart immediate-force-modep)) ; delay forced hyps to forcing round :in-theory (enable (:executable-counterpart immediate-force-modep)) ; split on forced hyps immediately See [force] for background information. When a [force]d hypothesis cannot be established a record is made of that fact and the proof continues. When the proof succeeds a ``forcing round'' is undertaken in which the system attempts to prove each of the [force]d hypotheses explicitly. However, if the [rune] (:executable-counterpart immediate-force-modep) is [enable]d at the time the hypothesis is [force]d, then ACL2 does not delay the attempt to prove that hypothesis but undertakes the attempt more or less immediately.") (IMPLIES (BASICS ACL2-BUILT-INS) "Logical implication Implies is the ACL2 implication function. (implies P Q) means that either P is false (i.e., nil) or Q is true (i.e., not nil). Function: (defun implies (p q) (declare (xargs :guard t)) (if p (if q t nil) t))") (IMPROPER-CONSP (LISTS ACL2-BUILT-INS) "Recognizer for improper (non-null-terminated) non-empty lists Improper-consp is the function that checks whether its argument is a non-empty list that ends in other than nil. See [proper-consp] and also see [true-listp]. Function: (defun improper-consp (x) (declare (xargs :guard t)) (and (consp x) (not (true-listp x))))") (IN-ARITHMETIC-THEORY (EVENTS) "Designate theory for some rewriting done for non-linear arithmetic We assume familiarity with [theories]; in particular, see [in-theory] for the normal way to set the current theory. Here, we discuss an analogous event that pertains only to non-linear arithmetic (see [non-linear-arithmetic]). Example: (in-arithmetic-theory '(lemma1 lemma2)) General Form: (in-arithmetic-theory term :doc doc-string) where term is a term that when evaluated will produce a theory (see [theories]), and doc-string, if non-nil, is an optional string that can provide documentation but is essentially ignored by ACL2. Except for the variable [world], term must contain no free variables. Term is evaluated with the variable [world] bound to the current [world] to obtain a theory and the corresponding runic theory (see [theories]) is then used by non-linear arithmetic (see [non-linear-arithmetic]). Warning: If term involves macros such as [enable] and [disable] you will probably not get what you expect! Those macros are defined relative to the [current-theory]. But in this context you might wish they were defined in terms of the ``CURRENT-ARITHMETIC-THEORY'' which is not actually a defined function. We do not anticipate that users will repeatedly modify the arithmetic theory. We expect term most often to be a constant list of runes and so have not provided ``arithmetic theory manipulation functions'' analogous to [current-theory] and [enable]. See [non-linear-arithmetic].") (IN-PACKAGE (PACKAGES ACL2-BUILT-INS) "Select current package Example: (in-package \"MY-PKG\") General Form: (in-package str) where str is a string that names an existing ACL2 package, i.e., one of the initial packages such as \"KEYWORD\" or \"ACL2\" or a package introduced with [defpkg]. For a complete list of the known packages created with [defpkg], evaluate (strip-cars (known-package-alist state)). See [defpkg]. An ACL2 book (see [books]) must contain a single in-package form, which must be the first form in that book.") (IN-TAU-INTERVALP (TAU-SYSTEM ACL2-BUILT-INS) "Boolean membership in a tau interval General Form: (in-tau-intervalp e x) Here, x should be an interval (see [tau-intervalp]). This function returns t or nil indicating whether e, which is generally but not necessarily a number, is an element of interval x. By that is meant that e satisfies the domain predicate of the interval and lies between the two bounds. Suppose x is an interval with the components dom, lo-rel, lo, hi-rel and hi. Suppose (= i 0)) :scheme (recursion-by-sub2 i)))) In ACL2, as in Nqthm, the functions in a conjecture ``suggest'' the inductions considered by the system. Because every recursive function must be admitted with a justification in terms of a measure that decreases in a well-founded way on a given set of ``controlling'' arguments, every recursive function suggests a dual induction scheme that ``unwinds'' the function from a given application. For example, since [append] (actually [binary-append], but we'll ignore the distinction here) decomposes its first argument by successive [cdr]s as long as it is a non-nil true list, the induction scheme suggested by (append x y) has a base case supposing x to be either not a true list or to be nil and then has an induction step in which the induction hypothesis is obtained by replacing x by (cdr x). This substitution decreases the same measure used to justify the definition of [append]. Observe that an induction scheme is suggested by a recursive function application only if the controlling actuals are distinct variables, a condition that is sufficient to ensure that the ``substitution'' used to create the induction hypothesis is indeed a substitution and that it drives down a certain measure. In particular, (append (foo x) y) does not suggest an induction unwinding [append] because the induction scheme suggested by (append x y) requires that we substitute (cdr x) for x and we cannot do that if x is not a variable symbol. Once ACL2 has collected together all the suggested induction schemes it massages them in various ways, combining some to simultaneously unwind certain cliques of functions and vetoing others because they ``flaw'' others. We do not further discuss the induction heuristics here; the interested reader should see Chapter XIV of A Computational Logic (Boyer and Moore, Academic Press, 1979) which represents a fairly complete description of the induction heuristics of ACL2. However, unlike Nqthm, ACL2 provides a means by which the user can elaborate the rules under which function applications suggest induction schemes. Such rules are called :induction rules. The definitional principle automatically creates an :induction rule, named (:induction fn), for each admitted recursive function, fn. It is this rule that links applications of fn to the induction scheme it suggests. Disabling (:induction fn) will prevent fn from suggesting the induction scheme derived from its recursive definition. It is possible for the user to create additional :induction rules by using the :induction rule class in [defthm]. Technically we are ``overloading'' [defthm] by using it in the creation of :induction rules because no theorem need be proved to set up the heuristic link represented by an :induction rule. However, since [defthm] is generally used to create rules and rule-class objects are generally used to specify the exact form of each rule, we maintain that convention and introduce the notion of an :induction rule. An :induction rule can be created from any lemma whatsoever. General Form of an :induction Lemma or Corollary: T General Form of an :induction rule-class: (:induction :pattern pat-term :condition cond-term :scheme scheme-term) where pat-term, cond-term, and scheme-term are all terms, pat-term is the application of a function symbol, fn, scheme-term is the application of a function symbol, rec-fn, that suggests an induction, and, finally, every free variable of cond-term and scheme-term is a free variable of pat-term. We actually check that rec-fn is either recursively defined --- so that it suggests the induction that is intrinsic to its recursion --- or else that another :induction rule has been proved linking a call of rec-fn as the :pattern to some scheme. The induction rule created is used as follows. When an instance of the :pattern term occurs in a conjecture to be proved by induction and the corresponding instance of the :condition term is known to be non-nil (by type reasoning alone), the corresponding instance of the :scheme term is created and the rule ``suggests'' the induction, if any, suggested by that term. (Analysis of that term may further involve induction rules, though the applied rule is removed from consideration during that further analysis, in order to avoid looping.) If rec-fn is recursive, then the suggestion is the one that unwinds that recursion. Consider, for example, the example given above, (:induction :pattern (* 1/2 i) :condition (and (integerp i) (>= i 0)) :scheme (recursion-by-sub2 i)). In this example, we imagine that recursion-by-sub2 is the function: (defun recursion-by-sub2 (i) (if (and (integerp i) (< 1 i)) (recursion-by-sub2 (- i 2)) t)) Observe that this function recursively decomposes its integer argument by subtracting 2 from it repeatedly and stops when the argument is 1 or less. The value of the function is irrelevant; it is its induction scheme that concerns us. The induction scheme suggested by (recursion-by-sub2 i) is (and (implies (not (and (integerp i) (< 1 i))) ; base case (:p i)) (implies (and (and (integerp i) (< 1 i)) ; induction step (:p (- i 2))) (:p i))) We can think of the base case as covering two situations. The first is when i is not an integer. The second is when the integer i is 0 or 1. In the base case we must prove (:p i) without further help. The induction step deals with those integer i greater than 1, and inductively assumes the conjecture for i-2 while proving it for i. Let us call this scheme ``induction on i by twos.'' Suppose the above :induction rule has been added. Then an occurrence of, say, (* 1/2 k) in a conjecture to be proved by induction would suggest, via this rule, an induction on k by twos, provided k was known to be a nonnegative integer. This is because the induction rule's :pattern is matched in the conjecture, its :condition is satisfied, and the :scheme suggested by the rule is that derived from (recursion-by-sub2 k), which is induction on k by twos. Similarly, the term (* 1/2 (length l)) would suggest no induction via this rule, even though the rule ``fires'' because it creates the :scheme (recursion-by-sub2 (length l)) which suggests no inductions unwinding recursion-by-sub2 (since the controlling argument of recursion-by-sub2 in this :scheme is not a variable symbol). Continuing this example one step further illustrates the utility of :induction rules. We could define the function recursion-by-cddr that suggests the induction scheme decomposing its [consp] argument two [cdr]s at a time. We could then add the :induction rule linking (* 1/2 (length x)) to (recursion-by-cddr x) and arrange for (* 1/2 (length l)) to suggest induction on l by [cddr]. Observe that :induction rules require no proofs to be done. Such a rule is merely a heuristic link between the :pattern term, which may occur in conjectures to be proved by induction, and the :scheme term, from which an induction scheme may be derived. Hence, when an :induction rule-class is specified in a [defthm] event, the theorem proved is irrelevant. The easiest theorem to prove is, of course, t. Thus, we suggest that when an :induction rule is to be created, the following form be used: (defthm name T :rule-classes ((:induction :pattern pat-term :condition cond-term :scheme scheme-term))) The name of the rule created is (:induction name). When that rune is disabled the heuristic link between pat-term and scheme-term is broken.") (INITIALIZE-EVENT-USER (PROVER-OUTPUT) "User-supplied code to initiate [events] This utility is intended for system hackers, not standard ACL2 users. See [finalize-event-user] to see how to supply code to be run at the end of [events]. We assume familiarity with finalize-event-user; here we focus on how to supply code for the beginning as well as the end of events. As with [finalize-event-user], you attach your own function of argument list (ctx qbody state) to initialize-event-user. (See [finalize-event-user] for discussion of ctx and body.) The attachment should return state and have a trivial guard, requiring (implicitly) only that state satisfies state-p unless you use trust tags to avoid that requirement. For example: (defattach initialize-event-user initialize-event-user-test) Why would you want to do this? Presumably you are building a system on top of ACL2 and you want to track your own data. For example, suppose you want to save the time in some [state] global variable, my-time. You could do the following. (defun my-init (ctx body state) (declare (xargs :stobjs state :guard-hints ((\"Goal\" :in-theory (enable read-run-time)))) (ignore ctx body)) (mv-let (seconds state) (read-run-time state) (f-put-global 'start-time seconds state))) (defun my-final (ctx body state) (declare (xargs :stobjs state :guard-hints ((\"Goal\" :in-theory (enable read-run-time)))) (ignore ctx body)) (mv-let (seconds state) (read-run-time state) (prog2$ (if (boundp-global 'start-time state) (cw \"Time: ~x0 seconds~%\" (- seconds (fix (@ start-time)))) (cw \"BIG SURPRISE!~%\")) (f-put-global 'end-time seconds state)))) (defattach initialize-event-user my-init) (defattach finalize-event-user my-final) Here is an abbreviated log, showing the time being printed at the end. ACL2 !>(thm (equal (append (append x y) x y x y x y x y) (append x y x y x y x y x y))) *1 (the initial Goal, a key checkpoint) is pushed for proof by induction. .... ACL2 Error in ( THM ...): See :DOC failure. ******** FAILED ******** Time: 869/100 seconds ACL2 !>") (INSTRUCTIONS (PROOF-CHECKER) "Instructions to the proof checker See [proof-checker] for an introduction to the interactive ``proof-checker'' goal manager, which supports much more direct control of the proof process than is available by direct calls to the prover (as are normally made using [defthm] or [thm]). In brief, typical use is to evaluate the form (verify SOME-GOAL), where SOME-GOAL is a formula (i.e., term) that you would like to prove. Various commands (instructions) are available at the resulting prompt; see [proof-checker-commands]. When the proof is completed, suitable invocation of the exit command will print out a form containing an :instructions field that provides the instructions that you gave interactively, so that this form can be evaluated non-interactively. Thus, also see [defthm] for the role of :instructions in place of :[hints]. As illustrated by the following example, the value associated with :instructions is a list of [proof-checker] commands. Example: (defthm associativity-of-append (equal (append (append x y) z) (append x (append y z))) :instructions (:induct (:dv 1) (:dv 1) :x :up :x (:dv 2) := (:drop 2) :top (:dv 2) :x :top :s :bash)) See [proof-checker-commands] for a list of supported proof-checker instructions and links to their documentation. Below, we describe a capability for supplying :instructions as :[hints]. The most basic utilities for directing the discharge of a proof obligation are :[hints] and (less commonly) :instructions. Individual instructions may call the prover with :hints; in that sense, prover hints may occur inside instructions. We now describe how, on the other hand, instructions may occur inside hints. ACL2 supports :instructions as a hints keyword. The following example forms the basis for our running example. This example does not actually need hints, but imagine that the inductive step --- which is \"Subgoal *1/2\" --- was difficult. You could submit that goal to [verify], do an interactive proof, submit (exit t) to obtain the list of :instructions, and then paste in those instructions. When you submit the resulting event, you might see the following. Below we'll explain the hint processing. ACL2 !>(thm (equal (append (append x y) z) (append x (append y z))) :hints ((\"Subgoal *1/2\" :instructions (:promote (:dv 1) (:dv 1) :x :up :x (:dv 2) := (:drop 2) :top (:dv 2) :x :top :s)))) Name the formula above *1. Perhaps we can prove *1 by induction. Three induction schemes are suggested by this conjecture. Subsumption reduces that number to two. However, one of these is flawed and so we are left with one viable candidate. We will induct according to a scheme suggested by (BINARY-APPEND X Y). This suggestion was produced using the :induction rule BINARY-APPEND. If we let (:P X Y Z) denote *1 above then the induction scheme we'll use is (AND (IMPLIES (AND (NOT (ENDP X)) (:P (CDR X) Y Z)) (:P X Y Z)) (IMPLIES (ENDP X) (:P X Y Z))). This induction is justified by the same argument used to admit BINARY-APPEND. When applied to the goal at hand the above induction scheme produces two nontautological subgoals. [Note: A hint was supplied for our processing of the goal below. Thanks!] Subgoal *1/2 (IMPLIES (AND (NOT (ENDP X)) (EQUAL (APPEND (APPEND (CDR X) Y) Z) (APPEND (CDR X) Y Z))) (EQUAL (APPEND (APPEND X Y) Z) (APPEND X Y Z))). But the trusted :CLAUSE-PROCESSOR function PROOF-CHECKER-CL-PROC replaces this goal by T. Subgoal *1/1 (IMPLIES (ENDP X) (EQUAL (APPEND (APPEND X Y) Z) (APPEND X Y Z))). By the simple :definition ENDP we reduce the conjecture to Subgoal *1/1' (IMPLIES (NOT (CONSP X)) (EQUAL (APPEND (APPEND X Y) Z) (APPEND X Y Z))). But simplification reduces this to T, using the :definition BINARY-APPEND and primitive type reasoning. That completes the proof of *1. Q.E.D. Summary Form: ( THM ...) Rules: ((:DEFINITION BINARY-APPEND) (:DEFINITION ENDP) (:DEFINITION NOT) (:FAKE-RUNE-FOR-TYPE-SET NIL) (:INDUCTION BINARY-APPEND)) Time: 0.02 seconds (prove: 0.01, print: 0.01, other: 0.00) Proof succeeded. ACL2 !> To understand how the :instructions supplied above were processed, observe proof-checker instruction interpreter may be viewed as a ``clause-processor'': a function that takes an input goal and returns a list of goals (which can be the empty list). Such a function has the property that if all goals in that returned list are theorems, then so is the input goal. This view of the proof-checker instruction interpreter as a clause-processor leads to the following crucial observation. IMPORTANT!. Each call of the proof-checker instruction interpreter is treated as a standalone clause-processor that is insensitive to the surrounding prover environment. In particular: * The proof-checker's theory is not sensitive to :in-theory [hints] already processed in the surrounding proof. Indeed, the current theory for which proof-checker commands are processed is just the current theory of the ACL2 logical [world], i.e., the value of (current-theory :here). Moreover, references to (current-theory :here) in a proof-checker in-theory command, even implicit references such as provided by [enable] and [disable] expressions, are also references to the current theory of the ACL2 logical [world]. * The [rune]s used during an :instructions hint are not tracked beyond that hint, hence may not show up in the summary of the overall proof. Again, think of the :instructions hint as a [clause-processor] call, which has some effect not tracked by the surrounding proof other than for the child goals that it returns. We continue now with our discussion of the proof-checker instruction interpreter as a clause-processor. In the example above, the input goal (\"Subgoal *1/2\") was processed by the proof-checker instruction interpreter. The result was the empty goal stack, therefore proving the goal, as reported in the output, which we repeat here. [Note: A hint was supplied for our processing of the goal below. Thanks!] Subgoal *1/2 (IMPLIES (AND (NOT (ENDP X)) (EQUAL (APPEND (APPEND (CDR X) Y) Z) (APPEND (CDR X) Y Z))) (EQUAL (APPEND (APPEND X Y) Z) (APPEND X Y Z))). But the trusted :CLAUSE-PROCESSOR function PROOF-CHECKER-CL-PROC replaces this goal by T. Remark. This brief remark can probably be ignored, but we include it for completeness. The :CLAUSE-PROCESSOR message above may be surprising, since the hint attached to \"Subgoal *1/2\" is an :instructions hint, not a :clause-processor hint. But :instructions is actually a custom keyword hint (see [custom-keyword-hints]), and may be thought of as a macro that expands to a :[clause-processor] hint, one that specifies proof-checker-cl-proc as the clause-processor function. The keen observer may notice that the clause-processor is referred to as ``trusted'' in the above output. Normally one needs a trust tag (see [defttag]) to install a trusted clause-processor, but that is not the case for the built-in clause-processor, proof-checker-cl-proc. Finally, we note that :instructions [hints] are ``spliced'' into the hints as follows: the appropriate :[clause-processor] hint replaces the :instructions hint, and the other hints remain intact. It may seems surprising that one can thus, for example, use :instructions and :in-theory together; but although the :in-theory hint will have no effect on execution of the :instructions (see first bullet above), the :in-theory hint will apply in the usual manner to any child goals (see [hints-and-the-waterfall]). End of Remark. Now consider the case that the supplied instructions do not prove the goal. That is, suppose that the execution of those instructions results in a non-empty goal stack. In that case, the resulting goals become children of the input goals. The following edited log provides an illustration using a modification of the above example, this time with a single instruction that splits into two cases. ACL2 !>(thm (equal (append (append x y) z) (append x (append y z))) :hints ((\"Subgoal *1/2\" :instructions ((:casesplit (equal x y)))))) [[ ... output omitted ... ]] Subgoal *1/2 (IMPLIES (AND (NOT (ENDP X)) (EQUAL (APPEND (APPEND (CDR X) Y) Z) (APPEND (CDR X) Y Z))) (EQUAL (APPEND (APPEND X Y) Z) (APPEND X Y Z))). We now apply the trusted :CLAUSE-PROCESSOR function PROOF-CHECKER-CL-PROC to produce two new subgoals. Subgoal *1/2.2 [[ ... output omitted ... ]] Subgoal *1/2.1 [[ ... output omitted ... ]] We have seen that an :instructions hint may produce zero or more subgoals. There may be times where you wish to insist that it produce zero subgoals, i.e., that it prove the desired goal. The proof-checker `finish' command works nicely for this purpose. For example, the following form is successfully admitted, but if you delete some of the commands (for example, the :s command at the end), you will see an informative error message. (thm (equal (append (append x y) z) (append x (append y z))) :hints ((\"Subgoal *1/2\" :instructions ((finish :promote (:dv 1) (:dv 1) :x :up :x (:dv 2) := (:drop 2) :top (:dv 2) :x :top :s))))) If an :instructions hint of the form ((finish ...)) fails to prove the goal, the clause-processor is deemed to have caused an error. Indeed, any ``failure'' of a supplied proof-checker instruction will be deemed to cause an error. In this case, you should see an error message such as the following: Saving proof-checker error state; see :DOC instructions. To retrieve: (RETRIEVE :ERROR1) In this case, you can evaluate the indicated [retrieve] command in the ACL2 read-eval-print loop, to get to the point of failure. You may have noticed that there is no output from the proof-checker in the examples above. This default behavior prevents confusion that could arise from use of proof-checker commands that call the theorem prover such as prove, bash, split, and induct. These commands produce output for what amounts to a fresh proof attempt, which could confuse attempts to understand the surrounding proof log. You can override the default behavior by providing a command of the form (comment inhibit-output-lst VAL) where VAL is either the keyword :SAME (indicating that no change should be made to which output is inhibited) or else is a legal value for inhibited output; see [set-inhibit-output-lst]. The following two variants of the immediately preceding THM form will each produce output from the proof-checker commands, assuming in the first variant that output hasn't already been inhibited. (thm (equal (append (append x y) z) (append x (append y z))) :hints ((\"Subgoal *1/2\" :instructions ((comment inhibit-output-lst :same) (:casesplit (equal x y)))))) (thm (equal (append (append x y) z) (append x (append y z))) :hints ((\"Subgoal *1/2\" :instructions ((comment inhibit-output-lst (proof-tree)) (:casesplit (equal x y)))))) Note that such a comment instruction must be provided explicitly (i.e., not by way of a proof-checker [macro-command]) as the first instruction, in order to have the effect on inhibited output that is described above. The following contrived example gives a sense of how one might want to use :instructions within :[hints]. If you submit the following theorem (thm (implies (true-listp x) (equal (reverse (reverse x)) x))) then you will see the following checkpoint printed with the summary. Subgoal *1/3'' (IMPLIES (AND (CONSP X) (EQUAL (REVAPPEND (REVAPPEND (CDR X) NIL) NIL) (CDR X)) (TRUE-LISTP (CDR X))) (EQUAL (REVAPPEND (REVAPPEND (CDR X) (LIST (CAR X))) NIL) X)) This suggests proving the following theorem. Here we state it using [defthmd], so that it is immediately disabled. Normally disabling would be unnecessary, but for our contrived example it is useful to imagine disabling it, say because we are following a methodology that tends to keep [rewrite] rules disabled. (defthmd revappend-revappend (equal (revappend (revappend x y) z) (revappend y (append x z)))) We might then enter the [proof-checker] to prove the original theorem interactively, as follows. ACL2 !>(verify (implies (true-listp x) (equal (reverse (reverse x)) x))) ->: bash ***** Now entering the theorem prover ***** Goal' ([ A key checkpoint: Goal' (IMPLIES (TRUE-LISTP X) (EQUAL (REVAPPEND (REVAPPEND X NIL) NIL) X)) Goal' is subsumed by a goal yet to be proved. ]) Q.E.D. Creating one new goal: (MAIN . 1). The proof of the current goal, MAIN, has been completed. However, the following subgoals remain to be proved: (MAIN . 1). Now proving (MAIN . 1). ->: th ; show current goal (\"th\" for \"theorem\") *** Top-level hypotheses: 1. (TRUE-LISTP X) The current subterm is: (EQUAL (REVAPPEND (REVAPPEND X NIL) NIL) X) ->: p ; show current subterm only (EQUAL (REVAPPEND (REVAPPEND X NIL) NIL) X) ->: 1 ; dive to first argument ->: p (REVAPPEND (REVAPPEND X NIL) NIL) ->: sr ; show-rewrites 1. REVAPPEND-REVAPPEND (disabled) New term: (REVAPPEND NIL (APPEND X NIL)) Hypotheses: Equiv: EQUAL 2. REVAPPEND New term: (AND (CONSP (REVAPPEND X NIL)) (REVAPPEND (CDR (REVAPPEND X NIL)) (LIST (CAR (REVAPPEND X NIL))))) Hypotheses: Equiv: EQUAL ->: (r 1) ; rewrite with rule #1 above Rewriting with REVAPPEND-REVAPPEND. ->: p (REVAPPEND NIL (APPEND X NIL)) ->: top ; move to the top of the conclusion, making it the current subterm ->: p (EQUAL (REVAPPEND NIL (APPEND X NIL)) X) ->: prove ; finish the proof ***** Now entering the theorem prover ***** Q.E.D. *!*!*!*!*!*!* All goals have been proved! *!*!*!*!*!*!* You may wish to exit. ->: (exit t) ; the argument, t, causes :instructions to be printed (DEFTHM T (IMPLIES (TRUE-LISTP X) (EQUAL (REVERSE (REVERSE X)) X)) :INSTRUCTIONS (:BASH (:DV 1) (:REWRITE REVAPPEND-REVAPPEND) :TOP :PROVE)) NIL ACL2 !>(thm (IMPLIES (TRUE-LISTP X) (EQUAL (REVERSE (REVERSE X)) X)) :hints ((\"Goal\" :INSTRUCTIONS ; copy what was printed above: (:BASH (:DV 1) (:REWRITE REVAPPEND-REVAPPEND) :TOP :PROVE)))) Goal' Q.E.D. Q.E.D. Q.E.D. Summary Form: ( THM ...) Rules: NIL Hint-events: ((:CLAUSE-PROCESSOR PROOF-CHECKER-CL-PROC)) Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) Proof succeeded. ACL2 !> Finally we present an even more contrived example, based on the one above. This example illustrates that there is actually no limit imposed on the nesting of :instructions within :[hints] within :instructions, and so on. Notice the indication of nesting levels: ``1>'' to ``<1'' for output from nesting level 1, and ``2>'' to ``<2'' for output from nesting level 2. (thm (implies (true-listp x) (equal (reverse (reverse x)) x)) :hints ((\"Goal\" :instructions ((comment inhibit-output-lst :same) (:prove :hints ((\"Goal\" :in-theory (disable append)) (\"Subgoal *1/3''\" :instructions ((comment inhibit-output-lst :same) :bash (:dv 1) (:rewrite revappend-revappend))))))))) Here is an edited version of the resulting log. [Note: A hint was supplied for our processing of the goal above. Thanks!] [[1> Executing proof-checker instructions]] ->: (COMMENT INHIBIT-OUTPUT-LST :SAME) ->: (:PROVE :HINTS ((\"Goal\" :IN-THEORY (DISABLE APPEND)) (\"Subgoal *1/3''\" :INSTRUCTIONS ((COMMENT INHIBIT-OUTPUT-LST :SAME) :BASH (:DV 1) (:REWRITE REVAPPEND-REVAPPEND))))) ***** Now entering the theorem prover ***** [[ ... output omitted ... ]] [Note: A hint was supplied for our processing of the goal below. Thanks!] Subgoal *1/3'' (IMPLIES (AND (CONSP X) (EQUAL (REVAPPEND (REVAPPEND (CDR X) NIL) NIL) (CDR X)) (TRUE-LISTP (CDR X))) (EQUAL (REVAPPEND (REVAPPEND (CDR X) (LIST (CAR X))) NIL) X)). [[2> Executing proof-checker instructions]] ->: (COMMENT INHIBIT-OUTPUT-LST :SAME) ->: :BASH ***** Now entering the theorem prover ***** [Note: A hint was supplied for our processing of the goal above. Thanks!] But we have been asked to pretend that this goal is subsumed by the yet-to-be-proved |PROOF-CHECKER Goal|. Q.E.D. Creating one new goal: (MAIN . 1). The proof of the current goal, MAIN, has been completed. However, the following subgoals remain to be proved: (MAIN . 1). Now proving (MAIN . 1). ->: (:DV 1) ->: (:REWRITE REVAPPEND-REVAPPEND) Rewriting with REVAPPEND-REVAPPEND. [[<2 Completed proof-checker instructions]] We now apply the trusted :CLAUSE-PROCESSOR function PROOF-CHECKER-CL-PROC to produce one new subgoal. Subgoal *1/3''' [[ ... output omitted ... ]] [[<1 Completed proof-checker instructions]] The nesting levels are independent of whether or not output is enabled; for example, if the first (comment ...) form below is omitted, then we will see only the output bracketed by ``2>'' to ``<2''. Note also that these levels are part of the error states saved for access by [retrieve] (as indicated above); for example, a failure at level 1 would be associated with symbol :ERROR1 as indicated above, while a failure at level 2 would be associated with symbol :ERROR2.") (INT= (NUMBERS ACL2-BUILT-INS) "Test equality of two integers (int= x y) is logically equivalent to (equal x y). Unlike [equal], int= requires its arguments to be numbers (or else causes a [guard] violation; see [guard]). Generally, int= is executed more efficiently than [equal] or [=] on integers. Macro: (defmacro int= (i j) (list 'eql (if (integerp i) i (list 'the 'integer i)) (if (integerp j) j (list 'the 'integer j))))") (INTEGER-LENGTH (NUMBERS ACL2-BUILT-INS) "Number of bits in two's complement integer representation For non-negative integers, (integer-length i) is the minimum number of bits needed to represent the integer. Any integer can be represented as a signed two's complement field with a minimum of (+ (integer-length i) 1) bits. The [guard] for integer-length requires its argument to be an integer. Integer-length is defined in Common Lisp. See any Common Lisp documentation for more information. Function: (defun integer-length (i) (declare (xargs :guard (integerp i))) (if (zip i) 0 (if (= i -1) 0 (+ 1 (integer-length (floor i 2))))))") (INTEGER-LISTP (NUMBERS LISTS ACL2-BUILT-INS) "Recognizer for a true list of integers The predicate integer-listp tests whether its argument is a true list of integers. Function: (defun integer-listp (l) (declare (xargs :guard t)) (cond ((atom l) (eq l nil)) (t (and (integerp (car l)) (integer-listp (cdr l))))))") (INTEGER-RANGE-P (NUMBERS ACL2-BUILT-INS) "Recognizer for integers between two bounds. The predicate (integer-range-p lower upper x) tests whether x is an integer greater than or equal to lower and less than upper. Function: (defun integer-range-p (lower upper x) (declare (xargs :guard (and (integerp lower) (integerp upper)))) (and (integerp x) (<= lower x) (< x upper)))") (INTEGERP (NUMBERS ACL2-BUILT-INS) "Recognizer for whole numbers (integerp x) is true if and only if x is an integer.") (INTERESTING-APPLICATIONS (ACL2-TUTORIAL) "Some industrial examples of ACL2 use ACL2 is an interactive system in which you can model digital artifacts and guide the system to mathematical proofs about the behavior of those models. It has been used at such places as AMD, Centaur, IBM, and Rockwell Collins to verify interesting properties of commercial designs. It has been used to verify properties of models of microprocessors, microcode, the Sun Java Virtual Machine, operating system kernels, other verifiers, and interesting algorithms. Here we list just a few of the industrially-relevant results obtained with ACL2. Reading the list may help you decide you want to learn how to use ACL2. If you do decide you want to learn more, we recommend that you take [The Tours] after you leave this page. ACL2 was used at Motorola Government Systems to certify several microcode programs for the Motorola CAP digital signal processor, including a comparator sort program that is particularly subtle. In the same project, ACL2 was used to model the CAP at both the pipelined architectural level and the instruction set level. The architectural model was bit- and cycle-accurate: it could be used to predict every bit of memory on every cycle. The models were proved equivalent under certain hypotheses, the most important being a predicate that analyzed the microcode for certain pipeline hazards. This predicate defined what the hazards were, syntactically, and the equivalence of the two models established the correctness of this syntactic characterization of hazards. Because ACL2 is a functional programming language, the ACL2 models and the hazard predicate could be executed. ACL2 executed microcode interpretr several times faster than the hardware simulator could execute it -- with assurance that the answers were equivalent. In addition, the ACL2 hazard predicate was executed on over fifty microcode programs written by Motorola engineers and extracted from the ROM mechanically. Hazards were found in some of these. (See, for example, Bishop Brock and Warren. A. Hunt, Jr. ``Formal analysis of the motorola CAP DSP.'' In Industrial-Strength Formal Methods. Springer-Verlag, 1999.) ACL2 was used at Advanced Micro Devices (AMD) to verify the compliance of the AMD Athon's (TM) elementary floating point operations with their IEEE 754 specifications. This followed ground-breaking work in 1995 when ACL2 was used to prove the correctness of the microcode for floating-point division on the AMD K5. The AMD Athlon work proved addition, subtraction, multiplication, division, and square root compliant with the IEEE standard. Bugs were found in RTL designs. These bugs had survived undetected in hundreds of millions of tests but were uncovered by ACL2 proof attempts. The RTL in the fabricated Athlon FPU has been mechanically verified by ACL2. Similar ACL2 proofs have been carried out for every major AMD FPU design fabricated since the Athlon. (See for example, David Russinoff. ``A mechanically checked proof of correctness of the AMD5K86 floating-point square root microcode''. Formal Methods in System Design Special Issue on Arithmetic Circuits, 1997.) ACL2 was used at IBM to verify the floating point divide and square root on the IBM Power 4. (See Jun Sawada. ``Formal verification of divide and square root algorithms using series calculation''. In Proceedings of the ACL2 Workshop 2002, Grenoble, April 2002.) ACL2 was used to verify floating-point addition/subtraction instructions for the media unit from Centaur Technology's 64-bit, X86-compatible microprocessor. This unit implements over one hundred instructions, with the most complex being floating-point addition/subtraction. The media unit can add/subtract four pairs of floating-point numbers every clock cycle with an industry-leading two-cycle latency. The media unit was modeled by translating its Verilog design into an HDL deeply embedded in the ACL2 logic. The proofs used a combination of AIG- and BDD-based symbolic simulation, case splitting, and theorem proving. (See Warren A. Hunt, Jr. and Sol Swords. ``Centaur Technology Media Unit Verification''. In CAV '09: Proceedings of the 21st International Conference on Computer Aided Verification, pages 353--367, Berlin, Heidelberg, 2009. Springer-Verlag.) Rockwell Collins used ACL2 to prove information flow properties about its Advanced Architecture MicroProcessor 7 Government Version (AAMP7G), a Multiple Independent Levels of Security (MILS) device for use in cryptographic applications. The AAMP7G provides MILS capability via a verified secure hardware-based separation kernel. The AAMP7G's design was proved to achieve MILS using ACL2, in accordance with the standards set by EAL-7 of the Common Criteria and Rockwell Collins has received National Security Agency (NSA) certification for the device based on this work. (See Matthew M. Wilding, David A. Greve, Raymond J. Richards, and David S. Hardin. ``Formal Verification of Partition Management for the AAMP7G Microprocessor''. In Design and Verification of Microprocessor Systems for High-Assurance Applications, David S. Hardin, ed., pages 175--191, Springer US, 2010.) Key properties of the Sun Java Virtual Machine and its bytecode verifier were verified in ACL2. Among the properties proved were that certain invariants are maintained by class loading and that the bytecode verifier insures that execution is safe. In addition, various JVM bytecode programs have been verified using this model of the JVM. (See Hanbing Liu. Formal Specification and Verification of a JVM and its Bytecode Verifier. PhD thesis, University of Texas at Austin, 2006.) The Boyer-Moore fast string searching algorithm was verified with ACL2, including a model of the JVM bytecode for the search algorithm itself (but not the preprocessing). (See J S. Moore and Matt Martinez. ``A mechanically checked proof of the correctness of the Boyer-Moore fast string searching algorithm.'' In Engineering Methods and Tools for Software Safety and Security pages 267--284. IOS Press, 2009.) ACL2 was used to verify the fidelity between an ACL2-like theorem prover and a simple (``trusted by inspection'') proof checker, thereby establishing (up to the soundness of ACL2) the soundness of the ACL2-like theorem prover. This project was only part of a much larger project in which the resulting ACL2 proof script was then hand-massaged into a script suitable for the ACL2-like theorem prover to process, generating a formal proof of its fidelity that has been checked by the trusted proof checker. (See Jared Davis. Milawa: A Self-Verifying Theorem Prover. Ph.D. Thesis, University of Texas at Austin, December, 2009.) These are but a few of the interesting projects carried out with ACL2. Many of the authors mentioned above have versions of the papers on their web pages. In addition, see {Books and Papers about ACL2 and its Applications | http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html}. Also, see the presentations in each of the {ACL2 Workshops | http://www.cs.utexas.edu/users/moore/acl2/workshops.html}.") (INTERFACING-TOOLS (TOP ACL2) "Libraries and tools for doing basic [file i/o], using raw [Common Lisp libraries], working with the [operating system], and interfacing with [other programs]. Subtopics [Command-line] Handling of command-line arguments when ACL2 is invoked [Defttag] Introduce a trust tag (ttag) [Io] Input/output facilities in ACL2 [Save-exec] Save an executable image and a wrapper script [Sys-call] Make a system call to the host operating system") (INTERN (SYMBOLP PACKAGES ACL2-BUILT-INS) "Create a new symbol in a given package (intern symbol-name symbol-package-name) returns a symbol with the given [symbol-name] and the given [symbol-package-name]. We restrict Common Lisp's intern so that the second argument is either the symbol *main-lisp-package-name*, the value of that constant, or is one of \"ACL2\", \"ACL2-INPUT-CHANNEL\", \"ACL2-OUTPUT-CHANNEL\", or \"KEYWORD\". To avoid that restriction, see [intern$]. In ACL2 intern is actually implemented as a macro that expands to a call of a similar function whose second argument is a symbol. Invoke :pe intern to see the definition, or see [intern-in-package-of-symbol]. To see why is intern so restricted consider (intern \"X\" \"P\"). In particular, is it a symbol and if so, what is its [symbol-package-name]? One is tempted to say ``yes, it is a symbol in the package \"P\".'' But if package \"P\" has not yet been defined, that would be premature because the imports to the package are unknown. For example, if \"P\" were introduced with (defpkg \"P\" '(LISP::X)) then in Common Lisp (symbol-package-name (intern \"X\" \"P\")) returns \"LISP\". The obvious restriction on intern is that its second argument be the name of a package known to ACL2. We cannot express such a restriction (except, for example, by limiting it to those packages known at some fixed time, as we do). Instead, we provide [intern-in-package-of-symbol] which requires a ``witness symbol'' for the package instead of the package. The witness symbol is any symbol (expressible in ACL2) and uniquely specifies a package necessarily known to ACL2.") (INTERN$ (SYMBOLP PACKAGES ACL2-BUILT-INS) "Create a new symbol in a given package Intern$ is a macro that behaves the same as the macro [intern], except for weakening the restriction to a fixed set of package names so that any package name other than \"\" is legal. See [intern]. Note that if you evaluate a call (intern$ x y) for which there is no package with name y that is known to ACL2, you will get an error. (Intern$ x y) expands to: (intern-in-package-of-symbol x (pkg-witness y)) See [intern-in-package-of-symbol] and see [pkg-witness].") (INTERN-IN-PACKAGE-OF-SYMBOL (SYMBOLP PACKAGES ACL2-BUILT-INS) "Create a symbol with a given name Completion Axiom (completion-of-intern-in-package-of-symbol): (equal (intern-in-package-of-symbol x y) (if (and (stringp x) (symbolp y)) (intern-in-package-of-symbol x y) nil)) [Guard] for (intern-in-package-of-symbol x y): (and (stringp x) (symbolp y)) Intuitively, (intern-in-package-of-symbol x y) creates a symbol with [symbol-name] x [intern]ed in the package containing y. More precisely, suppose x is a string, y is a symbol with [symbol-package-name] pkg and that the [defpkg] event creating pkg had the list of symbols imports as the value of its second argument. Then (intern-in-package-of-symbol x y) returns a symbol, ans, the [symbol-name] of ans is x, and the [symbol-package-name] of ans is pkg, unless x is the [symbol-name] of some member of imports with [symbol-package-name] ipkg, in which case the [symbol-package-name] of ans is ipkg. Because [defpkg] requires that there be no duplications among the [symbol-name]s of the imports, intern-in-package-of-symbol is uniquely defined. For example, suppose \"MY-PKG\" was created by (defpkg \"MY-PKG\" '(ACL2::ABC LISP::CAR)). Let w be 'my-pkg::witness. Observe that (symbolp w) is t ; w is a symbol (symbol-name w) is \"WITNESS\" ; w's name is \"WITNESS\" (symbol-package-name w) is \"MY-PKG\" ; w is in the package \"MY-PKG\" The construction of w illustrates one way to obtain a symbol in a given package: write it down as a constant using the double-colon notation. But another way to obtain a symbol in a given package is to create it with intern-in-package-of-symbol. (intern-in-package-of-symbol \"XYZ\" w) is MY-PKG::XYZ (intern-in-package-of-symbol \"ABC\" w) is ACL2::ABC (intern-in-package-of-symbol \"CAR\" w) is LISP::CAR (intern-in-package-of-symbol \"car\" w) is MY-PKG::|car|") (INTERSECTION$ (LISTS ACL2-BUILT-INS) "Elements of one list that are not elements of another General Forms: (intersection$ l1 l2 ... lk) (intersection$ l1 l2 ... lk :test 'eql) ; same as above (intersection$ l1 l2 ... lk :test 'eq) ; same, but eq is equality test (intersection$ l1 l2 ... lk :test 'equal) ; same, but equal is equality test (Intersection$ x y) equals a list that contains the members of x that are also members of y. More precisely, the resulting list is the result of deleting from x those members that that are not members of y. The optional keyword, :TEST, has no effect logically, but provides the test (default [eql]) used for comparing members of the two lists. Intersection$ need not take exactly two arguments, though it must take at least one argument: (intersection$ x) is x, (intersection$ x y z ... :test test) is (intersection$ x (intersection$ y z ... :test test) :test test), and if :TEST is not supplied, then (intersection$ x y z ...) is (intersection$ x (intersection$ y z ...)). For the discussion below we restrict ourselves, then, to the cases (intersection$ x y) and (intersection$ x y :test test). The [guard] for a call of intersection$ (in the two cases just above) depends on the test. In all cases, both arguments must satisfy [true-listp]. If the test is [eql], then one of the arguments must satisfy [eqlable-listp]. If the test is [eq], then one of the arguments must satisfy [symbol-listp]. See [equality-variants] for a discussion of the relation between intersection$ and its variants: (intersection-eq x lst) is equivalent to (intersection$ x lst :test 'eq); (intersection-equal x lst) is equivalent to (intersection$ x lst :test 'equal). In particular, reasoning about any of these primitives reduces to reasoning about the function intersection-equal. Note that intersection-eq can take any positive number of arguments, in analogy to intersection$; indeed, (intersection-eq ...) expands to (intersection$ ... :test 'eq). However, intersection-equal is a function, not a macro, and takes exactly two arguments. Intersection$ is similar to the Common Lisp primitive intersection. However, Common Lisp does not specify the order of elements in the result of a call of intersection. Function: (defun intersection-equal (l1 l2) (declare (xargs :guard (and (true-listp l1) (true-listp l2)))) (cond ((endp l1) nil) ((member-equal (car l1) l2) (cons (car l1) (intersection-equal (cdr l1) l2))) (t (intersection-equal (cdr l1) l2))))") (INTERSECTION-EQ (POINTERS) "See [intersection$].") (INTERSECTION-EQUAL (POINTERS) "See [intersection$].") (INTERSECTION-THEORIES (THEORIES THEORY-FUNCTIONS) "Intersect two [theories] Example: (intersection-theories (current-theory :here) (theory 'arith-patch)) General Form: (intersection-theories th1 th2) where th1 and th2 are theories (see [theories]). To each of the arguments there corresponds a runic theory. This function returns the intersection of those two runic [theories], represented as a list and ordered chronologically. This ``function'' is actually a macro that expands to a term mentioning the single free variable [world]. When theory expressions are evaluated by [in-theory] or the :[in-theory] hint, [world] is bound to the current ACL2 [world].") (INTERSECTP (LISTS ACL2-BUILT-INS) "Test whether two lists intersect General Forms: (set-difference$ l1 l2) (set-difference$ l1 l2 :test 'eql) ; same as above (eql as equality test) (set-difference$ l1 l2 :test 'eq) ; same, but eq is equality test (set-difference$ l1 l2 :test 'equal) ; same, but equal is equality test (Intersectp l1 l2) returns t if l1 and l2 have a [member] in common, else it returns nil. The optional keyword, :TEST, has no effect logically, but provides the test (default [eql]) used for comparing members of the two lists. The [guard] for a call of intersectp depends on the test. In all cases, both arguments must satisfy [true-listp]. If the test is [eql], then one of the arguments must satisfy [eqlable-listp]. If the test is [eq], then one of the arguments must satisfy [symbol-listp]. See [equality-variants] for a discussion of the relation between intersectp and its variants: (intersectp-eq x lst) is equivalent to (intersectp x lst :test 'eq); (intersectp-equal x lst) is equivalent to (intersectp x lst :test 'equal). In particular, reasoning about any of these primitives reduces to reasoning about the function intersectp-equal. Function: (defun intersectp-equal (x y) (declare (xargs :guard (and (true-listp x) (true-listp y)))) (cond ((endp x) nil) ((member-equal (car x) y) t) (t (intersectp-equal (cdr x) y))))") (INTERSECTP-EQ (POINTERS) "See [intersectp].") (INTERSECTP-EQUAL (POINTERS) "See [intersectp].") (INTRODUCTION-TO-A-FEW-SYSTEM-CONSIDERATIONS (INTRODUCTION-TO-THE-THEOREM-PROVER) "The mechanics of interaction with the theorem prover ACL2 is implemented in Common Lisp. There are many different Common Lisps and they differ in details relating to interacting with the system. We sometimes refer to the host Common Lisp as ``raw Lisp.'' The new user is advised not to operate in raw Lisp as it is possible to, say, redefine ACL2 system faclities like defthm. Most people use Emacs (see [Emacs] [{ICON}]) or the ACL2 Sedan (Eclipse) interface (see [ACL2-Sedan] [{ICON}]). They provide protection against certain common mistakes, e.g., trying to edit a block of input text after the operating system has buffered it up and sent it to the Lisp reader which is parsing it as you type. More on this below. In addition, the Sedan provides helpful syntax checking and a disciplined approach to the stack of lemmas generated by The Method. But the variety of interfaces to the variety of Lisps mean that there is great variation in what one must type to interact with ACL2. The best example is perhaps trying to interrupt a running proof. If your host Common Lisp is GCL or Allegro and you are typing directly to the Common Lisp process, then you can interrupt a computation by typing ``ctrl-c'' (hold down the Control key and hit the ``c'' key once). But other Lisps may require some other control sequence. If you are typing to an Emacs process which is running the GCL or Allegro Common Lisp process in a shell buffer, you should type ctrl-c ctrl-c. If you are running the ACL2 Sedan, you can use the Interrupt Session button on the tool bar. The environment you enter when you interrupt depends on various factors and basically you should endeavor to get back to the top level ACL2 command loop, perhaps by typing some kind of Lisp depenent ``abort'' command like A or :q, or :abort!. You can usually determine what environment you're in by paying attention to the prompt, which we discuss below. The ACL2 ``interactive loop'' is called [lp] ([{ICON}]) and is generally invoked automatically from your Common Lisp when you start up the ACL2 process. LP is just a special case of an ACL2 function called [ld] [{ICON}], which the user can call from within the ACL2 interactive loop to enter the loop recursively. New users don't have to know this except that it helps explain why some commands have the string ``-ld-'' in their names! ACL2 presents itself as a ``read-eval-print'' loop: you're repeatedly prompted for some type-in, which is read, evaluated, and may cause some printing. The prompt tells you something about ACL2's state. In the standard environment, the prompt is ACL2 !> The ``ACL2'' tells you that the symbols you use in your command are those defined in the standard ACL2 namespace (or, in the jargon of Lisp, the ``current package,'' see [current-package] [{ICON}]). You could create a new namespace (see [defpkg] [{ICON}]) and set the current package to it (see [in-package] [{ICON}]). The next part of the prompt above (``!''), the exclamation mark) tells you that before ACL2 evaluates your type-in it will check to see whether [guard]s ([{ICON}]) are respected, i.e., whether the functions used in your command are being supplied arguments in their ``expected domains.'' If evaluation is allowed by the guards, it proceeds exactly according to the ACL2 axioms; if evaluation is not allowed, an error is signaled. ACL2 event commands check their arguments thoroughly at run-time, regardless of Lisp's notion of ``expected domains.'' If the exclamation mark is missing from the prompt, ACL2 > then evaluation occurs strictly according to the ACL2 axioms, without regard for any declared guards. You can switch between these two prompts by typing ACL2 !>:set-guard-checking nil to turn guard checking off and ACL2 >:set-guard-checking t to turn it on. Try typing (car 7) to each prompt. If there is a ``p'' in the prompt, ACL2 p!> with or without the exclamation mark: ACL2 p> it means you are in :[program] ([{ICON}]) mode rather than :[logic] ([{ICON}]) mode. In :program mode, defun just defines Common Lisp programs that you can evaluation but it adds no axioms and you cannot use such defined functions in theorems or invoke defthm. :Program mode is often used to prototype a model. Most commands are just typical parenthesized Lisp expressions, like ACL2 !>(defthm rev-rev (implies (true-listp x) (equal (rev (rev x)) x))) but some are typed as keywords followed by a certain number of arguments. For example, to undo the last event you may type ACL2 !>:u or to undo back through the introduction of rev you may type ACL2 !>:ubt rev The first is equivalent to evaluating (u) and the second is equivalent to evaluating (ubt 'rev). See [keyword-commands] [{ICON}]. So if you see a sentence like ``to turn on the break rewrite facility, execute :brr t,'' we mean type ACL2 !>:brr t or equivalently ACL2 !>(brr t) If you see a prompt that doesn't look like those above you are probably not typing commands to the standard ACL2 read-eval-print loop! If you've somehow called LD recursively, the prompt ``gets deeper,'' e.g., ACL2 !>> and you can pop out one level with :[q] [{ICON}] (for ``quit'') or pop to the outermost ACL2 loop with :abort! [{ICON}]. If you are in the outermost call of the ACL2 interactive loop and you type :q, you pop out into raw lisp. The prompt there is generally different from the ACL2 prompt but that is outside our our control and varies from Lisp to Lisp. We have arranged for many (but not all) Lisps to use a raw lisp prompt involving the string \"[RAW LISP]\". To get back into the ACL2 interactive loop from raw lisp, evaluate (LP). If you see a prompt that looks like an ACL2 prompt but has a number in front of it, e.g., 1 ACL2 > then you're talking to the break rewrite facility (and you are 1 level deep in the example above). Presumably at earlier time in this session you enabled that facility, with :brr t, installed a monitor on some rule, invoked the prover, entered the break, and forgot. Everything you have done (e.g., lemmas you might have proved with defthm) inside that break will be lost when you exit the break. Since the break rewrite facility is ``ours'' we can tell you how to exit it! To exit our breaks and return to the top-level ACL2 loop, execute :abort!. If you discover you've been working in a brr break, exit, turn off the break facility wih :brr nil, and redo whatever defuns and defthms you did while in that break. Users of the Emacs interface may occasionally type commands directly in the *shell* buffer running ACL2. This can be ``dangerous'' for two reasons. One is that if you type an event, like a defun or defthm, directly to the shell, it will not be recorded in your ``script'' buffer and you may forget it in your final script. The other is that if you attempt to edit a multi-line command on any but the most recent line, e.g., to correct the spelling of defthm below after you've typed the ``(implies (true-listp x)'' you will confuse the Lisp parser because it has already read ``(defth rev-rev''. ACL2 !>(defth rev-rev (implies (true-listp x) This usually provokes the raw Lisp to enter a low level error break from which you must abort, possibly reenter the ACL2 loop, and re-type the corrected command from scratch. Another common mistake when using interfaces other than the ACL2 Sedan is to type an ill-formed ACL2 expression containing dots or commas, which also often provokes a break into the raw Lisp's error handler. The fundamental lesson is that you should pay attention to the prompt and learn what the different prompts mean -- or use the ACL2 Sedan. If you have been working your way through the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-the-theorem-prover].") (INTRODUCTION-TO-HINTS (INTRODUCTION-TO-THE-THEOREM-PROVER) "How to provide hints to the theorem prover We assume you've read [introduction-to-rewrite-rules-part-1], [introduction-to-key-checkpoints], and [introduction-to-the-database]. You may give the theorem prover a hint that is specific to a particular subgoal generated during a proof attempt. Of course, you learn the name of the subgoal by inspecting the key checkpoints or other proof output. You are not expected to anticipate the need for hints at specific subgoals; instead, you usually deduce that a hint is required because the subgoals is not proved but you see that existing rules and context make it provable. The most common hint is to enable and/or disable a particular rule on some particular subgoal. (defthm name formula :hints ((\"Subgoal *1/3.2''\" :in-theory (disable nth-nthcdr)))) The hint above tells the rewriter that just before it begins to work on Subgoal *1/3.2'' it should switch to a local theory in which all of the rules generated from the event nth-nthcdr are disabled. That local theory remains the one in use for all descendent subgoals generated from the one named, until and unless one of those descendent subgoals has an :in-theory hint associated with it. There are many kinds of hints besides :in-theory and in general, after each subgoal name, you can give various forms of advice and list various adjustments you wish to make to the context in which the prover is operating when it begins addressing the subgoal named. The top-level goal is always named Goal. Thus (defthm name formula :hints ((\"Goal\" ...hints1...) (\"Subgoal *1/3.2''\" ...hints2...))) has the effect of using hints1 for the top-level goal and all of its children throughout the entire proof, except for Subgoal *1/3.2'' and its children, where hints2 is used instead. There are a few hints which ``take effect'' exactly on the subgoal to which they are attached and are not inherited by their descendents. Here is an incomplete list of some of the more common hints; we note the ones that do not pass on their effects to their descendents. We recommend that you not follow the advanced links (marked ``[{ICON}]'') below until you have read the entire tutorial. See [in-theory] [{ICON}] for how to enable and/or disable rules. The new theory is computed by a ``theory expression'' (see [theories] [{ICON}]) such as (disable nth-nthcdr) and typically makes adjustments such as additions or deletions to the global current theory. All the relevant new theories are computed before the proof begins. Thus, in (defthm name formula :hints ((\"Goal\" :in-theory (disable rule1)) (\"Subgoal *1/3.2''\" (disable rule2)))) the theory mentioned for Goal is the global current theory minus rule1, while the theory mentioned for its descendent, Subgoal *1/3.2'', is the global current theory minus rule2. In particular, if both rule1 and rule2 are enabled in the global current theory, then rule1 is enabled during the processing of Subgoal *1/3.2'' because it was not removed explicitly there. See [use] [{ICON}] for how to force the theorem prover to take note of particular instances of particular theorems; in particular, the instances are created and added as hypotheses to the subgoal in question. The hint is not inherited by the descendents of the subgoal (since the formula being proved has been modified by the hint). If the rule you are using (with a :use hint) is an enabled rewrite rule, it might interfere with the added hypothesis -- by rewriting itself to T -- and thus often you will both :use ... and :in-theory (disable ...). See [expand] [{ICON}] for how to tell the theorem prover to expand one or more function calls whenever encountered. See [cases] [{ICON}] for how to force the theorem prover to do a case split to prove the subgoal under each of an exhaustive list of cases given in the hint. This hint takes action specifically at the named subgoal and is not passed down to its children. See [induct] [{ICON}] for how to tell the theorem prover to go immediately into induction for the subgoal in question, and to use the induction scheme suggested by the hint rather than the one suggested by the terms in the subgoal itself. This hint is not inherited by its descendents. See [hints] [{ICON}] for a complete list of all hints, and see [hints-and-the-waterfall] [{ICON}] for a more thorough description of how the effects of hints at a subgoal are inherited by the descendents. If you are reading this as part of the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-the-theorem-prover].") (INTRODUCTION-TO-KEY-CHECKPOINTS (INTRODUCTION-TO-THE-THEOREM-PROVER) "What questions to ask at key checkpoints We assume you've read about rewrite rules; see [introduction-to-rewrite-rules-part-1]. When a proof attempt fails, ACL2 prints some key checkpoints. These are formulas that we think you should look at. There are two kinds printed: key checkpoints before an induction, and key checkpoints under a top-level induction. (Key checkpoints under deeper inductions and checkpoints that aren't considered ``key'' may exist in the proof attempt, but ACL2 doesn't print them at the end of failed proofs because you shouldn't be distracted by them.) Below is a list of questions to ask yourself about the key checkpoints. Initially, we recommend just picking one key checkpoint before an induction (perhaps the simplest looking one) and asking these questions. These questions may lead you to look at other key checkpoints. As you gain more experience you'll elaborate and generalize this advice. (1) Do you believe this formula is a theorem? If you don't think it is, it's pointless to try to prove it! You should reconsider your top-level formula in light of the special case suggested by this key checkpoint. (2) Can it be simplified? Is there some combination of function symbols in it that could be eliminated or simplified by exploiting some simpler fact? By a ``simpler fact'' we mean a theorem about a few of the symbols in this formula. For an example of this see [dealing-with-key-combinations-of-function-symbols]. Don't think about the deep question ``how can I prove the checkpoint?'' until you've got it into its simplest form. (3) Is the simpler fact already in the database? If there is some simpler fact that would help clean up the checkpoint but you believe the simpler fact is already in the database, you can use :[pl] [{ICON}], :[pc] [{ICON}], :[pbt] [{ICON}], and other history commands to inspect the database; (see [history] [{ICON}]). But if you find the allegedly relevant simpler fact in the database, you must ask: why wasn't it used? There are four principal reasons: (3a) it is disabled -- so enable it; you'll learn how when you read the coming sections on [introduction-to-the-database] and [introduction-to-hints]. (3b) its left-hand side doesn't match the target -- so improve the rule by generalizing its left-hand side or prove a new rule for this situation; if you decide to remove the old rule from the database, see undo commands in [history] [{ICON}]. (3c) it is an IFF rule but the target doesn't occur propositionally -- so see if you you can strengthen the rule to an EQUAL rule or weaken the context of the target by changing the conjecture to use the target propositionally; if you decide to remove the old rule from the database, see undo commands in [history] [{ICON}]. (3d) the hypotheses of the rule cannot be relieved for this occurrence of the target; this can be caused by the rule's hypotheses being too strong (requiring more than they should), or by the hypotheses of the current conjecture being too weak (you forgot some key hypothesis), or by ACL2 not having the rules it needs to prove that the conjecture's hypotheses really do imply the rule's. Tools are available (:see [brr] [{ICON}]) help you figure out why the rule failed, so use them and improve the rule, or the current conjecture, or the database as appropriate. (4) If the simpler fact is not already known, prove it. This means you must create a new defthm event with appropriate rule-classes to store your new theorem so that it will be used. See [dealing-with-key-combinations-of-function-symbols]. Then you must start using The Method recursively to prove your new lemma. (5) Otherwise, is this formula something you'd prove by induction? If you can't simplify it, it may be because you ``need this fact to prove this fact,'' in which case, induction is the right thing to do. But first, remember that in order for a formulas to be provable by induction, it must be very general. Why must it be general? Because in an inductive proof, the main thing you have to work with is the induction hypothesis, which is an instance of the theorem you're proving. If the theorem is not general enough, you won't be able to assume an instance that will help you. ACL2 may try induction even on formulas that are not general enough. Don't assume that the formula is ripe for induction just because ACL2 found an induction to do! Before you ``approve'' a formula for induction, ask whether it is perhaps a special case of some more general theorem. See [generalizing-key-checkpoints] now and then come back here. If you found a generalization, you should probably be proving that formula instead of this one. So formulate the appropriate defthm and use The Method recursively to prove it. (6) If the formula is right for induction, did ACL2 do an induction for it? You can answer that without looking at the proof. Just see if there are any key checkpoints after induction. If not, why didn't ACL2 induct? Perhaps you told ACL2 not to induct! Perhaps no term in the conjecture suggests an appropriate induction? You could remedy this by extending ACL2's induction analysis by adding to the database. Or you could just tell ACL2 what induction to do for this formula. You'll learn about both later (when you read coming sections of the tutorial). (7) If ACL2 did do an induction, was it the right one? You can find the induction scheme used by reading the first induction message in the output log after you submitted the conjecture to ACL2. But most often you will realize the ``wrong'' induction was done just by looking at the post-induction key checkpoints, keeping in mind that each is supposed to be a natural special case of the theorem you're proving. Is the case analysis inappropriate? Are induction hypotheses missing? If so, you should look at the induction scheme. If you determine the wrong induction was done, extend ACL2's induction analysis or tell it which induction to do, which you'll learn about in the coming sections of the tutorial. For more advice about looking at post-induction key checkpoints, see [post-induction-key-checkpoints] now and then come back here. (8) If the post-induction key checkpoints seems plausible, then repeat the questions above for each one of them, perhaps starting with the simplest. In any case, after successfully taking whatever action you've decided on, e.g., proving some new lemma and adding it as a rule: Start over trying to prove your main conjecture. This is important! Do not just scroll back to the key checkpoints generated the last time you tried to prove it. Instead, re-generate them in the context of your new, improved database and hints. You will be following this general outline almost all of the time that you're interacting with ACL2. You will not often be asking ``Why is ACL2 making me think about this subgoal? What did ACL2 do to get here? How does ACL2 work?'' Two other ideas are helpful to keep in mind. Is a key checkpoint unexpectedly complicated? Pay special attention to the case where the complication seems to be the introduction of low-level details you thought you'd dealt with or by the introduction of symbols you didn't expect to see in this proof. These can be signs that you ought to disable some rules in the database (e.g., a definition of a complicated function about which you've proved all the necessary lemmas or some lemma that transforms the problem as was appropriate for some other proof). Does the theorem prover just hang up, printing nothing? If this happens, you must interrupt it. How you interrupt the prover is dependent on which Common Lisp and which interface you're using. But most Common Lisps treat control-c as a console interrupt. If you're in Emacs running ACL2 as a shell process, you must type control-c control-c. If you're in ACL2s, hit the Interrupt Session button. Interrupting ACL2 can leave you in an interactive loop similar in appearance but different from ACL2's top-level! So pay careful attention to the prompt and see [breaks] [{ICON}]. Once you've regained control from the ``runaway'' theorem prover, there are several tools you can use to find out what it is doing in real-time. Generally speaking, when the theorem prover goes silent for a very long time it is either in some kind of rewrite loop caused by rules that cause it to flip back and forth between various supposedly normal forms, or else it has split the problem into a huge number of cases and suffering a combinatoric explosion. See [dmr] [{ICON}] and, perhaps, see [accumulated-persistence] [{ICON}]. If you are reading this as part of the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-the-theorem-prover].") (INTRODUCTION-TO-REWRITE-RULES-PART-1 (INTRODUCTION-TO-THE-THEOREM-PROVER) "Introduction to ACL2's notion of rewrite rules Rewrite rules make ACL2 replace one term by another. This is done by the rewriter, which is part of ACL2's simplifier. The rewriter sweeps through the goal formula trying all the rewrite rules it knows. Here's an example. Just pretend that you have made a rewrite rule from the formula below. (implies (and (natp i) (< i (len a))) (equal (put i v (append a b)) (append (put i v a) b))) Then every time the rewriter sees a target term that matches (put i v (append a b)) it considers the rule, with the variables i, v, a, and b of the rule bound to whatever terms matched them in the target, say the terms i, v, a, and b. To consider the rule, the rewriter first tries to establish (``relieve'') the hypotheses. In particular, it rewrites: (natp i) ; hyp 1 and (< i (len a)). ; hyp 2 If both hyptheses rewrite to true, then the rule fires and replaces the target by: (append (put i v a) b). In short, rewrite rules direct ACL2 to rearrange the terms in the goal formulas. We are more precise later, but for now we turn to the question of how do you make a rewrite rule from a formula? The answer is, you prove the formula with the defthm command. Recall that (defthm name formula ...) commands ACL2 to try to prove formula and, if successful, build it into the database as a rule according to your specification in the rule-classes argument of the ... part of the command. To make it easy for you to generate rewrite rules, defthm has a simple heuristic: if you don't tell it what kind of rule to generate from formula, it generates a rewrite rule! Thus, if this command (defthm name formula) is successful, ACL2 will have a new rewrite rule in the database, even though you did not explicitly tell it to add a rule. A common mistake for new users is to forget that the above command adds a rewrite rule. This often results in a tangle of rules that lead nowhere or to infinite rewriting that you will have to interrupt. It is also good to remember that the command only adds a rule. It does not magically make ACL2 aware of all the mathematical consequences of the formula: it just makes a rewrite rule. When you prove a theorem with defthm you are programming ACL2. Being careless in your statement of lemmas is tantamount to being careless in your programming. ACL2 can generate rewrite rules from formulas that look like this: (IMPLIES (AND hyp1 ... hypk) (eqv lhs rhs)) where eqv is either EQUAL or IFF, and lhs is not a variable symbol, not a constant, and not a call of the function IF, and not a call of an abbreviation (``macro'') that expands to any of these. So illegal lhs include X, 0, (IF X Y Y), and (OR p q). The last is illegal because OR is just an abbreviation for a certain IF-expression. Technical Note: This tutorial introduction to the theorem prover takes liberties with the truth! We are trying to give you a useful predictive model of the system without burdening you with all the details, which are discussed in the ACL2 User's Manual. For example, using directives in the rule-classes you can rearrange the proved formula into the form you want your rule to take, and you can make ACL2 take advantage of equivalence relations eqv other than just EQUAL and IFF. But we'll ignore these fine points for now. We call the hyp terms the hypotheses of the rule. We call lhs the left-hand side of the rule, and we call rhs the right-hand side of the rule. If the conclusion of the rule is an EQUAL term we call it an equality rule. Otherwise, it is a propositional equivalence rule. If there are no hypotheses, k=0, we say the rule is an unconditional rewrite rule; otherwise it is conditional. ACL2 allows several special cases of the shapes above. See [special-cases-for-rewrite-rules], but come back here and continue. A rewrite rule makes ACL2 seek out occurrences of terms that match the left-hand side of the rule and replace those occurrences using the right-hand side, provided all the hypotheses rewrite to true in the context of the application of the rule. That is, the left-hand side is treated as a pattern that triggers the rule. The hypotheses are conditions that have to be proved in order for the rule to fire. The right-hand side is the replacement and is put into the formula where the pattern occurred. Now for some clarifications. ACL2 only considers enabled rules. And ACL2 will use a propositional rule to replace a target only if the target occurs in a propositional place in the formula. Generally that means it occurs in the argument of a propositional connective, like AND, OR, NOT, IMPLIES, and IFF, or in the test of an IF. When we say that the left-hand side of the rule must match the target we mean that we can instantiate the variables in the rule to make the left-hand side identical to the target. To relieve or establish the hypotheses of the rule, ACL2 just applies other rewrite rules to try to prove the instantiated hypotheses from the assumptions governing the occurrence of the target. When ACL2 replaces the target, it replaces it with the instantiated right-hand side of the rule and then applies rewrite rules to that. If a hypothesis has variables that do not occur in the left-hand side of the rule, then the pattern matching process won't find values for those variables. We call those free variables. They must be instantiated before ACL2 can relieve that hypothesis. To instantiate them, ACL2 has to guess values that would make the hypothesis true in this context, i.e., true given the assumptions of the goal theorem. So if you're trying to prove (IMPLIES (AND (TRUE-LISTP A) (MEMBER (CAR P) A) (MEMBER (CDR P) A)) ...) and the target you're rewriting is in the ``...'' part of the formula, the rewriter knows that (TRUE-LISTP A) (MEMBER (CAR P) A) and (MEMBER (CDR P) A) are true. So if a rewrite rule is considered and the rule has (member e x) as a hypothesis, where e is a free variable but x was bound to A in the pattern matching, then it will guess that e must be (CAR P) or (CDR P), even though there are many other possibilities that would make (MEMBER e A) true. Of course, whatever guess it makes must also satisfy all the other hypotheses that mention e in the rule. It simply isn't very imaginative at guessing! The most predictable rewrite rules have no free variables. You can add pragmatic advice to help ACL2 with free variables, telling it to try all the possibilities it finds, to try just the first, or even to compute a ``creative'' guess. It is possible to make the rewriting process loop forever, e.g., by rewriting alpha to beta with one set of rules and rewriting beta to alpha with another. Even a single rule can make the process loop; we'll show you an example of that later in the tutorial. ACL2 can handle commutativity rules without looping. It uses (equal (+ x y) (+ y x)) to replace (+ B A) by (+ A B), but not vice versa. (It is sensitive to alphabetic ordering when dealing with permutative rules.) Logically equivalent formulas can generate radically different rewrite rules! Rearranging the propositional structure of the formula or swapping the left and right sides of an equality -- while having no effect on the mathematical meaning of a formula -- can have a drastic impact on the pragmatic meaning as a rule. To see an illustration of this, see [equivalent-formulas-different-rewrite-rules]. Developing an effective set of rewrite rules is key to success at using ACL2. We'll look more at this later in the tutorial. If you are working your way through the tutorial for the theorem prover, use your browser's Back Button now to return to [introduction-to-the-theorem-prover]. If you are reading just about how to make effective rewrite rules, go on to [introduction-to-rewrite-rules-part-2].") (INTRODUCTION-TO-REWRITE-RULES-PART-2 (INTRODUCTION-TO-THE-THEOREM-PROVER) "How to arrange rewrite rules You should design your rewrite rules to canonicalize the terms in your problem, that is, your rules should drive terms into some normal form so that different but equivalent terms are rewritten into the preferred shape, making equivalent terms identical. You are very familiar with this idea from algebra, where you learned to normalize polynomials. Thus, when you see (2x + 6)(3x - 9) you automaticaly normalize it, by ``multiplying out and collecting like terms,'' to get (6x^2 - 54). This normalization strategy allows you to recognize equivalent terms presented differently, such as 6(x^2 - 9). The ACL2 user is responsible for making up the rules. (Standard ``books'' -- files of ACL2 definitions and theorems -- can often provide rules for some sets of functions, e.g., arithmetic.) This is a heavy burden on you but it means you are in charge of your own normal forms. For example, if you use the function nthcdr, which returns the nth cdr of a list, you might see both (cdr (nthcdr i x)) and (nthcdr i (cdr x)). These two expressions are equivalent but not identical. You will want to decide which you want to see and prove the rewrite rule that converts the other to that preferred form. Most good users develop an implicit ordering on terms and rewrite ``heavy'' terms to ``lighter'' ones. This insures that there are no loops in their rewrite rules. But this ordering changes according to the user and the problem. Generally, the lightest terms are primitives such as IF, EQUAL, arithmetic, etc. Functions defined without explicit recursion tend to be ignored because they are just expanded away (but see below). Recursively defined functions tend to be heavier than any other recursive function used in their definitions, so, for example, if rev is defined in terms of append, rev is heavier than append. But the size and subtlety of recursively defined functions also affects their place in the ordering. But rewrite rules are surprisingly subtle. Recall that a rewrite rule can be made from a formula of this form: (IMPLIES (AND hyp1 ... hypk) (eqv lhs rhs)) where eqv is either EQUAL or IFF, and lhs is a call of a function other than IF. In such a rule, lhs is the pattern responsible for triggering the rule, the hypi are conditions which must be satisfied by the context of the target being rewritten, and rhs is the replacement. The replacement only happens if the rule is enabled, the pattern matches, the conditions are satisfied, and (in the case of an IFF rule) the target occurs propositionally. There are other heuristic restrictions that we won't discuss here. So how should you phrase a theorem in order to make it an effective rule? General Principles: * Strengthen the Formula: The fewer hypotheses a formula has the better the rewrite rule formed from it. The more general the left-hand side the better the rule. The fewer free variables in the hypothesis, the better. The idea is to form a rule that fires predictably. Later in this tutorial you'll get some practice formulating strong rules. * Choosing the Conclusion: If a lemma is an implication, you have to choose what the conclusion will be. (You'll also have to ``orient'' that conclusion by choosing a left-hand side and a right-hand side, but we discuss that below). You can swap the conclusion and any hypothesis by negating both, producing a different conclusion. There are generally two (possibly conflicting) heuristics for deciding which part of the formula should be the conclusion: Choosing the Conclusion Heuristic 1: Can you make the conclusion be an EQUAL or IFF expression that has a ``heavy term'' on one side? That will make a rule that replaces the heavy term with a lighter one. We discuss this situation more below. Choosing the Conclusion Heuristic 2: Can you make the conclusion be a non-propositional term that contains all the variables mentioned in the hypotheses? By ``non-propositional'' we mean a term that is not just the propositional combination (e.g., with AND or OR) of other terms but instead some call of some ``heavy'' function? If your conclusion contains all the variables mentioned in the hypotheses, matching it will instantiate all the variables in the hypotheses. That way ACL2 will not have to guess instantiations of unbound variables when it tries to relieve the hypotheses. It is not very good at guessing. * Orienting the Conclusion: If the conclusion is an EQUAL or an IFF, you have to decide which is the left-hand side and which is the right. If the conclusion is (NOT lhs), then the left-hand side is lhs and the right-hand side is NIL. If the conclusion is not an EQUAL, an IFF, or a NOT then the conclusion itself will be the left-hand side and the right-hand side will be T. If your lemma was created by looking at Key Checkpoints while using The Method, the left-hand side should match some term in that checkpoint. Remember, the left-hand side is the ``trigger'' that will make the rule fire. It is the pattern that ACL2 will be looking for. * Pay attention to the free variables: Look at the variables that occur in the pattern (the left-hand side) and compare them to the variables that occur in the hypotheses. Does some hypothesis contain a variable, say v, that is not in the pattern? We call v a free variable because it will not be assigned a value (``bound'') by the process of pattern matching. ACL2 will have to guess a value for v. If some hypothesis contains v as a free variable, ask whether more than one hypothesis contains v? ACL2 uses the first hypothesis containing a free v to guide its guess for v. To ``guess'' a value for v, ACL2 uses that hypothesis as a pattern and tries to match it against the assumptions in the checkpoint formula being proved. This means that key hypothesis must be in normal form, to match the rewritten assumptions of the goal. It also means that you should reorder the hypotheses to put the most unusual hypothesis containing a free v first in the list of conjuncts. For example, if v is free in two hypotheses, (natp v) and (member (nthcdr v a) b), then we recommend putting the member term first. There are likely to be many terms in the goal satisfying the natp hypothesis -- or none if natp has expanded to an integer inequality -- while there are likely to be few terms satisfying the member hypothesis, especially if a and b are bound by the left-hand side of the rule. Here are some (possibly conflicting) heuristics for choosing the left-hand side: Choose a Left-Hand Side that Occurs in a Key Checkpoint: If you use the Method you will tend to do this anyway, because you'll see terms in the Key Checkpoints that you want to get rid of. But many moderately experienced users ``look ahead'' to how the proof will go and formulate a few anticipatory rules with the idea of guiding ACL2 down the preferred path to the proof. When you do that, you risk choosing left-hand sides that won't actually arise in the problem. So when you formulate anticipatory rules, pay special attention to the functions and terms you put in the left-hand sides. The next few paragraphs deal with specific cases. Avoid Non-Recursive Functions in the Left-Hand Side: If the left-hand side contains a call of a defined function whose definition is not recursive, then it will almost never match any target in the formula being rewritten unless the function is disabled. Suppose for example you have defined SQ so that (SQ x) is (* x x). Suppose you considered choosing a left-hand side like (+ (SQ x) (SQ y)). Suppose you hoped it would hit the target (+ (SQ A) (SQ B)) in some formula. But when ACL2 simplifies the formula, it will first rewrite that target to (+ (* A A) (* B B)) by expanding the definition of SQ, since it could do so without introducing any recursive calls. But now the target won't match your rule. By choosing a left-hand side that occurs in a Key Checkpoint (and is not one of a handful of abbreviations ACL2 uses in its output like AND, NOT), you'll avoid this problem since SQ will have already been expanded before the Key Checkpoint is printed. Disable Non-Recursive Functions: If you insist on a left-hand side that contains calls of non-recursive functions, remember to disable those non-recursive functions after you've proved all the rules you want about them. By disabling SQ you can prevent ACL2 from expanding the definition as it did above. Sometimes you will define a function non-recursively to formalize some concept that is common in your application and you will want to create a sort of algebra of rules about the function. By all means do so, so you can conduct your formal reasoning in terms of the concepts you're informally manipulating. But after proving the required laws, disable the non-recursive concept so that ACL2 just uses your laws and not the messy definition. Choose a Left-Hand Side Already in Simplest Form: This is a generalization of the advice above. If any rule will rewrite your left-hand side, it will prevent your rule from matching any target. For example, if you write a left-hand side like (foo (car (cons x y))) then it would never match any target! The reason is that even if (FOO (CAR (CONS A B))) did occur in some goal formula, before ACL2 would try your rule about foo it will use the obvious rule about CAR and CONS to transform your imagined target to (FOO A). Thus, your rule would not match. So you have to keep in mind all your other rules when you choose a left-hand side (and when you choose the hypotheses to guide free variable selection). If you always choose a pattern that matches a term in a Key Checkpoint, you avoid this problem. Also see [community-books] example books/demos/knuth-bendix-problem-1.lisp. Make Sure the Left-Hand Side is ``Heavier'' than the Right: Sometimes this is obvious, as when you choose (REV (REV x)) for the left-hand side and x for the right. But what do you about (REV (APPEND x y)) versus (APPEND (REV y) (REV x))? Most of the time we choose to drive the heaviest function (in this case REV) down toward the variables, lifting the lighter function (APPEND) up so that we can reason about the lighter function's interaction with the surrounding ``matrix'' of the formula. So we'd rewrite (REV (APPEND x y)) to (APPEND (REV y) (REV x)), not vice versa. Alternative Ways to Talk About the Same Thing: If your problem and specification use two different ways to talk about the same thing, choose one form and rewrite the other into that form. For example, the ACL2 built-in nth returns the nth element of a list, and the built-in function nthcdr returns the nth cdr of a list. They are defined independently. But (nth n x) is the same thing as (car (nthcdr n x)). Since nth can be expressed in terms of nthcdr but not vice versa, it is clear we should prove (equal (nth n x) (car (nthcdr n x))) as a rewrite rule if both nth and nthcdr are involved in the problem. Don't Let Computational Efficiency Dictate the Terms: If you have two functions that are equivalent (perhaps one was defined to be computationally more efficient), prove their equivalence as a rewrite rule that eliminates the more complicated function. An extreme example would be a model that uses a sophisticated data structure (like a balanced binary tree, red-black tree, ordered array, or hash table) to implement something simple like an association of keys to values. By proving the equivalence as stated you can eliminate the messy function early and do the bulk of your reasoning in terms of its simple specification. The best ACL2 users become very good at keeping all these things in mind when designing their rewrite rules. Practice makes perfect. Don't be afraid during your learning of ACL2 to undo the rules you first invented and try to make better ones. Finally, be patient! There will be times when you think to yourself ``Why should I spend my time thinking of rules that guide ACL2? I know the proof!'' There are two reasons. First, you may ``know'' the proof but you may well be wrong and part-way through this whole exercise you may realize that you're missing a major hypothesis or special case that breaks your whole conception of the problem. The proof is in the details. Second, most of the time the library of rules you develop in this process will be used over and over again on variants of the main problem in the months and years ahead. This is sometimes called the proof maintenance problem. Theorems don't suffer bit rot! But the artifacts you're modeling change and you will need to prove new versions of old theorems. A good general purpose library makes this much easier. We now recommend that you practice inventing strong rules; see [strong-rewrite-rules]. For advice on handling specific kinds of formulas and definitions, see [specific-kinds-of-formulas-as-rewrite-rules]. For more information about the rewriter works and how rules are created, see [further-information-on-rewriting]. If you are working your way through the tutorial introduction to the theorem prover, use your browser's Back Button to return to [introduction-to-the-theorem-prover].") (INTRODUCTION-TO-THE-DATABASE (INTRODUCTION-TO-THE-THEOREM-PROVER) "How to update the database We assume you've read [introduction-to-rewrite-rules-part-1] and [introduction-to-key-checkpoints]. The theorem prover's heuristics are influenced by the database of rules and the enabled/disabled status of the rules. You can think of the database as a global hint, potentially affecting all parts of a proof attempt. However, in addition to the ``global hint,'' it is possible to give local hints that affect the theorem prover's behavior on specific subgoals. We discuss the database here and discuss local hints later in the tutorial. The theorem prover's ``database'' is called the ACL2 world. You change the world by issuing commands called events. The most common events are defun for defining new functions (and predicates) and defthm for proving new theorems. Both add rules to the database. Here are some commonly used events. We recommend that upon the first reading of this tutorial you do not follow the links shown below! The links take you into the hypertext reference manual, where it is easy to get lost unless you're looking for detail about one specific feature. See [defun] [{ICON}] to define a new function or predicate symbol. Definitional axioms are just a kind of rewrite rule, but defun may also add rules affecting the determination of the type of a term and rules affecting the induction analysis. When you issue a defun command you will always supply the name of the function or predicate, the list of formal parameters, v1,...vn, and the body: (defun name (v1 ... vn) body) If the event is accepted, a definitional axiom is added to the world, (name v1...vn)=body, stored as a special kind of unconditional rewrite rule. However, the defun event may require theorems to be proved. Specifically, measure theorems must be proved to establish that recursively defined functions always terminate, by proving that an ordinal measure of the formal parameters decreases in a well-founded way in every recursive call. In addition, if guards are being used to declare the expected domain of the newly defined function, guard theorems might be proved to establish that all functions stay within their expected domains. In any case, you may provide additional information to the defun event, coded as part of the declaration that Common Lisp allows: (defun name (v1 ... vn) (declare (xargs ...)) body) The xargs (``extra arguments to defun'') entry may specify, among other things, the measure to use in the termination proof, hints for use by the prover during the termination proof, the guard of the new function, and hints for use by the prover during the guard verification step. See [defthm] [{ICON}] to prove a theorem and to add it as a rule of one or more specified rule-classes. When you issue a defthm command you always specify a name for the theorem you're trying to prove and a formula stating the theorem. You may optionally supply some local hints as we describe later in the tutorial. You may also optionally supply some rule classes indicating how you want your formula stored as a rule, after it is proved. We discuss the defthm rule classes below. See [in-theory] [{ICON}] to enable or disable rules. Rules have names derived from the names you give to functions and theorems, e.g., (:REWRITE LEFT-IDENTITY-OF-FOO . 2) for the second rewrite rule you created from the theorem named LEFT-IDENTITY-OF-FOO. Rule names are called runes. A theory is just a set (list) of runes. The current theory is the list of enabled runes and the in-theory event can add runes to or delete runes from the current theory. See [include-book] [{ICON}] to change the world by loading a certified file of other events. The most common use of include-book is to load ``community books'' -- books written by other ACL2 users who have released them for distribution to the community. The most common books loaded are probably the arithmetic books: ; * for the most elementary arithmetic, needed for any problem ; that involves even simple addition and multiplication like ; (+ x (* 2 y) -3): (include-book \"arithmetic/top-with-meta\" :dir :system) ; * for more complicated arithmetic involving non-linear terms like ; (* x y), (expt x (+ i j)), and floor and mod (include-book \"arithmetic-5/top\" :dir :system) But for a complete list of system books, see [books] [{ICON}]. See [certify-book] [{ICON}] to certify a file of events for reuse later. See [defconst] [{ICON}] to define a new constant, allowing you to write a symbol, e.g., *weekdays* in place of some object, e.g., '(MON TUE WED THU FRI) in formulas. See [defmacro] [{ICON}] to define a new syntactic abbreviation. The macro facility in Lisp is quite powerful, allowing you to compute the form to which some type-in expands. For example, the primitive macro COND is defined so that (COND ((P X) 1)((Q X) 2)(T 3)) expands to (IF (P X) 1 (IF (Q X) 2 3)). See [defstobj] [{ICON}] to introduce a single-threaded object that your functions may modify ``destructively'' provided they follow strict syntactic rules. See [events] [{ICON}] for a complete list of the ACL2 events. There are events to allow mutually recursive definitions, to introduce some new function symbols constrained to satisfy given axioms, to allow the temporary introduction of a ``local'' event to help prove some goal theorem and then disappear, to provide the power of first-order quantification and a choice operator, and many other features. There are also commands that allow you to inspect the world, e.g., to print the command that introduced a given name, to show all the commands back to a certain one, undo the last command or more generally roll-back to an earlier command. See [history] [{ICON}]. The Defthm Rule-Classes We've already discussed the key role that rules play in controlling the behavior of the system. New rules are introduced primiarily with the defthm event, though defun and other events may introduce rules. To prove formula and generate, say a :rewrite rule and a :generalize rule from it, you would write (defthm name formula :rule-classes (:rewrite :generalize)) If you wanted to rearrange the shape of the formula before generating the :rewrite rule you could provide a :corollary modifier to the :rewrite rule class: (defthm name formula :rule-classes ((:rewrite :corollary ...) :generalize)). There are many classes of rules, affecting different parts of the system. Each class is denoted by a keyword, e.g., :REWRITE, :LINEAR, etc. You are responsible for specifying the class(es) of rules to be generated from a given formula and several different rules (possibly of different classes) may be derived from a single formula. Each class admits optional modifiers that allow you finer control over each rule. Each class admits the :corollary modifier with which you can rearrange the formula before a rule of that class is generated. This allows you to state a theorem in its most elegant form for publication purposes but store it as a rule with the most appropriate hypotheses and conclusion. Other modifiers tend to be specific to certain rule classes, but for example, :rewrite rule modifiers include an optional limit on the depth of backchaining and options for handling free variables. We give some links below to other classes of rules. However, we recommend that you not follow these links upon your first reading of this tutorial! See [rewrite] [{ICON}] for a description of how to create a rewrite rule. See [linear] [{ICON}] for a description of how to store theorems concluding with arithmetic inequalities. The trouble with storing (<= (len (delete e x)) (len x)) as a rewrite rule is that it only matches instances of that inequality and thus fails to match (<= (LEN (DELETE E X)) (+ 1 (LEN X))) ACL2 contains an extensible linear arithmetic decision procedure and by storing inequalities as :linear rules you can make that decision procedure aware of the basic inequalities between non-primitive numerically valued terms. See [equivalence] [{ICON}], see [congruence] [{ICON}], and see [refinement] [{ICON}] to learn how to introduce a new equivalence relation to the rewriter. For example, suppose you define set-equal so that it returns t precisely if its two arguments are lists containing the same elements, regardless of order or number of occurrences. Note that under this sense of ``equivalence'', (rev x) is the identity function and append is commutative, for example. (set-equal (rev x) x) (set-equal (append x y) (append y x)) You can make ACL2 use these two theorems as :rewrite rules to replace instances of (REV x) and (APPEND x y) by set-equal terms, even though the results are not actually EQUAL. This is possible provided the target occurs in a context admitting set-equal as a congruence relation. For example, the :congruence rule: (implies (set-equal a b) (iff (member e a) (member e b))) gives the rewriter permission to use the above set-equal rules as rewrite rules in the second argument of any member expression being used in a propositional way. See [elim] [{ICON}] for a description of how to make the system adopt a ``change of variable'' tactic that can trade in destructor functions for constructor functions. In analogy with how ACL2 eliminates (CAR X) and (CDR X) by replacing X with (CONS A B), you can make it eliminate other destructors. For example, the community book \"arithmetic-5/top\" provides an elim rule that eliminates (floor x y) and (mod x y) by replacing x by (+ r (* y q)), so that the floor expression becomes q and the mod expression becomes r. When introducing your own elim rules you will probably also need to introduce generalize rules (see below) so that the new variables are appropriately constrained. See [generalize] [{ICON}] for a description of how you can make ACL2 restrict the new variables it introduces when generalizing. ACL2 will sometimes replace a term by a new variable and with generalize rules you can insure that the new variable symbol has certain properties of the term it replaces. See [induction] [{ICON}] for a description of how to tailor the inductions suggested by a term. Most of the time when ACL2 chooses the ``wrong'' induction, the easiest fix is with a local :induct hint (see below). But if the same problem arises repeatedly in several theorems, you might want to ``educate'' ACL2's induction heuristic. For a complete list of rule-classes, See [rule-classes] [{ICON}]. If you are reading this as part of the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-the-theorem-prover].") (INTRODUCTION-TO-THE-TAU-SYSTEM (TAU-SYSTEM) "A decision procedure for runtime types This doc topic is the main source of information about the tau system and discusses the general idea behind the procedure and how to exploit it. A ``Type-Checker'' for an Untyped Language Because ACL2 is an untyped language it is impossible to type check it. All functions are total. An n-ary function may be applied to any combination of n ACL2 objects. The syntax of ACL2 stipulates that (fn a1...an) is a well-formed term if fn is a function symbol of n arguments and the ai are well-formed terms. No mention is made of the ``types'' of terms. That is what is meant by saying ACL2 is an untyped language. Nevertheless, the system provides a variety of monadic Boolean function symbols, like [natp], [integerp], [alistp], etc., that recognize different ``types'' of objects at runtime. Users typically define many more such recognizers for domain-specific ``types.'' Because of the prevalence of such ``types,'' ACL2 must frequently reason about the inclusion of one ``type'' in another. It must also reason about the consequences of functions being defined so as to produce objects of certain ``types'' when given arguments of certain other ``types.'' Because the word ``type'' in computer science tends to imply syntactic or semantic restrictions on functions, we avoid using that word henceforth. Instead, we just reason about monadic Boolean predicates. You may wish to think of ``tau'' as synonymous with ``type'' but without any suggestion of syntactic or semantic restrictions. Design Philosophy The following basic principles were kept in mind when developing tau checker and may help you exploit it. (1) The tau system is supposed to be a lightweight, fast, and helpful decision procedure for an elementary subset of the logic focused on monadic predicates and function signatures. (2) Most subgoals produced by the theorem prover are not in any decidable subset of the logic! Thus, decision procedures fail to prove the vast majority of the formulas they see and will be net time-sinks if tried too often no matter how fast they are. Tau reasoning is used by the prover as part of preprocess-clause, one of the first proof techniques the system tries. The tau system filters out ``obvious'' subgoals. The tau system is only tried when subgoals first enter the waterfall and when they are stable under simplification. (3) The tau system is ``benign'' in the sense that the only way it contributes to a proof is to eliminate (prove!) subgoals. It does not rewrite, simplify, or change formulas. Tau reasoning is not used by the rewriter. The tau system either eliminates a subgoal by proving it or leaves it unchanged. (4) It is impossible to infer automatically the relations between arbitrary recursively defined predicates and functions. Thus, the tau system's knowledge of tau relationships and function signatures is gleaned from theorems stated by the user and proved by the system. (5) Users wishing to build effective ``type-checkers'' for their models must learn how rules affect the tau system's behavior. There are two main forms of tau rules: those that reveal inclusion/exclusion relations between named tau predicates, e.g., that 16-bit naturals are also 32-bit naturals, (implies (n16p x) (n32p x)), and signatures for all relevant functions, e.g., writing a 32-bit natural to a legal slot in a register file produces a register file: (implies (and (natp n) (< n 16) (n32p val) (register-filep regs)) (register-filep (update-nth n val regs))). For a complete description of acceptable forms see :[tau-system]. (6) The tau system is ``greedy'' in its efforts to augment its database. Its database is potentially augmented when rules of any :rule-class (see :[rule-classes]) are proved. For example, if you make a :[rewrite] or :[type-prescription] rule which expresses a relationship between one tau and another (e.g., that (P x) implies (Q x)), ACL2 will build it into the tau database. The rule-class :[tau-system] can be used to add a rule to the tau database without adding any other kind of rule. (7) Greediness is forced into the design by benignity: the tau system may ``know'' some fact that the rewriter does not, and because tau reasoning is not used in rewriting, that missing fact must be conveyed to the rewriter through some other class of rule, e.g., a :[rewrite] or :[type-prescription] or :[forward-chaining] rule. By making the tau system greedy, we allow the user to program the rewriter and the tau system simultaneously while keeping them separate. However, this means you must keep in mind the effects of a rule on both the rewriter and the tau system and use :[tau-system] rules explicitly when you want to ``talk'' just to the tau system. (8) Tau rules are built into the database with as much preprocessing as possible (e.g., the system transitively closes inclusion/exclusion relationships at rule-storage time) so the checker can be fast. (9) For speed, tau does not track dependencies and is not sensitive to the enabled/disabled status (see [enable] and [disable]) of rules, other than [executable-counterpart] rules. Once a fact has been built into the tau database, the only way to prevent that fact from being used is by disabling the entire tau system, by disabling (:[executable-counterpart] tau-system). If any tau reasoning is used in a proof, the rune (:[executable-counterpart] tau-system) is reported in the summary. For a complete list of all the runes in the tau database, evaluate (global-val 'tau-runes (w state)). Any of these associated theorems could have been used. These design criteria are not always achieved! For example, the tau system's ``greediness'' can be turned off (see [set-tau-auto-mode]), the tau database can be regenerated from scratch to ignore disabled rules (see [regenerate-tau-database]), and disabling the [executable-counterpart] of a tau predicate symbol will prevent the tau system from trying to run the predicate on constants. The tau system's benignity can be frustrating since it might ``know'' something the rewriter does not. More problematically, the tau system is not always ``fast'' and not always ``benign!'' The typical way tau reasoning can slow a proof down is by evaulating expensive tau predicates on constants. The typical way tau reasoning can hurt a previously successful proof is by proving some subgoals (!) and thus causing the remaining subgoals to have different [clause-identifier]s, thus making explicit hints no longer applicable. We deal with such problems in [dealing-with-tau-problems]. Technical Details The tau system consists of both a database and an algorithm for using the database. The database contains theorems that match certain schemas allowing them to be stored in the tau database. Roughly speaking the schemas encode ``inclusion'' and ``exclusion'' relations, e.g., that natp implies integerp and that integerp implies not consp, and they encode ``signatures'' of functions, e.g., theorems that relate the output of a function to the input, provided only tau predicates are involved. By ``tau predicates'' we mean the application of a monadic Boolean-valued function symbol, the equality of something to a quoted constant, an arithmetic ordering relation between something and a rational constant, or the logical negation of such a term. Here are some examples of tau predicates: (natp i) (not (consp x)) (equal y 'MONDAY) (not (eql 23 k)) (< 8 max) (<= max 24) Synonyms for [equal] include [=], [eq], and [eql]. Note that negated equalites are also allowed. The arithmetic ordering relations that may be used are [<], [<=], [>=], and [>]. One of the arguments to every arithmetic ordering relation must be an integer or rational constant for the term to be treated as a tau predicate. A ``tau'' is a data object representing a set of signed (positive or negative) tau predicates whose meaning is the conjunction of the literals in the set. When we say that a term ``has'' a given tau we mean the term satisfies all of the recognizers in that tau. The tau algorithm is a decision procedure for the logical theory described (only) by the rules in the database. The algorithm takes a term and a list of assumptions mapping subterms (typically variable symbols) to tau, and returns the tau of the given term. When the system is called upon to decide whether a term satisfies a given monadic predicate, it computes the tau of the term and asks whether the predicate is in that set. More generally, to determine if a term satisfies a tau, s, we compute a tau, r, for the term and ask whether s is a subset of r. To determine whether a constant, c, satisfies tau s we apply each of the literals in s to c. Evaluation might, of course, be time-consuming for complex user-defined predicates. The tau database contains rules derived from definitions and theorems stated by the user. See :[tau-system] for a description of the acceptable forms of tau rules. To shut off the greedy augmentation of the tau database, see [set-tau-auto-mode]. This may be of use to users who wish to tightly control the rules in the tau database. To add a rule to the tau database without adding any other kind of rule, use the rule class :[tau-system]. There are some slight complexities in the design related to how we handle events with both :tau-system corollaries and corollaries of other :rule-classes, see [set-tau-auto-mode]. To prevent tau reasoning from being used, disable the :[executable-counterpart] of tau-system, i.e., execute (in-theory (disable (:executable-counterpart tau-system))) or, equivalently, (in-theory (disable (tau-system))) To prevent tau from being used in the proof of a particular subgoal, locally disable the :[executable-counterpart] of tau-system with a local :in-theory hint (see [hints]). The event command [tau-status] is a macro that can be used to toggle both whether tau reasoning is globally enabled and whether the tau database is augmented greedily. For example, the event (tau-status :system nil :auto-mode nil) prevents the tau system from being used in proofs and prevents the augmentation of the tau database by rules other than those explicitly labeled :[tau-system]. To see what the tau system ``knows'' about a given function symbol see [tau-data]. To see the entire tau database, see [tau-database]. To regenerate the tau database using only the runes listed in the current enabled theory, see [regenerate-tau-database]. Subtopics [Dealing-with-tau-problems] Some advice on dealing with problems caused by the tau system [Future-work-related-to-the-tau-system] Some tau system problems that we hope someone will address [Regenerate-tau-database] Regenerate the tau database relative to the current enabled theory") (INTRODUCTION-TO-THE-THEOREM-PROVER (ACL2-TUTORIAL) "How the theorem prover works -- level 0 Software is complex, and ACL2 is a piece of software that is used to analyze software -- adding another layer of complexity. Furthermore, instead of being limited to static analysis for certain fixed properties, ACL2 allows you -- indeed, forces you -- to formalize the problem and the questions. It ``knows'' nothing inherent about your problem before you start to interact with it. But it can be used to help answer the most complicated questions you can ask about software. All this is to say that it is not the kind of tool that you just install and then start to use effectively. So OK, you've installed it or confirmed that you can invoke it. Good for you. Now you have to learn how to use it! Your success ultimately comes down to your understanding of your problem domain and your appropriate exploitation of ACL2's strengths and avoidance of its weaknesses. So put aside the idea of sitting down and interacting with it. Instead, learn about it. We assume you know some of the [industrial applications] of ACL2. Realizing that such things can be done may sustain you during the long learning curve! We also assume you have taken both the [Flying Tour] and the [Walking Tour]. The tours give you a good overview of the whole system where this tutorial focuses on how to use the prover itself. If you haven't visited these links, please do so now. This tutorial will take you several hours -- maybe several days -- to work through. Do not breeze through it as you might a blog. Think your way through it. Remember what you read. Do not take short cuts. If you start to use ACL2 before you really know how, it will only frustrate you. We recommend that you read this tutorial with an HTML browser so that you can see which links you've followed and which you have not. To give you a sense of what is in store, here is a map of this document. But don't navigate through it from here! Read it linearly, following the links when the text directs you to. [introduction-to-the-theorem-prover] [introduction-to-rewrite-rules-part-1] [special-cases-for-rewrite-rules] [equivalent-formulas-different-rewrite-rules] [introduction-to-key-checkpoints] [dealing-with-key-combinations-of-function-symbols] [generalizing-key-checkpoints] [post-induction-key-checkpoints] [introduction-to-rewrite-rules-part-2] [strong-rewrite-rules] [practice-formulating-strong-rules] [practice-formulating-strong-rules-1] [practice-formulating-strong-rules-2] [practice-formulating-strong-rules-3] [practice-formulating-strong-rules-4] [practice-formulating-strong-rules-5] [practice-formulating-strong-rules-6] [specific-kinds-of-formulas-as-rewrite-rules] [further-information-on-rewriting] [introduction-to-the-database] [introduction-to-hints] [introduction-to-a-few-system-considerations] [introductory-challenges] [introductory-challenge-problem-1] [introductory-challenge-problem-2] [introductory-challenge-problem-3] (there are others but at least do a few) [frequently-asked-questions-by-newcomers] If any of the links above are marked as ``visited'' by your browser, use your browser's tools menu to mark all links as unvisited. As you can see, we really think you'll get the most out of this document if you take it seriously. As you read, you will see some links to ``advanced'' topics. These are marked with a tiny warning sign, ``[{ICON}]''. They lead out of this linear tutorial and into ACL2's hypertext reference manual. We recommend that you not visit any of these advanced links until you have read the entire tutorial at least once. After you finish this tutorial material, we recommend that you look at the ACL2 Demos, at the ``Demos'' link of the {ACL2 home page | http://www.cs.utexas.edu/users/moore/acl2}. Most users of ACL2 have bought the book Computer-Aided Reasoning: An Approach, Kaufmann, Manolios, and Moore, Kluwer Academic Publishers, June, 2000 which is available {in paperback | http://www.lulu.com/content/1746161} from Lulu for approximately $20 (as of 2010). That book contains hundreds of exercises in programming, proof, and using The Method described here to prove theorems. Solutions to the exercises are online, as are {appendices | http://link.springer.com/content/pdf/bbm%3A978-1-4615-4449-4%2F1.pdf} that focus on some practical usage aspects. See this { web page about the book | http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books}, which also includes information about its companion (also available on Lulu) describing applications of ACL2, some of which are from industry. Using ACL2 is akin to having a partner in the theorem proving enterprise. It will do some of the work and you will do some of the work. It can't really be any other way because theorem proving is undecidable. You bring a quirkly, error-prone, creative insight to the problem, and ACL2 brings accuracy, logic, and perserverance. Here we describe a ``model'' of how the system works and introduce some of the ideas and terminology you'll use repeatedly when interacting with it. This article is about the theorem prover itself, not the programming language and not the logic. We assume you know enough about the ACL2 programming language that you can define simple functions, run them, and read and write ACL2 constants and terms. For some examples of what we'll take for granted about ACL2 programming, see [programming-knowledge-taken-for-granted]. We also assume you know enough about logic to understand, for example, the words we use to talk about formulas and proofs. To see some examples of what we'll take for granted about your knowledge of logic terminology, see [logic-knowledge-taken-for-granted]. When you give the theorem prover a goal formula to prove, it tries to prove it by breaking it down into subgoals, each of which must be proved in order to prove the original goal. This breaking apart of the goal is done by various proof techniques built into ACL2. Different proof techniques break the formula apart in different ways. For example, the simplifier rips apart the propositional structure to isolate the various cases and applies rewrite rules to simplify the subterms of the formula, while the induction engine will attempt to break the goal into some base cases and some induction steps. The theorem prover's behavior is affected by a database of rules derived from axioms, definitions, and previously proved theorems. The database also records the enabled status of each rule; only enabled rules are seen by the prover and you can set the status of a rule. There are many other user-settable switches and parameters affecting the behavior of the prover; you'll learn about some of them later. You guide the theorem prover most of the time simply by identifying lemmas for it to prove. (A lemma is just a theorem that you think is useful in the proofs of other theorems.) Why does this guide the theorem prover? Because every time you get the system to prove a theorem, it turns the theorem into a rule (unless you tell it not to) and stores the rule in the database. That changes how the prover behaves subsequently. But you determine the kind of rule ACL2 stores. To learn to ``drive'' the theorem prover you have to learn how various rules affect the system's behavior and how it turns proved formulas into rules. But before we discuss this, we discuss a more mathematical activity: how do you figure out the lemmas ACL2 will need in order for it to prove interesting theorems? ACL2 can often help you in this activity, if you use it in the right way. Here is the way we recommend you use ACL2. The Method. (1) you present ACL2 with the goal conjecture to prove (2) typically, it fails to prove it (or you abort its attempt), but it prints some Key Checkpoints (3) you look at the Key Checkpoints and decide that you know a fact that will help; this tutorial will present some helpful questions to keep in mind (4) you formalize your knowledge as a formula, along with directions for how ACL2 should turn the formula into a rule; this tutorial will tell you about the most commonly used rule, the rewrite rule (5) you recursively apply The Method to get ACL2 to prove your formula and to store it as the kind of rule you specified (6) go to step (1) Caveat: This approach simply won't work on some theorems! Basically, this is a ``troubleshooting'' approach, where you're letting ACL2 determine the basic strategy and you're just helping with the subgoals. But for some theorems, ACL2's approach will be misguided and no amount of troubleshooting will salvage its strategy. You'll have a sense that this is happening when it happens because the formulas ACL2 presents to you will raise issues that feel irrelevant to you. The basic truth is that if you think a formula is always true there are usually strong intuitive reasons behind your belief. If you were asked to defend your belief, you'd start to explain your reasons and with training you can turn that into a proof. So when ACL2's formulas present you with things you haven't thought of either (a) you'll have an ``Ah ha!'' moment when you realize you hadn't considered that case or (b) you'll realize that ACL2's approach is different from your intuitive ``proof.'' But, surprisingly often, the troubleshooting approach to finding proofs works quite well, especially as you rein in your expectations and develop a sense of what ACL2 can handle on its own. Of course, if you can decompose the proof into a couple of main lemmas before you start, so much the better: write down your sequence of lemmas, thinking about the rules you want them to generate, and get ACL2 to prove each of them before giving it the main theorem. This proof planning approach will gradually become an integral part of your use of The Method. The only mechanized help we can offer with The Method, aside from the theorem prover itself, are tools to help you manage the stack of subgoals it generates when, in step (5) you recursively apply The Method to a lemma. There are both Emacs and Eclipse tools available. To use The Method you have to read the Key Checkpoints printed at the very end of failed proof attempts, just after the line that reads: The key checkpoint goals, below, may help you to debug this failure. Most users do not read the output from successful proofs and do not read the output during a proof -- they just let it stream by as a sort of gestalt meter on the theorem prover's progress or lack thereof. For example, you'll be able to tell it is in a loop and needs to be interrupted. You will respond to most Key Checkpoints by formulating new lemmas for the system to prove and store as rules designed by you to alter ACL2's behavior so that it proves the Key Checkpoints. You will give each lemma a name and write some formula to express the mathematical idea. You'll command ACL2 to prove it by typing: (defthm name formula ...) In the ``...'' you may provide two other kinds of information: hints for how to prove formula and directives, called rule-classes, for how to convert formula into a rule after it has proved formula. Note that you are in charge of determining what kind of rule ACL2 generates! There are over a dozen different types of rules with many opportunities to specialize each type. But the most common kind of rule you'll want to generate is a rewrite rule. We recommend that you read the following topics in the following order, without skipping anything except links into the ACL2 User's Manual, which are marked by the little warning sign, ``[{ICON}]''. (1) See [introduction-to-rewrite-rules-part-1] to read about the use and design of rewrite rules. (2) See [introduction-to-key-checkpoints] to see how to use The Method to help you design rules. (3) See [introduction-to-rewrite-rules-part-2] for general guidance on how to turn formulas into effective rules. (4) See [introduction-to-the-database] to see how to issue commands that build different kinds of rules and that affect the enabled status of existing rules. (5) See [introduction-to-hints] to see how to give the prover hints for how to prove specific theorems or even subgoals of specific proof attempts. (6) See [introduction-to-a-few-system-considerations] for a few words about system aspects of interacting with ACL2. (7) See [introductory-challenges] for a graduated sequence of good challenge problems for the new user to tackle. Do not skip this section! It is here that you really learn how to use ACL2 -- by using it. (8) See [frequently-asked-questions-by-newcomers] for a list of questions that new users frequently ask, answered mainly by providing links into the ACL2 User's Manual. We recommend that you skim through these questions and remember that you can find the answers here later. We are very interested in receiving suggestions for how to improve this FAQ and this tutorial. See the ACL2 home page, specifically the link ``Mailing Lists''. Please read all of the material cited above (skipping only the ACL2 User's Manual links (``[{ICON}]'')) before you try to use ACL2 on problems of your own. By this point you should have read, at least, the following topics from this tutorial introduction to the theorem prover: [introduction-to-the-theorem-prover] [introduction-to-rewrite-rules-part-1] [special-cases-for-rewrite-rules] [equivalent-formulas-different-rewrite-rules] [introduction-to-key-checkpoints] [dealing-with-key-combinations-of-function-symbols] [generalizing-key-checkpoints] [post-induction-key-checkpoints] [introduction-to-rewrite-rules-part-2] [strong-rewrite-rules] [practice-formulating-strong-rules] [practice-formulating-strong-rules-1] [practice-formulating-strong-rules-2] [practice-formulating-strong-rules-3] [practice-formulating-strong-rules-4] [practice-formulating-strong-rules-5] [practice-formulating-strong-rules-6] [specific-kinds-of-formulas-as-rewrite-rules] [further-information-on-rewriting] [introduction-to-the-database] [introduction-to-hints] [introduction-to-a-few-system-considerations] [introductory-challenges] [introductory-challenge-problem-1] [introductory-challenge-problem-2] [introductory-challenge-problem-3] (there are others but at least do a few) [frequently-asked-questions-by-newcomers] We also recommend that you look at the ACL2 Demos mentioned in the [ACL2-tutorial]. Most users of ACL2 have bought the book Computer-Aided Reasoning: An Approach, Kaufmann, Manolios, and Moore, Kluwer Academic Publishers, June, 2000 which is {available in paperback from Lulu | http://www.lulu.com/content/1746161} for approximately $20 (as of 2010). That book contains hundreds of exercises in programming, proof, and using The Method to prove theorems. Solutions to the exercises are online. See also this { web page about the book | http://www.cs.utexas.edu/users/moore/publications/acl2-papers.html#Books}, which also includes information about its companion (also available on Lulu) describing applications of ACL2, some of which are from industry. Thank you for spending the time to get acquainted with the basics of the ACL2 theorem prover. Don't hesitate to send further questions to the ACL2 Help address on the ``Mailing Lists'' link of the ACL2 home page. End of Tutorial Introduction to the Theorem Prover Below is a list of all of the topics cited on this page. Subtopics [Architecture-of-the-prover] A simple overview of how the prover works [Dealing-with-key-combinations-of-function-symbols] How to get rid of key combinations of function symbols [Equivalent-formulas-different-rewrite-rules] Logically equivalent formulas can generate radically different rules [Example-induction-scheme-binary-trees] Induction on binary trees [Example-induction-scheme-down-by-2] Induction downwards 2 steps at a time [Example-induction-scheme-nat-recursion] Induction on natural numbers [Example-induction-scheme-on-lists] Induction on lists [Example-induction-scheme-on-several-variables] Induction on several variables [Example-induction-scheme-upwards] Induction upwards [Example-induction-scheme-with-accumulators] Induction scheme with accumulators [Example-induction-scheme-with-multiple-induction-steps] Induction scheme with more than one induction step [Example-inductions] Some examples of induction schemes in ACL2 [Frequently-asked-questions-by-newcomers] Some questions newcomers frequently ask [Further-information-on-rewriting] A grab bag of advice and information on rewriting [Generalizing-key-checkpoints] Getting rid of unnecessary specificity [Introduction-to-a-few-system-considerations] The mechanics of interaction with the theorem prover [Introduction-to-hints] How to provide hints to the theorem prover [Introduction-to-key-checkpoints] What questions to ask at key checkpoints [Introduction-to-rewrite-rules-part-1] Introduction to ACL2's notion of rewrite rules [Introduction-to-rewrite-rules-part-2] How to arrange rewrite rules [Introduction-to-the-database] How to update the database [Introductory-challenge-problem-1] Challenge problem 1 for the new user of ACL2 [Introductory-challenge-problem-1-answer] Answer to challenge problem 1 for the new user of ACL2 [Introductory-challenge-problem-2] Challenge problem 2 for the new user of ACL2 [Introductory-challenge-problem-2-answer] Answer to challenge problem 2 for the new user of ACL2 [Introductory-challenge-problem-3] Challenge problem 3 for the new user of ACL2 [Introductory-challenge-problem-3-answer] Answer to challenge problem 3 for the new user of ACL2 [Introductory-challenge-problem-4] Challenge problem 4 for the new user of ACL2 [Introductory-challenge-problem-4-answer] Answer to challenge problem 4 for the new user of ACL2 [Introductory-challenges] Challenge problems for the new ACL2 user [Logic-knowledge-taken-for-granted] Background knowledge in ACL2 logic for theorem prover tutorial [Logic-knowledge-taken-for-granted-base-case] A brief explanation of base cases [Logic-knowledge-taken-for-granted-equals-for-equals] Substitution of equals for equals [Logic-knowledge-taken-for-granted-evaluation] Evaluation during proofs [Logic-knowledge-taken-for-granted-inductive-proof] A brief explanation of induction [Logic-knowledge-taken-for-granted-instance] A brief explanation of substitution instances [Logic-knowledge-taken-for-granted-propositional-calculus] A brief explanation of propositional calculus [Logic-knowledge-taken-for-granted-q1-answer] The inductive step of the rev-rev proof -- Answer to Question 1 [Logic-knowledge-taken-for-granted-q2-answer] The inductive step of the rev-rev proof -- Answer to Question 2 [Logic-knowledge-taken-for-granted-q3-answer] The inductive step of the rev-rev proof -- Answer to Question 2 [Logic-knowledge-taken-for-granted-rewriting] A brief explanation of rewriting from the logical perspective [Logic-knowledge-taken-for-granted-rewriting-repeatedly] Further information on expanding definitions via rewriting [Post-induction-key-checkpoints] Reading post-induction key checkpoints [Practice-formulating-strong-rules] A few simple checkpoints suggesting strong rules [Practice-formulating-strong-rules-1] Rules suggested by ([TRUE-LISTP] ([APPEND] (FOO A) (BAR B))) [Practice-formulating-strong-rules-2] Rules suggested by ([TRUE-LISTP] (REV (FOO A))) [Practice-formulating-strong-rules-3] Rules suggested by ([MEMBER] (FOO A) ([APPEND] (BAR B) (MUM C))) [Practice-formulating-strong-rules-4] Rules suggested by ([SUBSETP] ([APPEND] (FOO A) (BAR B)) (MUM C)) [Practice-formulating-strong-rules-5] Rules suggested by ([SUBSETP] (FOO A) ([APPEND] (BAR B) (MUM C))) [Practice-formulating-strong-rules-6] Rules suggested by ([MEMBER] (FOO A) (NATS-BELOW (BAR B))) [Programming-knowledge-taken-for-granted] Background knowledge in ACL2 programming for theorem prover tutorial [Special-cases-for-rewrite-rules] Convenient short forms for rewrite rule formulas [Specific-kinds-of-formulas-as-rewrite-rules] Advice about how to handle commonly occurring formulas as rewrite rules [Strong-rewrite-rules] Formulating good rewrite rules") (INTRODUCTORY-CHALLENGE-PROBLEM-1 (INTRODUCTION-TO-THE-THEOREM-PROVER) "Challenge problem 1 for the new user of ACL2 Start in a fresh ACL2, either by restarting your ACL2 image from scratch or executing :ubt! 1 which will undo everything since the first user event. Then define this function: (defun rev (x) (if (endp x) nil (append (rev (cdr x)) (list (car x))))) Then use The Method to prove: (defthm triple-rev (equal (rev (rev (rev x))) (rev x))) When you've solved this problem, compare your answer to ours; see [introductory-challenge-problem-1-answer]. Then, use your browser's Back Button to return to [introductory-challenges].") (INTRODUCTORY-CHALLENGE-PROBLEM-1-ANSWER (INTRODUCTION-TO-THE-THEOREM-PROVER) "Answer to challenge problem 1 for the new user of ACL2 This answer is in the form of an ACL2 script sufficient to lead ACL2 to a proof. (defun rev (x) (if (endp x) nil (append (rev (cdr x)) (list (car x))))) ; Trying triple-rev at this point produces a key checkpoint containing ; (REV (APPEND (REV (CDR X)) (LIST (CAR X)))), which suggests: (defthm rev-append (equal (rev (append a b)) (append (rev b) (rev a)))) ; And now triple-rev succeeds. (defthm triple-rev (equal (rev (rev (rev x))) (rev x))) ; An alternative, and more elegant, solution is to prove the rev-rev ; instead of rev-append: ; (defthm rev-rev ; (implies (true-listp x) ; (equal (rev (rev x)) x))) ; Rev-rev is also discoverable by The Method because it is ; suggested by the statement of triple-rev itself: rev-rev ; simplifies a simpler composition of the functions in triple-rev. ; Both solutions produce lemmas likely to be of use in future proofs ; about rev. Use your browser's Back Button now to return to [introductory-challenge-problem-1].") (INTRODUCTORY-CHALLENGE-PROBLEM-2 (INTRODUCTION-TO-THE-THEOREM-PROVER) "Challenge problem 2 for the new user of ACL2 Start in a fresh ACL2, either by restarting your ACL2 image from scratch or executing :ubt! 1. Use The Method to prove (defthm subsetp-reflexive (subsetp x x)) When you've solved this problem, compare your answer to ours; see [introductory-challenge-problem-2-answer]. Then, use your browser's Back Button to return to [introductory-challenges].") (INTRODUCTORY-CHALLENGE-PROBLEM-2-ANSWER (INTRODUCTION-TO-THE-THEOREM-PROVER) "Answer to challenge problem 2 for the new user of ACL2 This answer is in the form of a script sufficient to lead ACL2 to a proof. ; Trying subsetp-reflexive at this point produces the key checkpoint: ; (IMPLIES (AND (CONSP X) ; (SUBSETP (CDR X) (CDR X))) ; (SUBSETP (CDR X) X)) ; which suggests the generalization: (defthm subsetp-cdr (implies (subsetp a (cdr b)) (subsetp a b))) ; And now subsetp-reflexive succeeds. (defthm subsetp-reflexive (subsetp x x)) ; A weaker version of the lemma, namely the one in which we ; add the hypothesis that b is a cons, is also sufficient. ; (defthm subsetp-cdr-weak ; (implies (and (consp b) ; (subsetp a (cdr b))) ; (subsetp a b))) ; But the (consp b) hypothesis is not really necessary in ; ACL2's type-free logic because (cdr b) is nil if b is ; not a cons. For the reasons explained in the tutorial, we ; prefer the strong version. Use your browser's Back Button now to return to [introductory-challenge-problem-2].") (INTRODUCTORY-CHALLENGE-PROBLEM-3 (INTRODUCTION-TO-THE-THEOREM-PROVER) "Challenge problem 3 for the new user of ACL2 Start in a fresh ACL2, either by restarting your ACL2 image from scratch or executing :ubt! 1. Define the following functions and use The Method to prove the theorem at the bottom: (defun rev (x) (if (endp x) nil (append (rev (cdr x)) (list (car x))))) (defun dupsp (x) ; does x contain duplicate elements? (if (endp x) nil (if (member (car x) (cdr x)) t (dupsp (cdr x))))) (defthm dupsp-rev (equal (dupsp (rev x)) (dupsp x))) When you've solved this problem, compare your answer to ours; see [introductory-challenge-problem-3-answer]. Then, use your browser's Back Button to return to [introductory-challenges].") (INTRODUCTORY-CHALLENGE-PROBLEM-3-ANSWER (INTRODUCTION-TO-THE-THEOREM-PROVER) "Answer to challenge problem 3 for the new user of ACL2 This answer is in the form of a script sufficient to lead ACL2 to a proof. ; Trying dupsp-rev at this point produces the key checkpoint: ; (IMPLIES (AND (CONSP X) ; (NOT (MEMBER (CAR X) (CDR X))) ; (EQUAL (DUPSP (REV (CDR X))) ; (DUPSP (CDR X)))) ; (EQUAL (DUPSP (APPEND (REV (CDR X)) (LIST (CAR X)))) ; (DUPSP (CDR X)))) ; which suggests the lemma ; (defthm dupsp-append ; (implies (not (member e x)) ; (equal (dupsp (append x (list e))) ; (dupsp x)))) ; However, attempting to prove that, produces a key checkpoint ; containing (MEMBER (CAR X) (APPEND (CDR X) (LIST E))). ; So we prove the lemma: (defthm member-append (iff (member e (append a b)) (or (member e a) (member e b)))) ; Note that we had to use iff instead of equal since ; member is not a Boolean function. ; Having proved this lemma, we return to dupsp-append and succeed: (defthm dupsp-append (implies (not (member e x)) (equal (dupsp (append x (list e))) (dupsp x)))) ; So now we return to dups-rev, expecting success. But it fails ; with the same key checkpoint: ; (IMPLIES (AND (CONSP X) ; (NOT (MEMBER (CAR X) (CDR X))) ; (EQUAL (DUPSP (REV (CDR X))) ; (DUPSP (CDR X)))) ; (EQUAL (DUPSP (APPEND (REV (CDR X)) (LIST (CAR X)))) ; (DUPSP (CDR X)))) ; Why wasn't our dupsp-append lemma applied? We have two choices here: ; (1) Think. (2) Use tools. ; Think: When an enabled rewrite rule doesn't fire even though the ; left-hand side matches the target, the hypothesis couldn't be ; relieved. The dups-append rule has the hypothesis (not ; (member e x)) and after the match with the left-hand side, e ; is (CAR X) and x is (REV (CDR X)). So the system ; couldn't rewrite (NOT (MEMBER (CAR X) (REV (CDR X)))) to true, ; even though it knows that (NOT (MEMBER (CAR X) (CDR X))) from ; the second hypothesis of the checkpoint. Obviously, we need to ; prove member-rev below. ; Use tools: We could enable the ``break rewrite'' facility, with ; ACL2 !>:brr t ; and then install an unconditional monitor on the rewrite rule ; dupsp-append, whose rune is (:REWRITE DUPSP-APPEND), with: ; :monitor (:rewrite dupsp-append) t ; Then we could re-try our main theorem, dupsp-rev. At the resulting ; interactive break we type :eval to evaluate the attempt to relieve the ; hypotheses of the rule. ; (1 Breaking (:REWRITE DUPSP-APPEND) on ; (DUPSP (BINARY-APPEND (REV #) (CONS # #))): ; 1 ACL2 >:eval ; 1x (:REWRITE DUPSP-APPEND) failed because :HYP 1 rewrote to ; (NOT (MEMBER (CAR X) (REV #))). ; Note that the report above shows that hypothesis 1 of the rule ; did not rewrite to T but instead rewrote to an expression ; involving (member ... (rev ...)). Thus, we're led to the ; same conclusion that Thinking produced. To get out of the ; interactive break we type: ; 1 ACL2 >:a! ; Abort to ACL2 top-level ; and then turn off the break rewrite tool since we won't need it ; again right now, with: ; ACL2 !>:brr nil ; In either case, by thinking or using tools, we decide to prove: (defthm member-rev (iff (member e (rev x)) (member e x))) ; which succeeds. Now when we try to prove dups-rev, it succeeds. (defthm dupsp-rev (equal (dupsp (rev x)) (dupsp x))) Use your browser's Back Button now to return to [introductory-challenge-problem-3].") (INTRODUCTORY-CHALLENGE-PROBLEM-4 (INTRODUCTION-TO-THE-THEOREM-PROVER) "Challenge problem 4 for the new user of ACL2 Start in a fresh ACL2, either by restarting your ACL2 image from scratch or executing :ubt! 1. This problem is much more open ended than the preceding ones. The challenge is to define a function that collects exactly one copy of each element of a list and to prove that it returns a subset of the list with no duplications. Hint: We recommend that you read this hint to align your function names with our solution, to make comparisons easier. Our answer is shown in see [introductory-challenge-problem-4-answer]. In that page you'll see a definition of a function collect-once and the proofs of two theorems: (defthm main-theorem-1-about-collect-once (subsetp (collect-once x) x)) (defthm main-theorem-2-about-collect-once (not (dupsp (collect-once x)))) The function dupsp is as defined in see [introductory-challenge-problem-3]. This is quite easy. Then, we define a tail-recursive version of the method based on the pseudo-code: a = nil; while (x not empty) { a = if (member (car x) a) then a else (cons (car x) a); x = (cdr x); } return a; We formalize this with the function while-loop-version, where (while-loop-version x nil) is the ``semantics'' of the code above. I.e., the function while-loop-version captures the while loop in the pseudo-code above and returns the final value of a, and it should be invoked with the initial value of a being nil. We prove (while-loop-version x nil) returns a subset of x that contains no duplications. Furthermore, we do it two ways: first ``indirectly'' by relating while-loop-version to collect-once, and second (``directly'') without using collect-once. Both of these proofs are much harder than the collect-once approach, involving about a dozen lemmas each. Compare your solutions to ours at see [introductory-challenge-problem-4-answer]. Then, use your browser's Back Button to return to [introductory-challenges].") (INTRODUCTORY-CHALLENGE-PROBLEM-4-ANSWER (INTRODUCTION-TO-THE-THEOREM-PROVER) "Answer to challenge problem 4 for the new user of ACL2 This answer is in the form of a script sufficient to lead ACL2 to a proof, with a brief prologue. We wish to collect one copy of each element in x. We'll actually define the method two ways, primitive recursively and tail-recursively, the latter method being analogous to the program: a = nil; while (x not empty) { a = if (member (car x) a) then a else (cons (car x) a); x = (cdr x); } return a; We'll prove the two ``equivalent'' and we'll prove that they return a subset of x that contains no duplications. This page is organized into four sections. (A) We will start by proving that the primitive recursive version correct: it returns a subset of its argument that is duplication free. This will be straightforward. (B) Then we'll define the while-loop version and we will prove it ``equivalent'' to the primitive recursive version. This will be challenging primarily because the two methods collect their answers in different orders; even stating the relationship between the two is interesting. Proving it will involve a few lemmas. But once we prove their ``equivalence'' the correctness of the while-loop version will be straightforward from the correctness of the primitive recursive version. (C) We will disable the rules we prove about the while-loop version and prove it correct directly, without exploiting the primitive recursive version. This requires leading the theorem prover more carefully because reasoning about tail-recursive functions that accumulate results is sometimes delicate. (D) Lessons learned -- a narrative that summarizes what we learn from these examples. We follow The Method, which, recall, involves us in recursive attempts to prove lemmas. We use a notation to indicate our sequence of proof attempts. Here is an example (although in actual use we print things across multiple lines). The number in bracket indicates our ``stack depth''. The ``key term'' is some term from a Key Checkpoint in the failed proof which is responsible for our subsequent action. Sometimes instead of a Key Term we just give an English explanation of what we're thinking. [0] (defthm main ...) Failed! Key Term: ... [1] (defthm lemma-1 ...) Succeeded! [0] (defthm main ...) Failed! Key Term: ... [1] (defthm lemma-2 ...) Failed! Key Term: ... [2] (defthm lemma-2a ...) Succeeded! [2] (defthm lemma-2b ...) Succeeded! [1] (defthm lemma-2 ...) Succeeded! [0] (defthm main ...) Succeeded! The rest of this page is just a re-playable script. ; ----------------------------------------------------------------- ; Section A: The Primitive Recursive Version and Its Correctness ; The property of having duplications is defined as: (defun dupsp (x) (if (endp x) nil (if (member (car x) (cdr x)) t (dupsp (cdr x))))) ; The primitive recursive method of collecting one copy of each element is: (defun collect-once (x) (if (endp x) nil (if (member (car x) (cdr x)) (collect-once (cdr x)) (cons (car x) (collect-once (cdr x)))))) ; [0] (defthm main-theorem-1-about-collect-once (subsetp (collect-once x) x)) ; Succeeded! ; [0] ; (defthm main-theorem-2-about-collect-once ; (not (dupsp (collect-once x)))) ; Failed! ; Key Term: (MEMBER (CAR X) (COLLECT-ONCE (CDR X))) ; [1] (defthm member-collect-once (iff (member e (collect-once a)) (member e a))) ; Succeeded! ; [0] (defthm main-theorem-2-about-collect-once (not (dupsp (collect-once x)))) ; Succeeded! ; That was really easy! ;----------------------------------------------------------------- ; Section B: The While-Loop Version and Its Correctness -- ; presented in two parts: its equivalence to the primitive recursive ; version and then its correctness proved via that equivalence ; The tail-recursive, or while-loop version, is defined as follows. The ; function below is the loop itself and it ought to be called with a = nil to ; implement the initialization of a in the pseudo-code above. (defun while-loop-version (x a) (if (endp x) a (while-loop-version (cdr x) (if (member (car x) a) a (cons (car x) a))))) ; We wish to prove that the two are equivalent. But they are actually ; very different. For example, ; (collect-once '(2 4 1 3 1 2 3 4)) = (1 2 3 4) ; (while-loop-version '(2 4 1 3 1 2 3 4) nil) = (3 1 4 2) ; Things get a little more complicated if a is non-nil: ; (while-loop-version '(2 4 1 3 1 2 3 4) '(2 2 4 4)) = (3 1 2 2 4 4) ; Several observations help explain what is happening. (1) Collect-once ; collects the last occurrence of each element, in the order of their last ; occurrences. So, for example, since the last occurrence of 2 preceeds the ; last occurrence of 3 in '(2 4 1 3 1 2 3 4)), then the collected 2 preceeds ; the collected 3 in the answer. But while-loop-version collects the first ; occurrence of each element, in the reverse order of that occurrence. So it ; adds 2 to its accumulator first and adds 3 last, making 3 preceed 2 in the ; answer. ; (2) The while-loop-version does not collect anything already in a and indeed ; just adds stuff to the front of a, returning everything initially in a plus ; one occurrence of everything in x not in a. ; To state the relationship that holds between these two we have to define two ; other functions. ; This is our familiar list reverse function... (defun rev (x) (if (endp x) nil (append (rev (cdr x)) (list (car x))))) ; And this function ``removes'' from x all the elements in y, i.e., copies x ; while dropping the elements of y. (defun list-minus (x y) (if (endp x) nil (if (member (car x) y) (list-minus (cdr x) y) (cons (car x) (list-minus (cdr x) y))))) ; The specific equivalence we're really interested in is ; (equal (while-loop-version x nil) ; (collect-once (rev x))) ; But we will not be able to prove that by induction because it has the ; constant nil where we need a variable, a, in order to admit an appropriate ; inductive instance. So we will attack the most general problem. What is ; (while-loop-version x a) equal to, in terms of collect-once? ; The most general relationship between the two collection functions is: ; (equal (while-loop-version x a) ; (append (collect-once (list-minus (rev x) a)) a)) ; This formula bears thinking about! If you're like us, you won't believe it ; until it is proved! ; [0] ; (defthm general-equivalence ; (equal (while-loop-version x a) ; (append (collect-once (list-minus (rev x) a)) a))) ; Failed! ; Key term in checkpoint: ; (LIST-MINUS (APPEND (REV (CDR X)) (LIST (CAR X))) A) ; [1] (defthm list-minus-append (equal (list-minus (append a b) c) (append (list-minus a c) (list-minus b c)))) ; Succeeded! ; [0] ; (defthm general-equivalence ; (equal (while-loop-version x a) ; (append (collect-once (list-minus (rev x) a)) a))) ; Failed! ; Key term in checkpoint: ; (COLLECT-ONCE (APPEND (LIST-MINUS (REV (CDR X)) A) (LIST (CAR X)))) ; [1] ; (defthm collect-once-append ; (equal (collect-once (append a b)) ; (append (list-minus (collect-once a) b) ; (collect-once b)))) ; Failed! ; Key term: ; (MEMBER (CAR A) (APPEND (CDR A) B)) ; [2] (defthm member-append (iff (member e (append a b)) (or (member e a) (member e b)))) ; Succeeded! ; [1] (defthm collect-once-append (equal (collect-once (append a b)) (append (list-minus (collect-once a) b) (collect-once b)))) ; Succeeded! ; [0] ; (defthm general-equivalence ; (equal (while-loop-version x a) ; (append (collect-once (list-minus (rev x) a)) a))) ; Failed! ; Key term: ; (APPEND (APPEND (LIST-MINUS (COLLECT-ONCE (LIST-MINUS (REV (CDR X)) A)) ; [1] (defthm assoc-append (equal (append (append a b) c) (append a (append b c)))) ; Succeeded! ; [0] ; (defthm general-equivalence ; (equal (while-loop-version x a) ; (append (collect-once (list-minus (rev x) a)) a))) ; Failed! ; Key term: ; (LIST-MINUS (COLLECT-ONCE (LIST-MINUS (REV (CDR X)) A)) ...) ; This key term makes us think of the lemma to move the LIST-MINUS inside the ; COLLECT-ONCE. But when that's done, we will have two LIST-MINUS terms ; nestled together and we will want to combine them into one. Call these two ; lemmas (a) and (b). ; [1] (a) ; (defthm list-minus-collect-once ; (equal (list-minus (collect-once x) a) ; (collect-once (list-minus x a)))) ; Failed! ; Key term: ; (MEMBER (CAR X) (LIST-MINUS (CDR X) A)) ; [2] (A pretty fact) (defthm member-list-minus (iff (member e (list-minus x a)) (and (member e x) (not (member e a))))) ; Succeeded! ; [1] (a) (defthm list-minus-collect-once (equal (list-minus (collect-once x) a) (collect-once (list-minus x a)))) ; Succeeded! ; [1] (b) (defthm list-minus-list-minus (equal (list-minus (list-minus x a) b) (list-minus x (append b a)))) ; Succeeded! ; [0] (defthm general-equivalence (equal (while-loop-version x a) (append (collect-once (list-minus (rev x) a)) a))) ; Succeeded! ; That completes the proof of the ``equivalence'' of the two methods. ; Now we prove (1) that the result of while-loop-version is a subset, and (2) ; that it contains no duplications. We prove the two conjuncts separately. ; [0] (defthm main-theorem-1-about-while-loop (subsetp (while-loop-version x nil) x)) ; Succeeded! ; But the theorem prover works harder to do the proof above than one might have ; expected because it doesn't turn into an instance of ; main-theorem-1-about-collect-once because of the presence of the rev term. ; However, we're content that ACL2 managed to do the proof on its own. ; [0] (defthm main-theorem-2-about-while-loop (not (dupsp (while-loop-version x nil)))) ; So we see that the proof of correctness of while-loop-version isn't hard, ; after we establish the relationship with the primitive recursive version. ; But finding and proving the relationship is fairly challenging. ; ----------------------------------------------------------------- ; Section C: A Direct Proof of the Correctness of the While-Loop Version ; Some would consider the proof in Section B ``indirect'' because we first showed ; how while-loop-version could be expressed as a collect-once and then proved ; our main theorems about while-loop-version, which means those main proofs ; were conducted in terms of collect-once, not while-loop-version. ; It is interesting to compare this proof with the ``direct'' one in which ; we don't use collect-once at all and reason only about while-loop-version. ; So to do that comparison, let's disable all the lemmas we've proved about ; while-loop-version and try to prove the two main theorems above about ; while-loop-version. (in-theory (disable general-equivalence main-theorem-1-about-while-loop main-theorem-2-about-while-loop)) ; [0] ; (defthm main-theorem-1-about-while-loop-redux ; (subsetp (while-loop-version x nil) x)) ; Failed! [Well, the truth is below...] ; We don't even submit this event above because we recognize that it is not ; general enough to permit proof by induction. We need to deal with the nil in ; the second argument of while-loop-version. Experience with induction tells ; us this should be a variable, so we can assume an appropriate inductive ; instance. Therefore, we adopt this subgoal immediately: ; [1] ; (defthm main-lemma-1-about-while-loop-version ; (subsetp (while-loop-version x a) (append x a))) ; Failed! ; Key Term: Does the wrong induction. ; [1] ; (defthm main-lemma-1-about-while-loop-version ; (subsetp (while-loop-version x a) (append x a)) ; :hints ((\"Goal\" :induct (while-loop-version x a)))) ; Failed! Two key terms are suggested ; Key term: (IMPLIES (AND ... (SUBSETP (WHILE-LOOP-VERSION (CDR X) A) (APPEND (CDR X) A))) ; (SUBSETP (WHILE-LOOP-VERSION (CDR X) A) (CONS ... (APPEND (CDR X) A)))) ; Key term: (SUBSETP A A) ; So we'll prove both before trying again. ; [2] (defthm subsetp-cons (implies (subsetp a b) (subsetp a (cons e b)))) ; Succeeded! ; [2] (defthm subsetp-reflexive (subsetp a a)) ; Succeeded! ; [1] ; (defthm main-lemma-1-about-while-loop-version ; (subsetp (while-loop-version x a) (append x a)) ; :hints ((\"Goal\" :induct (while-loop-version x a)))) ; Failed! ; Key Term: ; (IMPLIES (AND ... ; (SUBSETP (WHILE-LOOP-VERSION (CDR X) (CONS (CAR X) A)) ; (APPEND (CDR X) (CONS (CAR X) A)))) ; (SUBSETP (WHILE-LOOP-VERSION (CDR X) (CONS (CAR X) A)) ; (CONS (CAR X) (APPEND (CDR X) A)))) ; We'd be done if we could rewrite the ; (APPEND (CDR X) (CONS (CAR X) A)) ; to ; (CONS (CAR X) (APPEND (CDR X) A)) ; These two terms are not equal! But they are ``set-equal'' and this kind of ; rewriting is possible using user-defined equivalences and congruence rules. ; But the new user should not dive into congruences yet. So we will do this ; with ordinary lemmas: ; The plan then is to prove ; (iff (subsetp a (append b (cons e c))) ; (subsetp a (cons e (append b c)))) ; Consider the first half of this bi-implication: ; (implies (subsetp a (append b (cons e c))) ; hyp1 ; (subsetp a (cons e (append b c)))) ; concl ; Notice that if we knew ; (subsetp (append b (cons e c)) (cons e (append b c))) ; hyp2 ; then we could use hyp1 and hyp2 together with the transitivity of ; subsetp to get concl. ; The proof in the other direction is comparable but requires the ; (subsetp (cons e (append b c)) (append b (cons e c))) ; Thus, our plan is prove ; (a) transitivity of subsetp ; (b) (subsetp (append b (cons e c)) (cons e (append b c))) ; (c) (subsetp (cons e (append b c)) (append b (cons e c))) ; in order to prove ; (d) (iff (subsetp a (append b (cons e c))) ; (subsetp a (cons e (append b c)))) ; [2] (a) (defthm trans-subsetp (implies (and (subsetp a b) (subsetp b c)) (subsetp a c))) ; Succeeded! ; [2] (b) (defthm append-cons-v-cons-append-1 (subsetp (append b (cons e c)) (cons e (append b c)))) ; Succeeded! ; [2] (c) (defthm append-cons-v-cons-append-2 (subsetp (cons e (append b c)) (append b (cons e c)))) ; Succeeded! ; [2] (d) (defthm subsetp-append-cons-cons-append (iff (subsetp a (append b (cons e c))) (subsetp a (cons e (append b c))))) ; Succeeded! ; [1] (defthm main-lemma-1-about-while-loop-version (subsetp (while-loop-version x a) (append x a)) :hints ((\"Goal\" :induct (while-loop-version x a)))) ; Succeeded! ; [0] ; (defthm main-theorem-1-about-while-loop-version ; (subsetp (while-loop-version x nil) x)) ; Failed! [But the truth is below...] ; But we don't submit this because we don't expect it to be proved ; from the main lemma just proved: they don't match! But ; note that if we instantiated the main lemma, replacing a by nil, ; we get: ; (subsetp (while-loop-version x nil) (append x nil)) ; and we could simplify the (append x nil) to x in this context, with ; another congruence rule -- if we were using them. So let's prove ; first that we can simplify (append x nil) inside a subsetp: ; [1] (defthm subsetp-append-nil (iff (subsetp x (append y nil)) (subsetp x y))) ; Succeeded! ; and then just tell ACL2 how to use the lemma to get the main theorem. Note ; that we give a hint to instantiate main-lemma-1... but we also disable ; main-lemma-1... because otherwise it will rewrite itself away! Once the ; instance of main-lemma-1... is sitting around as a hypothesis, ; subsetp-append-nil will rewrite the (append x nil) to x for us and finish the ; proof. ; [0] (defthm main-theorem-1-about-while-loop-version (subsetp (while-loop-version x nil) x) :hints ((\"Goal\" :use (:instance main-lemma-1-about-while-loop-version (x x) (a nil)) :in-theory (disable main-lemma-1-about-while-loop-version)))) ; Succeeded! ; Recall that the main-theorem-1... just proved is just half of what we want. ; We also want: ; [0] ; (defthm main-theorem-2-about-while-loop-version ; (not (dupsp (while-loop-version x nil)))) ; Failed! [But the truth is below...] ; But, again, we don't submit that because the nil makes it not general enough for ; induction. Instead we go immediately to: ; [1] (defthm main-lemma-2-about-while-loop-version (implies (not (dupsp a)) (not (dupsp (while-loop-version x a))))) ; Succeeded! ; This time we know our main-lemma-2... will match (there's no (append x nil) ; in there to mess things up) and so we can complete the proof with: ; [0] (defthm main-theorem-2-about-while-loop-version (not (dupsp (while-loop-version x nil)))) ; Succeeded! ;----------------------------------------------------------------- ; Section D: Lessons Learned ; The most obvious lesson is that it is easier to reason about the primitive ; recursive collect-once than about the while-loop-version. Thus, if your only ; need is for a function that collects one occurrence of each element of a list ; and you don't care about the order in which you collect them and you don't ; need it to be very sparing of stack space when it executes, then use the ; primitive recursive definition and don't even think about while loops! ; So why might you be driven to while-loop-version? One possibility is that ; the list you wish to process is very long and the primitive recursive version ; would produce a stack overflow. In ACL2, that would mean the list would have ; to be several thousand long. Is your application really so demanding? ; Another possibility is that you are modeling in Lisp a while loop expressed ; in some other programming language. In that case, the fidelity of your model to ; the artifact being modeled is important and you should use while-loop-version. ; Another possibility is that for some reason order matters and you really are ; interested in collecting the first occurrence rather than the last. Of ; course this is most likely to be relevant in more interesting applications ; where the occurrences are somehow distinguishable. ; If you are forced to deal with the while-loop-version the question is do you ; do an indirect proof as in Section B or a direct proof as in Section C? ; The indirect proof involved 10 theorems and the direct proof involved 11. ; That is not a significant difference. ; But our sense is that the indirect proof is easier to find, once you figure ; out the basic shape of the relation between while-loop-version collect-once. ; In particular, we had to give the theorem prover two hints in the direct ; proof (versus no hints in the indirect proof). One of our hints was about ; what induction to do and the other was about how to use a previously proved ; instance of a lemma involving an accumulator. Furthermore, we had to think ; carefully about the use of the transitivity of subsetp and we had to hack our ; way around rewriting (append a (cons e b)) to (cons e (append a b)) in a ; subsetp-expression. ; Some of these ``set'' problems could have been handled a lot more elegantly by ; defining set-equal as an equivalence relation and proving the congruence ; rules to allow the rewriting of set-equal terms to set-equal terms inside ; certain expressions like subsetp and member. However, that involves a lot of ; overhead in the form of congruence rules showing that set-equality is ; maintained by replacement of set-equals by set-equals in various argument ; positions of the various functions. See :doc congruence. In general, we ; find congruence-based reasoning extremely neat and powerful when the ; appropriate infrastructure has been built up. But because the infrastructure ; is ``heavy'' we tend not to invest in it for small projects. ; In summary, different users might take home different lessons about whether a ; direct or indirect proof is better here. This is in part due to the ; complexity of the functional relationship between collect-once and ; while-loop-version, which additionall involved append, list-minus, and rev. ; Had the relationship been simpler, the indirect proof would have been ; preferred. ; An undeniable lesson, however, is that it is helpful to know both styles of ; proof and to be able to explore both as needed in your applications. Use your browser's Back Button now to return to [introductory-challenge-problem-4].") (INTRODUCTORY-CHALLENGES (INTRODUCTION-TO-THE-THEOREM-PROVER) "Challenge problems for the new ACL2 user Do each of the problems. In each case, start with a fresh ACL2 (or undo all effects of previous events with :ubt! 1). This may require that you ``re-discover'' the same lemma more than once in different problems, but recognizing the need for something you used in some previous project is part of the training. We recommend that you follow The Method and consult the documentation as needed -- but that you not look at our answers until you're well and truly baffled! See [introductory-challenge-problem-1] (Answer: [introductory-challenge-problem-1-answer]) See [introductory-challenge-problem-2] (Answer: [introductory-challenge-problem-2-answer]) See [introductory-challenge-problem-3] (Answer: [introductory-challenge-problem-3-answer]) See [introductory-challenge-problem-4] (Answer: [introductory-challenge-problem-4-answer]) In addition to these explicit challenge problems designed for beginners, the ACL2 documentation has many example solutions to problems (not always phrased in the question/answer format here). If you are looking for other examples, you should consider [annotated-ACL2-scripts] (Answer: the answers are given in the examples) When you've done the problems and compared your solutions to ours, use your browser's Back Button now to return to [introduction-to-the-theorem-prover].") (INVARIANT-RISK (POINTERS) "See [program-wrapper].") (INVISIBLE-FNS-TABLE (LOOP-STOPPER) "Functions that are invisible to the [loop-stopper] algorithm Examples: ACL2 !>(invisible-fns-table (w state)) ((binary-+ unary--) (binary-* unary-/) (unary-- unary--) (unary-/ unary-/)) Among other things, the setting above has the effect of making [unary--] ``invisible'' for the purposes of applying permutative :[rewrite] rules to [binary-+] trees. Also see [add-invisible-fns] and see [remove-invisible-fns], which manage macro aliases (see [macro-aliases-table]), as well as see [set-invisible-fns-table]. See [table] for a general discussion of tables. The ``invisible functions [table]'' is an alist with elements of the following form, where fn is a function symbol and the ufni are unary function symbols in the current ACL2 [world], and k is at least 1. (fn ufn1 ufn2 ... ufnk) This [table] thus associates with certain function symbols, e.g., fn above, a set of unary functions, e.g., the ufni above. The ufni associated with fn in the invisible functions table are said to be ``invisible with respect to fn.'' If fn is not the [car] of any pair in the alist, then no function is invisible for it. Thus for example, setting the invisible functions alist to nil completely eliminates the consideration of invisibility. The notion of invisibility is involved in the use of the :[loop-stopper] field of :[rewrite] rules to prevent the indefinite application of permutative rewrite rules. Roughly speaking, if rewrite rules are being used to permute arg and (ufni arg) inside of a nest of fn calls, and ufni is invisible with respect to fn, then arg and (ufni arg) are considered to have the same ``weight'' and will be permuted so as to end up as adjacent tips in the fn nest. See [loop-stopper].") (IO (INTERFACING-TOOLS STATE PROGRAMMING) "Input/output facilities in ACL2 Example: (mv-let (channel state) (open-input-channel \"foo.lisp\" :object state) (mv-let (eofp obj state) (read-object channel state) (. . (let ((state (close-input-channel channel state))) (mv final-ans state))..))) Also see [std/io] and [file-reading-example]. For advanced ways to control printing, see [print-control]. For a discussion of formatted printing, see [fmt]. To control ACL2 abbreviation (``evisceration'') of objects before printing them, see [set-evisc-tuple], see [without-evisc], and see [set-iprint]. To redirect output to a file, see [output-to-file]. ACL2 supports input and output facilities equivalent to a subset of those found in Common Lisp. ACL2 does not support random access to files or bidirectional streams. In Common Lisp, input and output are to or from objects of type stream. In ACL2, input and output are to or from objects called ``channels,'' which are actually symbols. Although a channel is a symbol, one may think of it intuitively as corresponding to a Common Lisp stream. Channels are in one of two ACL2 packages, \"ACL2-INPUT-CHANNEL\" and \"ACL2-OUTPUT-CHANNEL\". When one ``opens'' a file one gets back a channel whose [symbol-name] is the file name passed to ``open,'' postfixed with -n, where n is a counter that is incremented every time an open or close occurs. There are three channels which are open from the beginning and which cannot be closed: acl2-input-channel::standard-character-input-0 acl2-input-channel::standard-object-input-0 acl2-input-channel::standard-character-output-0 All three of these are really Common Lisp's *standard-input* or *standard-output*, appropriately. For convenience, three global variables are bound to these rather tedious channel names: *standard-ci* *standard-oi* *standard-co* Common Lisp permits one to open a stream for several different kinds of io, e.g. character or byte. ACL2 permits an additional type called ``object''. In ACL2 an ``io-type'' is a keyword, either :character, :byte, or :object. When one opens a file, one specifies a type, which determines the kind of io operations that can be done on the channel returned. The types :character and :byte are familiar. Type :object is an abstraction not found in Common Lisp. An :object file is a file of Lisp objects. One uses read-object to read from :object files and print-object$ (or print-object$-ser) to print to :object files. (The reading and printing are really done with the Common Lisp read and print functions. For those familiar with read, we note that the recursive-p argument is nil.) The function read-object-suppress is logically the same as read-object except that read-object-suppress throws away the second returned value, i.e. the value that would normally be read, simply returning (mv eof state); under the hood, read-object-suppress avoids errors, for example those caused by encountering symbols in packages unknown to ACL2. File-names are strings. ACL2 does not support the Common Lisp type [pathname]. However, for the file-name argument of the output-related functions listed below, ACL2 supports a special value, :STRING. For this value, the channel connects (by way of a Common Lisp output string stream) to a string rather than to a file: as characters are written to the channel they can be retrieved by using get-output-stream-string$. Here are the names, formals and output descriptions of the ACL2 io functions. Input Functions: (open-input-channel (file-name io-type state) (mv channel state)) (open-input-channel-p (channel io-type state) boolean) (close-input-channel (channel state) state) (read-char$ (channel state) (mv char/nil state)) ; nil for EOF (peek-char$ (channel state) boolean) (read-byte$ (channel state) (mv byte/nil state)) ; nil for EOF (read-object (channel state) (mv eof-read-flg obj-read state)) (read-object-suppress (channel state) (mv eof-read-flg state)) Output Functions: (open-output-channel (file-name io-type state) (mv channel state)) (open-output-channel! (file-name io-type state) (mv channel state)) (open-output-channel-p (channel io-type state) boolean) (close-output-channel (channel state) state) (princ$ (obj channel state) state) (write-byte$ (byte channel state) state) (print-object$ (obj channel state) state) (print-object$-ser (obj serialize-character channel state) state) (fms (string alist channel state evisc-tuple) state) (fms! (string alist channel state evisc-tuple) state) (fmt (string alist channel state evisc-tuple) (mv col state)) (fmt! (string alist channel state evisc-tuple) (mv col state)) (fmt1 (string alist col channel state evisc-tuple) (mv col state)) (fmt1! (string alist col channel state evisc-tuple) (mv col state)) (cw (string arg0 arg1 ... argn) nil) (get-output-stream-string$ (channel state &optional (close-p 't) (ctx ''get-output-stream-string$)) (mv erp string state)) The ``formatting'' functions are particularly useful; see [fmt] and see [cw]. In particular, [cw] prints to a ``comment window'' and does not involve the ACL2 [state], so many may find it easier to use than [fmt] and its variants. The functions [fms!], [fmt!], and [fmt1!] are the same as their respective functions without the ``!,'' except that the ``!'' functions are guaranteed to print forms that can be read back in (at a slight readability cost). When one enters ACL2 with (lp), input and output are taken from [*standard-oi*] to [*standard-co*]. Because these are synonyms for *standard-input* and *standard-output*, one can drive ACL2 io off of arbitrary Common Lisp streams, bound to *standard-input* and *standard-output* before entry to ACL2. The macro get-output-stream-string$ returns the string accumulated into the given channel. By default, a call of this macro closes the supplied output channel. However, a third argument is optional (default t), and if it evaluates to nil then the channel remains open. The fourth argument is an optional context, which generally evaluates to a symbol, for error reporting. The following example illustrates. ACL2 !> (mv-let (channel state) (open-output-channel :string :object state) (pprogn (print-object$-ser 17 nil channel state) (print-object$-ser '(a b (c d)) nil channel state) (er-let* ((str1 (get-output-stream-string$ channel state nil))) ; keep the channel open (pprogn (print-object$-ser 23 nil channel state) (print-object$-ser '((e f)) nil channel state) (er-let* ; close the channel ((str2 (get-output-stream-string$ channel state))) (value (cons str1 str2))))))) (\" 17 (A B (C D))\" . \" 23 ((E F))\") ACL2 !> Also see [printing-to-strings] for a discussion of formatted printing functions such as fmt-to-string that do not take a channel or [state] argument and return a string. By default, symbols are printed in upper case when vertical bars are not required, as specified by Common Lisp. See [set-print-case] for how to get ACL2 to print symbols in lower case. By default, numbers are printed in radix 10 (base 10). See [set-print-base-radix] for how to get ACL2 to print numbers in radix 2, 8, or 16. To see the [guard] of an IO function, or indeed any function, see [args] or call the function guard; but some built-in functions (including some IO functions) will print the result using the variable STATE-STATE. While that is logically correct, if you want to execute the guard then you should replace that variable by STATE and also replace each built-in function symbol of the form xxx-p1 by corresponding function symbol xxx-p. Consider the following example. ACL2 !>:args princ$ Function PRINC$ Formals: (X CHANNEL STATE-STATE) Signature: (PRINC$ * * STATE) => STATE Guard: (AND (OR (ACL2-NUMBERP X) (CHARACTERP X) (STRINGP X) (SYMBOLP X)) (STATE-P1 STATE-STATE) (SYMBOLP CHANNEL) (OPEN-OUTPUT-CHANNEL-P1 CHANNEL :CHARACTER STATE-STATE)) Guards Verified: T Defun-Mode: :logic Type: (CONSP (PRINC$ X CHANNEL STATE-STATE)) Documentation available via :DOC PRINC$ ACL2 !>(untranslate (guard 'princ$ nil (w state)) t (w state)) (AND (OR (ACL2-NUMBERP X) (CHARACTERP X) (STRINGP X) (SYMBOLP X)) (STATE-P1 STATE-STATE) (SYMBOLP CHANNEL) (OPEN-OUTPUT-CHANNEL-P1 CHANNEL :CHARACTER STATE-STATE)) ACL2 !> If you want to execute the guard for [princ$], then according to the suggestion above, you should consider the guard for (princ$ x channel state) to be as follows. (AND (OR (ACL2-NUMBERP X) (CHARACTERP X) (STRINGP X) (SYMBOLP X)) (STATE-P STATE) (SYMBOLP CHANNEL) (OPEN-OUTPUT-CHANNEL-P CHANNEL :CHARACTER STATE)) For example, we can check the guard for a given value and channel as follows. ACL2 !>(let ((x 3) (channel *standard-co*)) (AND (OR (ACL2-NUMBERP X) (CHARACTERP X) (STRINGP X) (SYMBOLP X)) (STATE-P STATE) (SYMBOLP CHANNEL) (OPEN-OUTPUT-CHANNEL-P CHANNEL :CHARACTER STATE))) T ACL2 !> Comment for advanced users: Function [open-output-channel!] is identical as a function to open-output-channel, except that the former may be called even during [make-event] expansion and [clause-processor] [hints], but requires that there is an active trust tag (see [defttag]). Finally, we note that the [std/io] library contains useful file io functions whose definitions illustrate some of the features described above. Subtopics [*standard-ci*] An ACL2 character-based analogue of CLTL's *standard-input* [*standard-co*] The ACL2 analogue of CLTL's *standard-output* [*standard-oi*] An ACL2 object-based analogue of CLTL's *standard-input* [Character-encoding] How bytes are parsed into characters [Cw] Print to the comment window [Cw!] Print to the comment window [Evisc-tuple] Control suppression of details when printing [Eviscerate-hide-terms] To print ([hide] ...) as [Fms] ([fms] str alist co-channel state evisc) => state [Fms!] ([fms!] str alist co-channel state evisc) => state [Fmt] Formatted printing [Fmt!] ([fmt!] str alist co-channel state evisc) => state [Fmt-to-comment-window] Print to the comment window [Fmt1] ([fmt1] str alist col co-channel state evisc) => ([mv] col state) [Fmt1!] ([fmt1!] str alist col channel state evisc) => ([mv] col state) [Msg] Construct a ``message'' suitable for the ~@ directive of [fmt] [Observation] Print an observation [Open-output-channel!] When trust tags are needed to open output channels [Output-to-file] Redirecting output to a file [Princ$] Print an atom [Print-base-p] Recognizer for print bases that are understood by functions such as [explode-nonnegative-integer] and [explode-atom]. [Print-control] Advanced controls of ACL2 printing [Printing-to-strings] Printing to strings instead of files or standard output [Proofs-co] The proofs character output channel [Serialize] Routines for saving ACL2 objects to files, and later restoring them [Set-evisc-tuple] Control suppression of details when printing [Set-fmt-hard-right-margin] Set the right margin for formatted output [Set-fmt-soft-right-margin] Set the soft right margin for formatted output [Set-iprint] Control whether abbreviated output can be read back in [Set-print-base] Control radix in which numbers are printed [Set-print-base-radix] Control radix in which numbers are printed and printing of the radix [Set-print-case] Control whether symbols are printed in upper case or in lower case [Set-print-radix] Control printing of the radix for numbers [Standard-co] The character output channel to which [ld] prints [Standard-oi] The standard object input ``channel'' [Without-evisc] Print output in full [Wof] Direct standard output and proofs output to a file") (IPRINT (POINTERS) "See [set-iprint].") (IPRINTING (POINTERS) "See [set-iprint].") (IRRELEVANT-FORMALS (PROGRAMMING) "Formals that are used but only insignificantly Let fn be a function of n arguments. Let x be the ith formal of fn. We say x is ``irrelevant in fn'' if x does not occur in either the [guard] or the measure for fn, and the value of (fn a1...ai...an) is independent of ai. The easiest way to define a function with an irrelevant formal is simply not to use the formal in the body of the function. Such formals are said to be ``ignored'' by Common Lisp and a special declaration is provided to allow ignored formals. ACL2 makes a distinction between ignored and irrelevant formals. Note however that if a variable is [declare]d ignored or ignorable, then it will not be reported as irrelevant. An example of an irrelevant formal is x in the definition of fact below. (defun fact (i x) (declare (xargs :guard (and (integerp i) (<= 0 i)))) (if (zerop i) 1 (* i (fact (1- i) (cons i x))))). Observe that x is only used in recursive calls of fact; it never ``gets out'' into the result. ACL2 can detect some irrelevant formals by a closure analysis on how the formals are used. For example, if the ith formal is only used in the ith argument position of recursive calls, then it is irrelevant. This is how x is used above. It is possible for a formal to appear only in recursive calls but still be relevant. For example, x is not irrelevant below, even though it only appears in the recursive call. (defun fn (i x) (if (zerop i) 0 (fn x (1- i)))) The key observation above is that while x only appears in a recursive call, it appears in an argument position, namely i's, that is relevant. (The function above can be admitted with a :measure of (+ (nfix i) (nfix x)).) Establishing that a formal is irrelevant, in the sense defined above, can be an arbitrarily hard problem because it requires theorem proving. For example, is x irrelevant below? (defun test (i j k x) (if (p i j k) 0 x)) Note that the value of (test i j k x) is independent of x --- thus making x irrelevant --- precisely if (p i j k) is a theorem. ACL2's syntactic analysis of a definition does not guarantee to notice all irrelevant formals. We regard the presence of irrelevant formals as an indication that something is wrong with the definition. We cause an error on such definitions and suggest that you recode the definition so as to eliminate the irrelevant formals. If you must have an irrelevant formal, one way to ``trick'' ACL2 into accepting the definition, without slowing down the execution of your function, is to use the formal in an irrelevant way in the [guard]. For example, to admit fact, above, with its irrelevant x one might use (defun fact (i x) (declare (xargs :guard (and (integerp i) (<= 0 i) (equal x x)))) (if (zerop i) 0 (* i (fact (1- i) (cons i x))))) For those who really want to turn off this feature, we have provided a way to use the [ACL2-defaults-table] for this purpose; see [set-irrelevant-formals-ok].") (KEEP (BOOKS-TOUR) "How we know if [include-book] read the correct files The certificate (see [certificate] for general information) of a certified file is divided into two parts, a [portcullis] and a keep. These names come from castle lore. The keep is the strongest and usually tallest tower of a castle from which the entire courtyard can be surveyed by the defenders. The keep of a book is a list of file names and check sums used after the book has been included, to determine if the files read were (up to check sum) those certified. Once the [portcullis] is open, [include-book] can enter the book and read the event forms therein. The non-[local] event forms are in fact executed, extending the host theory. That may read in other [books]. When that has been finished, the keep of the [certificate] is inspected. The keep is a list of the book names which are included (hereditarily through all sub-books) in the certified book (including the certified book itself) together with the check sums of the objects in those [books] at the time of certification. We compare the check sums of the [books] just included to the check sums of the [books] stored in the keep. If differences are found then we know that the book or one of its sub-books has been changed since certification. See [include-book] to continue the guided tour through [books].") (KEYWORD (POINTERS) "See [keywordp].") (KEYWORD-COMMANDS (LD) "How keyword commands like :u and :pbt are processed Examples: user type-in form evaluated :pc 5 (ACL2::PC '5) :pcs app rev (ACL2::PCS 'app 'rev) :length (1 2 3) (ACL2::LENGTH '(1 2 3)) :quit (ACL2::QUIT) ; Note: avoid optional argument When a keyword, :key, is read as a command, ACL2 determines whether the symbol with the same name in the \"ACL2\" package, acl2::key, is a function or simple macro of n arguments. If so, ACL2 reads n more objects, obj1, ..., objn, and then acts as though it had read the following form (for a given key): (ACL2::key 'obj1 ... 'objn) Thus, by using the keyword command hack you avoid typing the parentheses, the \"ACL2\" package name, and the quotation marks. See [ld-keyword-aliases] for how to customize this behavior. Note the generality of this hack. Any function or macro in the \"ACL2\" package can be so invoked, not just ``commands.'' Indeed, there is no such thing as a distinguished class of commands. Users may take advantage of the keyword command hack by defining functions and macros in the \"ACL2\" package. The one caveat is that when the keyword hack is used to invoke a macro, only the required arguments for that macro are read before calling that macro: none of the &optional, &rest, &body, or &key arguments are read for that call. The macro is thus called with only its required arguments. The following log illustrates this caveat. ACL2 !>:set-iprint t ACL2 Query (:SET-IPRINT): Action (T, NIL, RESET, RESET-ENABLE, SAME, Q or ?): ACL2 Observation in SET-IPRINT: Iprinting has been enabled. ACL2 !> What happened? First, the command :set-iprint was read. Since the macro [set-iprint] has no required arguments, the ACL2 evaluator was then called on the form (set-iprint), that is, calling the macro on no arguments. Set-iprint is defined to query the ACL2 user when its first argument is omitted. The log shows that query, which is set up to read the next form from the input stream. That form was available immediately: the form t that had been supplied by the user. So the query returned immediately and the set-iprint call was completed.") (KEYWORD-VALUE-LISTP (KEYWORDP LISTS ACL2-BUILT-INS) "Recognizer for true lists whose even-position elements are keywords (keyword-value-listp l) is true if and only if l is a list of even length of the form (k1 a1 k2 a2 ... kn an), where each ki is a keyword. Function: (defun keyword-value-listp (l) (declare (xargs :guard t)) (cond ((atom l) (null l)) (t (and (keywordp (car l)) (consp (cdr l)) (keyword-value-listp (cddr l)))))) Subtopics [Assoc-keyword] Look up key in a [keyword-value-listp]") (KEYWORDP (SYMBOLS ACL2-BUILT-INS) "Recognizer for keywords (Keywordp x) is true if and only if x is a keyword, i.e., a symbol in the \"KEYWORD\" package. Such symbols are typically printed using a colon (:) followed by the [symbol-name] of the symbol. Keywordp has a [guard] of t. Keywordp is a Common Lisp function. See any Common Lisp documentation for more information. The following log may be illuminating. ACL2 !>(intern \"ABC\" \"KEYWORD\") :ABC ACL2 !>(symbol-name ':ABC) \"ABC\" ACL2 !>(symbol-package-name ':ABC) \"KEYWORD\" ACL2 !> Function: (defun keywordp (x) (declare (xargs :guard t)) (and (symbolp x) (equal (symbol-package-name x) \"KEYWORD\"))) Subtopics [Keyword-value-listp] Recognizer for true lists whose even-position elements are keywords") (KWOTE (TERM ACL2-BUILT-INS) "Quote an arbitrary object For any object x, (kwote x) returns the two-element list whose elements are the symbol quote and the given x, respectively. The guard of (kwote x) is t. Function: (defun kwote (x) (declare (xargs :guard t)) (mbe :logic (list 'quote x) :exec (cond ((eq x nil) *nil*) ((eq x t) *t*) ((eql x 0) *0*) ((eql x 1) *1*) ((eql x -1) *-1*) (t (list 'quote x)))))") (KWOTE-LST (TERM ACL2-BUILT-INS) "Quote an arbitrary true list of objects The function kwote-lst applies the function kwote to each element of a given list. The guard of (kwote-lst lst) is (true-listp lst). Function: (defun kwote-lst (lst) (declare (xargs :guard (true-listp lst))) (cond ((endp lst) nil) (t (cons (kwote (car lst)) (kwote-lst (cdr lst))))))") (LAMBDA (POINTERS) "See [term].") (LAST (LISTS ACL2-BUILT-INS) "The last [cons] (not element) of a list (Last l) is the last [cons] of a list. Here are examples. ACL2 !>(last '(a b . c)) (B . C) ACL2 !>(last '(a b c)) (C) (Last l) has a [guard] of (listp l); thus, l need not be a [true-listp]. Last is a Common Lisp function. See any Common Lisp documentation for more information. Unlike Common Lisp, we do not allow an optional second argument for last. Function: (defun last (l) (declare (xargs :guard (listp l))) (if (atom (cdr l)) l (last (cdr l))))") (LAST-PROVER-STEPS (SET-PROVER-STEP-LIMIT WITH-PROVER-STEP-LIMIT PROGRAMMING-WITH-STATE ACL2-BUILT-INS) "The number of prover steps most recently taken For discussions of prover step limits, See [set-prover-step-limit] and see [with-prover-step-limit]. The value of the form (last-prover-steps state) indicates the number of prover steps taken, in the sense described below, for the most recent context in which an event summary would normally be printed. Note that the value of (last-prover-steps state) is updated for all [events], and for all other forms such as calls of [thm] or [certify-book], that would print a summary --- regardless of whether or not such output is inhibited (see [set-inhibit-output-lst] and see [set-inhibited-summary-types]). In particular, the value is updated (typically to nil) for [table] [events], even when no summary is printed; for example, the value is updated to nil for table events such as ([logic]), ([program]), and even calls of [set-prover-step-limit]. The value of (last-prover-steps state) is determined as follows, based on the most recent summary context (as described above): nil, if no prover steps were taken; else, the (positive) number of steps taken, if the number of steps did not exceed the starting limit; else, the negative of the starting limit. We conclude with a remark for advanced users who wish to invoke last-prover-steps in the development of utilities that track prover steps. Suppose that you want to write a utility that takes some action based on the number of prover steps performed by the first defun event that is generated, among others, for example the number of prover steps taken to admit f1 in the following example. (progn (defun f1 ...) (defun f2 ...)) A solution is to record the steps taken by the first [defun] before executing subsequent events, as follows (see [make-event]). (progn (defun f1 ...) (make-event (pprogn (f-put-global 'my-step-count (last-prover-steps state) state) (value '(value-triple nil)))) (defun f2 ...))") (LD (MISCELLANEOUS) "The ACL2 read-eval-print loop, file loader, and [command] processor Examples: (LD \"foo.lisp\") ; read and evaluate each form in file ; \"foo.lisp\", in order (LD \"foo.lisp\" :ld-pre-eval-print t) ; as above, but print each form to standard ; character output just before it is evaluated General Form: (LD standard-oi ; open obj in channel, stringp file name ; to open and close, or list of forms ; Optional keyword arguments: :dir ... ; use this add-include-book-dir directory :standard-co ... ; open char out or file to open and close :proofs-co ... ; open char out or file to open and close :current-package ... ; known package name :ld-skip-proofsp ... ; nil, 'include-book, or t ; (see [ld-skip-proofsp]) :ld-redefinition-action ... ; nil or '(:a . :b) :ld-prompt ... ; nil, t, or some prompt printer fn :ld-missing-input-ok ... ; nil, t, :warn, or warning message :ld-pre-eval-filter ... ; :all, :query, or some new name :ld-pre-eval-print ... ; nil, t, or :never :ld-post-eval-print ... ; nil, t, or :command-conventions :ld-evisc-tuple ... ; nil or '(alist nil nil level length) :ld-error-triples ... ; nil or t :ld-error-action ... ; :return!, :return, :continue, :error, ; or (:exit N) :ld-query-control-alist ... ; alist supplying default responses :ld-verbose ...) ; nil or t Ld is the top-level ACL2 read-eval-print loop. (When you call [lp], a little initialization is done in raw Common Lisp and then ld is called.) Ld is also a general-purpose ACL2 file loader and a [command] interpreter. Ld is actually a macro that expands to a function call involving [state]. Ld returns an ``error triple'' (mv erp val state) as explained below. (For much more on error triples, see [programming-with-state].) See [rebuild] for a variant of ld that skips proofs. See [output-to-file] for examples showing how to redirect output to a file. The arguments to ld, except for :dir, all happen to be global variables in [state] (see [state] and see [programming-with-state]). For example, '[current-package] and '[ld-verbose] are global variables, which may be accessed via (@ current-package) and (@ ld-verbose). When ld is called, it ``binds'' these variables. By ``binds'' we actually mean the variables are globally set but restored to their old values on exit. Because ld provides the illusion of [state] global variables being bound, they are called ``ld specials'' (after the Lisp convention of calling a variable ``special'' if it is referenced freely after having been bound). Note that all arguments but the first are passed via keyword. Any variable not explicitly given a value in a call retains its pre-call value, with the exception of :[ld-error-action], which generally defaults to :return! if not explicitly specified. Just as an example to drive the point home: If [current-package] is \"ACL2\" and you typed (ld *standard-oi* :current-package \"MY-PKG\") you would find yourself in (an inner) read-eval-print loop in which the [current-package] was \"MY-PKG\". You could operate there as long as you wished, changing the current package at will. But when you typed :[q] you would return to the outer read-eval-print loop where the current package would still be \"ACL2\". Roughly speaking, ld repeatedly reads a form from [standard-oi], evaluates it, and prints its result to [standard-co]. It does this until the form is :[q] or evaluates to an error triple whose value component is :[q], or until the input channel or list is emptied. However, ld has many bells and whistles controlled by the ld specials. Each such special is documented individually. For example, see the documentation for [standard-oi], [current-package], [ld-pre-eval-print], etc. A more precise description of ld is as follows. In the description below we use the ld specials as variables, e.g., we say ``a form is read from [standard-oi].'' By this usage we refer to the current value of the named [state] global variable, e.g., we mean ``a form is read from the current value of '[standard-oi].'' This technicality has an important implication: If while interacting with ld you change the value of one of the ld specials, e.g., '[standard-oi], you will change the behavior of ld, e.g., subsequent input will be taken from the new value. Three ld specials are treated as channels: [standard-oi] is treated as an object input channel and is the source of forms evaluated by ld; [standard-co] and [proofs-co] are treated as character output channels and various flavors of output are printed to them. However, the supplied values of these specials need not actually be channels; several special cases are recognized. If the supplied value of one of these is in fact an open channel of the appropriate type, that channel is used and is not closed by ld. If the supplied value of one of these specials is a string, the string is treated as a file name in (essentially) Unix syntax (see [pathname]) and a channel of the appropriate type is opened to/from that file. Any channel opened by ld during the binding of the ld specials is automatically closed by ld upon termination. If [standard-co] and [proofs-co] are equal strings, only one channel to that file is opened and is used for both. As a special convenience, when [standard-oi] is a string and the :dir argument provided and not nil, we look up :dir in the table of directories maintained by [add-include-book-dir], and prepend this directory to [standard-oi] to create the filename. (In this case, however, we require that standard-oi is a relative pathname, not an absolute pathname.) For example, one can write (ld \"arithmetic/top-with-meta.lisp\" :dir :system) to ld that particular community books library. (Of course, you should almost always load books like arithmetic/top-with-meta using [include-book] instead of ld.) If :dir is not specified, then a relative pathname is resolved using the connected book directory; see [cbd]. Several other alternatives are allowed for [standard-oi]. If [standard-oi] is a true list then it is taken as the list of forms to be processed. If [standard-oi] is a list ending in an open channel, then ld processes the forms in the list and then reads and processes the forms from the channel. Analogously, if [standard-oi] is a list ending a string, an object input channel from the named file is opened and ld processes the forms in the list followed by the forms in the file. That channel is closed upon termination of ld. In the cases that a string is to be converted to an object input channel --- that is, when [standard-oi] is a string or is a list ending in a string --- an error occurs by default if the conversion fails, presumably because the file named by the string does not exist. However, if keyword argument :ld-missing-input-ok is t, then ld immediately returns without error in this case, but without reading or executing any forms, as though standard-oi is nil and keyword arguments :ld-verbose and ld-prompt both have value nil. The other legal values for :ld-missing-input-ok are nil, which gives the default behavior, and :warn, which behaves the same as t except that a warning is printed, which contains the same information as would be printed for the default error described above. The remaining ld specials are handled more simply and generally have to be bound to one of a finite number of tokens described in the :[doc] entries for each ld special. Should any ld special be supplied an inappropriate value, an error message is printed. Next, if [ld-verbose] is t, ld prints the message ``ACL2 loading name'' where name names the file or channel from which forms are being read. At the conclusion of ld, it will print ``Finished loading name'' if [ld-verbose] is t. Finally, ld repeatedly executes the ACL2 read-eval-print step, which may be described as follows. A [prompt] is printed to [standard-co] if [ld-prompt] is non-nil. The format of the [prompt] is determined by [ld-prompt]. If it is t, the default ACL2 [prompt] is used. If it is any other non-nil value then it is treated as an ACL2 function that will print the desired [prompt]. See [ld-prompt]. In the exceptional case where ld's input is coming from the terminal (*standard-oi*) but its output is going to a different sink (i.e., [standard-co] is not [*standard-co*]), we also print the [prompt] to the terminal. Ld then reads a form from [standard-oi]. If the object read is a keyword, ld constructs a ``keyword command form'' by possibly reading several more objects. See [keyword-commands]. This construction process is sensitive to the value of [ld-keyword-aliases]. See [ld-keyword-aliases]. Otherwise, the object read is treated as the command form. Ld next decides whether to evaluate or skip this form, depending on [ld-pre-eval-filter]. Initially, the filter must be either :all, :query, or a new name. If it is :all, it means all forms are evaluated. If it is :query, it means each form that is read is displayed and the user is queried. Otherwise, the filter is a name and each form that is read is evaluated as long as the name remains new, but if the name is ever introduced then no more forms are read and ld terminates. See [ld-pre-eval-filter]. If the form is to be evaluated, then ld first prints the form to [standard-co], if [ld-pre-eval-print] is t. With this feature, ld can process an input file or form list and construct a script of the session that appears as though each form was typed in. See [ld-pre-eval-print]. Ld then evaluates the form, with [state] bound to the current [state]. The result is some list of (multiple) values. If a [state] is among the values, then ld uses that [state] as the subsequent current [state]. Depending on [ld-error-triples], ld may interpret the result as an ``error.'' See [ld-error-triples]. We first discuss ld's behavior if no error signal is detected (either because none was sent or because ld is ignoring them because [ld-error-triples] is nil). In the case of a non-erroneous result, ld does two things: First, if the logical [world] in the now current [state] is different than the [world] before execution of the form, ld adds to the [world] a ``[command] landmark'' containing the form evaluated. See [command-descriptor]. Second, ld prints the result to [standard-co], but only if [ld-post-eval-print] is not nil. The result is printed as a list of (multiple) values unless [ld-post-eval-print] is :command-conventions, [ld-error-triples] is t, and the result is an ``error triple'', i.e., of the form (mv * * state) (see [error-triples]). In that case, only the non-erroneous ``value'' component of the result is printed. See [ld-post-eval-print]. Whenever ld prints anything (whether the input form, a query, or some results) it ``eviscerates'' it if ld-evisc-tuple is non-nil. Essentially, evisceration is a generalization of Common Lisp's use of *print-level* and *print-length* to hide large substructures. See [evisc-tuple] and also see [set-iprint]. We now return to the case of a form whose evaluation signals an error. In this case, ld first restores the ACL2 logical [world] to what it was just before the erroneous form was evaluated. Thus, a form that partially changes the [world] (i.e., begins to store properties) and then signals an error, has no effect on the [world]. You may see this happen on [command]s that execute several [events] (e.g., an [encapsulate] or a [progn] of several [defuns]): even though the output makes it appear that the initial [events] were executed, if an error is signalled by a later event the entire block of [events] is discarded. After rolling back, ld takes an action determined by [ld-error-action]. If the action is :continue, ld merely iterates the read-eval-print step. Note that nothing suggestive of the value of the ``erroneous'' form is printed. If the action is :return, ld terminates normally; similarly if the action is :return!, but a special value is returned that can cause superior ld commands to terminate; see [ld-error-action] for details. If the action is :error, ld terminates signalling an error to its caller. If its caller is in fact another instance of ld and that instance is watching out for error signals, the entire [world] created by the inner ld will be discarded by the outer ld if the inner ld terminates with an error. Note that if the action is (:exit N), then there is no rolling back, because ACL2 quits immediately with exit status N. Ld returns an error triple, (mv erp val state). Erp is t or nil indicating whether an error is being signalled. If no error is signalled, val is the ``reason'' ld terminated and is one of :exit (meaning :[q] was read), :eof (meaning the input source was exhausted), :error (meaning an error occurred but has been suppressed), :filter (meaning the [ld-pre-eval-filter] terminated ld), or a cons pair whose first component is the symbol :STOP-LD, which typically indicates that an error occurred while the value of variable '[ld-error-action] was :RETURN!. See [ld-error-action] for details of this last case. Subtopics [A!] To return to the top-level of ACL2's command loop [Abort!] To return to the top-level of ACL2's command loop [Calling-ld-in-bad-contexts] Errors caused by calling [ld] in inappropriate contexts [Current-package] The package used for reading and printing [Default-print-prompt] The default [prompt] printed by [ld] [I-am-here] A convenient marker for use with [rebuild] or [ld] [Keyword-commands] How keyword commands like :u and :pbt are processed [Ld-error-action] Determines [ld]'s response to an error [Ld-error-triples] Determines whether a form caused an error during [ld] [Ld-evisc-tuple] Determines whether [ld] suppresses details when printing [Ld-keyword-aliases] Abbreviation of some keyword commands [Ld-missing-input-ok] Determines which forms [ld] evaluates [Ld-post-eval-print] Determines whether and how [ld] prints the result of evaluation [Ld-pre-eval-filter] Determines which forms [ld] evaluates [Ld-pre-eval-print] Determines whether [ld] prints the forms to be eval'd [Ld-prompt] Determines the [prompt] printed by [ld] [Ld-query-control-alist] How to default answers to queries [Ld-redefinition-action] To allow redefinition without undoing [Ld-skip-proofsp] How carefully ACL2 processes your [command]s [Ld-verbose] Determines whether [ld] prints ``ACL2 Loading ...'' [Lp] The Common Lisp entry to ACL2 [P!] To pop up (at least) one level of ACL2's command loop [Prompt] The prompt printed by [ld] [Rebuild] A convenient way to reconstruct your old [state] [Redef] A common way to set [ld-redefinition-action] [Redef!] A common way to set [ld-redefinition-action] [Redef+] System hacker's redefinition [command] [Redef-] Turn off system hacker's redefinition [command] [Reset-ld-specials] Restores initial settings of the [ld] specials [Wormhole] [ld] without [state] --- a short-cut to a parallel universe") (LD-ERROR-ACTION (LD) "Determines [ld]'s response to an error Ld-error-action is an [ld] special (see [ld]). The accessor is (ld-error-action state) and the updater is (set-ld-error-action val state). Ld-error-action must be :continue, :return, :return!, :error, or (:exit N) for some natural number N. The initial value of ld-error-action is :continue, which means that the top-level ACL2 [command] loop (see [lp]) will not exit when an error is caused by user-typein. But the default value for ld-error-action on calls of [ld] is :return!, with one exception: in the case that the value of [ld] special ld-error-action is (:exit N), the default remains that value. The general-purpose ACL2 read-eval-print loop, [ld], reads forms from [standard-oi], evaluates them and prints the result to [standard-co]. Note that the ACL2 top-level loop (see [lp]) results from an invocation of [ld]. However, there are various flags that control [ld]'s behavior and ld-error-action is one of them. Suppose that [ld-error-triples] is t and a form evaluates to an error triple (mv erp val state); see [error-triples]. If the ``error component'', erp, is non-nil, then an error is said to have occurred. If an error occurs, [ld]'s action depends on ld-error-action. If it is :continue, [ld] just continues processing the forms in [standard-oi]. If it is :return or :return!, [ld] stops and returns as though it had emptied the channel. If it is :error, [ld] stops and returns, signalling an error to its caller by returning an error triple with non-nil error component, and reverting the logical [world] to its value just before that call of [ld]. If it is (:exit N), then ACL2 quits with exit status N. To see this effect of :ERROR for ld-error-action, consider the following example. (ld '((defun f (x) x) (defun bad (x)) (defun g (x) x))) When the [defun] of bad fails (because its body is missing), evaluation of the ld call stops; thus, the [defun] of g is not evaluated. The definition of f will be removed from the logical [world] before the call of ld returns. However, by default each user call of ld is made with a ld-error-action of :RETURN! (not :ERROR). In the common case that all nested calls of ld inside the ACL2 loop are made this way, an error will not roll back the logical [world]. However, it will still halt evaluation of forms for the current call of ld and any parent calls of ld (other than the call made on behalf of lp that entered the ACL2 loop in the first place), as though there were no more forms to evaluate. We have already discussed the behavior of ld when an error occurs. But there is another case when ld can stop processing more forms: when ld-error-action is not :CONTINUE, [ld-error-triples] is t, and evaluation of a form returns an error triple (mv nil val state), where nil is the error component and whose ``value component'', val is a [cons] pair whose [car] is the symbol :STOP-LD. Let val be the pair (:STOP-LD . x). Then the call of ld returns the error triple (mv nil (:STOP-LD n . x) state), where n is the value of [state] global variable 'ld-level at the time of termination. The following example illustrates how this works. (ld '((defun f1 (x) x) (ld '((defun f2 (x) x) (mv nil '(:STOP-LD my-error more-info) state) (defun g2 (x) x))) (defun g1 (x) x))) The outer call of ld returns the value (:STOP-LD 2 3 MY-ERROR MORE-INFO) and leaves us in a world the includes definitions for f1 and f2, but no definition for g1 or g2 since neither of their two defun forms was evaluated. The value of [state] global 'ld-level is incremented from 1 to 2 when the outer ld is entered and then again to 3 when the inner ld is entered. When the inner ld escounters the error triple (mv nil (:STOP-LD my-error more-info) state), it sees :STOP-LD in the car of the value component and pushes the current value of 'ld-level, 3, onto the [cdr] of that value, to return the value triple (mv nil (:STOP-LD my-error 3 more-info) state). The outer of ld then sees this value and returns (mv nil (:STOP-LD my-error 2 3 more-info) state), since its current value of 'ld-level is 2 after the inner ld exits. That concludes our discussion of how these special :STOP-LD values are handled; but how are they created? While they can be created directly by evaluation results as suggested in the example above, that is not the standard way. Rather, ld returns an error triple (mv nil (:STOP-LD n) state), where n is the value of variable ld-level at the time of termination, when the following conditions hold: an error occurs, ld-error-action is RETURN! (which is the default), and [ld-error-triples] is t (the default). The following example, which is a bit similar to the preceding one, illustrates both creation and handling of the special :STOP-LD values. (ld '((defun f1 (x) x) (ld '((defun f2 (x) x) (ld '((defun f3 (x) x) (defun bad (x)) ; ERROR -- missing the body (defun g3 (x) x))) (defun g2 (x) x))) (defun g1 (x) x))) The result is that f1, f2, and f3 are defined, but none of g1, g2, or g3 is defined. Let's see why. The innermost call of [ld] has a default :ld-error-action of :RETURN! (as do the other calls). So when the definition of bad fails, then the innermost ld returns (mv nil (:STOP-LD 4) state). The middle ld sees this value, and since its :ld-error-action is not :CONTINUE (because it has the default value of :RETURN!), it returns before considering the definition of g2, with value (mv nil (:STOP-LD 3 4) state). The topmost call of ld similarly sees the :STOP-LD; stops evaluation of forms, without defining g1; and returns (mv nil (:STOP-LD 2 3 4) state).") (LD-ERROR-TRIPLES (LD) "Determines whether a form caused an error during [ld] Ld-error-triples is an [ld] special (see [ld]). The accessor is (ld-error-triples state) and the updater is (set-ld-error-triples val state). Ld-error-triples must be either t or nil. The initial value of ld-error-triples is t. The general-purpose ACL2 read-eval-print loop, [ld], reads forms from [standard-oi], evaluates them and prints the result to [standard-co]. Note that the ACL2 top-level loop (see [lp]) results from an invocation of [ld]. However, there are various flags that control [ld]'s behavior and ld-error-triples is one of them. If this variable has the value t then when a form evaluates to an error triple (mv erp val state) (see [error-triples]) such that erp is non-nil, then an error is deemed to have occurred. When an error occurs in evaluating a form, [ld] rolls back the ACL2 [world] to the configuration it had at the conclusion of the last error-free form. Then [ld] takes the action determined by [ld-error-action].") (LD-EVISC-TUPLE (LD) "Determines whether [ld] suppresses details when printing Ld-evisc-tuple is an [ld] special (see [ld]). The accessor is (ld-evisc-tuple state) and an updater is (set-ld-evisc-tuple val state), although the use of [set-evisc-tuple] is preferred for updating. Ld-evisc-tuple must be either nil, which is its initial value, or a legal evisc-tuple: see [set-evisc-tuple]. The general-purpose ACL2 read-eval-print loop, [ld], reads forms from [standard-oi], evaluates them and prints the result to [standard-co]. Note that the ACL2 top-level loop (see [lp]) results from an invocation of [ld]. However, there are various flags that control [ld]'s behavior and ld-evisc-tuple is one of them. [Ld] may print the forms it is evaluating and/or the results of evaluation. Depending on the value of ld-evisc-tuple [ld] may ``eviscerate'' objects before printing them. See [set-evisc-tuple] for a discussion of evisceration and of how other evisc-tuples affect the printing of error messages and warnings, as well as other output not from ld.") (LD-KEYWORD-ALIASES (LD) "Abbreviation of some keyword commands Examples: (set-ld-keyword-aliases '((:q 0 q-fn) (:e 0 exit-acl2-macro)) state) (ld-keyword-aliases state) ; current value of the ld-keyword-aliases table Ld-keyword-aliases is the name of a ACL2 table (see [table]) and also the name of a function of state that returns the value of this table. That value must be an alist, each element of which is of the form (:keyword n fn), where :keyword is a keyword, n is a nonnegative integer, and fn is a function symbol of arity n, a macro symbol, or a lambda expression of arity n. When keyword is typed as an [ld] command, n more forms are read, x1, ..., xn, and the form (fn 'x1 ... 'xn) is then evaluated. The initial value of the ld-keyword-aliases [table] is nil. ACL2 provides functions to modify the ld-keyword-aliases table, as follows. (Set-ld-keyword-aliases val state): sets the table to val, which must be a legal alist as described above. This is an event that may go into a book (see [events]), but its effect will be [local] to that book. Set-ld-keyword-aliases! is the same as set-ld-keyword-aliases, except that its effect is not [local]. Indeed, the form (set-ld-keyword-aliases val state) is equivalent to the form (local (set-ld-keyword-aliases! val state). (Add-ld-keyword-alias key val state): modifies the table by binding the keyword key to val, which must be a legal value as described above. This is an event that may go into a book (see [events]), but its effect will be [local] to that book. Add-ld-keyword-alias! is the same as add-ld-keyword-alias, except that its effect is not [local]. Indeed, the form (add-ld-keyword-alias key val state) is equivalent to the form (local (add-ld-keyword-alias! key val state). Consider the first example above: (set-ld-keyword-aliases '((:q 0 q-fn) (:e 0 exit-acl2-macro)) state) With this event, :[q] is redefined to have the effect of executing (q-fn), so for example if you have defined q-fn with (defmacro q-fn () '(er soft 'q \"You un-bound :q and now we have a soft error.\")) then :[q] will cause an error, and if you have defined (defmacro exit-acl2-macro () '(exit-ld state)) then :e will cause the effect (it so happens) that :[q] normally has. If you prefer :e to :[q] for exiting the ACL2 loop, you might even want to put such definitions of q-fn and exit-acl2-macro together with the set-ld-keyword-aliases form above into your \"acl2-customization.lsp\" file; see [ACL2-customization]. The general-purpose ACL2 read-eval-print loop, [ld], reads forms from [standard-oi], evaluates them and prints the result to [standard-co]. Note that the ACL2 top-level loop (see [lp]) results from an invocation of [ld]. However, there are various flags that control [ld]'s behavior and ld-keyword-aliases is one of them. Ld-keyword-aliases affects how keyword commands are parsed. Generally speaking, [ld]'s command interpreter reads ``:fn x1 ... xn'' as ``(fn 'x1 ... 'xn)'' when :fn is a keyword and fn is the name of an n-ary function; see [keyword-commands]. But this parse is overridden, as described above, for the keywords bound in the ld-keyword-aliases [table].") (LD-MISSING-INPUT-OK (LD) "Determines which forms [ld] evaluates ld-missing-input-ok is an [ld] special (see [ld]). The accessor is (ld-missing-input-ok state) and the updater is (set-ld-missing-input-ok val state). ld-missing-input-ok must be either nil, t, or :warn. The initial value of ld-missing-input-ok is nil. The general-purpose ACL2 read-eval-print loop, [ld], is controlled by various flags that control its behavior, and ld-missing-input-ok is one of them. In brief, the first argument of ld can indicate a file from which to read input. If the file does not exist, it is an error by default, but ld becomes essentially a no-op if t or :warn is supplied for :ld-missing-input-ok, where :warn prints a warning. Also see [ld].") (LD-POST-EVAL-PRINT (LD) "Determines whether and how [ld] prints the result of evaluation Ld-post-eval-print is an [ld] special (see [ld]). The accessor is (ld-post-eval-print state) and the updater is (set-ld-post-eval-print val state). Ld-post-eval-print must be either t, nil, or :command-conventions. The initial value of ld-post-eval-print is :command-conventions. The general-purpose ACL2 read-eval-print loop, [ld], reads forms from [standard-oi], evaluates them and prints the result to [standard-co]. Note that the ACL2 top-level loop (see [lp]) results from an invocation of [ld]. However, there are various flags that control [ld]'s behavior and ld-post-eval-print is one of them. If this global variable is t, [ld] prints the result. In the case of a form that produces a multiple value, [ld] prints the list containing all the values (which, logically speaking, is what the form returned). If ld-post-eval-print is nil, [ld] does not print the values. This is most useful when [ld] is used to load a previously processed file. Finally, if ld-post-eval-print is :command-conventions and also ld-error-triples is t, then [ld] prints the result but treats ``error triples'' specially. An ``error triple'' (see [error-triples]) is a result, (mv erp val state), that consists of two ordinary values and [state]. Many ACL2 functions use such triples to signal errors. The convention is that if erp (the first value) is nil, then the function is returning val (the second value) as its conventional single result and possibly side-effecting [state] (as with some output). If erp is not nil, then an error has been caused, val is irrelevant and the error message has been printed in the returned [state]. Example ACL2 functions that follow this convention include [defun] and [in-package]. If such ``error producing'' functions are evaluated while ld-post-eval-print is set to t, then you would see them producing lists of length 3. This is disconcerting to users accustomed to Common Lisp (where these functions produce single results but sometimes cause errors or side-effect [state]). For more information about error triples, see [programming-with-state]. When ld-post-eval-print is :command-conventions and a form produces an error triple (mv erp val state) as its value, [ld] prints nothing if erp is non-nil and otherwise [ld] prints just val. Because it is a misrepresentation to suggest that just one result was returned, [ld] prints the value of the global variable 'triple-print-prefix before printing val. 'triple-print-prefix is initially \" \", which means that when non-erroneous error triples are being abbreviated to val, val appears one space off the left margin instead of on the margin. In addition, when ld-post-eval-print is :command-conventions and the value component of an error triple is the keyword :invisible then [ld] prints nothing. This is the way certain commands (e.g., :[pc]) appear to return no value. By printing nothing when an error has been signalled, [ld] makes it appear that the error (whose message has already appeared in [state]) has ``thrown'' the computation back to load without returning a value. By printing just val otherwise, we suppress the fact that [state] has possibly been changed.") (LD-PRE-EVAL-FILTER (LD) "Determines which forms [ld] evaluates Ld-pre-eval-filter is an [ld] special (see [ld]). The accessor is (ld-pre-eval-filter state) and the updater is (set-ld-pre-eval-filter val state). Ld-pre-eval-filter must be either :all, :query, or a new name that could be defined (e.g., by [defun] or [defconst]). The initial value of ld-pre-eval-filter is :all. The general-purpose ACL2 read-eval-print loop, [ld], reads forms from [standard-oi], evaluates them and prints the result to [standard-co]. Note that the ACL2 top-level loop (see [lp]) results from an invocation of [ld]. However, there are various flags that control [ld]'s behavior and ld-pre-eval-filter is one of them. If the filter is :all, then every form read is evaluated. If the filter is :query, then after a form is read it is printed to [standard-co] and the user is asked if the form is to be evaluated or skipped. If the filter is a new name, then all forms are evaluated until that name is introduced, at which time [ld] terminates normally. The :all filter is, of course, the normal one. :Query is useful if you want to replay selected the [command]s in some file. The new name filter is used if you wish to replay all the [command]s in a file up through the introduction of the given one.") (LD-PRE-EVAL-PRINT (LD) "Determines whether [ld] prints the forms to be eval'd Ld-pre-eval-print is an [ld] special (see [ld]). The accessor is (ld-pre-eval-print state) and the updater is (set-ld-pre-eval-print val state). Ld-pre-eval-print must be either t, nil, or :never. The initial value of ld-pre-eval-print is nil. The general-purpose ACL2 read-eval-print loop, [ld], reads forms from [standard-oi], evaluates them and prints the result to [standard-co]. Note that the ACL2 top-level loop (see [lp]) results from an invocation of [ld]. However, there are various flags that control [ld]'s behavior and ld-pre-eval-print is one of them. If this global variable is t, then before evaluating the form just read from [standard-oi], [ld] prints the form to [standard-co]. If the variable is nil, no such printing occurs. The t option is useful if you are reading from a file of [command]s and wish to assemble a complete script of the session in [standard-co]. The value :never of ld-pre-eval-print is rarely used. During the evaluation of [encapsulate] and of [certify-book] forms, subsidiary events are normally printed, even if ld-pre-eval-print is nil. Thus for example, when the user submits an [encapsulate] form, all subsidiary events are generally printed even in the default situation where ld-pre-eval-print is nil. But occasionally one may want to suppress such printing. In that case, ld-pre-eval-print should be set to :never. As described elsewhere (see [set-inhibit-output-lst]), another way to suppress such printing is to execute (set-inhibit-output-lst lst) where lst evaluates to a list including 'prove and 'event.") (LD-PROMPT (LD) "Determines the [prompt] printed by [ld] Ld-prompt is an [ld] special (see [ld]). The accessor is (ld-prompt state) and the updater is (set-ld-prompt val state). Ld-prompt must be either nil, t, or a function symbol that, when given an open output character channel and [state], prints the desired [prompt] to the channel and returns two values: the number of [characters] printed and the [state]. The initial value of ld-prompt is t. The general-purpose ACL2 read-eval-print loop, [ld], reads forms from [standard-oi], evaluates them and prints the result to [standard-co]. Note that the ACL2 top-level loop (see [lp]) results from an invocation of [ld]. However, there are various flags that control [ld]'s behavior and ld-prompt is one of them. Ld-prompt determines whether [ld] prints a [prompt] before reading the next form from [standard-oi]. If ld-prompt is nil, [ld] prints no [prompt]. If ld-prompt is t, the default [prompt] printer is used, which displays information that includes the current package, default [defun-mode], [guard] checking status (on or off), and [ld-skip-proofsp]; see [default-print-prompt]. If ld-prompt is neither nil nor t, then it should be a function name, fn, such that (fn channel state) will print the desired [prompt] to channel in [state] and return (mv col state), where col is the number of [characters] output (on the last line output). You may define your own [prompt] printing function. If you supply an inappropriate [prompt] function, i.e., one that causes an error or does not return the correct number and type of results, the following odd [prompt] will be printed instead: Bad Prompt See :DOC ld-prompt> which will lead you to this message. You should either call [ld] appropriately next time or assign an appropriate value to ld-prompt.") (LD-QUERY-CONTROL-ALIST (LD) "How to default answers to queries Ld-query-control-alist is an [ld] special (see [ld]). The accessor is (ld-query-control-alist state) and the updater is (set-ld-query-control-alist val state). Roughly speaking, ld-query-control-alist is either nil (meaning all queries should be interactive), t (meaning all should default to the first accepted response), or an alist that pairs query ids to keyword responses. The alist may end in either t or nil, indicating the default value for all ids not listed explicitly. Formally, the ld-query-control-alist must satisfy ld-query-control-alistp. The initial ld-query-control-alist is nil, which means all queries are handled interactively. When an ACL2 query is raised, a unique identifying symbol is printed in parentheses after the word ``Query''. This symbol, called the ``query id,'' can be used in conjunction with ld-query-control-alist to prevent the query from being handled interactively. By ``handled interactively'' we mean that the query is printed to [*standard-co*] and a response is read from [*standard-oi*]. The alist can be used to obtain a ``default value'' for each query id. If this value is nil, then the query is handled interactively. In all other cases, the system handles the query without interaction (although text may be printed to [standard-co] to make it appear that an interaction has occurred; see below). If the default value is t, the system acts as though the user responded to the query by typing the first response listed among the acceptable responses. If the default value is neither nil nor t, then it must be a keyword and one of the acceptable responses. In that case, the system acts as though the user responded with the given keyword. Next, we discuss how the ld-query-control-alist assigns a default value to each query id. It assigns each id the first value paired with the id in the alist, or, if no such pair appears in the alist, it assigns the final [cdr] of the alist as the value. Thus, nil assigns all ids nil. T assigns all ids t. '((:filter . nil) (:sysdef . :n) . t) assigns nil to the :filter query, :n to the :sysdef query, and t to all others. It remains only to discuss how the system prints text when the default value is not nil, i.e., when the query is handled without interaction. In fact, it is allowed to pair a query id with a singleton list containing a keyword, rather than a keyword, and this indicates that no printing is to be done. Thus for the example above, :sysdef queries would be handled noninteractively, with printing done to simulate the interaction. But if we change the example so that :sysdef is paired with (:n), i.e., if ld-query-control-alist is '((:filter . nil) (:sysdef :n) . t), then no such printing would take place for sysdef queries. Instead, the default value of :n would be assigned ``quietly''.") (LD-REDEFINITION-ACTION (LD) "To allow redefinition without undoing Ld-redefinition-action is an [ld] special (see [ld]). The accessor is (ld-redefinition-action state) and the updater is (set-ld-redefinition-action val state). WARNING! If ld-redefinition-action is non-nil then ACL2 is liable to be made unsafe or unsound either by ill-considered definitions, or because redefining a macro or inlined function called in the body of a function, g, may not cause the new definition to be called by g. The keyword command :[redef] will set ld-redefinition-action to a convenient setting allowing unsound redefinition. See below. When ld-redefinition-action is nil, redefinition is prohibited. In that case, an error message is printed upon any attempt to introduce a name that is already in use. There is one exception to this rule. It is permitted to redefine a function symbol in :[program] mode to be a function symbol in :[logic] mode provided the formals and body remain the same. This is the standard way a function ``comes into'' logical existence. Throughout the rest of this discussion we exclude from our meaning of ``redefinition'' the case in which a function in :[program] mode is identically redefined in :[logic] mode. At one time, ACL2 freely permitted the [signature]-preserving redefinition of :[program] mode functions but it no longer does. See [redefining-programs]. When ld-redefinition-action is non-nil, you are allowed to redefine a name that is already in use. The system may be rendered unsound by such an act. It is important to understand how dangerous redefinition is. Suppose fn is a function symbol that is called from within some other function, say g. Suppose fn is redefined so that its arity changes. Then the definition of g is rendered syntactically ill-formed by the redefinition. This can be devastating since the entire ACL2 system assumes that terms in its database are well-formed. For example, if ACL2 executes g by running the corresponding function in raw Common Lisp the redefinition of fn may cause raw lisp to break in irreparable ways. As Lisp programmers we live with this all the time by following the simple rule: after changing the syntax of a function don't run any function that calls it via its old syntax. This rule also works in the context of the evaluation of ACL2 functions, but it is harder to follow in the context of ACL2 deductions, since it is hard to know whether the database contains a path leading the theorem prover from facts about one function to facts about another. Finally, of course, even if the database is still syntactically well-formed there is no assurance that all the rules stored in it are valid. For example, theorems proved about g survive the redefinition of fn but may have crucially depended on the properties of the old fn. In summary, we repeat the warning: all bets are off if you set ld-redefinition-action to non-nil. ACL2 provides some enforcement of the concern above, by disabling [certify-book] if any [world]-changing [events] exist in the certification [world] that were executed with a non-nil value of 'ld-redefinition-action. (This value is checked at the end of each top-level command, but the value does not change during evaluation of embedded event forms; see [embedded-event-form].) If at any point in a session you wish to see the list of all names that have been redefined, see [redefined-names]. That said, we'll give you enough rope to hang yourself. When ld-redefinition-action is non-nil, it must be a pair, (a . b). The value of a determines how the system interacts with you when a redefinition is submitted. The value of b allows you to specify how the property list of the redefined name is to be ``renewed'' before the redefinition. There are several dimensions to the space of possibilities controlled by part a: Do you want to be queried each time you redefine a name, so you can confirm your intention? (We sometimes make typing mistakes or simply forget we have used that name already.) Do you want to see a warning stating that the name has been redefined? Do you want ACL2 system functions given special protection from possible redefinition? Below are the choices for part a: :query --- every attempt to redefine a name will produce a query. The query will allow you to abort the redefinition or proceed. It will will also allow you to specify the part b for this redefinition. :Query is the recommended setting for users who wish to dabble in redefinition. :warn --- any user-defined function may be redefined but a post-redefinition warning is printed. The attempt to redefine a system name produces a query. If you are prototyping and testing a big system in ACL2 this is probably the desired setting for part a. :doit --- any user-defined function may be redefined silently (without query or warning) but when an attempt is made to redefine a system function, a query is made. This setting is recommended when you start making massive changes to your prototyped system (and tire of even the warning messages issued by :warn). In support of our own ACL2 systems [programming] there are two other settings. We suggest ordinary users not use them. :warn! --- every attempt to redefine a name produces a warning but no query. Since ACL2 system functions can be redefined this way, this setting should be used by the only-slightly-less-than supremely confident ACL2 system hacker. :doit! --- this setting allows any name to be redefined silently (without query or warnings). ACL2 system functions are fair game. This setting is reserved for the supremely confident ACL2 system hacker. (Actually, this setting is used when we are loading massively modified versions of the ACL2 source files.) Part b of ld-redefinition-action tells the system how to ``renew'' the property list of the name being redefined. There are two choices: :erase --- erase all properties stored under the name, or :overwrite --- preserve existing properties and let the redefining overwrite them. It should be stressed that neither of these b settings is guaranteed to result in an entirely satisfactory state of affairs after the redefinition. Roughly speaking, :erase returns the property list of the name to the state it was in when the name was first introduced. Lemmas, type information, etc., stored under that name are lost. Is that what you wanted? Sometimes it is, as when the old definition is ``completely wrong.'' But other times the old definition was ``almost right'' in the sense that some of the work done with it is still (intended to be) valid. In that case, :overwrite might be the correct b setting. For example if fn was a function and is being re-[defun]'d with the same [signature], then the properties stored by the new [defun] should overwrite those stored by the old [defun] but the properties stored by [defthm]s will be preserved. In addition, neither setting will cause ACL2 to erase properties stored under other symbols! Thus, if FOO names a rewrite rule which rewrites a term beginning with the function symbol BAR and you then redefine FOO to rewrite a term beginning with the function symbol BAZ, then the old version of FOO is still available (because the rule itself was added to the rewrite rules for BAR, whose property list was not cleared by redefining FOO). The b setting is only used as the default action when no query is made. If you choose a setting for part a that produces a query then you will have the opportunity, for each redefinition, to specify whether the property list is to be erased or overwritten. The keyword command :[redef] sets ld-redefinition-action to the pair (:query . :overwrite). Since the resulting query will give you the chance to specify :erase instead of :overwrite, this setting is quite convenient. But when you are engaged in heavy-duty prototyping, you may wish to use a setting such as :warn or even :doit. For that you will have to invoke a form such as: (set-ld-redefinition-action '(:doit . :overwrite) state) . [Encapsulate] causes somewhat odd interaction with the user if redefinition occurs within the encapsulation because the [encapsulate]d event list is processed several times. For example, if the redefinition action causes a query and a non-local definition is actually a redefinition, then the query will be posed twice, once during each pass. C'est la vie. Finally, it should be stressed again that redefinition is dangerous because not all of the rules about a name are stored on the property list of the name. Thus, redefinition can render ill-formed terms stored elsewhere in the database or can preserve now-invalid rules. See [redundant-events], in particular the section ``Note About Unfortunate Redundancies,'' for more discussion of potential pitfalls of redefinition.") (LD-SKIP-PROOFSP (LD) "How carefully ACL2 processes your [command]s Examples: ACL2 !>(set-ld-skip-proofsp t state) T ACL2 !s>(set-ld-skip-proofsp nil state) NIL ACL2 !>(set-ld-skip-proofsp 'include-book state) INCLUDE-BOOK ACL2 !s> A global variable in the ACL2 [state], called 'ld-skip-proofsp, determines the thoroughness with which ACL2 processes your [command]s. This variable may take on one of three values: t, nil or '[include-book]. When ld-skip-proofsp is non-nil, the system assumes that which ought to be proved and is thus unsound. The form (set-ld-skip-proofsp flg state) is the general-purpose way of setting ld-skip-proofsp. This global variable is an ``[ld] special,'' which is to say, you may call [ld] in such a way as to ``bind'' this variable for the dynamic extent of the [ld]. When ld-skip-proofsp is non-nil, the default [prompt] displays the character s. Thus, the [prompt] ACL2 !s> means that the default [defun-mode] is :[logic] (otherwise the character p, for :[program], would also be printed; see [default-print-prompt]) but ``proofs are being skipped.'' Observe that there are two legal non-nil values, t and '[include-book]. When ld-skip-proofsp is t, ACL2 skips all proof obligations but otherwise performs all other required analysis of input [events]. When ld-skip-proofsp is '[include-book], ACL2 skips not only proof obligations but all analysis except that required to compute the effect of successfully executed [events]. To explain the distinction, let us consider one particular event, say a [defun]. Very roughly speaking, a [defun] event normally involves a check of the syntactic well-formedness of the submitted definition, the generation and proof of the termination conditions, and the computation and storage of various rules such as a :[definition] rule and some :[type-prescription] rules. By ``normally'' above we mean when ld-skip-proofsp is nil. How does a [defun] behave when ld-skip-proofsp is non-nil? If ld-skip-proofsp is t, then [defun] performs the syntactic well-formedness checks and computes and stores the various rules, but it does not actually carry out the termination proofs. If ld-skip-proofsp is '[include-book], [defun] does not do the syntactic well-formedness check nor does it carry out the termination proof. Instead, it merely computes and stores the rules under the assumption that the checks and proofs would all succeed. Observe that a setting of '[include-book] is ``stronger'' than a setting of t in the sense that '[include-book] causes [defun] to assume even more about the admissibility of the event than t does. As one might infer from the choice of name, the [include-book] event sets ld-skip-proofsp to '[include-book] when processing the [events] in a book being loaded. Thus, [include-book] does the miminal work necessary to carry out the effects of every event in the book. The syntactic checks and proof obligations were, presumably, successfully carried out when the book was certified. A non-nil value for ld-skip-proofsp also affects the system's output messages. Event summaries (the paragraphs that begin ``Summary'' and display the event forms, rules used, etc.) are not printed when ld-skip-proofsp is non-nil. Warnings and observations are printed when ld-skip-proofsp is t but are not printed when it is '[include-book]. Intuitively, ld-skip-proofsp t means skip just the proofs and otherwise do all the work normally required for an event; while ld-skip-proofsp '[include-book] is ``stronger'' and means do as little as possible to process [events]. In accordance with this intuition, [local] [events] are processed when ld-skip-proofsp is t but are skipped when ld-skip-proofsp is '[include-book]. The ACL2 system itself uses only two settings, nil and '[include-book], the latter being used only when executing the [events] inside of a book being included. The ld-skip-proofsp setting of t is provided as a convenience to the user. For example, suppose one has a file of [events]. By loading it with [ld] with ld-skip-proofsp set to t, the [events] can all be checked for syntactic correctness and assumed without proof. This is a convenient way to recover a state lost by a system crash or to experiment with a modification of an [events] file. The foregoing discussion is actually based on a lie. ld-skip-proofsp is allowed two other values, 'initialize-acl2 and 'include-book-with-locals. The first causes behavior similar to t but skips [local] [events] and avoids some error checks that would otherwise prevent ACL2 from properly booting. The second is identical to '[include-book] but also executes [local] [events]. These additional values are not intended for use by the user, but no barriers to their use have been erected. We close by reminding the user that ACL2 is potentially unsound if ld-skip-proofsp is ever set by the user. We provide access to it simply to allow experimentation and rapid reconstruction of lost or modified logical [world]s.") (LD-VERBOSE (LD) "Determines whether [ld] prints ``ACL2 Loading ...'' Ld-verbose is an [ld] special (see [ld]). The accessor is (ld-verbose state) and the updater is (set-ld-verbose val state). Ld-verbose must be t, nil or a string or [consp] suitable for [fmt] printing via the ~@ command. The initial value of ld-verbose is a [fmt] message that prints the ACL2 version number, [ld] level and connected book directory. Note: Ld-verbose has no effect on proofs. See [set-gag-mode] and see [set-inhibit-output-lst] for how to control the size of proof output. Before processing the forms in [standard-oi], [ld] may print a header. The printing of this header is controlled by ld-verbose. If ld-verbose is nil, no header is printed. If it is t, [ld] prints the message ACL2 loading where is the input channel supplied to [ld]. A similar message is printed when [ld] completes. If ld-verbose is neither t nor nil then it is presumably a header and is printed with the ~@ [fmt] directive before [ld] begins to read and process forms. In this case the ~@ [fmt] directive is interpreted in an environment in which #\\v is the ACL2 version string, #\\l is the level of the current recursion in [ld] and/or [wormhole], and #\\c is the connected book directory (cbd).") (LEMMA-INSTANCE (HINTS FUNCTIONAL-INSTANTIATION) "An object denoting an instance of a theorem Lemma instances are the objects one provides via :use and :by [hints] (see [hints]) to bring to the theorem prover's attention some previously proved or easily provable fact. A typical use of the :use hint is given below. The value specified is a list of five lemma instances. :use (reverse-reverse (:type-prescription app) (:instance assoc-of-app (x a) (y b) (z c)) (:functional-instance p-f (p consp) (f flatten)) (:instance (:theorem (equal x x)) (x (flatten a)))) Observe that an event name can be a lemma instance. The :use hint allows a single lemma instance to be provided in lieu of a list, as in: :use reverse-reverse or :use (:instance assoc-of-app (x a) (y b) (z c)) A lemma instance denotes a formula which is either known to be a theorem or which must be proved to be a theorem before it can be used. To use a lemma instance in a particular subgoal, the theorem prover adds the formula as a hypothesis to the subgoal before the normal theorem proving heuristics are applied. A lemma instance, or lmi, is of one of the following five forms: (1) name, where name names a previously proved theorem, axiom, or definition and denotes the formula (theorem) of that name. (2) rune, where rune is a [rune] (see [rune]) denoting the :[corollary] justifying the rule named by the [rune]. (3) (:theorem term), where term is any term alleged to be a theorem. Such a lemma instance denotes the formula term. But before using such a lemma instance the system will undertake to prove term. (4) (:instance lmi (v1 t1) ... (vn tn)), where lmi is recursively a lemma instance, the vi's are distinct variables, and the ti's are terms. Such a lemma instance denotes the formula obtained by instantiating the formula F denoted by lmi, normally by replacing each vi by ti in F and requiring that each vi must be bound in F. There are two exceptions. If the keyword :extra-bindings-ok is inserted immediately after the lemma instance in order to remove that requirement, as follows, then that requirement is ignored: (:instance lmi :extra-bindings-ok (v1 t1) ... (vn tn)). Otherwise, if one or more variables vi do not occur in F, but for each such vi exactly one variable v with the same [symbol-name] as vi occurs in F and no other vj with the same symbol-name as v is bound in the substitution, then the pair (vi ti) is replaced by the pair (v ti) in the substitution. (5) (:functional-instance lmi (f1 g1) ... (fn gn)), where lmi is recursively a lemma instance and each fi is an ``instantiable'' function symbol of arity ni and gi is a function symbol, a macro alias for a function symbol gi' (see [macro-aliases-table]) in which case we treat gi as gi', or a pseudo-lambda expression of arity ni. An instantiable function symbol is any defined or constrained function symbol except the primitives [not], [member], [implies], and [o<], and a few others, as listed by the constant *non-instantiable-primitives*. These are built-in in such a way that we cannot recover the [constraint]s on them. (Special case: a function introduced in the :partial-theory of a dependent clause-processor is not instantiable; see [define-trusted-clause-processor].) A pseudo-lambda expression is an expression of the form (lambda (v1 ... vn) body) where the vi are distinct variable symbols and body is any term. No a priori relation is imposed between the vi and the variables of body, i.e., body may ignore some vi's and may contain ``free'' variables. However, we do not permit v to occur freely in body if the functional substitution is to be applied to any formula (lmi or the [constraint]s to be satisfied) in a way that inserts v into the scope of a binding of v by [let] or [mv-let] (or, [lambda]). If you happen to violate this restriction, an informative error message will be printed. That message will list for you the potentially illegal choices for v in the context in which the functional substitution is offered. A :functional-instance lemma instance denotes the formula obtained by functionally instantiating the formula denoted by lmi, replacing fi by gi. However, before such a lemma instance can be used, the system will generate proof obligations arising from the replacement of the fi's by the gi's in constraints that ``support'' the lemma to be functionally instantiated; see [constraint]. One might expect that if the same instantiated constraint were generated on behalf of several events, then each of those instances would have to be proved. However, for the sake of efficiency, ACL2 stores the fact that such an instantiated constraint has been proved and avoids it in future events. Note that ACL2(r) (see [real]) imposes additional requirements for functional instantiation. See [functional-instantiation-in-ACL2r]. Obscure case for [definition]s. If the lemma instance refers to a :definition [rune], then it refers to the [corollary] formula of that rune, which can be a simplified (``normalized'') form of the original formula. However, if the hint is a :by hint and the lemma instance is based on a name (i.e., a symbol), rather than a rune, then the formula is the original formula of the event, as shown by :[pe], rather than the normalized version, as shown by :[pf]. This is as one would expect: If you supply the name of an event, you expect it to refer to the original event. For :use hints we use the simplified (normalized) form instead, which is reasonable since one would expect simplification during the proof that re-traces the normalization done at the time the rule was created. See [functional-instantiation-example] for an example of the use of :functional-instance (so-called ``functional instantiation).''") (LEN (LISTS ACL2-BUILT-INS) "Length of a list Len returns the length of a list. A Common Lisp function that is appropriate for both strings and proper lists is length; see [length]. The guard for len is t. (Low-level implementation note. ACL2 provides a highly-optimized implementation of len, which is tail-recursive and fixnum-aware, that differs from its simple ACL2 definition.) Function: (defun len (x) (declare (xargs :guard t)) (if (consp x) (+ 1 (len (cdr x))) 0))") (LENGTH (LISTS STRINGS ACL2-BUILT-INS) "Length of a string or proper list Length is the function for determining the length of a sequence. In ACL2, the argument is required to be either a [true-listp] or a string. For a similar function that is logically defined to be equal to zero on any atom, including any string, see [len]. Length is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun length (x) (declare (xargs :guard (if (true-listp x) t (stringp x)))) (if (stringp x) (len (coerce x 'list)) (len x)))") (LET (BASICS ACL2-BUILT-INS) "Binding of lexically scoped (local) variables Introduction Example (let ((x (* x x)) (y (* 2 x))) (list x y)) If the form above is executed in an environment in which x has the value -2, then the result is '(4 -4). Let expressions bind variables so that their ``local'' values, the values they have when the ``body'' of the let is evaluated, are possibly different than their ``global'' values, the values they have in the context in which the let expression appears. In the let expression above, the local variables bound by the let are x and y. They are locally bound to the values delivered by the two forms (* x x) and (* 2 x), respectively, that appear in the ``bindings'' of the let. The body of the let is (list x y). Suppose that the let expression above occurs in a context in which x has the value -2. (The global value of y is irrelevant to this example.) For example, one might imagine that the let form above occurs as the body of some function, fn, with the formal parameter x and we are evaluating (fn -2). To evaluate the let above in a context in which x is -2, we first evaluate the two forms specifying the local values of the variables. Thus, (* x x) is evaluated and produces 4 (because x is -2) and (* 2 x) is evaluated and produces -4 (because x is -2). Then x and y are bound to these values and the body of the let is evaluated. Thus, when the body, (list x y) is evaluated, x is 4 and y is -4. Thus, the body produces '(4 -4). Note that the binding of y, which is written after the binding of x and which mentions x, nevertheless uses the global value of x, not the new local value. That is, the local variables of the let are bound ``in parallel'' rather than ``sequentially.'' In contrast, if the example let* form: (let* ((x (* x x)) (y (* 2 x))) (list x y)) is evaluated when the global value of x is -2, then the result is '(4 8), because the local value of y is computed after x has been bound to 4. [Let*] binds its local variables ``sequentially.'' General let forms (let ((var1 term1) ... (varn termn)) body) and (let ((var1 term1) ... (varn termn)) (declare ...) ... (declare ...) body) where the vari are distinct variables, the termi are terms involving only variables bound in the environment containing the let, and body is a term involving only the vari plus the variables bound in the environment containing the let. Each vari must be used in body or else [declare]d ignored. A let form is evaluated by first evaluating each of the termi, obtaining for each a vali. Then, each vari is bound to the corresponding vali and body is evaluated. Actually, let forms are just abbreviations for certain uses of lambda notation. In particular (let ((var1 term1) ... (varn termn)) (declare ...) body) is equivalent to ((lambda (var1 ... varn) (declare ...) body) term1 ... termn). [Let*] forms are used when it is desired to bind the vari sequentially, i.e., when the local values of preceding varj are to be used in the computation of the local value for vari. General let* forms: (let* ((var1 term1) ... (varn termn)) body) and (let* ((var1 term1) ... (varn termn)) (declare (ignore x1 ... xm)) body) where the vari are variables (not necessarily distinct), the termi are terms involving only variables bound in the environment containing the [let*] and those varj such that j (defun lexorder (x y) (declare (xargs :guard t)) (cond ((atom x) (cond ((atom y) (alphorder x y)) (t t))) ((atom y) nil) ((equal (car x) (car y)) (lexorder (cdr x) (cdr y))) (t (lexorder (car x) (car y)))))") (LINEAR (RULE-CLASSES) "Make some arithmetic inequality rules See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. Example: (defthm length-member-leq-length If inequality reasoning begins to (implies (and (eqlablep e) consider how (length (member a b)) (true-listp x)) compares to any other term, add to (<= (length (member e x)) the set of known inequalities the fact (length x))) that it is no larger than (length b), :rule-classes :linear) provided (eqlablep a) and (true-listp b) rewrite to t. General Form: (and ... (implies (and ...hi...) (implies (and ...hk...) (and ... (rel lhs rhs) ...))) ...) We process the :[corollary] formula of one :linear rule class object to create one or more :linear rules. The first step is to flatten the [and] and [implies] structure of the formula, transforming it into a conjunction of formulas, each of the form (implies (and h1 ... hn) (rel lhs rhs)) where no hypothesis is a conjunction and rel is one of the inequality relations [<], [<=], [=], [/=], [>], or [>=]. If necessary, the hypothesis of such a conjunct may be vacuous. We create a :linear rule for each such conjunct, if possible, and otherwise cause an error. To create a :linear rule from a term (i.e., from a single such conjunct), we apply the following sequence of transformations. 1. Remove [guard-holders] such as [prog2$] from the term to obtain (implies hyp concl), where hyp is t in the case of an unconditional rule. 2. If concl is (not (not concl2)), replace concl by concl2. 3. For the resulting concl, replace [=] and [/=] by [equal] and not equal, respectively. 4. Finally, the resulting concl is processed (``linearized'') to attempt to create a corresponding polynomial or disjunction of two polynomials. This process includes the evaluation of ground subexpressions, for example replacing (* '3 '4) by '12, and employs techniques that include [type-set] reasoning. Each rule has one or more ``trigger terms'' which may be specified by the user using the :trigger-terms field of the rule class or which may be defaulted to values chosen by the system. We discuss the determination of trigger terms after discussing how linear rules are used. :Linear rules are used by an arithmetic decision procedure during rewriting. See [linear-arithmetic] and see [non-linear-arithmetic]. Here we assume that the reader is familiar with the material described in [linear-arithmetic]. Recall that we eliminate the unknowns of an inequality in term-order, largest unknowns first. (See [term-order].) In order to facilitate this strategy, we store the inequalities in ``linear pots''. For purposes of the present discussion, let us say that an inequality is ``about'' its largest unknown. Then, all of the inequalities about a particular unknown are stored in the same linear pot, and the pot is said to be ``labeled'' with that unknown. This storage layout groups all of the inequalities which are potential candidates for cancellation with each other into one place. It is also key to the efficient operation of :linear rules. If the arithmetic decision procedure has stabilized and not yielded a contradiction, we scan through the list of linear pots examining each label as we go. If the trigger term of some :linear rule can be instantiated to match the label, we so instantiate that rule and attempt to relieve the hypotheses with general-purpose rewriting. If we are successful, we rewrite each of the two terms being compared by the conclusion (which is an equality or inequality), under the substitution produced by the rule's instantation. We then add the resulting equality or inequality to our set of inequalities. This may let cancellation continue. Note: Problems may arise if you explicitly store a linear lemma under a trigger term that, when instantiated, is not the largest unknown in the instantiated concluding inequality. Suppose for example you store the linear rule (<= (fn i j) (/ i (* j j))) under the trigger term (fn i j). Then when the system ``needs'' an inequality about (fn a b), (i.e., because (fn a b) is the label of some linear pot, and hence the largest unknown in some inequality), it will appeal to the rule and deduce (<= (fn a b) (/ a (* b b))). However, the largest unknown in this inequality is (/ a (* b b)) and hence it will be stored in a linear pot labeled with (/ a (* b b)). The original, triggering inequality which is in a pot about (fn a b) will therefore not be cancelled against the new one. It is generally best to specify as a trigger term one of the ``maximal'' terms of the polynomial, as described below. We now describe how the trigger terms are determined. Most of the time, the trigger terms are not specified by the user and are instead selected by the system. However, the user may specify the terms by including an explicit :trigger-terms field in the rule class, e.g., General Form of a Linear Rule Class: (:LINEAR :COROLLARY formula :TRIGGER-TERMS (term1 ... termk)) Each termi must be a term and must not be a variable, quoted constant, lambda application, let-expression or if-expression. In addition, each termi must be such that if all the variables in the term are instantiated and then the hypotheses of the corollary formula are relieved (possibly instantiating additional free variables), then all the variables in the concluding inequality are instantiated. We generate a linear rule for each conjuctive branch through the corollary and store each rule under each of the specified triggers. Thus, if the corollary formula contains several conjuncts, the variable restrictions on the termi must hold for each conjunct. If :trigger-terms is omitted the system computes a set of trigger terms. Each conjunct of the corollary formula may be given a unique set of triggers depending on the variables that occur in the conjunct and the addends that occur in the concluding inequality. In particular, the trigger terms for a conjunct is the list of all ``maximal addends'' in the concluding inequality. The ``addends'' of (+ x y) and (- x y) are the union of the addends of x and y. The addends of (- x) and (* n x), where n is a rational constant, is just {x}. The addends of an inequality are the union of the addends of the left- and right-hand sides. The addends of any other term, x, is {x}. A term is maximal for a conjunct (implies hyps concl) of the corollary if (a) the term is a non-variable, non-quote, non-lambda application, non-[let] and non-[if] expression, (b) the term contains enough variables so that when they are instantiated and the hypotheses are relieved (which may bind some free variables; see [free-variables]) then all the variables in concl are instantiated, and (c) no other addend is always ``bigger'' than the term, in the technical sense described below. The technical notion referenced above depends on the notion of fn-count, the number of function symbols in a term, and pseudo-fn-count, which is essentially the number of function symbols implicit in a constant (see [term-order], specifically the discussion of ``pseudo-function application count'' at the end). We say term1 is always bigger than term2 if all instances of term1 have a larger fn-count (actually lexicographic order of fn-count and pseudo-fn-count) than the corresponding instances of term2. This is equivalent to saying that the fn-count of term1 is larger than that of term2 (by ``fn-count'' here we mean the lexicographic order of fn-count and pseudo-fn-count) and the variable bag for term2 is a subbag of that for term1. For example, (/ a (* b b)) is always bigger than (fn a b) because the first has two function applications and {a b} is a subbag of {a b b}, but (/ a (* b b)) is not always bigger than (fn a x). Subtopics [Backchain-limit] Limiting the effort expended on relieving hypotheses [Bind-free] To bind free variables of a rewrite, definition, or linear rule [Case-split] Like force but immediately splits the top-level goal on the hypothesis [Force] Identity function used to force a hypothesis [Linear-arithmetic] A description of the linear arithmetic decision procedure [Non-linear-arithmetic] Non-linear Arithmetic [Syntaxp] Attach a heuristic filter on a rule") (LINEAR-ARITHMETIC (LINEAR) "A description of the linear arithmetic decision procedure We describe the procedure very roughly here. Fundamental to the procedure is the notion of a linear polynomial inequality. A ``linear polynomial'' is a sum of terms, each of which is the product of a rational constant and an ``unknown.'' The ``unknown'' is permitted to be 1 simply to allow a term in the sum to be constant. Thus, an example linear polynomial is 3*x + 7*a + 2; here x and a are the (interesting) unknowns. However, the unknowns need not be variable symbols. For example, (length x) might be used as an unknown in a linear polynomial. Thus, another linear polynomial is 3*(length x) + 7*a. A ``linear polynomial inequality'' is an inequality (either [<] or [<=]) relation between two linear polynomials. Note that an equality may be considered as a pair of inequalities; e.q., 3*x + 7*a + 2 = 0 is the same as the conjunction of 3*x + 7*a + 2 <= 0 and 0 <= 3*x + 7*a + 2. Certain linear polynomial inequalities can be combined by cross-multiplication and addition to permit the deduction of a third inequality with fewer unknowns. If this deduced inequality is manifestly false, a contradiction has been deduced from the assumed inequalities. For example, suppose we have two assumptions p1: 3*x + 7*a < 4 p2: 3 < 2*x and we wish to prove that, given p1 and p2, a < 0. As suggested above, we proceed by assuming the negation of our goal p3: 0 <= a. and looking for a contradiction. Our first step will be to eliminate the variable x. To that end, we cross-multiply based on the coefficients of x in the two inequalities. By multiplying p1 by 2 and p2 by 3, and then adding the respective sides, we deduce the intermediate result p4: 6*x + 14*a + 9 < 8 + 6*x which, after cancellation, is: p4: 14*a + 1 < 0. If we then cross-multiply and add p3 to p4, we get p5: 1 <= 0, a contradiction. Thus, we have proved that p1 and p2 imply the negation of p3. All of the unknowns of an inequality must be eliminated by cancellation in order to produce a constant inequality. We can choose to eliminate the unknowns in any order, but we eliminate them in term-order, largest unknowns first. (See [term-order].) That is, two polys are cancelled against each other only when they have the same largest unknown. For instance, in the above example we see that x is the largest unknown in each of p1 and p2, and a in p3 and p4. Now suppose that this procedure does not produce a contradiction but instead yields a set of nontrivial inequalities. A contradiction might still be deduced if we could add to the set some additional inequalities allowing further cancellations. That is where :linear lemmas come in. When the set of inequalities has stabilized under cross-multiplication and addition and no contradiction is produced, we search the database of :[linear] rules for rules about the unknowns that are candidates for cancellation (i.e., are the largest unknowns in their respective inequalities). See [linear] for a description of how :[linear] rules are used. See also [non-linear-arithmetic] for a description of an extension to the linear-arithmetic procedure described here.") (LIST (LISTS ACL2-BUILT-INS) "Build a list List is the macro for building a list of objects. For example, (list 5 6 7) returns a list of length 3 whose elements are 5, 6, and 7 respectively. Also see [list*]. List is defined in Common Lisp. See any Common Lisp documentation for more information. Macro: (defmacro list (&rest args) (list-macro args)) Function: (defun list-macro (lst) (declare (xargs :guard t)) (if (consp lst) (cons 'cons (cons (car lst) (cons (list-macro (cdr lst)) nil))) nil))") (LIST* (LISTS ACL2-BUILT-INS) "Build a list List* is the Common Lisp macro for building a list of objects from given elements and a tail. For example, (list* 5 6 '(7 8 9)) equals the list '(5 6 7 8 9). Also see [list]. List* is a Common Lisp function. See any Common Lisp documentation for more information. Macro: (defmacro list* (&rest args) (declare (xargs :guard (consp args))) (list*-macro args)) Function: (defun list*-macro (lst) (declare (xargs :guard (and (true-listp lst) (consp lst)))) (if (endp (cdr lst)) (car lst) (cons 'cons (cons (car lst) (cons (list*-macro (cdr lst)) nil)))))") (LISTP (LISTS CONSES ACL2-BUILT-INS) "Recognizer for (not necessarily proper) lists (listp x) is true when x is either a [cons] pair or is nil. Listp has no [guard], i.e., its [guard] is t. Listp is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun listp (x) (declare (xargs :guard t)) (or (consp x) (equal x nil)))") (LISTS (PROGRAMMING) "Lists of objects, the classic Lisp data structure. Subtopics [ACL2-number-listp] Recognizer for a true list of numbers [Add-to-set] Add a symbol to a list [Append] [concatenate] zero or more lists [Atom-listp] Recognizer for a true list of [atom]s [Boolean-listp] Recognizer for a true list of booleans [Butlast] All but a final segment of a list [Character-listp] Recognizer for a true list of characters [Concatenate] Concatenate lists or strings together [Count] Count the number of occurrences of an item in a string or true-list [Endp] Recognizer for empty lists [Eqlable-listp] Recognizer for a true list of objects each suitable for [eql] [Fix-true-list] Coerce to a true list [Good-atom-listp] Recognizer for a true list of ``good'' [atom]s [Improper-consp] Recognizer for improper (non-null-terminated) non-empty lists [Integer-listp] Recognizer for a true list of integers [Intersection$] Elements of one list that are not elements of another [Intersectp] Test whether two lists intersect [Keyword-value-listp] Recognizer for true lists whose even-position elements are keywords [Last] The last [cons] (not element) of a list [Len] Length of a list [Length] Length of a string or proper list [List] Build a list [List*] Build a list [Listp] Recognizer for (not necessarily proper) lists [Make-list] Make a list of a given size [Member] Membership predicate [Nat-listp] Recognizer for a true list of natural numbers [No-duplicatesp] Check for duplicates in a list [Nth] The nth element (zero-based) of a list [Nthcdr] Final segment of a list [Pairlis] See [pairlis$] [Pairlis$] Zipper together two lists [Position] Position of an item in a string or a list [Proper-consp] Recognizer for proper (null-terminated) non-empty lists [Rational-listp] Recognizer for a true list of rational numbers [Real-listp] ACL2(r) recognizer for a true list of real numbers [Remove] Remove all occurrences [Remove-duplicates] Remove duplicates from a string or a list [Remove1] Remove first occurrences, testing using [eql] [Revappend] Concatentate the [reverse] of one list to another [Reverse] Reverse a list or string [Search] Search for a string or list in another string or list [Set-difference$] Elements of one list that are not elements of another [Standard-char-listp] Recognizer for a true list of standard characters [String-listp] Recognizer for a true list of strings [Subseq] Subsequence of a string or list [Subsetp] Test if every [member] of one list is a [member] of the other [Substitute] Substitute into a string or a list, using [eql] as test [Symbol-listp] Recognizer for a true list of symbols [Take] Initial segment (first n elements) of a list [True-list-listp] Recognizer for true (proper) lists of true lists [True-listp] Recognizer for proper (null-terminated) lists [Union$] Elements of one list that are not elements of another [Update-nth] Modify a list by putting the given value at the given position") (LOCAL (EVENTS) "Hiding an event in an encapsulation or book Examples: (local (defthm hack1 (implies (and (acl2-numberp x) (acl2-numberp y) (equal (* x y) 1)) (equal y (/ x))))) (local (defun double-naturals-induction (a b) (cond ((and (integerp a) (integerp b) (< 0 a) (< 0 b)) (double-naturals-induction (1- a) (1- b))) (t (list a b))))) General Form: (local ev) where ev is an event form. If the current default [defun-mode] (see [default-defun-mode]) is :[logic] and [ld-skip-proofsp] is nil or t, then (local ev) is equivalent to ev. But if the current default [defun-mode] is :[program] or if [ld-skip-proofsp] is '[include-book], then (local ev) is a no-op. Thus, if such forms are in the event list of an [encapsulate] event or in a book, they are processed when the encapsulation or book is checked for admissibility in :[logic] mode but are skipped when extending the host [world]. Such [events] are thus considered ``local'' to the verification of the encapsulation or book. The non-local [events] are the ones ``exported'' by the encapsulation or book. See [encapsulate] for a thorough discussion. Also see [local-incompatibility] for a discussion of a commonly encountered problem with such event hiding: you can't make an event local if its presence is required to make sense of a non-local one. Note that [events] that change the default [defun-mode], and in fact any [events] that set the [ACL2-defaults-table], are disallowed inside the scope of local. See [embedded-event-form].") (LOCAL-INCOMPATIBILITY (MISCELLANEOUS) "When non-local [events] won't replay in isolation Sometimes a ``[local] incompatibility'' is reported while attempting to embed some [events], as in an [encapsulate] or [include-book]. This is generally due to the use of a locally defined name in a non-local event or the failure to make a witnessing definition [local]. [Local] incompatibilities may be detected while trying to execute the strictly non-local [events] of an embedding. For example, [encapsulate] operates by first executing all the [events] ([local] and non-local) with [ld-skip-proofsp] nil, to confirm that they are all admissible. Then it attempts merely to assume the non-local ones to create the desired theory, by executing the [events] with [ld-skip-proofsp] set to '[include-book]. Similarly, [include-book] assumes the non-local ones, with the understanding that a previously successful [certify-book] has performed the admissiblity check. How can a sequence of [events] admitted with [ld-skip-proofsp] nil fail when [ld-skip-proofsp] is '[include-book]? The key observation is that in the latter case only the non-local [events] are processed. The [local] ones are skipped and so the non-local ones must not depend upon them. Two typical mistakes are suggested by the detection of a [local] incompatibility: (1) a locally defined function or macro was used in a non-[local] event (and, in the case of [encapsulate], was not included among the [signature]s) and (2) the witnessing definition of a function that was included among the [signature]s of an [encapsulate] was not made [local]. An example of mistake (1) would be to include among your [encapsulate]d [events] both (local (defun fn ...)) and (defthm lemma (implies (fn ...) ...)). Observe that fn is defined locally but a formula involving fn is defined non-locally. In this case, either the [defthm] should be made [local] or the [defun] should be made non-local. An example of mistake (2) would be to include (fn (x) t) among your [signature]s and then to write (defun fn (x) ...) in your [events], instead of (local (defun fn ...)). One subtle aspect of [encapsulate] is that if you constrain any member of a mutually recursive clique you must define the entire clique locally and then you must constrain those members of it you want axiomatized non-locally. Errors due to [local] incompatibility should never occur in the assumption of a fully certified book. Certification ensures against it. Therefore, if [include-book] reports an incompatibility, we assert that earlier in the processing of the [include-book] a warning was printed advising you that some book was uncertified. If this is not the case --- if [include-book] reports an incompatibility and there has been no prior warning about lack of certification --- please report it to us. When a [local] incompatibility is detected, we roll-back to the [world] in which we started the [encapsulate] or [include-book]. That is, we discard the intermediate [world] created by trying to process the [events] skipping proofs. This is clean, but we realize it is very frustrating because the entire sequence of [events] must be processed from scratch. Assuming that the embedded [events] were, once upon a time, processed as top-level [command]s (after all, at some point you managed to create this sequence of [command]s so that the [local] and non-local ones together could survive a pass in which proofs were done), it stands to reason that we could define a predicate that would determine then, before you attempted to embed them, if [local] incompatibilities exist. We hope to do that, eventually. We conclude with a subtle example of [local] incompatibility. The problem is that in order for foo-type-prescription to be admitted using the specified :typed-term (foo x), the conclusion (my-natp (foo x)) depends on my-natp being a [compound-recognizer]. This is fine on the first pass of the [encapsulate], during which lemma my-natp-cr is admitted. But my-natp-cr is skipped on the second pass because it is marked [local], and this causes foo-type-prescription to fail on the second pass. (defun my-natp (x) (declare (xargs :guard t)) (and (integerp x) (<= 0 x))) (defun foo (x) (nfix x)) (encapsulate () (local (defthm my-natp-cr (equal (my-natp x) (and (integerp x) (<= 0 x))) :rule-classes :compound-recognizer)) (defthm foo-type-prescription (my-natp (foo x)) :hints ((\"Goal\" :in-theory (enable foo))) :rule-classes ((:type-prescription :typed-term (foo x)))))") (LOGAND (NUMBERS ACL2-BUILT-INS) "Bitwise logical `and' of zero or more integers When integers are viewed in their two's complement representation, logand returns their bitwise logical `and'. In ACL2 logand is a macro that expands into calls of the binary function binary-logand, except that (logand) expands to -1 and (logand x) expands to x. The [guard] for binary-logand requires its arguments to be integers. Logand is defined in Common Lisp. See any Common Lisp documentation for more information. Macro: (defmacro logand (&rest args) (cond ((null args) -1) ((null (cdr args)) (car args)) (t (xxxjoin 'binary-logand args)))) Function: (defun binary-logand (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (cond ((zip i) 0) ((zip j) 0) ((eql i -1) j) ((eql j -1) i) (t (let ((x (* 2 (logand (floor i 2) (floor j 2))))) (+ x (cond ((evenp i) 0) ((evenp j) 0) (t 1)))))))") (LOGANDC1 (NUMBERS ACL2-BUILT-INS) "Bitwise logical `and' of two ints, complementing the first When integers are viewed in their two's complement representation, logandc1 returns the bitwise logical `and' of the second with the bitwise logical `not' of the first. The [guard] for logandc1 requires its arguments to be integers. Logandc1 is defined in Common Lisp. See any Common Lisp documentation for more information. Function: (defun logandc1 (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (logand (lognot i) j))") (LOGANDC2 (NUMBERS ACL2-BUILT-INS) "Bitwise logical `and' of two ints, complementing the second When integers are viewed in their two's complement representation, logandc2 returns the bitwise logical `and' of the first with the bitwise logical `not' of the second. The [guard] for logandc2 requires its arguments to be integers. Logandc2 is defined in Common Lisp. See any Common Lisp documentation for more information. Function: (defun logandc2 (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (logand i (lognot j)))") (LOGBITP (NUMBERS ACL2-BUILT-INS) "The ith bit of an integer For a nonnegative integer i and an integer j, (logbitp i j) is a Boolean, which is t if and only if the value of the ith bit is 1 in the two's complement representation of j. (Logbitp i j) has a [guard] that i is a nonnegative integer and j is an integer. Logbitp is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun logbitp (i j) (declare (xargs :guard (and (integerp j) (integerp i) (>= i 0)))) (oddp (floor (ifix j) (expt 2 (nfix i)))))") (LOGCOUNT (NUMBERS ACL2-BUILT-INS) "Number of ``on'' bits in a two's complement number (Logcount x) is the number of ``on'' bits in the two's complement representation of x. (Logcount x) has a [guard] of (integerp x). Logcount is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun logcount (x) (declare (xargs :guard (integerp x))) (cond ((zip x) 0) ((< x 0) (logcount (lognot x))) ((evenp x) (logcount (nonnegative-integer-quotient x 2))) (t (1+ (logcount (nonnegative-integer-quotient x 2))))))") (LOGEQV (NUMBERS ACL2-BUILT-INS) "Bitwise logical equivalence of zero or more integers When integers are viewed in their two's complement representation, logeqv returns their bitwise logical equivalence. In ACL2 logeqv is a macro that expands into calls of the binary function binary-logeqv, except that (logeqv) expands to -1 and (logeqv x) expands to x. The [guard] for binary-logeqv requires its arguments to be integers. Logeqv is defined in Common Lisp. See any Common Lisp documentation for more information. Macro: (defmacro logeqv (&rest args) (cond ((null args) -1) ((null (cdr args)) (car args)) (t (xxxjoin 'binary-logeqv args)))) Function: (defun binary-logeqv (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (logand (logorc1 i j) (logorc1 j i)))") (LOGIC (DEFUN-MODE) "To set the default [defun-mode] to :logic Example: ACL2 p!>:logic ACL2 !> Typing the keyword :logic sets the default [defun-mode] to :logic. Functions defined in :logic mode are logically defined. See [defun-mode]. Note: This is an event! It does not print the usual event summary but nevertheless changes the ACL2 logical [world] and is so recorded. See [defun-mode] for a discussion of the [defun-mode]s available and what their effects on the logic are. See [default-defun-mode] for a discussion of how the default [defun-mode] is used. This event is equivalent to (table acl2-defaults-table :defun-mode :logic), and hence is [local] to any [books] and [encapsulate] [events] in which it occurs. See [ACL2-defaults-table]. Recall that the top-level form :logic is equivalent to (logic); see [keyword-commands]. Thus, to change the default [defun-mode] to :logic in a book, use (logic), which is an embedded event form, rather than :logic, which is not a legal form for [books]. See [embedded-event-form].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED (INTRODUCTION-TO-THE-THEOREM-PROVER) "Background knowledge in ACL2 logic for theorem prover tutorial You might think that in order to use the theorem prover you have to know the mathematical logic supported by ACL2. But you need to know a lot less about it than you might think. Technically, a theorem is a formula that can be derived from axioms by using rules of inference. Thus, to do a proof you have to know (a) the syntax of formulas, (b) the axioms, and (c) the rules of inference. Traditionally, these things are spelled out in excruciating detail in treatments of mathematical logic -- and for good reason. The whole point of proving theorems is that it is a way to determine that a formula is ``always true'' (under some model of the axioms). By ``always true'' we actually mean what logicians mean when they say the formula is valid: true in the model, for all possible values of the variables. Here by ``model of the axioms'' we mean an understanding of the meaning of the various function symbols so that the axioms are true for all values of the variables. If the variables in your conjecture can take on an infinite number of values, proof is often the only way to determine that a conjecture is ``always true.'' So if proof is being used to determine that a questionable formula is always true the proof must be carried out flawlessly. Thus, the (a) syntax, (b) axioms, and (c) rules of inference must be described precisely and followed to the letter. But formal mathematical logic was invented to explain how people reason. To the extent that logic mimics human reasoning, proofs can be seen as just extremely carefully crafted arguments. Given that ACL2 is responsible for following the rules ``to the letter,'' your main job is ``explain'' the big leaps. To use the theorem prover you must understand (a) the syntax, because you must be able to write formulas flawlessly. But you don't have to know (b) the axioms and (c) the rules of inference at nearly the same level of precision, as long as you understand the basic structure and language of proofs. Below is part of a proof of a certain theorem. You ought to be able to understand the following. Since what we describe is a proof of one case of the formula, we hope that you're convinced that the formula holds for that case. Read this and follow the links to confirm that you understand what happens. Be sure to then use your browser's Back Button to return to this page and continue. An Annotated Proof of (implies (true-listp z) (equal (rev (rev z)) z)) ``We will prove that reversing the reverse of a true-listp yields the original list. The formula stating this is above. We will prove it by [induction] on the list structure of z. The [base case] of the induction is: (implies (endp z) (implies (true-listp z) (equal (rev (rev z)) z))). This formula is equivalent, by [propositional calculus], to (implies (and (endp z) (true-listp z)) (equal (rev (rev z)) z)) [Rewriting] with the definition of endp produces: (implies (and (not (consp z)) (true-listp z)) (equal (rev (rev z)) z)) [Rewriting repeatedly] starting with the definition of true-listp produces: (implies (and (not (consp z)) (equal z nil)) (equal (rev (rev z)) z)) Then using the second hypothesis, just [substituting equals for equals], we get (implies (and (not (consp z)) (equal z nil)) (equal (rev (rev nil)) nil)) Since the conclusion involves no variables, we can [evaluate] it, getting (implies (and (not (consp z)) (equal z nil)) T) But this is an [instance] of the [tautology] (implies p T). Thus, the base case is proved.'' Now it is time for a little quiz. There are just three questions. Q1: The case above was the Base Case of an inductive proof of (implies (true-listp z) (equal (rev (rev z)) z)) in which we did induction on the structure of the linear list z. What is the Induction Step? That is, what do you have to prove besides the Base Case to complete this inductive proof? Below are four commonly given answers; choose one. Then look [here] to find out if you're right. Induction Step -- Choice (i): (implies (not (endp z)) (implies (true-listp z) (equal (rev (rev z)) z))) Induction Step -- Choice (ii): (implies (true-listp (cdr z)) (equal (rev (rev (cdr z))) (cdr z))) Induction Step -- Choice (iii): (implies (and (not (endp z)) (equal (rev (rev (cdr x))) (cdr x))) (implies (true-listp z) (equal (rev (rev z)) z))) Induction Step -- Choice (iv): (implies (and (not (endp z)) (implies (true-listp (cdr z)) (equal (rev (rev (cdr z))) (cdr z)))) (implies (true-listp z) (equal (rev (rev z)) z))) Q2: To prove the Induction Step we must prove one or more of the goals below. Which combinations are sufficient to imply the Induction Step? Decide what is required and then look [here] to find out if you're right. To help you, the Induction Step is of the form: Induction Step: (implies (and c (implies p' q')) (implies p q)) and beside each candidate subgoal we show its structure in those terms. Subgoal (i): (implies (and (not (endp z)) ; (implies (and c (true-listp z)) ; p) (true-listp (cdr z))) ; p') Subgoal (ii): (implies (and (not (endp z)) ; (implies (and c (true-listp z) ; p (equal (rev (rev (cdr z))) (cdr z))) ; q') (equal (rev (rev z)) z)) ; q) Subgoal (iii): (implies (and (not (endp z)) ; (implies (and c (equal (rev (rev (cdr z))) (cdr z))) ; q') (equal (rev (rev z)) z)) ; q) Subgoal (iv): (implies (and (not (endp z)) ; (implies (and c (true-listp (cdr z)) ; p' (equal (rev (rev (cdr z))) (cdr z))) ; q') (equal (rev (rev z)) z)) ; q) Q3: Suppose you know the theorem Theorem: (implies (p (f x)) (equal (g (h x)) x)) and you wish to rewrite the target (g (h a)) to a in Goal Conjecture: (implies (and (q (f a)) (r a)) (s (g (h a)))) What must you prove to relieve the hypothesis of Theorem? After you've thought about it, look [here] for our answer. End of the Quiz If this page made sense, you're ready to read the introduction to the theorem prover. If you are reading this as part of the tutorial introduction to the theorem prover, use your browser's Back Button now to return to [introduction-to-the-theorem-prover].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-BASE-CASE (INTRODUCTION-TO-THE-THEOREM-PROVER) "A brief explanation of base cases According to the sentence, the conjecture being proved is ``reversing the reverse of a true-listp yields the original list.'' The formula corresponding to this conjecture is: (implies (true-listp z) (equal (rev (rev z)) z)). We're also told that this is an inductive proof. Evidently we're doing an induction on the structure of the list z. Then the Base Case is the formula: (implies (endp z) (implies (true-listp z) (equal (rev (rev z)) z))). Now use your browser's Back Button to return to the example proof in [logic-knowledge-taken-for-granted].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-EQUALS-FOR-EQUALS (INTRODUCTION-TO-THE-THEOREM-PROVER) "Substitution of equals for equals Anytime you have an equality hypothesis relating two terms, e.g., (equal lhs rhs) it is legal to substitute one for the other anyplace else in the formula. Doing so does not change the truthvalue of the formula. You can use a negated equality this way provided it appears in the conclusion. For example, it is ok to transform (implies (true-listp x) (not (equal x 23))) to (implies (true-listp 23) (not (equal x 23))) by substitutions of equals for equals. That is because, by [propositional calculus], we could rearrange the formulas into their contrapositive forms: (implies (equal x 23) (not (true-listp x))) and (implies (equal x 23) (not (true-listp 23))) and see the equality as a hypothesis and the substitution of 23 for x as sensible. Sometimes people speak loosely and say ``substitution of equals for equals'' when they really mean ``substitutions of equivalents for equivalents.'' Equality, as tested by EQUAL, is only one example of an equivalence relation. The next most common is propositional equivalence, as tested by IFF. You can use propositional equivalence hypotheses to substitute one side for the other provided the target term occurs in a propositional place, as discussed at the bottom of [propositional calculus]. Now use your browser's Back Button to return to the example proof in [logic-knowledge-taken-for-granted].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-EVALUATION (INTRODUCTION-TO-THE-THEOREM-PROVER) "Evaluation during proofs Any time you are proving a formula and see a subterm in the formula that contains no variables, you can just evaluate the subterm. This is familiar from algebra: It is not uncommon to rearrange a polynominal to collect all the constants and then add them up: (3x + 2 + 7y + 2) = (3x + 7y + (2 + 2)) = (3x + 7y + 4). That last step is just evaluation. It happens often in ACL2 proofs because theorems involve constants and defined functions and when those constants ``drift into the maw'' of a function, the function call can be eliminated and replaced by a new constant. ACL2 does this automatically; you don't have to tell it. In fact, there are a few occasions where you might prefer it not evaluate and those are the ones you have to look out for! They'll be obvious when they happen because you'll see a mysterious constant crop up in the proof. Evaluation is legal because it is just the repeated use of unconditional rewriting to replace definitions by their instantiated bodies until no function calls remain. Now use your browser's Back Button to return to the example proof in [logic-knowledge-taken-for-granted].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INDUCTIVE-PROOF (INTRODUCTION-TO-THE-THEOREM-PROVER) "A brief explanation of induction We start by showing classical induction on the natural numbers in an ACL2 setting before turning to a more general treatment of induction. Classical Induction on Natural Numbers: Induction is familiar in the arithmetic setting. Let (p n) denote some formula involving the variable n (and perhaps some other variables which we don't exhibit). Then to prove (p n), for all n, by classical induction on the construction of the natural numbers, prove each of the following: Base Case: (implies (zp n) (p n)) Induction Step: (implies (and (not (zp n)) (p (- n 1))) (p n)) The Base Case establishes that p holds for 0. In fact, because of the definition of [zp] [{ICON}], it establishes that (p n) holds when n is 0 and it holds when n is not a natural number. The Induction Step establishes that if n is a natural number other than 0, and if p holds for n-1, then p holds for n. The hypothesis (p (- n 1)) above is called the induction hypothesis. Note that if the Base Case and Induction Step are valid, then we know (p n), for all n. You can convince yourself of this by picking any object and asking ``how do I know p holds for this object?'' For example, (p -7), (p 'abc), and (p 0) are all established by the Base Case. What about (p 1)? That follows from (p 0), given the Induction Step. Why? To prove (p 1) using the Induction Step, you have to establish (not (zp 1)), which is true, and (p (- 1 1)), which is (p 0), which is true by the Base Case. So (p 1) is true. Similar reasoning proves (p 2) from from (p 1), etc. Clearly, for every natural number other than 0 we could reason like this to show that p holds. Since the Base Case handled all the objects that are not natural numbers, and handled 0, we know (p n), for all n. There is a duality between recursion and induction that ACL2 exploits. The fact that the Base and Induction steps above are sufficient to prove p for all objects is related to the fact that the following recursion defines a total, terminating function: (defun nat-recursion (n) (if (zp n) n (nat-recursion (- n 1)))) When this function is admitted we have to prove that if (zp n) does not hold, then (- n 1) is smaller, in some sense, than n. This sense of ``smaller'' is determined by some measure of the arguments. That measure must return an ordinal ([ordinals] [{ICON}]), but the most common measures return natural numbers, which are among the ordinals. Furthermore, that measure should insure that the terms in the recursive calls are smaller than the formals, i.e., the measure of (- n 1) must be smaller than the measure of n, when the recursive branches are taken. This sense of ``smaller'' must be well-founded: it must be impossible to have an infinitely descending chain of smaller things. This is true of the less-than relation on the ordinals (see [o<] [{ICON}]). Well-foundedness means that eventually any recursion must ``bottom out'' because things can't keep getting smaller forever. The recursion in nat-recursion suggests the induction shown above: the Base Case is defined by the if branch that does not lead to a recursive call. The Induction Step is defined by the other branch. The induction hypothesis is defined by what we recur on, i.e., (- n 1). The theorems proved when nat-recursion is introduced justify the classical induction scheme noted above. Every recursively defined ACL2 function suggests a legal induction and vice versa. Furthermore, every call of a recursively defined function on distinct variable symbols also suggests a legal induction: just take the induction suggested by the function's recursive definition after renaming the formal parameters to be the variables in the call. For example, it should be clear that (nat-recursion a) suggests a Base Case defined by (zp a), and induction step defined by (not (zp a)) and an induction hypothesis about (- a 1). Note that the term (fact n) suggests the same classical induction on natural numbers shown above, where fact is defined as follows (even though we've used the formal parameter k below). (defun fact (k) (if (zp k) 1 (* k (fact (- k 1))))) The induction suggested by a term like (fact n) is insensitive to the name of the formal parameter used in the defun. The induction suggested by a function or term is insensitive to the value returned by the function or term. It doesn't matter what the function returns in its ``base case'' (e.g., 1 in fact) or what the function ``does'' to its recursive call (e.g., multiply by k in the defun of fact). All that matters is (i) how the if structure breaks down the cases on k, (ii) which branches lead to recursion, and (iii) what arguments are passed to the recursive calls. Those things determine (i) the case analysis of the induction scheme, (ii) which cases are Base Cases and which are Induction Steps, and (iii) what the induction hypotheses are. For a selection of common inductions schemes in ACL2 (e.g., on the structure of natural numbers, lists, and trees and on several variables at once, multiple base cases, multiple induction hypotheses, multiple induction steps, etc.) [check this link]. Every legal ACL2 induction corresponds to an admissible recursive function and vice versa. Similarly, every legal ACL2 induction corresponds to a call of a recursively defined function on distinct variables. ACL2 chooses which induction to do by looking at the terms that occur in the conjecture. For many elementary theorems, ACL2 chooses the right induction by itself. You may occasionally need to tell it what induction to do. You do that by showing it a term that suggests the induction you want. We'll explain how you communicate this to ACL2 later. If you understand how recursive functions suggest inductions, then you know what you need to know to use ACL2. The main point of this discussion of induction is familiarize you with the basic terms: Base Case (of which there may be several), Induction Step (of which there may be several), Induction Hypothesis (of which there may be several in each Induction Step), measure and well-founded relation justifying an induction, and the induction suggested by a term or recursive function definition. Furthermore, every Induction Hypothesis is always an [instance] of the conjecture being proved: each induction hypothesis is obtained from the conjecture being proved by applying a substitution replacing variables by terms. If you are reviewing the material taken for granted about logic while working your way through the introduction to the theorem prover, please use your browser's Back Button to return to the example proof in [logic-knowledge-taken-for-granted].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-INSTANCE (INTRODUCTION-TO-THE-THEOREM-PROVER) "A brief explanation of substitution instances Let p and q be terms or formulas (there is no difference in ACL2). Then we say p is an instance or substitution instance of q if and only if p can be obtained from q by uniformly replacing the variables of q by terms. Sometimes we call p the target and q the pattern because by choosing appropriate replacements we can make the pattern match many different targets. For example, the following target is an instance of the given pattern: target: (APP (APP (REV A) (REV B)) (REV C)) pattern: (APP (APP x y ) (REV z)) The replacement or substitution used in this match of the pattern to the target is: variable in pattern replacement term x (REV A) y (REV B) z C Such substitutions are usually written this way in ACL2: ((x (REV A)) (y (REV B)) (z C)). Please use your browser's Back Button to return to the page that mentioned ``instance.''") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-PROPOSITIONAL-CALCULUS (INTRODUCTION-TO-THE-THEOREM-PROVER) "A brief explanation of propositional calculus It is impossible in this short introduction to teach you propositional calculus if you don't already know it! A typical use of propositional calculus is to observe that (implies (endp z) (implies (true-listp z) (equal (rev (rev z)) z))) is equivalent to: (implies (and (endp z) (true-listp z)) (equal (rev (rev z)) z)) If this is surprising and you know propositional calculus, then the problem might be our notation. We're exploiting the tautology (p ---> (q ---> r)) <---> ((p & q) ---> r) where ---> and <---> are meant to be the traditional arrows denoting logical implication and logical equivalence. If you don't know propositional calculus, we'll say just a few things to help ease your journey. A propositional formula, in ACL2, is any formula written entirely in terms of variable symbols, T, NIL, and the propositional functions AND, OR, NOT, IMPLIES, and IFF. The ``tautology'' above in traditional notation is this propositional formula in ACL2: (IFF (IMPLIES P (IMPLIES Q R)) (IMPLIES (AND P Q) R)). If you have a formula like (implies hyp concl) then we say that formula is an implication, that hyp is the hypothesis, and that concl is the conclusion. If the hypothesis is an and expression, as in (implies (and hyp1 hyp2 ...) concl) then we call hyp1 is the first hypothesis, hyp2 is the second hypothesis, etc. If a term is of the form (and term1 term2 ...) we say it is a conjunction and that term1 is the first conjunct, term2 is the second conjunct, etc. We treat an or-term analogously but call it a disjunction and its arguments are disjuncts. A tautology is any propositional formula that can be proved by testing it under all combinations of Boolean assignments to its variables. We give an example of such a truth-table proof below, but hasten to add that ACL2 does not generally use truth tables to recognize tautologies. It primarily uses IF-normalization and BDDs to recognize tautologies, which can be seen as a mix of symbolic manipulation and case analysis. Many tautologies have names, but ACL2 doesn't refer to them by name because it derives them from first principles. We list a few here because we sometimes use the names in our documentation; more importantly, you should look at these formulas and convince yourself that they're always true for all Boolean values of the variables: Double Negation: (iff (not (not p)) p) DeMorgan: (iff (not (and p q)) (or (not p) (not q))) Distributivity: (iff (and p (or q r)) (or (and p q) (and p r))) Promotion: (iff (implies p (implies q r)) (implies (and p q) r)) Implicative Disjunction: (iff (implies p q) (or (not p) q)) Contrapositive: (iff (implies p q) (implies (not q) (not p))) Generalized Contrapositive: (iff (implies (and p r) q) (implies (and p (not q)) (not r))) There are, of course, many others, even with these same names! For example, there is a dual version of DeMorgan showing how not distributes over or, a dual version of Distributivity for or over and, etc. Dealing with propositional calculus will not generally be a problem for you because it is decidable and ACL2 has procedures that decide propositional formulas. However, propositional calculus can lead to exponential explosion and can thus explain why ACL2 has ``gone out to lunch.'' In addition, sometimes if you are curious as to why ACL2 is working on a certain subgoal the reason can be traced back to propositional calculus. The most common example of this is that to prove a formula of the form (implies (implies p1 q1) (implies p2 q2)) propositional calculus will convert it to (and (implies (and p2 (not p1)) q2) (implies (and p2 q1) q2)) Many users are surprised that the first conjunct above does not have q1 as a hypothesis. If you ever stare at an ACL2 goal and say to yourself ``A hypothesis is missing!'' the chances are that propositional calculus is ``to blame.'' In particular, if you are trying to prove that (implies p1 q1) implies something, you must deal with the case that (implies p1 q1) is true because p1 is false. Think about it. Now we illustrate the truth table method for deciding tautologies, even though that is not what ACL2 generally uses. Consider the formula called Promotion above: (IFF (IMPLIES P (IMPLIES Q R)) (IMPLIES (AND P Q) R)) The formula above is a tautology. It contains three variables, P, Q, and R, and so there are 8 combinations of Boolean assignments to them. If we let formula1: (IMPLIES P (IMPLIES Q R)) formula2: (IMPLIES (AND P Q) R) then we wish to test the formula (IFF formula1 formula2): P Q R formula1 formula2 (IFF formula1 formula2) --------- T T T T T T T T NIL NIL NIL T T NIL T T T T T NIL NIL T T T NIL T T T T T NIL T NIL T T T NIL NIL T T T T NIL NIL NIL T T T So we see that the formula always returns T and is thus a tautology. Recall that in the original example at the top of this page we were trying to prove the formula (implies (endp z) (implies (true-listp z) (equal (rev (rev z)) z))) This formula is an [instance] of (implies p (implies q r)). The substitution required by the match is sigma: ((p (endp z)) (q (true-listp z)) (r (equal (rev (rev z)) z))) Since we know the tautology: (iff (implies p (implies q r)) (implies (and p q) r)). is always true no matter what Boolean values p, q, and r have, then we know this instance of it (obtained by applying the substitution sigma above) is always true: (iff (implies (endp z) formula1' (implies (true-listp z) (equal (rev (rev z)) z))) (implies (and (endp z) formula2' (true-listp z)) (equal (rev (rev z)) z))). Thus, if we're trying to prove formula1' it is permitted to try to to prove formula2' instead, because they return the same truthvalue. This sketch of propositional reasoning in ACL2 is a little suspect because we didn't address the possibility that the substitution might replace the propositional variables by non-propositional terms. But the tautology was verified only on Boolean values for those variables. This actually works out because in ACL2 all propositional testing is done against nil and any non-nil value, including t, is as good as another. However, the tautology allows us to replace one formula by the other only in contexts in which we just care about propositional truth, i.e., whether the formula is nil or not. When we prove a formula in ACL2 we are really establishing that it never returns nil, i.e., no matter what the values of the variables, the value of the formula is non-nil. A very simple example of this is with Double Negation. (iff (not (not p)) p) is a tautology. This means that if we were trying to prove (implies (not (not p)) ...) we could transform it to (implies p ...). But if we were trying to prove: (equal (not (not p)) p) we could not prove it by using Double Negation! The formula above claims that (not (not p)) and p have identical values. They do not! For example, (not (not 3)) is t, not 3. However, (not (not 3)) and t are propositionally equivalent (i.e., satisfy iff) because one is as good as the other in a test. That is what Double Negation says. As long as you only use propositional formulas in propositional places this aspect of ACL2 should not affect you. Now please use your browser's Back Button to return to the example proof in [logic-knowledge-taken-for-granted].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q1-ANSWER (INTRODUCTION-TO-THE-THEOREM-PROVER) "The inductive step of the rev-rev proof -- Answer to Question 1 The correct answer to Question 1 in [logic-knowledge-taken-for-granted] is Choice (iv). The Induction Step of the inductive proof of (implies (true-listp z) (equal (rev (rev z)) z)) for an induction on the linear list z is: Induction Step: (implies (and (not (endp z)) (implies (true-listp (cdr z)) (equal (rev (rev (cdr z))) (cdr z)))) (implies (true-listp z) (equal (rev (rev z)) z))) The second hypothesis above is the the induction hypothesis. The conclusion above is the formula we are trying to prove. Each induction hypothesis is always an [instance] of the formula being proved, i.e., it is obtained from the formula being proved by uniformly replacing the variables in the formula with terms. Notice how the induction hypothesis above is the same as the induction conclusion, except that all the zs have been replaced by (cdr z). If you thought the right answer was Induction Step -- Choice (i): (implies (not (endp z)) (implies (true-listp z) (equal (rev (rev z)) z))) then perhaps you didn't understand that we're doing an inductive proof. Certainly if you prove the Base Case already discussed and you prove Choice (i) above, then you will have proved the goal conjecture, but you would have done it by simple case analysis: prove it when (endp z) and prove it when (not (endp z)). While logically valid, you probably can't prove Choice (i) directly because you have no induction hypothesis to work with. If you thought the right answer was: Induction Step -- Choice (ii): (implies (true-listp (cdr z)) (equal (rev (rev (cdr z))) (cdr z))) then perhaps you misunderstand the difference between the Induction Step and the Induction Hypothesis. The Induction Step is the ``other half'' of the main proof, balancing the Base Case. The Induction Hypothesis is just a hypothesis you get to use during the Induction Step. The question Q1 asked what is the Induction Step. If you thought the right answer was: Induction Step -- Choice (iii): (implies (and (not (endp z)) (equal (rev (rev (cdr x))) (cdr x))) ; ``induction hyp'' (implies (true-listp z) (equal (rev (rev z)) z))) then you are making the most common mistake newcomers make to induction. You are giving yourself an ``induction hypothesis'' that is not an instance of the conjecture you're proving. This alleged induction hypothesis says that (rev (rev (cdr x))) is (cdr x), whereas the correct induction hypothesis says those two terms are equal if (true-listp (cdr x)). This alleged induction hypothesis is a stronger claim than we're trying to prove. It turns out that by making this mistake you can ``prove'' conjectures that are not always true! Remember: the induction hypothesis is always an instance of the conjecture you're proving, not just some piece of it. Of course, ACL2 ``knows'' this and will never make this mistake. But we remind you of it because there may be times when you intuit a different hypothesis and don't understand why ACL2 doesn't use it. If this doesn't make sense, perhaps you should read about [induction] again. When you understand why Choice (iv) is the correct answer, use your browser's Back Button to return to [logic-knowledge-taken-for-granted] and go to question Q2.") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q2-ANSWER (INTRODUCTION-TO-THE-THEOREM-PROVER) "The inductive step of the rev-rev proof -- Answer to Question 2 The correct answer to Question 2 in [logic-knowledge-taken-for-granted] is Subgoal (i) plus any one of the other other three. For your reference, the four choices were: Subgoal (i): (implies (and (not (endp z)) (true-listp z)) (true-listp (cdr z))) Subgoal (ii): (implies (and (not (endp z)) (true-listp z) (equal (rev (rev (cdr z))) (cdr z))) (equal (rev (rev z)) z)) Subgoal (iii): (implies (and (not (endp z)) (equal (rev (rev (cdr z))) (cdr z))) (equal (rev (rev z)) z)) Subgoal (iv): (implies (and (not (endp z)) (true-listp (cdr z)) (equal (rev (rev (cdr z))) (cdr z))) (equal (rev (rev z)) z)) In particular, it is wrong to think the Induction Step of the proof of (implies (true-listp z) (equal (rev (rev z)) z)) can be established by proving just Subgoal (ii), Subgoal (iii), Subgoal (iv), or combinations of those three. You must also prove Subgoal (i) or something like it! The Inductive Step for the conjecture above is Induction Step: (implies (and (not (endp z)) ; Induction Hypothesis: (implies (true-listp (cdr z)) (equal (rev (rev (cdr z))) (cdr z)))) ; Induction Conclusion: (implies (true-listp z) (equal (rev (rev z)) z))) Note that the Inductive Hypothesis is an implication: (implies (true-listp (cdr z)) (equal (rev (rev (cdr z))) (cdr z))) This hypothesis can be true two different ways. The ``normal'' way -- the way everybody remembers -- is that (true-listp (cdr z)) is true and thus (equal (rev (rev (cdr z))) (cdr z)) is true. But the way many people forget is that (true-listp (cdr z)) is false. You must prove the Induction Step even in this ``forgetable'' case. In this case, the Induction Step simplifies to Induction Step: (implies (and (not (endp z)) (not (true-listp (cdr z)))) (implies (true-listp z) (equal (rev (rev z)) z))) By Promotion (see the list of tautologies in our discussion of [propositional calculus]) this is Induction Step': (implies (and (not (endp z)) (not (true-listp (cdr z))) (true-listp z)) (equal (rev (rev z)) z)) Using the Contrapositive and rearranging the order of the hypotheses (see [propositional calculus] again), this is Induction Step'': (implies (and (not (endp z)) (true-listp z) (not (equal (rev (rev z)) z))) (true-listp (cdr z))) Notice that Subgoal (i) implies Induction Step'': Subgoal (i): (implies (and (not (endp z)) (truelistp z)) (truelistp (cdr z))) Every inductive proof of an implication raises a case like this. If we denote the conjecture (implies p q) as p ---> q, then the Induction Step will look like this: ( c & (p' ---> q')) ---> (p ---> q) where c is the test that determines the inductive step, (e.g., (not (endp z))) and p' and q' are inductive instances of p and q. Promotion produces ( c & p & (p' ---> q')) ---> q It is then very common to prove that p implies p', (i): (c & p) ---> p' and then prove that q' implies q, (ii): (c & p & q') ---> q These correspond exactly to our choices Subgoal (i) and Subgoal (ii). It is sometimes helpful to remember this diagram: (c & (p' ---> q') ^ | | | | v --> (p ---> q ) When you understand why Subgoals (i) and (ii) are sufficient, use your browser's Back Button to return to [logic-knowledge-taken-for-granted] and go to question Q3.") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-Q3-ANSWER (INTRODUCTION-TO-THE-THEOREM-PROVER) "The inductive step of the rev-rev proof -- Answer to Question 2 The correct answer to Question 3 in [logic-knowledge-taken-for-granted] is that you need to prove Subgoal to Relieve Hyp 1: (implies (and (q (f a)) (r a)) (p (f a))) in order to use Theorem: (implies (p (f x)) (equal (g (h x)) x)) to rewrite the target (g (h a)) to a in Goal Conjecture: (implies (and (q (f a)) (r a)) (s (g (h a)))) If you don't see why, re-read the discussion of [rewriting] again. Forgetting about the need to relieve hypotheses is a common mistake in informal proofs. ACL2 won't forget to relieve them. But if you forget about the need to do it, you may be confused when ACL2 doesn't see the ``proof'' you see! Now use your browser's Back Button to return to the end of quiz in [logic-knowledge-taken-for-granted].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-REWRITING (INTRODUCTION-TO-THE-THEOREM-PROVER) "A brief explanation of rewriting from the logical perspective First we give two examples of rewriting. Then we give a rather detailed description. We recommend you read the description, even if you understand the two examples, just so that you learn our terminology. Example 1: Suppose your goal conjecture is: Goal Conjecture: (implies (and (endp z) (true-listp z)) (equal (rev (rev z)) z)) Then you can use the following theorem (actually the definitional axiom introduced by the defun of endp): Definitional Axiom: endp (equal (endp x) (not (consp x))). to rewrite the Goal Conjecture to Rewritten Goal Conjecture: (implies (and (not (consp z)) (true-listp z)) (equal (rev (rev z)) z)) Note that in this example, rewriting replaced the call of endp by its body after instantiating its body with the actuals from the call. This is sometimes just called expanding the definition of endp. (The notions of formal, body, call, and actuals are discussed in [programming-knowledge-taken-for-granted].) Expanding a definition is an example of unconditional rewriting. All definitions in ACL2 are just bare equalities relating a call of the function on its formals to its body. Any time you use an equality theorem, whether a definitional equality or something more general like (equal (append (append x y) z) (append x (append y z))) to replace an instance of one side by the corresponding instance of the other in a goal conjecture, we call that unconditional rewriting with the equality. Example 2: Suppose your goal conjecture is: Goal Conjecture: (implies (and (subsetp a b) (true-listp b) (member e a)) (< (len (rm e b)) (len b))). This conjecture may be read ``if a is a subset of the true-listp b and e is a member of a, then the result of removing e from b has a shorter length than b.'' You can use the following theorem: Theorem: (implies (member u v) (equal (len (rm u v)) (- (len v) 1))) to rewrite the Goal Conjecture to Rewritten Goal Conjecture: (implies (and (subsetp a b) (true-listp b) (member e a)) (< (- (len b) 1) (len b))). To do this you must know that the following subgoal is provable: Subgoal to Relieve Hyp 1: (implies (and (subsetp a b) (true-listp b) (member e a)) (member e b)). This is an example of conditional rewriting. In order to use the Theorem we had to establish that its hypotheses are satisfied. That is called relieving the hypotheses and was done by proving the Subgoal to Relieve Hyp 1. Conditional rewriting is the most commonly used proof technique in ACL2. Unconditional rewriting is just a special case, where there are no hypotheses to relieve. Expanding a definition is just another special case, where there are no hypotheses to relieve and the pattern is easy to match because it is a call of a function on distinct variables. This page discusses rewriting from the logical perspective. It is important that you are familiar with the notions of a pattern term being an [instance] of a target term. We often say the pattern matches the target. These notions involve a corresponding substitution of terms for variables. All these notions are discussed in the link for ``[instance]'' above and we recommend you read it before continuing. Then use your browser's Back Button to come back here. You should also be aware of the terms introduced in our discussion of [propositional calculus]. Rewriting is a fundamental rule of inference in our system. The rule allows you to use a theorem, i.e., an axiom, lemma, or definition, to replace one term by another in the goal conjecture you're trying to prove. Suppose you have a theorem that is of the form (or can be put into the form): Theorem: (implies (and hyp1 ... hypk) (equal pattern replacement)) From the logical perspective we don't care how the theorem was actually written when it was proved. It might have no hypotheses (in which case the hypi could just be t), or it could have been written in a different but equivalent propositional style, (or (not hyp1) ...), or the equality could have been written the other way around, (equal replacement pattern). Such syntactic details don't matter. Just take a theorem and use propositional calculus to rearrange it equivalently into this form for the purposes of this one rewrite step. Suppose pattern is an instance of some target term, target that occurs in your goal conjecture. Let the corresponding substitution be sigma. If sigma does not contain a binding for every variable that occurs in Theorem, then extend sigma to sigma' by adding one binding for each such variable. (This is necessary only if pattern does not contain every variable in Theorem.) Let replacement' be the result of instantiating replacement with sigma'. Let hypi' be the result of instantiating hypi with sigma'. Then the Rewrite Rule of Inference tells us it is permitted to replace that occurrence of target in the goal by replacement' -- if you can prove each hypi' in this context. We make this last condition clear in a moment. The justification for this is that Theorem is true for all values of the variables. Hence, it is true for the values specified by sigma'. If the hypi' are true, then the target is really equal to replacement'. But it is always permitted to replace something by something it's equal to. Rewriting thus involves several steps: (1) Finding a target and a theorem to use to rewrite it to some more desirable replacement. (2) Instantiating pattern in the (rearranged) theorem to match target. (3) Extending sigma to sigma' to bind all the variables in Theorem. (4) Establishing that the sigma' instances of each of the hypi hold. This is called relieving the hypotheses of the theorem and is discussed in greater detail below. (5) Replacing the occurrence of target in the goal conjecture by the sigma' instance of replacement, provided all the hypotheses are relieved. Step (4) above, relieving the hypotheses, requires first identifying the ``context'' of the target in the goal conjecture. To do this, use propositional calculus to rearrange the goal conjecture so the occurrence of target is in the conclusion and let context be the hypothesis. Rearranged Conjecture: (implies context (... target ...)) To relieve the hypotheses you must then prove each of the following subgoals: Subgoal to Relieve Hyp i: (implies context hypi'). It is important to note that this description of rewriting with Theorem describes the process from a strictly logical perspective. The syntax of the theorem and the goal don't matter. You're free to use propositional calculus to rearrange them to put them into the appropriate forms to fit the descriptions given. Clearly, if you have a candidate Theorem in the ``wrong'' form and but it can be rearranged with propositional calculus into the ``right'' form, then that rearranged theorem is also a Theorem and can be used as described. But in the actual implementation of ACL2, the syntactic form of a proved Theorem affects how it is used by rewriting. If a proved theorem takes the form of an implication concluding with an equality, ACL2 treats the left-hand side of the equality as pattern and the right-hand side as replacement, unless you tell it otherwise. We'll discuss this later. Furthermore, being from the logical perspective this discussion of rewriting does not address (a) how you extend simga to sigma' -- any extension will do provided it allows you to relieve the hypotheses. The ACL2 theorem prover uses certain heuristics which we'll discuss later, including methods by which you can guide the system in the selection. Crucially, it does not discuss whether it is a good idea to do a particular rewrite! For example, the definitional equality: (equal (len x) (if (endp x) 0 (+ 1 (len (cdr x))))) may be used repeatedly, endlessly, to replace (len a) by an ever growing sequence of terms: (len a) = (if (endp a) 0 (+ 1 (len (cdr a)))) = (if (endp a) 0 (+ 1 (if (endp (cdr a)) 0 (+ 1 (len (cdr (cdr a))))))) = ... The ACL2 implmentation of rewriting uses certain heuristics and the you can guide the system in its choices. We'll discuss this later. Now use your browser's Back Button to return to the example proof in [logic-knowledge-taken-for-granted].") (LOGIC-KNOWLEDGE-TAKEN-FOR-GRANTED-REWRITING-REPEATEDLY (INTRODUCTION-TO-THE-THEOREM-PROVER) "Further information on expanding definitions via rewriting We assume you've read about ``[instances]'' and picked up our basic terminology including the ideas of matching a pattern term to a target term, obtaining a substitution and how to instantiate a term with a substitution. We use these notions below without further citation. In addition, we assume you've read about ``[rewriting]'' where we introduced the idea of treating a theorem (axiom, definition, or lemma) as a conditional rewrite rule and replaced one term by an equivalent one provided we can relieve the hypotheses. Suppose you're trying to prove formula1 and you transform it to formula2 by rewriting. What happened? formula1: (implies (and (not (consp z)) (true-listp z)) (equal (rev (rev z)) z)) formula2: (implies (and (not (consp z)) (equal z nil)) (equal (rev (rev z)) z)) Evidently we replaced (true-listp z) by (equal z nil). But how did that happen? What really happened was the sequential application of several unconditional rewrites and the use of replacement of equals by equals. The definition of true-listp is: (defun true-listp (x) (if (consp x) (true-listp (cdr x)) (equal x nil))). By rewriting once with the definition of true-listp, we transform formula1 to: formula1': (implies (and (not (consp z)) (if (consp z) (true-listp (cdr z)) (equal z nil))) (equal (rev (rev z)) z)). Note how the call of true-listp has been replaced by the entire body of true-listp. Next, note that the first hypothesis above is that (consp z) is false. That is, (not (consp z)) is the same as (equal (consp z) nil). Thus, replacement of equals by equals means we can transform formula1' to formula1'': (implies (and (not (consp z)) (if nil (true-listp (cdr z)) (equal z nil))) (equal (rev (rev z)) z)). (We will explore replacement of equals by equals later.) Furthermore, we know the basic axiom about if: Axiom if-nil: (if nil x y) = y. Rewriting with this particular axiom, using (if nil x y) as the pattern and y as the replacement, will transform formula1'' to formula2: (implies (and (not (consp z)) (equal z nil)) (equal (rev (rev z)) z)). Often when we say we derived one formula from another by ``expansion'' and or by ``rewriting'' we take many rewrite steps, as here. We typically use hypotheses of the formula without noting ``replacement of equals by equals'' as when we replaced (consp z) by nil, and we typically omit to mention the use of basic axioms like if-nil above. Now use your browser's Back Button to return to the example proof in [logic-knowledge-taken-for-granted].") (LOGICAL-NAME (EVENTS WORLD) "A name created by a logical event Examples: assoc caddr + \"ACL2-USER\" \"arith\" \"project/task-1/arith.lisp\" :here A logical name is either a name introduced by some event, such as [defun], [defthm], or [include-book], or else is the keyword :here, which refers to the most recent such event. See [events]. Every logical name is either a symbol or a string. For the syntactic rules on names, see [name]. The symbols name functions, macros, constants, axioms, theorems, labels, and [theories]. The strings name packages or [books]. We permit the keyword symbol :here to be used as a logical name denoting the most recently completed event. The logical name introduced by an [include-book] is the full book name string for the book (see [full-book-name]). Thus, under the appropriate setting for the current book directory (see [cbd]) the event (include-book \"arith\") may introduce the logical name \"/usr/home/smith/project/task-1/arith.lisp\" . Under a different [cbd] setting, it may introduce a different logical name, perhaps \"/local/src/acl2/library/arith.lisp\" . It is possible that identical [include-book] events forms in a session introduce two different logical names because of the current book directory. A logical name that is a string is either a package name or a book name. If it is not a package name, we support various conventions to interpret it as a book name. If it does not end with the string \".lisp\" we extend it appropriately. Then, we search for any book name that has the given logical name as a terminal substring. Suppose (include-book \"arith\") is the only [include-book] so far and that \"/usr/home/smith/project/task-1/arith.lisp\" is the source file it processed. Then \"arith\", \"arith.lisp\" and \"task-1/arith.lisp\" are all logical names identifying that [include-book] event (unless they are package names). Now suppose a second (include-book \"arith\") is executed and processes \"/local/src/acl2/library/arith.lisp\". Then \"arith\" is no longer a logical name, because it is ambiguous. However, \"task-1/arith\" is a logical name for the first [include-book] and \"library/arith\" is a logical name for the second. Indeed, the first can be named by \"1/arith\" and the second by \"y/arith\". Logical names are used primarily in the theory manipulation functions, e.g., [universal-theory] and [current-theory] with which you may obtain some standard [theories] as of some point in the historical past. The reference points are the introductions of logical names, i.e., the past is determined by the [events] it contains. One might ask, ``Why not discuss the past with the much more flexible language of [command] descriptors?'' (See [command-descriptor].) The reason is that inside of such [events] as [encapsulate] or macro [command]s that expand to [progn]s of [events], [command] descriptors provide too coarse a grain. When logical names are used as referents in theory expressions used in [books], one must consider the possibility that the defining event within the book in question becomes redundant by the definition of the name prior to the assumption of the book. See [redundant-events].") (LOGIOR (NUMBERS ACL2-BUILT-INS) "Bitwise logical inclusive or of zero or more integers When integers are viewed in their two's complement representation, logior returns their bitwise logical inclusive or. In ACL2 logior is a macro that expands into calls of the binary function binary-logior, except that (logior) expands to 0 and (logior x) expands to x. The [guard] for binary-logior requires its arguments to be integers. Logior is defined in Common Lisp. See any Common Lisp documentation for more information. Macro: (defmacro logior (&rest args) (cond ((null args) 0) ((null (cdr args)) (car args)) (t (xxxjoin 'binary-logior args)))) Function: (defun binary-logior (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (lognot (logand (lognot i) (lognot j))))") (LOGNAND (NUMBERS ACL2-BUILT-INS) "Bitwise logical `nand' of two integers When integers are viewed in their two's complement representation, lognand returns their bitwise logical `nand'. The [guard] for lognand requires its arguments to be integers. Lognand is defined in Common Lisp. See any Common Lisp documentation for more information. Function: (defun lognand (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (lognot (logand i j)))") (LOGNOR (NUMBERS ACL2-BUILT-INS) "Bitwise logical `nor' of two integers When integers are viewed in their two's complement representation, lognor returns the bitwise logical `nor' of the first with the second. The [guard] for lognor requires its arguments to be integers. Lognor is defined in Common Lisp. See any Common Lisp documentation for more information. Function: (defun lognor (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (lognot (logior i j)))") (LOGNOT (NUMBERS ACL2-BUILT-INS) "Bitwise not of a two's complement number (lognot i) is the two's complement bitwise `not' of the integer i. Lognot is actually defined by coercing its argument to an integer (see [ifix]), negating the result, and then subtracting 1. The [guard] for lognot requires its argument to be an integer. Lognot is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun lognot (i) (declare (xargs :guard (integerp i))) (+ (- (ifix i)) -1))") (LOGORC1 (NUMBERS ACL2-BUILT-INS) "Bitwise logical inclusive or of two ints, complementing the first When integers are viewed in their two's complement representation, logorc1 returns the bitwise logical inclusive or of the second with the bitwise logical `not' of the first. The [guard] for logorc1 requires its arguments to be integers. Logorc1 is defined in Common Lisp. See any Common Lisp documentation for more information. Function: (defun logorc1 (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (logior (lognot i) j))") (LOGORC2 (NUMBERS ACL2-BUILT-INS) "Bitwise logical inclusive or of two ints, complementing the second When integers are viewed in their two's complement representation, logorc2 returns the bitwise logical inclusive or of the first with the bitwise logical `not' of the second. The [guard] for logorc2 requires its arguments to be integers. Logorc2 is defined in Common Lisp. See any Common Lisp documentation for more information. Function: (defun logorc2 (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (logior i (lognot j)))") (LOGTEST (NUMBERS ACL2-BUILT-INS) "Test if two integers share a `1' bit When integers x and y are viewed in their two's complement representation, (logtest x y) is true if and only if there is some position for which both x and y have a `1' bit in that position. The [guard] for logtest requires its arguments to be integers. Logtest is defined in Common Lisp. See any Common Lisp documentation for more information. Function: (defun logtest (x y) (declare (xargs :guard (and (integerp x) (integerp y)))) (not (zerop (logand x y))))") (LOGXOR (NUMBERS ACL2-BUILT-INS) "Bitwise logical exclusive or of zero or more integers When integers are viewed in their two's complement representation, logxor returns their bitwise logical exclusive or. In ACL2 logxor is a macro that expands into calls of the binary function binary-logxor, except that (logxor) expands to 0 and (logxor x) expands to x. The [guard] for binary-logxor requires its arguments to be integers. Logxor is defined in Common Lisp. See any Common Lisp documentation for more information. Macro: (defmacro logxor (&rest args) (cond ((null args) 0) ((null (cdr args)) (car args)) (t (xxxjoin 'binary-logxor args)))) Function: (defun binary-logxor (i j) (declare (xargs :guard (and (integerp i) (integerp j)))) (lognot (logeqv i j)))") (LOOP-STOPPER (REWRITE) "Limit application of permutative rewrite rules See [rule-classes] for a discussion of the syntax of the :loop-stopper field of :[rewrite] rule-classes. Here we describe how that field is used, and also how that field is created when the user does not explicitly supply it. For example, the built-in :[rewrite] rule commutativity-of-+, (implies (and (acl2-numberp x) (acl2-numberp y)) (equal (+ x y) (+ y x))), creates a rewrite rule with a loop-stopper of ((x y binary-+)). This means, very roughly, that the term corresponding to y must be ``smaller'' than the term corresponding to x in order for this rule to apply. However, the presence of [binary-+] in the list means that certain functions that are ``invisible'' with respect to [binary-+] (by default, [unary--] is the only such function) are more or less ignored when making this ``smaller'' test. We are much more precise below. Our explanation of loop-stopping is in four parts. First we discuss ACL2's notion of ``term order.'' Next, we bring in the notion of ``invisibility'', and use it together with term order to define orderings on terms that are used in the loop-stopping algorithm. Third, we describe that algorithm. These topics all assume that we have in hand the :loop-stopper field of a given rewrite rule; the fourth and final topic describes how that field is calculated when it is not supplied by the user. ACL2 must sometimes decide which of two terms is syntactically simpler. It uses a total ordering on terms, called the ``term order.'' Under this ordering constants such as '(a b c) are simpler than terms containing variables such as x and (+ 1 x). Terms containing variables are ordered according to how many occurrences of variables there are. Thus x and (+ 1 x) are both simpler than (cons x x) and (+ x y). If variable counts do not decide the order, then the number of function applications are tried. Thus (cons x x) is simpler than (+ x (+ 1 y)) because the latter has one more function application. Finally, if the number of function applications do not decide the order, a lexicographic ordering on Lisp objects is used. See [term-order] for details. When the loop-stopping algorithm is controlling the use of permutative :[rewrite] rules it allows term1 to be moved leftward over term2 only if term1 is smaller, in a suitable sense. Note: The sense used in loop-stopping is not the above explained term order but a more complicated ordering described below. The use of a total ordering stops rules like commutativity from looping indefinitely because it allows (+ b a) to be permuted to (+ a b) but not vice versa, assuming a is smaller than b in the ordering. Given a set of permutative rules that allows arbitrary permutations of the tips of a tree of function calls, this will normalize the tree so that the smallest argument is leftmost and the arguments ascend in the order toward the right. Thus, for example, if the same argument appears twice in the tree, as x does in the [binary-+] tree denoted by the term (+ a x b x), then when the allowed permutations are done, all occurrences of the duplicated argument in the tree will be adjacent, e.g., the tree above will be normalized to (+ a b x x). Suppose the loop-stopping algorithm used term order, as noted above, and consider the [binary-+] tree denoted by (+ x y (- x)). The arguments here are in ascending term order already. Thus, no permutative rules are applied. But because we are inside a +-expression it is very convenient if x and (- x) could be given virtually the same position in the ordering so that y is not allowed to separate them. This would allow such rules as (+ i (- i) j) = j to be applied. In support of this, the ordering used in the control of permutative rules allows certain unary functions, e.g., the unary minus function above, to be ``invisible'' with respect to certain ``surrounding'' functions, e.g., [+] function above. Briefly, a unary function symbol fn1 is invisible with respect to a function symbol fn2 if fn2 belongs to the value of fn1 in [invisible-fns-table]; also see [set-invisible-fns-table], which explains its format and how it can be set by the user. Roughly speaking, ``invisible'' function symbols are ignored for the purposes of the term-order test. Consider the example above, (+ x y (- x)). The translated version of this term is (binary-+ x (binary-+ y (unary-- x))). The initial [invisible-fns-table] makes [unary--] invisible with repect to [binary-+]. The commutativity rule for [binary-+] will attempt to swap y and (unary-- x) and the loop-stopping algorithm is called to approve or disapprove. If term order is used, the swap will be disapproved. But term order is not used. While the loop-stopping algorithm is permuting arguments inside a [binary-+] expression, [unary--] is invisible. Thus, insted of comparing y with (unary-- x), the loop-stopping algorithm compares y with x, approving the swap because x comes before y. Here is a more precise specification of the total order used for loop-stopping with respect to a list, fns, of functions that are to be considered invisible. Let x and y be distinct terms; we specify when ``x is smaller than y with respect to fns.'' If x is the application of a unary function symbol that belongs to fns, replace x by its argument. Repeat this process until the result is not the application of such a function; let us call the result x-guts. Similarly obtain y-guts from y. Now if x-guts is the same term as y-guts, then x is smaller than y in this order iff x is smaller than y in the standard term order. On the other hand, if x-guts is different than y-guts, then x is smaller than y in this order iff x-guts is smaller than y-guts in the standard term order. Now we may describe the loop-stopping algorithm. Consider a rewrite rule with conclusion (equiv lhs rhs) that applies to a term x in a given context; see [rewrite]. Suppose that this rewrite rule has a loop-stopper field (technically, the :heuristic-info field) of ((x1 y1 . fns-1) ... (xn yn . fns-n)). (Note that this field can be observed by using the command :[pr] with the name of the rule; see [pr].) We describe when rewriting is permitted. The simplest case is when the loop-stopper list is nil (i.e., n is 0); in that case, rewriting is permitted. Otherwise, for each i from 1 to n let xi' be the actual term corresponding to the variable xi when lhs is matched against the term to be rewritten, and similarly correspond yi' with y. If xi' and yi' are the same term for all i, then rewriting is not permitted. Otherwise, let k be the least i such that xi' and yi' are distinct. Let fns be the list of all functions that are invisible with respect to every function in fns-k, if fns-k is non-empty; otherwise, let fns be nil. Then rewriting is permitted if and only if yi' is smaller than xi' with respect to fns, in the sense defined in the preceding paragraph. It remains only to describe how the loop-stopper field is calculated for a rewrite rule when this field is not supplied by the user. (On the other hand, to see how the user may specify the :loop-stopper, see [rule-classes].) Suppose the conclusion of the rule is of the form (equiv lhs rhs). First of all, if rhs is not an instance of the left hand side by a substitution whose range is a list of distinct variables, then the loop-stopper field is nil. Otherwise, consider all pairs (u . v) from this substitution with the property that the first occurrence of v appears in front of the first occurrence of u in the print representation of rhs. For each such u and v, form a list fns of all functions fn in lhs with the property that u or v (or both) appears as a top-level argument of a subterm of lhs with function symbol fn. Then the loop-stopper for this rewrite rule is a list of all lists (u v . fns). Subtopics [Add-invisible-fns] Make some unary functions invisible to the [loop-stopper] algorithm [Invisible-fns-table] Functions that are invisible to the [loop-stopper] algorithm [Remove-invisible-fns] Make some unary functions no longer invisible [Set-invisible-fns-table] Set the invisible functions table") (LOWER-CASE-P (CHARACTERS ACL2-BUILT-INS) "Recognizer for lower case characters (Lower-case-p x) is true if and only if x is a lower case character, i.e., a member of the list #\\A, #\\B, ..., #\\Z. The [guard] for lower-case-p requires its argument to be a standard character (see [standard-char-p]). Lower-case-p is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun lower-case-p (x) (declare (xargs :guard (and (characterp x) (standard-char-p x)))) (and (member x '(#\\a #\\b #\\c #\\d #\\e #\\f #\\g #\\h #\\i #\\j #\\k #\\l #\\m #\\n #\\o #\\p #\\q #\\r #\\s #\\t #\\u #\\v #\\w #\\x #\\y #\\z)) t))") (LP (LD) "The Common Lisp entry to ACL2 To enter the ACL2 [command] loop from Common Lisp, call the Common Lisp program lp (which stands for ``loop,'' as in ``read-eval-print loop'' or ``[command] loop.'') The ACL2 [command] loop is actually coded in ACL2 as the function [ld] (which stands for ``load''). The [command] loop is just what you get by loading from the standard object input channel, [*standard-oi*]. Calling [ld] directly from Common Lisp is possible but fragile because hard lisp errors or aborts throw you out of [ld] and back to the top-level of Common Lisp. Lp calls [ld] in such a way as to prevent this and is thus the standard way to get into the ACL2 [command] loop. Also see [ACL2-customization] for information on the loading of an initialization file. All of the visible functionality of lp is in fact provided by [ld], which is written in ACL2 itself. Therefore, you should see [ld] for detailed [documentation] of the ACL2 [command] loop. We sketch it below, for novice users. Every expression typed to the ACL2 top-level must be an ACL2 expression. Any ACL2 expression may be submitted for evaluation. Well-formedness is checked. Some well-formed expressions cannot be evaluated because they involve (at some level) undefined constrained functions (see [encapsulate]). In addition, ACL2 does not allow ``global variables'' in expressions to be evaluated. Thus, (car '(a b c)) is legal and evaluates to A, but (car x) is not, because there is no ``global context'' or binding environment that gives meaning to the variable symbol x. There is an exception to the global variable rule outlined above: single-threaded objects (see [stobj]) may be used as global variables in top-level expressions. The most commonly used such object is the ACL2 ``current state,'' which is the value of the variable symbol [state]. This variable may occur in the top-level form to be evaluated, but must be passed only to ACL2 functions ``expecting'' state as described in the documentation for [state] and for [stobj]s in general. If the form returns a new [state] object as one of its values, then that is considered the new ``current'' [state] for the evaluation of the subsequent form. See [state]. ACL2 provides some support for the functionality usually provided by global variables in a read-eval-print loop, namely the saving of the result of a computation for subsequent re-use in another expression. See [assign] and see [@]. If the form read is a single keyword, e.g., :[pe] or :[ubt], then special procedures are followed. See [keyword-commands]. The [command] loop keeps track of the [command]s you have typed and allows you to review them, display them, and roll the logical [state] back to that created by any [command]. See [history]. ACL2 makes the convention that if a top-level form returns three values, the last of which is an ACL2 [state], then the first is treated as a flag that means ``an error occurred,'' the second is the value to be printed if no error occurred, and the third is (of course) the new [state]. When ``an error occurs'' no value is printed. Thus, if you execute a top-level form that happens to return three such values, only the second will be printed (and that will only happen if the first is nil!). See [ld] for details. Subtopics [Q] Quit ACL2 (type :q) --- reenter with ([lp])") (MACRO-ALIASES-TABLE (MACROS) "A [table] used to associate function names with macro names Example: (table macro-aliases-table 'append 'binary-append) This example associates the function symbol [binary-append] with the macro name [append]. As a result, the name [append] may be used as a runic designator (see [theories]) by the various theory functions. Thus, for example, it will be legal to write (in-theory (disable append)) as an abbreviation for (in-theory (disable binary-append)) which in turn really abbreviates (in-theory (set-difference-theories (current-theory :here) '(binary-append))) General Form: (table macro-aliases-table 'macro-name 'function-name) or very generally (table macro-aliases-table macro-name-form function-name-form) where macro-name-form and function-name-form evaluate, respectively, to a macro name and a symbol in the current ACL2 [world]. See [table] for a general discussion of tables and the table event used to manipulate tables. Note that function-name-form (above) does not need to evaluate to a function symbol, but only to a symbol. As a result, one can introduce the alias before defining a recursive function, as follows. (table macro-aliases-table 'mac 'fn) (defun fn (x) (if (consp x) (mac (cdr x)) x)) Although this is obviously contrived example, this flexibility can be useful to macro writers; see for example the definition of ACL2 system macro [defun-inline]. The [table] [macro-aliases-table] is an alist that associates macro symbols with function symbols, so that macro names may be used as runic designators (see [theories]). For a convenient way to add entries to this [table], see [add-macro-alias]. To remove entries from the [table] with ease, see [remove-macro-alias]. This [table] is used by the theory functions; see [theories]. For example, in order that (disable append) be interpreted as (disable binary-append), it is necessary that the example form above has been executed. In fact, this [table] does indeed associate many of the macros provided by the ACL2 system, including [append], with function symbols. Loosely speaking, it only does so when the macro is ``essentially the same thing as'' a corresponding function; for example, (append x y) and (binary-append x y) represent the same term, for any expressions x and y.") (MACRO-ARGS (MACROS) "The formals list of a macro definition Examples: (x y z) (x y z &optional max (base '10 basep)) (x y &rest rst) (x y &key max base) (&whole sexpr x y) The ``lambda-list'' of a macro definition may include simple formal parameter names as well as appropriate uses of the following lambda-list keywords from CLTL (pp. 60 and 145), respecting the order shown: &whole, &optional, &rest, &body, &key, and &allow-other-keys. ACL2 does not support &aux and &environment. In addition, we make the following restrictions: (1) initialization forms in &optional and &key specifiers must be quoted values; (2) &allow-other-keys may only be used once, as the last specifier; and (3) destructuring is not allowed. You are encouraged to experiment with the macro facility. One way to do so is to define a macro that does nothing but return the quotation of its arguments, e.g., (defmacro demo (x y &optional opt &key key1 key2) (list 'quote (list x y opt key1 key2))) You may then execute the macro on some sample forms, e.g., term value (demo 1 2) (1 2 NIL NIL NIL) (demo 1 2 3) (1 2 3 NIL NIL) (demo 1 2 :key1 3) error: non-even key/value arglist (because :key1 is used as opt) (demo 1 2 3 :key2 5) (1 2 3 NIL 5) In particular, Common Lisp specifies that if you use both &rest and &key, then both will be bound using the same list of arguments. The following example should serve to illustrate how this works. ACL2 !>(defmacro foo (&rest args &key k1 k2 k3) (list 'quote (list args k1 k2 k3))) Summary Form: ( DEFMACRO FOO ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FOO ACL2 !>(foo :k1 3 :k2 4 :k3 5) ((:K1 3 :K2 4 :K3 5) 3 4 5) ACL2 !>(foo :k1 3 :k2 4) ((:K1 3 :K2 4) 3 4 NIL) ACL2 !>(foo :k1 3 :bad-key 7) ACL2 Error in macro expansion: Illegal key/value args (:BAD-KEY 7) in macro expansion of (FOO :K1 3 :BAD-KEY 7). The argument list for FOO is (&REST ARGS &KEY K1 K2 K3). ACL2 !> If we don't want to get the error above, we can use &allow-other-keys, as follows. ACL2 !>(defmacro bar (&rest args &key k1 k2 k3 &allow-other-keys) (list 'quote (list args k1 k2 k3))) Summary Form: ( DEFMACRO BAR ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) BAR ACL2 !>(bar :k1 3 :bad-key 7) ((:K1 3 :BAD-KEY 7) 3 NIL NIL) ACL2 !> Also see [trans].") (MACRO-COMMAND (PROOF-CHECKER) "Compound command for the proof-checker The proof-checker (see [proof-checker]) allows the user to supply interactive commands. Compound commands, called macro commands, may be defined; these expand into zero or more other commands. Some of these are ``atomic'' macro commands; these are viewed as a single command step when completed successfully. More [documentation] will be written on the [proof-checker]. For now, we simply point out that there are lots of examples of the use of define-pc-macro and define-pc-atomic-macro in the ACL2 source file \"proof-checker-b.lisp\". The former is used to create macro commands, which can be submitted to the interactive loop (see [verify]) and will ``expand'' into zero or more commands. The latter is similar, except that the undoing mechanism (see [ACL2-pc::undo]) understands atomic macro commands to represent single interactive commands. Also see [ACL2-pc::comm] and see [ACL2-pc::commands] for a discussion of the display of interactive commands. Also see [toggle-pc-macro] for how to change a macro command to an atomic macro command, and vice versa.") (MACROS (ACL2) "Macros allow you to extend the syntax of ACL2. Subtopics [Add-binop] Associate a function name with a macro name [Add-macro-alias] Associate a function name with a macro name [Add-macro-fn] Associate a function name with a macro name [Defabbrev] A convenient form of macro definition for simple expansions [Defmacro] Define a macro [Macro-aliases-table] A [table] used to associate function names with macro names [Macro-args] The formals list of a macro definition [Make-event] Evaluate (expand) a given form and then evaluate the result [Remove-binop] Remove the association of a function name with a macro name [Remove-macro-alias] Remove the association of a function name with a macro name [Remove-macro-fn] Remove the association of a function name with a macro name [Trans] Print the macroexpansion of a form [Trans!] Print the macroexpansion of a form without single-threadedness concerns [Trans1] Print the one-step macroexpansion of a form [Untrans-table] Associates a function symbol with a macro for printing user-level terms [User-defined-functions-table] An advanced [table] used to replace certain system functions") (MAKE (DEFREC ACL2-BUILT-INS) "Constructor macro for [defrec] structures. The make macro is built into ACL2, and allows you to construct new instances of structures that have been introduced with [defrec]. For instance: (make employee :name \"Jimmy\" :salary 0 :position \"Unpaid Intern\") Creates a new employee structure with the given values for its name, salary, and position fields. See [defrec] for more information.") (MAKE-CHARACTER-LIST (CHARACTERS ACL2-BUILT-INS) "[coerce] to a list of characters Non-characters in the given list are [coerce]d to the character with code 0. Function: (defun make-character-list (x) (declare (xargs :guard t)) (cond ((atom x) nil) ((characterp (car x)) (cons (car x) (make-character-list (cdr x)))) (t (cons (code-char 0) (make-character-list (cdr x))))))") (MAKE-EVENT (EVENTS MACROS) "Evaluate (expand) a given form and then evaluate the result Make-event is a utility for generating [events]. It provides a capability not offered by Lisp macros (see [defmacro]), as it allows access to the ACL2 [state] and logical [world]. In essence, the expression (make-event form) replaces itself with the result of evaluating form, say, ev, as though one had submitted ev instead of the make-event call. For example, (make-event (quote (defun f (x) x))) is equivalent to the event (defun f (x) x). We break this documentation into the following sections. Introduction Detailed Documentation Error Reporting Restriction to Event Contexts Examples Illustrating How to Access State Advanced Expansion Control We begin with an informal introduction, which focuses on examples and introduces the key notion of ``expansion phase''. Introduction Make-event is particularly useful for those who program using the ACL2 [state]; see [programming-with-state]. That is because the evaluation of form may read and even modify the ACL2 [state]. Suppose for example that we want to define a constant *world-length*, that is the length of the current ACL2 [world]. A make-event form can accomplish this task, as follows. ACL2 !>(length (w state)) 98883 ACL2 !>(make-event (list 'defconst '*world-length* (length (w state)))) Summary Form: ( DEFCONST *WORLD-LENGTH* ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) Summary Form: ( MAKE-EVENT (LIST ...)) Rules: NIL Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) *WORLD-LENGTH* ACL2 !>*world-length* 98883 ACL2 !>(length (w state)) 98890 ACL2 !> How did this work? First, evaluation of the form (list 'defconst '*world-length* (length (w state))) returned the event form (defconst *world-length* 98883). Then that event form was automatically submitted to ACL2. Of course, that changed the ACL2 logical [world], which is why the final value of (length (w state)) is greater than its initial value. The example above illustrates how the evaluation of a make-event call takes place in two phases. The first phase evaluates the argument of the call, in this case (list 'defconst '*world-length* (length (w state))), to compute an event form, in this case (defconst *world-length* 98883). We call this evaluation the ``expansion'' phase. Then the resulting event form is evaluated, which in this case defines the constant *world-length*. Now suppose we would like to introduce such a [defconst] form any time we like. It is common practice to define macros to automate such tasks. Now we might be tempted simply to make the following definition. ; WRONG! (defmacro define-world-length-constant (name state) (list 'defconst name (length (w state)))) But ACL2 rejects such a definition, because a macro cannot take the ACL2 state as a parameter; instead, the formal parameter to this macro named \"STATE\" merely represents an ordinary object. You can try to experiment with other such direct methods to define such a macro, but they won't work. Instead, however, you can use the approach illustrated by the make-event example above to define the desired macro, as follows. (defmacro define-world-length-constant (name) `(make-event (list 'defconst ',name (length (w state))))) Here are example uses of this macro. ACL2 !>(define-world-length-constant *foo*) Summary Form: ( DEFCONST *FOO* ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) Summary Form: ( MAKE-EVENT (LIST ...)) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) *FOO* ACL2 !>*foo* 98891 ACL2 !>:pe *foo* 2:x(DEFINE-WORLD-LENGTH-CONSTANT *FOO*) > (DEFCONST *FOO* 98891) ACL2 !>(length (w state)) 98897 ACL2 !>(define-world-length-constant *bar*) Summary Form: ( DEFCONST *BAR* ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) Summary Form: ( MAKE-EVENT (LIST ...)) Rules: NIL Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) *BAR* ACL2 !>*bar* 98897 ACL2 !>:pe *bar* 3:x(DEFINE-WORLD-LENGTH-CONSTANT *BAR*) > (DEFCONST *BAR* 98897) ACL2 !>(length (w state)) 98903 ACL2 !> Finally, we note that the expansion phase can be used for computation that has side effects, generally by modifying state. Here is a modification of the above example that does not change the world at all, but instead saves the length of the world in a state global. (make-event (pprogn (f-put-global 'my-world-length (length (w state)) state) (value '(value-triple nil)))) Notice that this time, the value returned by the expansion phase is not an event form, but rather, is an error triple (see [error-triples]) whose value component is an event form, namely, the event form (value-triple nil). Evaluation of that event form does not change the ACL2 world (see [value-triple]). Thus, the sole purpose of the make-event call above is to change the [state] by associating the length of the current logical world with the state global named 'my-world-length. After evaluating this form, (@ my-world-length) provides the length of the ACL2 world, as illustrated by the following transcript. ACL2 !>:pbt 0 0:x(EXIT-BOOT-STRAP-MODE) ACL2 !>(length (w state)) 98883 ACL2 !>(make-event (pprogn (f-put-global 'my-world-length (length (w state)) state) (value '(value-triple nil)))) Summary Form: ( MAKE-EVENT (PPROGN ...)) Rules: NIL Time: 0.01 seconds (prove: 0.00, print: 0.00, other: 0.01) NIL ACL2 !>(length (w state)) 98883 ACL2 !>:pbt 0 0:x(EXIT-BOOT-STRAP-MODE) ACL2 !> When make-event is invoked by a book, it is expanded during book certification but not, by default, when the book is included. So for the example (define-world-length-constant *foo*) given above, if that form is in a book, then the value of *foo* will be the length of the world at the time this form was invoked during book certification, regardless of world length at [include-book] time. (The expansion is recorded in the book's [certificate], and re-used.) To overcome this default, you can specify keyword value :CHECK-EXPANSION t. This will cause an error if the expansion is different, but it can be useful for side effects. For example, if you insert the following form in a book, then the length of the world will be printed when the form is encountered, whether during [certify-book] or during [include-book]. (make-event (pprogn (fms \"Length of current world: ~x0~|\" (list (cons #\\0 (length (w state)))) *standard-co* state nil) (value '(value-triple nil))) :check-expansion t) Detailed Documentation Examples: ; Trivial example: evaluate (quote (defun foo (x) x)) to obtain ; (defun foo (x) x), which is then evaluated. (make-event (quote (defun foo (x) x))) ; Evaluate (generate-form state) to obtain (mv nil val state), and ; then evaluate val. (Generate-form is not specified here, but ; imagine for example that it explores the state and then generates ; some desired definition or theorem.) (make-event (generate-form state)) ; As above, but make sure that if this form is in a book, then when ; we include the book, the evaluation of (generate-form state) ; should return the same value as it did when the book was ; certified. (make-event (generate-form state) :CHECK-EXPANSION t) ; As above (where the :CHECK-EXPANSION value can be included or ; not), where if there is an error during expansion, then the error ; message will explain that expansion was on behalf of the indicated ; object, typically specified as the first argument. (make-event (generate-form state) :ON-BEHALF-OF (generate-form state)) General Form: (make-event form :CHECK-EXPANSION chk :ON-BEHALF-OF obj :EXPANSION? form) where chk is nil (the default), t, or the intended ``expansion result'' from the evaluation of form (as explained below); and if supplied, obj is an arbitrary ACL2 object, used only in reporting errors in expansion, i.e., in the evaluation of form. The :EXPANSION? keyword is discussed in the final section, on Advanced Expansion Control. We strongly recommend that you browse some .lisp files in the community books directory books/make-event/. You may even find it helpful, in order to understand make-event, to do so before continuing to read this documentation. You may also find it useful to browse community book books/misc/eval.lisp, which contains definitions of macros must-succeed and must-fail that are useful for testing and are used in many books in the books/make-event/ directory, especially eval-tests.lisp. Another example, books/make-event/defrule.lisp, shows how to use macros whose calls expand to make-event forms, which in turn can generate [events]. For more examples, see file books/make-event/Readme.lsp. Other than the examples, the explanations here should suffice for most users. If you want explanations of subtler details, see [make-event-details]. Note that make-event may only be used at the ``top level'' or where an event is expected. See the section ``Restriction to Event Contexts'', below. Make-event is related to Lisp macroexpansion in the sense that its argument is evaluated to obtain an expansion result, which is evaluated again. Let us elaborate on each of these notions in turn: ``is evaluated,'' ``expansion result'', and ``evaluated again.'' The final section, on Advanced Expansion Control, will generalize these processes in a way that we ignore for now. ``is evaluated'' --- The argument can be any expression, which is evaluated as would be any expression submitted to ACL2's top level loop. Thus, [state] and user-defined [stobj]s may appear in the form supplied to make-event. Henceforth, we will refer to this evaluation as ``expansion.'' Expansion is actually done in a way that restores ACL2's built-in [state] global variables, including the logical [world], to their pre-expansion values (with a few exceptions --- see [make-event-details] --- and where we note that changes to user-defined [state] global variables (see [assign]) are preserved). So, for example, events might be evaluated during expansion, but they will disappear from the logical [world] after expansion returns its result. Moreover, proofs are enabled by default at the start of expansion (see [ld-skip-proofsp]) if keyword :CHECK-EXPANSION is supplied and has a non-nil value. ``expansion result'' --- The above expansion may result in an ordinary (non-[state], non-[stobj]) value, which we call the ``expansion result.'' Or, expansion may result in a multiple value of the form (mv erp val state), or, more generally, (mv erp val state stobj-1 ... stobj-k) where each stobj-i is a [stobj]; then the expansion result is val unless erp is not nil, in which case there is no expansion result, and the original make-event evaluates to a soft error. In either case (single or multiple value), either val is an embedded event form (see [embedded-event-form]), or else the original make-event evaluates to a soft error, printed as described under ``Error Reporting'' below. (Technical remark: The expansion result described above may be modified for [include-book], [add-include-book-dir], and [add-include-book-dir!], replacing book names by full pathnames, using syntax (:system . relative-pathname) for [community-books] (i.e., system books); see [full-book-name], and for further details see comments in source function make-include-books-absolute. End of technical remark.) ``evaluated again'' --- the expansion result is evaluated in place of the original make-event. The expansion process can invoke subsidiary calls of make-event, and the expansion result can (perhaps after macroexpansion) be a call of make-event. It can be useful to track all these make-event calls. The [state] global variable make-event-debug may be set to a non-nil value, for example (assign make-event-debug t), in order to see a trace of the expansion process, where a level is displayed (as in ``3>'') to indicate the depth of subsidiary expansions. Expansion of a make-event call will yield an event that replaces the original make-event call. In particular, if you put a make-event form in a book, then in essence it is replaced by its expansion result, created during the proof pass of the [certify-book] process. We now elaborate on this idea of keeping the original expansion. A make-event call generates a ``make-event replacement'' that may be stored by the system. In the simplest case, this replacement is the expansion result. When a book is certified, these replacements are stored in a book's certificate (technically, in the :EXPANSION-ALIST field). Thus, although the book is not textually altered during certification, one may imagine a ``book expansion'' corresponding to the original book, in which events are substituted by replacements that were generated during the proof phase of certification. A subsequent [include-book] will then include the book expansion corresponding to the indicated book. When a book is compiled during [certify-book], it is actually the corresponding book expansion, stored as a temporary file, that is compiled instead. That temporary file is deleted after compilation unless one first evaluates the form (assign keep-tmp-files t). Note however that all of the original forms must still be legal [events]; see [embedded-event-form]. So for example, if the first event in a book is (local (defmacro my-id (x) x)), and is followed by (my-id (make-event ...)), the final ``include-book'' pass of [certify-book] will fail because my-id is not defined when the my-id call is encountered. A make-event replacement might not be the expansion when either of the keyword arguments :CHECK-EXPANSION or :EXPANSION? is supplied. We deal with the latter in the final section, on Advanced Expansion Control. If :CHECK-EXPANSION t is supplied and the expansion is exp, then the replacement is obtained from the original make-event call, by substituting exp for t as the value of keyword :CHECK-EXPANSION. Such a make-event call --- during the second pass of an [encapsulate], or during event processing on behalf of [include-book] other than when including a book near the end of its certification process --- will do the expansion again and check that the expansion result is equal to the original expansion result, exp. In the unusual case that you know the expected expansion result, res, you can specify :CHECK-EXPANSION res in the first place, so that the check is also done during the initial evaluation of the make-event form. IMPORTANT BUT OBSCURE DETAIL: That expansion check is only done when processing events, not during a preliminary load of a book's compiled file. The following paragraph elaborates. (Here are details on the point made just above, for those who use the :CHECK-EXPANSION argument to perform side-effects on the [state]. When you include a book, ACL2 generally loads a compiled file before processing the events in the book; see [book-compiled-file]. While it is true that a non-nil :CHECK-EXPANSION argument causes [include-book] to perform expansion of the make-event form during event processing it does not perform expansion when the compiled file (or expansion file; again, see [book-compiled-file]) is loaded.) ACL2 performs the following space-saving optimization: when the expansion result is a [local] event, then the make-event replacement is (local (value-triple :ELIDED)). The notion of ``expansion'' and ``replacement'' extend to the case that a call of make-event is found in the course of macroexpansion. The following example illustrates this point. (encapsulate () (defmacro my-mac () '(make-event '(defun foo (x) x))) (my-mac)) :pe :here The above call of [pe] shows that the form (my-mac) has a make-event expansion (and replacement) of (DEFUN FOO (X) X): (ENCAPSULATE NIL (DEFMACRO MY-MAC NIL '(MAKE-EVENT '(DEFUN FOO (X) X))) (RECORD-EXPANSION (MY-MAC) (DEFUN FOO (X) X))) Error Reporting Suppose that expansion produces a soft error as described above. That is, suppose that the argument of a make-event call evaluates to a multiple value (mv erp val state ...) where erp is not nil. If erp is a string, then that string is printed in the error message. If erp is a [cons] pair whose [car] is a string, then the error prints \"~@0\" with #\\0 bound to that cons pair; see [fmt]. Any other non-nil value of erp causes a generic error message to be printed. Restriction to Event Contexts A make-event call must occur either at the top level, or during make-event expansion, or as an argument of an event constructor. We explain in more detail below. This restriction is imposed to enable ACL2 to track expansions produced by make-event. The following examples illustrate this restriction. ; Legal: (progn (with-output :on summary (make-event '(defun foo (x) x)))) ; Illegal: (mv-let (erp val state) (make-event '(defun foo (x) x)) (mv erp val state)) More precisely: a make-event call that is not itself evaluated during make-event expansion is subject to the following requirement. After macroexpansion has taken place, such a make-event call must be in an ``event context'', defined recursively as follows. (All but the first two cases below correspond to similar cases for constructing events; see [embedded-event-form].) * A form submitted at the top level, or more generally, supplied to a call of [ld], is in an event context. * A form occurring at the top level of a book is in an event context. * If ([local] x1) is in an event context, then so is x1. * If ([skip-proofs] x1) is in an event context, then so is x1. * If ([make-event] x ...) is in an event context and its expansion x1 is an embedded event form, then x1 is in an event context. * If ([with-output] ... x1), ([with-prover-step-limit] ... x1 ...), or ([with-prover-time-limit] ... x1) is in an event context, then so is x1. * For any call of [progn] or [progn!], each of its arguments is in an event context. * For any call of [encapsulate], each of its arguments except the first (the signature list) is in an event context. * If (RECORD-EXPANSION x1 x2) is in an event context, then x1 and x2 are in event contexts. Note: record-expansion is intended for use only by the implementation, which imposes the additional restriction that x1 and its subsidiary make-event calls (if any) must specify a :CHECK-EXPANSION argument that is a [consp]. Low-level remark, for system implementors. There is the one exception to the above restriction: a single [state-global-let*] form immediately under a progn! call. For example: (progn! (state-global-let* (make-event ...))) However, the following form may be preferable (see [progn!]): (progn! :STATE-GLOBAL-BINDINGS (make-event ...)) Also see [remove-untouchable] for an interesting use of this exception. Examples Illustrating How to Access State You can modify the ACL2 [state] by doing your state-changing computation during the expansion phase, before expansion returns the event that is submitted. Here are some examples. First consider the following. Notice that expansion modifies state global my-global during make-event expansion, and then expansion returns a [defun] event to be evaluated. (make-event (er-progn (assign my-global (length (w state))) (value '(defun foo (x) (cons x x))))) Then we get: ACL2 !>(@ my-global) 72271 ACL2 !>:pe foo L 1:x(MAKE-EVENT (ER-PROGN # #)) >L (DEFUN FOO (X) (CONS X X)) ACL2 !> Here's a slightly fancier example, where the computation affects the [defun]. In a new session, execute: (make-event (er-progn (assign my-global (length (w state))) (value `(defun foo (x) (cons x ,(@ my-global)))))) Then: ACL2 !>(@ my-global) 72271 ACL2 !>:pe foo L 1:x(MAKE-EVENT (ER-PROGN # #)) >L (DEFUN FOO (X) (CONS X 72271)) ACL2 !> Note that ACL2 [table] [events] may avoid the need to use [state] globals. For example, instead of the example above, consider this example in a new session. (make-event (let ((world-len (length (w state)))) `(progn (table my-table :STORED-WORLD-LENGTH ,world-len) (defun foo (x) (cons x ,world-len))))) Then: ACL2 !>(table my-table) ((:STORED-WORLD-LENGTH . 72271)) ACL2 !>:pe foo 1:x(MAKE-EVENT (LET # #)) >L (DEFUN FOO (X) (CONS X 72271)) ACL2 !> By the way, most built-in [state] globals revert after expansion. But your own global (like my-global above) can be set during expansion, and the new value will persist. Advanced Expansion Control We conclude this [documentation] section by discussing three kinds of additional control over make-event expansion. These are all illustrated in community book books/make-event/make-event-keywords-or-exp.lisp. The discussion below is split into the following three parts. (1) The value produced by expansion may have the form (:DO-PROOFS exp), which specifies exp as the expansion result, to be evaluated without skipping proofs even when including a book. (2) The value produced by expansion may have the form (:OR exp-1 ... exp-k), which specifies that the first form exp-i to evaluate without error is the expansion result. (3) The keyword argument :EXPANSION? can serve to eliminate the storing of make-event replacements, as described above for the ``book expansion'' of a book. We now elaborate on each of these. (1) :DO-PROOFS ``call'' produced by expansion. We have discussed the expansion result produced by the expansion phase of evaluating a make-event call. However, if the expansion phase produces an expression of the form (:DO-PROOFS exp), then the expansion result is actually exp. The :DO-PROOFS wrapper indicates that even if proofs are currently being skipped (see [ld-skip-proofsp]), then evaluation of exp should take place with proofs not skipped. For example, proofs will be performed when evaluating the make-event expansion, namely the indicated defthm event, in the following example. (set-ld-skip-proofsp t state) (make-event '(:DO-PROOFS (defthm app-assoc (equal (append (append x y) z) (append x y z))))) Note that such use of :DO-PROOFS causes proofs to be performed when evaluating the expansion while including an uncertified book. But when including a certified book, then unless :CHECK-EXPANSION is supplied a non-nil value, the make-event replacement will just be the expansion, which does not include the :DO-PROOFS wrapper and hence will be evaluated with proofs skipped. (2) :OR ``call'' produced by expansion. There may be times where you want to try different expansions. For example, the community book books/make-event/proof-by-arith.lisp attempts to admit a given event, which we'll denote EV, by trying events of the following form as BOOK varies over different community books. (encapsulate () (local (include-book BOOK :DIR :SYSTEM)) EV) A naive implementation of this macro would evaluate all such [encapsulate] events until one succeeds, and then return that successful event as the expansion. Then that event would need to be evaluated again! With some hacking one could avoid that re-evaluation by using [skip-proofs], but that won't work if you are trying to create a certified book without skipped proofs. Instead, the implementation creates an expansion of the form (:OR ev-1 ev-2 ... ev-k), where the list (ev-1 ev-2 ... ev-k) enumerates the generated encapsulate events. In general, for this ``disjunctive case'' of a result from expansion, each ev-i is evaluated in sequence, and the first that succeeds without error is considered to be the expansion result --- and a repeat evaluation is avoided. If evaluation of each ev-i results in an error, then so does the make-event call. This special use of :OR in a value produced by expansion is only supported at the top level. That is, the result can be (:OR ev-1 ev-2 ... ev-k) but then each ev-i must be a legal expansion result, without such further use of :OR --- except, ev-i may be (:DO-PROOFS ev-i'), where ev-i' then would serve as the expansion rather than ev-i. (3) The :EXPANSION? keyword argument. If keyword argument :EXPANSION? has a nonnil value, then the :CHECK-EXPANSION keyword must be omitted or have value nil or t, hence not a cons pair. The idea of the :EXPANSION? keyword is to give you a way to avoid storing expansion results in a book's [certificate]. Roughly speaking, when the expansion result matches the value of :EXPANSION?, then no expansion result is stored for the event by book certification; then when the book is later included, the value of :EXPANSION? is used as the expansion, thus bypassing the expansion phase. One could say that the event is its own make-event replacement, but it is more accurate to say that there is no make-event replacement at all, since nothing is stored in the certificate for this event. Below, we elaborate on make-event replacements when :EXPANSION is used and also discuss other properties of this keyword. We modify the notion of ``expansion result'' for make-event forms to comprehend the use of the :EXPANSION? keyword. For that purpose, let's consider a call of make-event to be ``reducible'' if it has an :EXPANSION? keyword with non-nil value, exp, and its :CHECK-EXPANSION keyword is missing or has value nil, in which case the ``reduction'' of this make-event call is defined to be exp. The expansion result as originally defined is modified by the following ``recursive reduction'' process: recur through the original expansion, passing through calls of [local], [skip-proofs], [with-output], [with-prover-step-limit], and [with-prover-time-limit], and replacing (recursively) any reducible call of make-event by its reduction. Furthermore, we refer to two forms as ``reduction equivalent'' if their recursive reductions are equal. Note that the recursive reduction process does not pass through [progn] or [encapsulate], but that process is applied to the computation of expansions for their subsidiary [make-event] calls. To explain further the effect of :EXPANSION? exp, we split into the following two cases. Case 1: Evaluation is not taking place when including a book or evaluating the second pass of an [encapsulate] event; more precisely, the value of (ld-skip-proofsp state) is not the symbol INCLUDE-BOOK. There are two subcases. * Case 1a: The expansion result is not reduction-equivalent to exp. Then the make-event call is processed as though the :EXPANSION? keyword had been omitted. * Case 2a: The expansion result is reduction-equivalent to exp. Then there is no make-event replacement for this call of make-event; no replacement will be put into the [certificate] file for a book containing this make-event call. When that book is subsequently included, the original form will be evaluated in the manner described in the next case. Case 2: Evaluation is taking place when including a book or evaluating the second pass of an [encapsulate] event; more precisely, the value of (ld-skip-proofsp state) is the symbol INCLUDE-BOOK. Then the expansion is exp. The expansion phase is skipped unless :CHECK-EXPANSION is t. The :EXPANSION? keyword can be particularly useful in concert with the disjunctive (``:OR'') case (2) discussed above. Suppose that expansion produces a value as discussed in (2) above, (:OR exp-1 ... exp-k). If one of these expressions exp-i is more likely than the others to be the expansion, then you may wish to specify :EXPANSION? exp-i, as this will avoid storing a make-event replacement in that common case. This could be useful if the expressions are large, to avoid enlarging the [certificate] file for a book containing the make-event call. It is legal to specify both :EXPANSION? exp and :CHECK-EXPANSION t. When either (ld-skip-proofsp state) is the symbol INCLUDE-BOOK, or evaluation is taking place in raw Lisp, then this combination is treated the same as if :EXPANSION? is omitted and the value of :CHECK-EXPANSION is exp. Otherwise, this combination is treated the same as :CHECK-EXPANSION t, modified to accommodate the effect of :EXPANSION? as discussed above: if the expansion is indeed the value of :EXPANSION?, then no make-event replacement is generated. Subtopics [Make-event-details] Details on [make-event] expansion") (MAKE-EVENT-DETAILS (MAKE-EVENT) "Details on [make-event] expansion The normal user of make-event can probably ignore this section, but we include it for completeness. We assume that the reader has read and understood the basic documentation for make-event (see [make-event]), but we begin below with a summary of expansion. Introduction Here is a summary of how we handle expansion involving make-event forms. (make-event form :check-expansion nil) This shows the :check-expansion default of nil, and is typical user input. We compute the expansion exp of form, which is the expansion of the original make-event expression and is evaluated in place of that expression. (make-event form :check-expansion t) The user presumably wants it checked that the expansion doesn't change in the future, in particular during [include-book]. If the expansion of form is exp, then we will evaluate exp to obtain the value as before, but this time we record that the expansion of the original make-event expression is (make-event form :check-expansion exp) rather than simply exp. (make-event form :check-expansion exp) ; exp a cons This is generated for the case that :check-expansion is t, as explained above. Evaluation is handled as described in that above case, except here we check that the expansion result is the given exp. (Actually, the user is also allowed supply such a form.) The original make-event expression does not undergo any expansion (intuitively, it expands to itself). Now let us take a look at how we expand [progn] forms ([encapsulate] is handled similarly). (progn ... (make-event form :check-expansion nil) ...) The expansion is obtained by replacing the make-event form as follows. Let exp be the expansion of form. Then replace the above make-event form, which we denote as F, by (record-expansion F exp). Here, record-expansion is a macro that returns its second argument. (progn ... (make-event form :check-expansion t) ...) The expansion is of the form (record-expansion F exp) as in the nil case above, except that this time exp is (make-event form :check-expansion exp'), where exp' is the expansion of form. (progn ... (make-event form :check-expansion exp) ...) ; exp a cons No expansion takes place unless expansion takes place for at least one of the other subforms of the progn, in which case each such form F is replaced by (record-expansion F exp) where exp is the expansion of F. Detailed semantics In our explanation of the semantics of make-event, we assume familiarity with the notion of ``embedded event form'' (see [embedded-event-form]). Let's say that the ``actual embedded event form'' corresponding to a given form is the underlying call of an ACL2 event: that is, [local]s are dropped when ld-skip-proofsp is 'include-book, and macros are expanded away, thus leaving us with a [progn], a [make-event], or an event form (possibly [encapsulate]), any of which might have surrounding [local], [skip-proofs], or [with-output] calls. Thus, such an actual embedded event form can be viewed as having the form (rebuild-expansion wrappers base-form) where base-form is a progn, a make-event, or an event form (possibly encapsulate), and wrappers are (as in ACL2 source function destructure-expansion) the result of successively removing the event form from the result of macroexpansion, leaving a sequence of (local), (skip-proofs), and (with-output ...) forms. In this case we say that the form ``destructures into'' the indicated wrappers and base-form, and that it can be ``rebuilt from'' those wrappers and base-form. Elsewhere we define the notion of the ``expansion result'' from an evaluation (see [make-event]), and we mention that when expansion concludes, the ACL2 logical [world] and most of the state are restored to their pre-expansion values. Specifically, after evaluation of the argument of make-event (even if it is aborted), the ACL2 logical world is restored to its pre-evaluation value, as are all state global variables in the list *protected-system-state-globals*. Thus, assignments to user-defined state globals (see [assign]) do persist after expansion, since they are not in that list. We recursively define the combination of evaluation and expansion of an embedded event form, as follows. We also simultaneously define the notion of ``expansion takes place,'' which is assumed to propagate upward (in a sense that will be obvious), such that if no expansion takes place, then the expansion of the given form is considered to be itself. It is useful to keep in mind a goal that we will consider later: Every make-event subterm of an expansion result has a :check-expansion field that is a [consp], where for this purpose make-event is viewed as a macro that returns its :check-expansion field. (Implementation note: The latest expansion of a [make-event], [progn], [progn!], or [encapsulate] is stored in state global 'last-make-event-expansion, except that if no expansion has taken place for that form then 'last-make-event-expansion has value nil.) If the given form is not an embedded event form, then simply cause a soft error, (mv erp val state) where erp is not nil. Otherwise: If the evaluation of the given form does not take place (presumably because [local] events are being skipped), then no expansion takes place. Otherwise: Let x be the actual embedded event form corresponding to the given form, which destructures into wrappers W and base-form B. Then the original form is evaluated by evaluating x, and its expansion is as follows. If B is (make-event form :check-expansion val), then expansion takes place if and only if val is not a consp and no error occurs, as now described. Let R be the expansion result from protected evaluation of form, if there is no error. R must be an embedded event form, or it is an error. Then evaluate/expand R, where if val is not nil then state global 'ld-skip-proofsp is initialized to nil. (This initialization is important so that subsequent expansions are checked in a corresponding environment, i.e., where proofs are turned on in both the original and subsquent environments.) It is an error if this evaluation causes an error. Otherwise, the evaluation yields a value, which is the result of evaluation of the original make-event expression, as well as an expansion, E_R. Let E be rebuilt from W and E_R. The expansion of the original form is E if val is nil, and otherwise is the result of replacing the original form's :check-expansion field with E, with the added requirement that if val is not t (thus, a consp) then E must equal val or else we cause an error. If B is either (progn form1 form2 ...) or (encapsulate sigs form1 form2 ...), then after evaluating B, the expansion of the original form is the result of rebuilding from B, with wrappers W, after replacing each formi in B for which expansion takes place by (record-expansion formi formi'), where formi' is the expansion of formi. Note that these expansions are determined as the formi are evaluated in sequence (where in the case of encapsulate, this determination occurs only during the first pass). Except, if no expansion takes place for any formi, then the expansion of the original form is itself. Otherwise, the expansion of the original form is itself. Similarly to the [progn] and [encapsulate] cases above, book certification causes a book to be replaced by its so-called ``book expansion.'' There, each event ev for which expansion took place during the proof pass of certification --- say, producing ev' --- is replaced by (record-expansion ev ev'). Implementation Note. The book expansion is actually implemented by way of the :expansion-alist field of its [certificate], which associates 0-based positions of top-level forms in the book (not including the initial [in-package] form) with their expansions. Thus, the book's source file is not overwritten; rather, the certificate's expansion-alist is applied when the book is included or compiled. End of Implementation Note. It is straightforward by computational induction to see that for any expansion of an embedded event form, every make-event sub-event has a [consp] :check-expansion field. Here, by ``sub-event'' we mean to expand macros; and we also mean to traverse progn and encapsulate forms as well as :check-expansion fields of make-event forms. Thus, we will only see make-event forms with consp :check-expansion fields in the course of include-book forms, the second pass of encapsulate forms, and raw Lisp. This fact guarantees that an event form will always be treated as its original expansion. Notes on ttags See [defttag] for documentation of the notion of ``trust tag'' (``ttag''). We note here that even if an event (defttag tag-name) for non-nil tag-name is admitted only during the expansion phase of a [make-event] form, then such expansion will nevertheless still cause tag-name to be recorded in the logical [world] (assuming that the make-event form is admitted). So in order to certify such a book, a suitable :ttags argument must be supplied; see [certify-book]. ACL2 does provide a way to avoid the need for :ttags arguments in such cases. The idea is to certify a book twice, where the results of make-event expansion are saved from the first call of [certify-book] and provided to the second call. See [set-write-ACL2x]. Finally, we discuss a very unusual case where certification does not involve trust tags but a subsequent [include-book] does involve trust tags: a make-event call specifying :check-expansion t, whose expansion generates a [defttag] event during [include-book] but not [certify-book]. Consider the following book. (in-package \"ACL2\") (make-event (er-progn (if (@ skip-notify-on-defttag) ; non-nil when including a certified book (pprogn (fms \"Value of (@ skip-notify-on-defttag): ~x0~|\" (list (cons #0 (@ skip-notify-on-defttag))) *standard-co* state nil) (encapsulate () (defttag :foo) (value-triple \"Imagine something bad here!\"))) (value nil)) (value '(value-triple :some-value))) :check-expansion t) This book certifies successfully without the need for a :ttags argument for [certify-book]. Indeed, the above book's [certificate] does not specify :foo as a trust tag associated with the book, because no defttag event was executed during book certification. Unfortunately, if we try to include this book without specifying a value of :ttags that allows :foo, book inclusion will cause executing of the above [defttag]. If that inclusion happens in the context of certifying some superior book and the appropriate :ttags arguments have not been provided, that certification will fail.") (MAKE-FAST-ALIST (FAST-ALISTS ACL2-BUILT-INS) "(make-fast-alist alist) creates a fast-alist from the input alist, returning alist itself or, in some cases, a new object equal to it. Note: it is often better to use with-fast-alist; see [with-fast-alist]. Logically, make-fast-alist is the identity function. Function: (defun make-fast-alist (alist) (declare (xargs :guard t)) alist) Under the hood, we construct and return an object that is equal to alist and which is a fast alist. If alist is already a fast alist, almost no work is required: we simply return it unchanged. When alist is not fast, we must minimally construct a hash table for its bindings. It is often possible to bind this new hash table to alist itself. But in certain cases when the alist keys are not [normed], a new alist must be constructed, also, and so we may return an equal but not eq alist. (In these cases, we still try to avoid at least some consing by reusing the \"longest normed tail\" of the alist.)") (MAKE-LIST (LISTS ACL2-BUILT-INS) "Make a list of a given size For a nonnegative integer size, (Make-list size) is a list of elements of length size, each of which is initialized to the :initial-element (which defaults to nil). Make-list is a macro in ACL2, defined in terms of a tail recursive function make-list-ac whose [guard] requires size to be a nonnegative integer. Make-list is a Common Lisp function. See any Common Lisp documentation for more information. Macro: (defmacro make-list (size &key initial-element) (cons 'make-list-ac (cons size (cons initial-element (cons 'nil 'nil))))) Function: (defun make-list-ac (n val ac) (declare (xargs :guard (and (integerp n) (>= n 0)))) (cond ((zp n) ac) (t (make-list-ac (1- n) val (cons val ac)))))") (MAKE-ORD (ORDINALS ACL2-BUILT-INS) "A constructor for ordinals. Make-ord is the ordinal constructor. Its use is recommended instead of using [cons] to make ordinals. For a discussion of ordinals, see [ordinals]. For any ordinal, alpha < epsilon-0, there exist natural numbers p and n, positive integers x1, x2, ..., xn and ordinals a1 > a2 > ... > an > 0 such that alpha > a1 and alpha = w^(a1)x1 + w^(a2)x2 + ... + w^(an)xn + p. We call a1 the ``first exponent'', x1 the ``first coefficient'', and the remainder (w^(a2)x2 + ... + w^(an)xn + p) the ``rest'' of alpha. (Make-ord fe fco rst) corresponds to the ordinal (w^fe)fco + rst. Thus the first infinite ordinal, w (omega), is constructed by (make-ord 1 1 0) and, for example, the ordinal (w^2)5 + w2 + 7 is constructed by: (make-ord 2 5 (make-ord 1 2 7)) . The reason make-ord is used rather than [cons] is that it allows us to reason more abstractly about the ordinals, without having to worry about the underlying representation. Function: (defun make-ord (fe fco rst) (declare (xargs :guard (and (posp fco) (o-p fe) (o-p rst)))) (cons (cons fe fco) rst))") (MAKE-TAU-INTERVAL (TAU-SYSTEM ACL2-BUILT-INS) "Make a tau interval General Form: (make-tau-interval doc lo-rel lo hi-rel hi) An interval is a structure of the form: (dom (lo-rel . lo) . (hi-rel . hi)). Every tau contains an interval used to represent the domain, the upper, and the lower bounds of the objects recognized by the tau. make-tau-interval constructs well-formed intervals only if its five arguments satisfy certain restrictions given below. When these restrictions are violated make-tau-interval can construct objects that are not intervals! make-tau-interval does not attempt to coerce or adjust its arguments to make well-formed intervals. For examples of intervals (and non-intervals!) constructed by make-tau-interval see [tau-intervalp]. For examples of what objects are contained in certain intervals, see [in-tau-intervalp]. The components of an interval are as follows: dom (``domain'') -- must be one of four symbols: INTEGERP, RATIONALP, ACL2-NUMBERP, or NIL denoting no restriction on the domain. The two ``relations,'' lo-rel and hi-rel are Booleans, where t denotes less-than inequality ([<]) and nil represents less-than-or-equal inequality ([<=]). Think of t meaning ``strong'' and nil meaning ``weak'' inequality. Lo and hi must be either nil or explicit rational numbers. If lo is nil it denotes negative infinity; if hi is nil it denotes positive infinity. Lo must be no greater than hi. Note: Even though ACL2-NUMBERP intervals may contain complex rationals, the lo and hi bounds must be rational. This is an arbitrary decision made by the implementors to simplify coding. Finally, if the dom is INTEGERP, then both relations should be weak and lo and hi must be integers when they are non-nil. For x to be ``in'' an interval it must be of the type described by the domain predicate dom, lo must be smaller than x in the strong or weak sense denoted by lo-rel, and x must be smaller than hi in the strong or weak sense denoted by hi-rel. The components of an interval may be accessed with the functions [tau-interval-dom], [tau-interval-lo-rel], [tau-interval-lo], [tau-interval-hi-rel], and [tau-interval-hi].") (MAKE-WORMHOLE-STATUS (WORMHOLE) "Creates a wormhole status object from given status, entry code, and data General Form: (make-wormhole-status whs code data) See [wormhole]. Whs should be a well-formed wormhole status, code should be :ENTER or :SKIP, and data is arbitrary. This function returns a new status with the specified entry code and data, reusing whs if it is appropriate.") (MANAGING-ACL2-PACKAGES (PACKAGES) "User-contributed documentation on packages Jared Davis has contributed documentation on {managing ACL2 packages | http://www.cs.utexas.edu/users/moore/acl2/contrib/managing-acl2-packages.html}. Also see [working-with-packages].") (MAX (NUMBERS ACL2-BUILT-INS) "The larger of two numbers (Max x y) is the larger of the numbers x and y. The [guard] for max requires its arguments to be rational ([real], in ACL2(r)) numbers. Max is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun max (x y) (declare (xargs :guard (and (real/rationalp x) (real/rationalp y)))) (if (> x y) x y))") (MAXIMUM-LENGTH (ARRAYS ACL2-BUILT-INS) "Return the :maximum-length from the [header] of an array Example Form: (maximum-length 'delta1 a) General Form: (maximum-length name alist) where name is an arbitrary object and alist is a 1- or 2-dimensional array. This function returns the contents of the :maximum-length field of the [header] of alist. Whenever an [aset1] or [aset2] would cause the length of the alist to exceed its maximum length, a [compress1] or [compress2] is done automatically to remove irrelevant pairs from the array. Maximum-length operates in virtually constant time if alist is the semantic value of name. See [arrays]. Function: (defun maximum-length (name l) (declare (xargs :guard (or (array1p name l) (array2p name l)))) (cadr (assoc-keyword :maximum-length (cdr (header name l)))))") (MBE (GUARD PROGRAMMING ACL2-BUILT-INS) "Attach code for execution The macro mbe (``must be equal'') can be used in function definitions in order to cause evaluation to use alternate code to that provided for the logic. An example is given below. However, the use of mbe can lead to non-terminating computations. See [defexec], perhaps after reading the present documentation, for a way to prove termination. In the ACL2 logic, (mbe :exec exec-code :logic logic-code) equals logic-code; the value of exec-code is ignored. However, in raw Lisp it is the other way around: this form macroexpands simply to exec-code. ACL2's [guard] verification mechanism ensures that the raw Lisp code is only evaluated when appropriate, since the guard proof obligations generated for (the macroexpansion of) this call of mbe include not only the guard proof obligations from exec-code, but also, under suitable contextual assumptions, the term (equal exec-code logic-code). See [verify-guards] (in particular, for discussion of the contextual assumptions from the :guard and [if]-tests) and, for general discussion of guards, see [guard]. Normally, during evaluation of an mbe call, only the :logic code is evaluated unless the call is in the body of a [guard]-verified function or under a call of a :[program] mode function; in those cases only the :exec code is evaluated. This implies that equality of :exec and :logic code is never checked at runtime. (Rather, such equality is proved when verifying guards.) We qualified with ``normally'' above because there are two exceptions. During a ``safe mode'', which is used in macroexpansion and evaluation of [defconst] forms, the :logic and :exec code are both evaluated and their equality is checked. Second, when guard-checking is set to :all or :none, then for any mbe call in the body of a :logic mode definition, only the :logic code will be evaluated. Note that the :exec and the :logic code in an mbe call must have the same output signature. For example, one cannot return ([mv] * *) while the other returns just a single value. Also see [mbt], which stands for ``must be true.'' You may find it more natural to use [mbt] for certain applications, as described in its [documentation]. Here is an example of the use of mbe. Suppose that you want to define factorial in the usual recursive manner, as follows. (defun fact (n) (if (zp n) 1 (* n (fact (1- n))))) But perhaps you want to be able to execute calls of fact on large arguments that cause stack overflows, perhaps during proofs. (This isn't a particularly realistic example, but it should serve.) So, instead you can define this tail-recursive version of factorial: (defun fact1 (n acc) (declare (xargs :guard (and (integerp n) (>= n 0) (integerp acc)))) (if (zp n) acc (fact1 (1- n) (* n acc)))) We are now ready to define fact using mbe. Our intention is that logically, fact is as shown in the first definition above, but that fact should be executed by calling fact1. Notice that we defer [guard] verification, since we are not ready to prove the correspondence between fact1 and fact. (defun fact (n) (declare (xargs :guard (and (integerp n) (>= n 0)) :verify-guards nil)) (mbe :exec (fact1 n 1) :logic (if (zp n) 1 (* n (fact (1- n)))))) Next, we prove the necessary correspondence lemmas. Notice the inclusion of a community book to help with the arithmetic reasoning. (include-book \"books/arithmetic/top-with-meta\") (defthm fact1-fact (implies (integerp acc) (equal (fact1 n acc) (* acc (fact n))))) We may now do guard verification for fact, which will allow the execution of the raw Lisp fact function, where the above mbe call expands simply to (fact1 n 1). (verify-guards fact) Now that guards have been verified, a trace of function calls illustrates that the evaluation of calls of fact is passed to evaluation of calls of fact1. The outermost call below is of the logical function stored for the definition of fact; all the others are of actual raw Common Lisp functions. ACL2 !>(trace$ fact fact1) NIL ACL2 !>(fact 3) 1> (ACL2_*1*_ACL2::FACT 3) 2> (FACT 3) 3> (FACT1 3 1) 4> (FACT1 2 3) 5> (FACT1 1 6) 6> (FACT1 0 6) <6 (FACT1 6) <5 (FACT1 6) <4 (FACT1 6) <3 (FACT1 6) <2 (FACT 6) <1 (ACL2_*1*_ACL2::FACT 6) 6 ACL2 !> You may occasionally get warnings when you compile functions defined using mbe. (For commands that invoke the compiler, see [compilation].) These can be inhibited by using an ignorable [declare] form. Here is a simple but illustrative example. Note that the declarations can optionally be separated into two [declare] forms. (defun foo (x y) (declare (ignorable x) (xargs :guard (equal x y))) (mbe :logic x :exec y)) Finally, we observe that when the body of a function contains a term of the form (mbe :exec exec-code :logic logic-code), the user would be unlikely to notice any difference in the theorem prover if this term were replaced by logic-code. ACL2 takes various steps to ensure this. For example, the proof obligations generated for admitting a function treat the above mbe term simply as logic-code. Function expansion, :use [hints], :[definition] rules, generation of [constraint]s for functional instantiation, and creation of rules of class :[rewrite] and :[forward-chaining] also treat mbe calls as their :logic code. Subtopics [Defexec] Attach a terminating executable function to a definition [Mbe1] Attach code for execution [Mbt] Introduce a test into the logic that, however, evaluates to t [Mbt*] Introduce a guard proof obligation [Must-be-equal] Attach code for execution") (MBE1 (MBE ACL2-BUILT-INS) "Attach code for execution The form (mbe1 exec logic) is equivalent to the forms (mbe :logic logic :exec exec) and (must-be-equal logic exec). See [mbe].") (MBT (MBE ACL2-BUILT-INS) "Introduce a test into the logic that, however, evaluates to t The macro mbt (``must be true'') can be used in order to add code in order to admit function definitions in :[logic] mode, without paying a cost in execution efficiency. Examples below illustrate its intended use. Semantically, (mbt x) equals x. However, in raw Lisp (mbt x) ignores x entirely, and macroexpands to t. ACL2's [guard] verification mechanism ensures that the raw Lisp code is only evaluated when appropriate, since a guard proof obligation (equal x t) is generated. See [verify-guards] and, for general discussion of guards, see [guard]. Also see [mbe], which stands for ``must be equal.'' Although mbt is more natural in many cases, mbe has more general applicability. In fact, (mbt x) is essentially defined to be (mbe :logic x :exec t). Another related utility is [mbt*], which generates the same proof obligation as mbt but logically, is simply t. We can illustrate the use of mbt on the following generic example, where , , , and are intended to be terms involving only the variable x. (defun foo (x) (declare (xargs :guard )) (if (foo ) )) In order to admit this function, ACL2 needs to discharge the proof obligation that is smaller than x, namely: (implies (o< (acl2-count ) (acl2-count x))) But suppose we need to know that is true in order to prove this. Since is only the [guard], it is not part of the logical definition of foo. A solution is to add the guard to the definition of foo, as follows. (defun foo (x) (declare (xargs :guard )) (if (mbt ) (if (foo ) ) nil)) If we do this using rather than (mbt ), then evaluation of every recursive call of foo will cause the evaluation of (the appropriate instance of) . But since (mbt ) expands to t in raw Lisp, then once we verify the guards of foo, the evaluations of will be avoided (except at the top level, when we check the guard before allowing evaluation to take place in Common Lisp). Other times, the guard isn't the issue, but rather, the problem is that a recursive call has an argument that itself is a recursive call. For example, suppose that is of the form (foo ). There is no way we can hope to discharge the termination proof obligation shown above. A standard solution is to add some version of this test: (mbt (o< (acl2-count ) (acl2-count x))) Here is a specific example based on one sent by Vernon Austel. (defun recurX2 (n) (declare (xargs :guard (and (integerp n) (<= 0 n)) :verify-guards nil)) (cond ((zp n) 0) (t (let ((call (recurX2 (1- n)))) (if (mbt (< (acl2-count call) n)) (recurX2 call) 1 ;; this branch is never actually taken ))))) (defthm recurX2-0 (equal (recurX2 n) 0)) (verify-guards recurX2) If you ([trace$] acl2-count), you will see that evaluation of (recurX2 2) causes several calls of [ACL2-count] before the [verify-guards]. But this evaluation does not call acl2-count after the verify-guards, because the ACL2 evaluation mechanism uses raw Lisp to do the evaluation, and the form (mbt (< (acl2-count call) n)) macroexpands to t in Common Lisp. You may occasionally get warnings when you compile functions defined using mbt. (For commands that invoke the compiler, see [compilation].) These can be inhibited by using an ignorable [declare] form. Here is a simple but illustrative example. Note that the declarations can optionally be separated into two [declare] forms. (defun foo (x y) (declare (ignorable x) (xargs :guard (equal x t))) (and (mbt x) y))") (MBT* (MBE ACL2-BUILT-INS) "Introduce a guard proof obligation The macro mbt* is a variant of mbt (``must be true''). However, unlike mbt, the call (mbt* test) is equivalent simply to t for both logic and evaluation. The only effective difference between (mbt* test) and t is that (mbt* test) generates a [guard] proof obligation (when used in a [logic]-mode definition) of test. If you think that mbt* might be of use, please see [assert*], which is defined using mbt* to create a [guard] proof obligation without any logical or execution burden.") (MEASURE (POINTERS) "See [xargs] for keyword :measure. Subtopics [Measure-debug] Generate markers to indicate sources of [measure] proof obligations") (MEASURE-DEBUG (MEASURE DEBUGGING) "Generate markers to indicate sources of [measure] proof obligations When ACL2 is asked to accept a recursive (or mutually recursive) function definition, it generates a goal often called the ``measure conjecture.'' That goal can split into numerous goals, some of which may not be theorems if the definition being processed has bugs. This [documentation] topic explains a capability provided by ACL2 to help find such bugs. For a similar utility appropriate for [guard] verification, see [guard-debug]. We begin with the following simple, admittedly artificial, example. (defun f (x) (if (consp x) (f (cons x x)) x)) ACL2 generates the following proof obligation.. (IMPLIES (CONSP X) (O< (ACL2-COUNT (CONS X X)) (ACL2-COUNT X))) In this simple example, it is obvious that ACL2 cannot prove the goal because in fact, (CONS X X) does not have a smaller [ACL2-count] than X, even assuming (CONSP X). But you can get ACL2 to show explicitly the source of this proof obligation by specifying :measure-debug t in an [xargs] [declare] form, as follows. ACL2 !>(defun f (x) (declare (xargs :measure-debug t)) (if (consp x) (f (cons x x)) x)) For the admission of F we will use the relation O< (which is known to be well-founded on the domain recognized by O-P) and the measure (ACL2-COUNT X). The non-trivial part of the measure conjecture is Goal (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F)) '(F (CONS X X))) (CONSP X)) (O< (ACL2-COUNT (CONS X X)) (ACL2-COUNT X))). The extra-info call is telling us the following about the measure conjecture: The appropriate well-founded relation (typically [o<]) holds between appropriate terms, because of the indicated recursive call, (F (CONS X X)). We now describe the measure-debug utility in some detail. (Extra-info x y) always returns t by definition. However, if the measure conjecture takes place with a non-nil value for the [xargs] keyword :measure-debug, then the goals generated will include hypotheses that are calls of extra-info. Such a hypothesis has one of the following forms. (extra-info '(:MEASURE (:RELATION function-name)) 'recursive-call) (extra-info '(:MEASURE (:DOMAIN function-name)) '(D (M term))) The first form says that the goal is to show that the measure decreases for the indicated recursive call in the body of the function named function-name. The second form says that the goal is to show that the measure always returns a suitable value. We illustrate with a slightly more elaborate, but still contrived, example, which we hope clearly illustrates the points above. Notice that :measure-debug t need only be specified for a single [defun] form in a call of [mutual-recursion]. Also notice in the output that when there is more than one source for a goal, each source is indicated by its own call of extra-info. ACL2 !>(defstub my-measure (x) t) ; for the contrived example below [[ .. output omitted here .. ]] ACL2 !>(mutual-recursion (defun f1 (x) (declare (xargs :measure (my-measure x) :measure-debug t)) (if (consp x) (f2 (cons x (cdr x))) t)) (defun f2 (x) (declare (xargs :measure (my-measure x))) (if (consp x) (f1 (cons (make-list (car x)) (cdr x))) nil))) For the admission of F1 and F2 we will use the relation O< (which is known to be well-founded on the domain recognized by O-P) and the measure (MY-MEASURE X) for F1 and (MY-MEASURE X) for F2. The non-trivial part of the measure conjecture is Goal (AND (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F1)) '(F2 (CONS X (CDR X)))) (CONSP X)) (O< (MY-MEASURE (CONS X (CDR X))) (MY-MEASURE X))) (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:RELATION F2)) '(F1 (CONS (MAKE-LIST-AC (CAR X) NIL NIL) (CDR X)))) (CONSP X)) (O< (MY-MEASURE (CONS (MAKE-LIST-AC (CAR X) NIL NIL) (CDR X))) (MY-MEASURE X))) (IMPLIES (AND (EXTRA-INFO '(:MEASURE (:DOMAIN F2)) '(O-P (MY-MEASURE X))) (EXTRA-INFO '(:MEASURE (:DOMAIN F1)) '(O-P (MY-MEASURE X)))) (O-P (MY-MEASURE X)))). All rules (see [rune]) associated with extra-info are [disable]d by default, so that hypotheses of the form described above are not simplified to t. These hypotheses are intended to ride along for free: you can generally expect the proof to have the same structure whether or not the :measure-debug option is supplied, though on rare occasions the proofs may diverge.") (MEMBER (LISTS ACL2-BUILT-INS) "Membership predicate General Forms: (member x lst) (member x lst :test 'eql) ; same as above (eql as equality test) (member x lst :test 'eq) ; same, but eq is equality test (member x lst :test 'equal) ; same, but equal is equality test (Member x lst) equals the longest tail of the list lst that begins with x, or else nil if no such tail exists. The optional keyword, :TEST, has no effect logically, but provides the test (default [eql]) used for comparing x with successive elements of lst. The [guard] for a call of member depends on the test. In all cases, the second argument must satisfy [true-listp]. If the test is [eql], then either the first argument must be suitable for [eql] (see [eqlablep]) or the second argument must satisfy [eqlable-listp]. If the test is [eq], then either the first argument must be a symbol or the second argument must satisfy [symbol-listp]. See [equality-variants] for a discussion of the relation between member and its variants: (member-eq x lst) is equivalent to (member x lst :test 'eq); (member-equal x lst) is equivalent to (member x lst :test 'equal). In particular, reasoning about any of these primitives reduces to reasoning about the function member-equal. Member is defined by Common Lisp. See any Common Lisp documentation for more information. Function: (defun member-equal (x lst) (declare (xargs :guard (true-listp lst))) (cond ((endp lst) nil) ((equal x (car lst)) lst) (t (member-equal x (cdr lst)))))") (MEMBER-EQ (POINTERS) "See [member].") (MEMBER-EQUAL (POINTERS) "See [member].") (MEMOIZE (PROGRAMMING HONS-AND-MEMOIZATION EVENTS) "Turn on memoization for a specified function This [documentation] topic relates to [hons-enabled] ACL2 executables, which are built by default. See [hons-and-memoization] for a general discussion of memoization and the related features of hash consing and applicative hash tables. Examples: (memoize 'foo) ; remember the values of calls ; of foo (memoize 'foo :condition t) ; same as above (memoize 'foo :condition '(test x)) ; memoize for args satisfying ; the given condition (memoize 'foo :condition-fn 'test) ; memoize for args satisfying ; a call of the given function (memoize 'foo :recursive nil) ; don't memoize recursive calls (memoize 'foo :aokp t) ; attachments OK for stored results (memoize 'foo :stats nil) ; don't collect info for (memsum) (memoize 'foo :ideal-okp t) ; memoize for raw Lisp even if foo is ; in :logic but not guard-verified General Form: (memoize fn ; memoizes fn and returns fn :condition condition ; optional (default t) :condition-fn condition-fn ; optional :hints hints ; optional, for verifying the ; guards of condition-fn :otf-flg otf-flg ; optional, for verifying the ; guards of condition-fn :recursive t/nil ; optional (default t) :commutative t/lemma-name ; optional (default nil) :forget t/nil ; optional (default nil) :memo-table-init-size size ; optional (default *mht-default-size*) :aokp t/nil ; optional (default nil) :stats t/nil ; optional (default t) :ideal-okp t/:warn/nil ; optional (default nil) :verbose t/nil ; optional (default t) ) where fn evaluates to a user-defined function symbol; condition is either t (the default), 't, nil, or 'nil, or else evaluates to an expression whose free variables are among the formal parameters of fn; and condition-fn is either nil (the default) or else evaluates to a legal function symbol. Further restrictions and options are discussed below. Note that all arguments are evaluated (but for the special handling of value t for :commutative, the argument must literally be t; see below). Generally fn must evaluate to a defined function symbol. However, this value can be the name of a macro that is associated with such a function symbol; see [macro-aliases-table]. That associated function symbol is the one called ``memoized'' in the discussion below, but we make no more mention of this subtlety. In the most common case, memoize takes a single argument, which evaluates to a function symbol. We call this function symbol the ``memoized function'' because ``memos'' are saved and re-used, in the following sense. When a call of the memoized function is evaluated, the result is ``memoized'' by associating the call's arguments with that result, in a suitable table. But first an attempt is made to avoid such evaluation, by doing a lookup in that table on the given arguments for the result, as stored for a previous call on those arguments. If such a result is found, then it is returned without further computation. This paragraph also applies if :condition is supplied but is t or 't. If keyword argument :condition-fn is supplied, but :condition is not, then the result of evaluating :condition-fn must be a defined function symbol whose formal parameter list and [guard] are the same as for the function being memoized. If fn is in :[logic] mode, then [guard]s must have been verified for :condition-fn. Such a ``condition function'' will be run whenever the memoized function is called, on the same parameters, and the lookup or table store described above are only performed if the result from the condition function call is non-nil. Suppose however that :condition is supplied. If the value supplied is t or 't, then the lookup and table store described above are always done. If the value is nil or 'nil, then this lookup and table store are never done, although statistics may be gathered; see [profile]. Now consider other values for :condition. An attempt will be made to define a condition function whose [guard] and formal parameters list are the same as those of the memoized function, and whose body is the result, r, of evaluating the given condition. The name of that condition function is the result of evaluating :condition-fn if supplied, else is the result of concatenating the string \"-MEMOIZE-CONDITION\" to the end of the name of the memoized function. The condition function will be defined with [guard] verification turned off, but that definition will be followed immediately by a [verify-guards] event; and this is where the optional :hints and :otf-flg are attached. At evaluation time the condition function is used as described in the preceding paragraph; so in effect, the condition (r, above) is evaluated, with its variables bound to the corresponding actuals of the memoized function call, and the memoized function attempts a lookup or table store if and only if the result of that evaluation is non-nil. Note that fn can be either a :[logic] mode function or a :[program] mode function. However, only the corresponding raw Lisp function is actually memoized, so [guard] violations can defeat memoization, and :[logic] mode functions without their [guard]s verified will only be memoized when called by :[program] mode functions. (See [guards-and-evaluation] for more information about guards and evaluation in ACL2.) If fn is a :[logic] mode function and :condition is supplied and not t or nil, then the condition must be a [guard]-verified function. Calls of this macro generate events of the form (table memoize-table fn ((:condition-fn fn) ...)). When successful, the returned value is of the form (mv nil function-symbol state). Suppose that a function is already memoized. Then it is illegal to memoize that function. Moreover, if the function was memoized with an associated condition (i.e., was memoized with keyword :condition or :condition-fn having value other than t or nil), then it is also illegal to convert the function from :[program] to :[logic] mode (see [verify-termination]). To turn off memoization, see [unmemoize]. Memoize is illegal for a function if its arguments include [state] or if it returns any [stobj]s. A stobj can be an input of a memoized function, but in that case, the memoization table for that stobj will be cleared every time that stobj is updated. By default, memoize does not store results when any attachments have been used (see [defattach]). However, such results are stored when memoize keyword parameter :aokp has value t. Note that for purposes of this discussion, the use of a stored value for a subsidiary function that was memoized with :aokp t is treated as the use of an attachment, since ACL2 does not know whether or not an attachment was actually used in that case. We conclude with by documenting keyword parameters not discussed above. Keyword parameter :recursive is t by default, which means that recursive calls of fn will be memoized just as ``top-level'' calls of fn. When :recursive is instead set to nil, memoization is only done at the top level. Using :recursive nil is similar to writing a wrapper function that just calls fn, and memoizing the wrapper instead of fn. If :trace has a non-nil value, then memoize also traces in a traditional Lisp style. If :trace has value notinline or notinline, then a corresponding declaration is added at the beginning of the new definition of fn. A non-nil value for :commutative can be supplied if fn is a binary function in :logic mode. Suppose that the memoize event is successful, and consider a subsequent call of fn for which some argument to fn is either a rational number or, in some host Lisps (currently either CCL, or GCL Version 2.6.12 or later) a [hons]. (Indeed, for such GCL versions this is true for any cons, not just a hons.) Then when the evaluation of fn on those arguments is memoized, the evaluation of fn on the swap of those arguments is, in essence, also memoized. If :commutative is supplied and is not nil or t, then it should be the name of a previously-proved theorem whose formula states the commutativity of fn, i.e., is the formula (equal (fn x y) (fn y x)) for a pair {x,y} of distinct variables. If :commutative is t --- but not merely an expression that evaluates to t --- then an attempt to prove such a lemma will be made on-the-fly. The name of the lemma is the symbol in the same package as fn, obtained by adding the suffix \"-COMMUTATIVE\" to the [symbol-name] of fn. If the proof attempt fails, then you may want first to prove the lemma yourself with appropriate hints and perhaps supporting lemmas, and then supply the name of that lemma as the value of :commutative. If :commutative is supplied, and a non-commutative condition is provided by :condition or :condition-fn, then although the results will be correct, the extra memoization afforded by :commutative is unspecified. If :memo-table-init-size is supplied, then it should be a positive integer specifying the initial size of an associated hash table. Argument :aokp is relevant only when attachments are used; see [defattach] for background on attachments. When :aokp is nil, the default, computed values are not stored when an attachment was used, or even when an attachment may have been used because a function was called that had been memoized using :aokp t. Otherwise, computed values are always stored, but saved values are not used except when attachments are allowed. To summarize: aokp=nil (default): ``Pure'', i.e., values do not depend on attachments - Fetch: always legal - Store: only store resulting value when attachments were not used aokp=t: ``Impure'', i.e., values may depend on attachments - Fetch: only legal when attachments are allowed (e.g., not during proofs) - Store: always legal The default value for :stats is essentially t. (Technically, this can be subverted by using raw Lisp, to change the default by changing the values of variables *record-xxx* introduced in ACL2 source file memoize-raw.lisp.) When :stats has its default value (assuming the above raw Lisp changes are not made) or value t, calls of memoized functions will collect information that can be displayed by calling [memsum]. But if :stats is nil, this information will not be collected, possibly resulting in better performance for the memoized function. As of this writing, built-in memoized functions use :stats nil to benefit performance. If :ideal-okp is supplied and not nil, then it is permitted to memoize an ``ideal-mode'' function: one in :[logic] mode whose [guard]s have not been verified. However, this might not have the effect you desire, because you will be memoizing the raw Lisp version of the function, not the safe (so-called ``*1*'') function that is executed in the ACL2 loop and on behalf of the prover. Thus, if you memoize an ideal-mode function and then call it at the top-level of the ACL2 loop (or, for example, it is called to evaluate a ground term arising in a proof or in the evaluation of a [meta]function in a proof), the effects of memoization will not be felt because the raw Lisp code is not run unless guards are verified. There are circumstances in which the raw Lisp code of an ideal-mode function is called. For example, if the ideal-mode function is called by a :[program] mode function, evaluation can transfer to raw Lisp where the effects of memoization will be felt. A trick, described below, with [ec-call] can provide some of the benefit of memoizing an ideal-mode function. The trick exploits the fact that ec-call allows you to call an ideal-mode function within a [guard]-verified (``Common Lisp compliant'') :[logic] mode function without having to verify guards for the ideal-mode function. The following edited log illustrates the points above. ACL2 !>(defun fib (n) (declare (xargs :guard (natp n) :verify-guards nil)) (if (zp n) 0 (if (eql n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))) [[ .. output omitted .. ]] FIB ACL2 !>(memoize 'fib :ideal-okp t) [[ .. output omitted .. ]] FIB ACL2 !>(time$ (fib 38)) ; slow, since *1*fib never calls fib ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited on recursive calls of the executable counterpart (i.e., in the ACL2 logic) of FIB. To check guards on all recursive calls: (set-guard-checking :all) To leave behavior unchanged except for inhibiting this message: (set-guard-checking :nowarn) ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 3.91 seconds realtime, 3.90 seconds runtime ; (416 bytes allocated). 39088169 ACL2 !>(time$ (fib 38)) ; still slow; no results were stored before ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited on recursive calls of the executable counterpart (i.e., in the ACL2 logic) of FIB. To check guards on all recursive calls: (set-guard-checking :all) To leave behavior unchanged except for inhibiting this message: (set-guard-checking :nowarn) ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 3.92 seconds realtime, 3.91 seconds runtime ; (416 bytes allocated). 39088169 ACL2 !>(defun fib-logic-wrapper (n) ; guard-verified (declare (xargs :guard (natp n))) (ec-call (fib n))) [[ .. output omitted .. ]] FIB-LOGIC-WRAPPER ACL2 !>(memoize 'fib-logic-wrapper) [[ .. output omitted .. ]] FIB-LOGIC-WRAPPER ACL2 !>(time$ (fib-logic-wrapper 38)) ; slow; no fib results are stored ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited on recursive calls of the executable counterpart (i.e., in the ACL2 logic) of FIB. To check guards on all recursive calls: (set-guard-checking :all) To leave behavior unchanged except for inhibiting this message: (set-guard-checking :nowarn) ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 3.92 seconds realtime, 3.91 seconds runtime ; (2,128 bytes allocated). 39088169 ACL2 !>(time$ (fib-logic-wrapper 38)) ; fast; fib-logic-wrapper result was stored ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 0.00 seconds realtime, 0.00 seconds runtime ; (16 bytes allocated). 39088169 ACL2 !>(time$ (fib-logic-wrapper 37)) ; slow; result only for 38 was stored ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking will be inhibited on recursive calls of the executable counterpart (i.e., in the ACL2 logic) of FIB. To check guards on all recursive calls: (set-guard-checking :all) To leave behavior unchanged except for inhibiting this message: (set-guard-checking :nowarn) ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 2.42 seconds realtime, 2.42 seconds runtime ; (416 bytes allocated). 24157817 ACL2 !>(defun fib-program-wrapper (n) ; program mode function (declare (xargs :guard (natp n) :mode :program)) (fib n)) Summary Form: ( DEFUN FIB-PROGRAM-WRAPPER ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) FIB-PROGRAM-WRAPPER ACL2 !>(time$ (fib-program-wrapper 100)) ; fast because raw-Lisp fib is called ; (EV-REC *RETURN-LAST-ARG3* ...) took ; 0.00 seconds realtime, 0.00 seconds runtime ; (7,600 bytes allocated). 354224848179261915075 ACL2 !> Two non-nil values are allowed for keyword parameter :ideal-okp: :warn and t. Both of these values allow memoization of ideal-mode functions, but if :warn is supplied then a warning will take place at memoization time, specifically for the resluting [table] event. Note that you may set the key :memoize-ideal-okp of the [ACL2-defaults-table] to value t or :warn to change the default, but if parameter :ideal-okp is supplied, the [ACL2-defaults-table] value is ignored. If :verbose is supplied, it should either be nil, which will inhibit proof, event, and summary output (see [with-output]), or else t (the default), which does not inhibit output. If the output baffles you, try :trans1 (memoize ...) to see the single-step macroexpansion of your memoize call. The default for :forget is nil. If :forget is supplied, and not nil, then it must be t, which causes all memoization done for a top-level call of fn to be forgotten when that top-level call exits. Subtopics [Clear-hash-tables] Deprecated feature [Clear-memoize-statistics] Clears all profiling info displayed by ([memoize-summary]) [Clear-memoize-table] Forget values remembered for the given function [Clear-memoize-tables] Forget values remembered for all the memoized functions [Memoize-summary] Display all collected profiling and memoization table info [Memsum] Display all collected profiling and memoization info [Never-memoize] Mark a function as unsafe to memoize. [Restore-memoization-settings] Restore the saved memoization settings [Save-and-clear-memoization-settings] Save and remove the current memoization settings [Unmemoize] Turn off memoization for the specified function") (MEMOIZE-SUMMARY (MEMOIZE) "Display all collected profiling and memoization table info Logically, this function just returns nil, but it displays profiling and memoization table information. The profiling statistics may be cleared with ([clear-memoize-statistics]). Function: (defun memoize-summary nil (declare (xargs :guard t)) nil)") (MEMSUM (MEMOIZE) "Display all collected profiling and memoization info This macro is an abbreviation for [memoize-summary]. Logically, it just returns nil.") (META (RULE-CLASSES) "Make a :meta rule (a hand-written simplifier) See [rule-classes] for a general discussion of rule classes, including how they are used to build rules from formulas and a discussion of the various keywords in a rule class description. Meta rules extend the ACL2 simplifier with hand-written code to transform certain terms to equivalent ones. To add a meta rule, the :[corollary] formula must establish that the hand-written ``metafunction'' preserves the meaning of the transformed term. Examples: (defthm fn-correct-1 ; Modify the rewriter to use fn to (equal (evl x a) ; transform terms that are calls of (evl (fn x) a)) ; nth or of foo. :rule-classes ((:meta :trigger-fns (nth foo)))) (defthm fn-correct-2 ; As above, but this illustrates (implies (and (pseudo-termp x) ; that without loss of generality we (alistp a)) ; may restrict x to be shaped like a (equal (evl x a) ; term and a to be an alist. (evl (fn x) a))) :rule-classes ((:meta :trigger-fns (nth foo)))) (defthm fn-correct-3 ; As above (with or without the (implies (and (pseudo-termp x) ; hypotheses on x and a), with the (alistp a) ; additional restriction that the (evl (hyp-fn x) a)) ; meaning of (hyp-fn x) is true in (equal (evl x a) ; the current context. That is, the (evl (fn x) a))) ; applicability of the transformation :rule-classes ; may be dependent upon some computed ((:meta :trigger-fns (nth foo)))) ; hypotheses. While our intention is that the set of ACL2 documentation topics is self-contained, readers might find it useful to see the following paper for an introduction to meta reasoning in ACL2. W. A. Hunt, Jr., R. B. Krug, M. Kaufmann, J S. Moore and E. W. Smith, ``Meta Reasoning in ACL2.'' TPHOLs 2005, ed. J. Hurd and T. F. Melham, LNCS 3603, Springer-Verlag, Berlin, 2005, pp. 163-178. A non-nil list of function symbols must be supplied as the value of the :trigger-fns field in a :meta rule class object (except that a macro alias can stand in for a function symbol; see [add-macro-alias]). General Forms: (implies (and (pseudo-termp x) ; this hyp is optional (alistp a) ; this hyp is optional (ev (hyp-fn x ...) a) ; this hyp is optional ; meta-extract hyps may also be included (see below) ) (equiv (ev x a) (ev (fn x ...) a))) where equiv is a known [equivalence] relation, x and a are distinct variable names, and ev is an evaluator function (see below), and fn is a function symbol, as is hyp-fn when provided. The arguments to fn and hyp-fn should be identical. In the most common case, both take a single argument, x, which denotes the term to be simplified. If fn and/or hyp-fn are [guard]ed, their [guard]s should be trivially implied by [pseudo-termp]. We say the theorem above is a ``metatheorem'' or ``metalemma'' and fn is a ``metafunction'', and hyp-fn is a ``hypothesis metafunction''. If ``...'' is empty, i.e., the metafunctions take just one argument, we say they are ``vanilla flavored.'' If ``...'' is non-empty, we say the metafunctions are ``extended.'' Extended metafunctions can access [state] and context sensitive information to compute their results, within certain limits. We discuss vanilla metafunctions here and recommend a thorough understanding of them before proceeding (at which time see [extended-metafunctions]). If a metafunction application to a term, u, evaluates to a result of the form (if TEST NEW-TERM u), then TEST is treated as an ``implicit hypothesis''. For discussion of this relatively advanced feature, see [meta-implicit-hypothesis]. Additional hypotheses are supported, called ``meta-extract hypotheses''. These allow metafunctions to depend on the validity of certain terms extracted from the context or the logical [world]. These hypotheses provide a relatively advanced form of metatheorem so we explain them elsewhere; see [meta-extract]. One might think that metafunctions and (if supplied) hypothesis metafunctions must be executable: that is, not constrained (i.e., introduced in the [signature] of [encapsulate] [events]), and not [declare]d :[non-executable]. After all, there is no point in installing a simplifier that cannot be run! However, such a restriction is not enforced, because one could introduce a metafunction using [encapsulate] and then use [defattach] to attach it to an executable function; see [defattach]. We defer discussion of the case in which there is a hypothesis metafunction and for now address the case in which the other two hypotheses are present. In the discussion below, we refer to the argument, x, of fn and hyp-fn as a ``(translated) term,'' i.e., an object satisfying the ACL2 built-in predicate termp. When these metafunctions are executed by the simplifier, they will be applied to (the quotations of) terms. But during the proof of the metatheorem itself, x may not be the quotation of a term. If the [pseudo-termp] hypothesis is omitted, x may be any object. Even with the [pseudo-termp] hypothesis, x may merely ``look like a term'' but use non-function symbols or function symbols of incorrect arity. In any case, the metatheorem is stronger than necessary to allow us to apply the metafunctions to terms, as we do in the discussion below. We return later to the question of proving the metatheorem. Suppose the general form of the metatheorem above is proved with the [pseudo-termp] and [alistp] hypotheses. Then when the simplifier encounters a term, (h t1 ... tn), that begins with a function symbol, h, listed in :trigger-fns, it applies the metafunction, fn, to the quotation of the term, i.e., it evaluates (fn '(h t1 ... tn)) to obtain some result, which can be written as 'val. If 'val is different from '(h t1 ... tn) and val is a term, then (h t1 ... tn) is replaced by val, which is then passed along for further rewriting. Because the metatheorem establishes the correctness of fn for all terms (even non-terms!), there is no restriction on which function symbols are listed in the :trigger-fns. Generally, of course, they should be the symbols that head up the terms simplified by the metafunction fn. Note that the result of applying a metafunction (or a hypothesis metafunction) must be a term. If not, then an error occurs. See [term-table] for how one obtains some assistance towards guaranteeing that val is indeed a term. ACL2 actually enforces a stronger requirement, disallowing calls of certain ``forbidden'' function symbols; see [set-skip-meta-termp-checks]. The ``evaluator'' function, ev, is a function that can evaluate a certain class of expressions, namely, all of those composed of variables, constants, and applications of a fixed, finite set of function symbols, g1, ..., gk. Generally speaking, the set of function symbols handled by ev is chosen to be exactly the function symbols recognized and manipulated by the metafunctions being introduced. For example, if fn manipulates expressions in which '[equal] and '[binary-append] occur as function symbols, then ev is generally specified to handle [equal] and [binary-append]. The actual requirements on ev become clear when the metatheorem is proved. The standard way to introduce an evaluator is to use the ACL2 macro [defevaluator], though this is not strictly necessary. See [defevaluator] if you want details. [Aside for the logic-minded.] Why are we justified in using metafunctions this way? Suppose (fn 'term1) is 'term2. What justifies replacing term1 by term2? The first step is to assert that term1 is (ev 'term1 a), where a is an alist that maps 'var to var, for each variable var in term1. This step is incorrect, because 'term1 may contain function symbols other than the ones, g1, ..., gk, that ev knows how to handle. But we can grow ev to a ``larger'' evaluator, ev*, an evaluator for all of the symbols that occur in term1 or term2. We can prove that ev* satisfies the [constraint]s on ev, provided no [defaxiom] events are adding constraints to ev (or callers of ev, and recursively); ACL2 checks this additional property. Hence, the metatheorem holds for ev* in place of ev, by functional instantiation. We can then carry out the proof of the [equivalence] of term1 and term2 as follows: Fix a to be an alist that maps the quotations of the variables of term1 and term2 to themselves. Then, term1 = (ev* 'term1 a) ; (1) by construction of ev* and a = (ev* (fn 'term1) a) ; (2) by the metatheorem for ev* = (ev* 'term2 a) ; (3) by evaluation of fn = term2 ; (4) by construction of ev* and a Note that in line (2) above, where we appeal to the (functional instantiation of the) metatheorem, we can relieve its (optional) [pseudo-termp] and [alistp] hypotheses by appealing to the facts that term1 is a term and a is an alist by construction. [End of Aside for the logic-minded.] There are subtleties related to the notion of ``growing'' ev to a ``larger'' evaluator, as mentioned in the paragraph just above. For corresponding restrictions on :meta rules, see [evaluator-restrictions]. Finally, we turn to the second case, in which there is a hypothesis metafunction. In that case, consider as before what happens when the simplifier encounters a term, (h t1 ... tn), where h is listed in :trigger-fns. This time, after it applies fn to '(h t1 ... tn) to obtain the quotation of some new term, 'val, it then applies the hypothesis metafunction, hyp-fn. That is, it evaluates (hyp-fn '(h t1 ... tn)) to obtain some result, which can be written as 'hyp-val. If hyp-val is not in fact a term, the metafunction is not used. Provided hyp-val is a term, the simplifier attempts to establish (by conventional backchaining) that this term is non-nil in the current context. Note that this backchaining is done just as it is done for hypotheses of [rewrite] (and [linear]) rules, namely, by rewriting with special attention to calls of certain functions including [force], [case-split], [syntaxp], and [bind-free]. If this attempt to establish this term fails, then the meta rule is not applied. Otherwise, (h t1...tn) is replaced by val as in the previous case (where there was no hypothesis metafunction). Why is it justified to make this extension to the case of hypothesis metafunctions? First, note that the rule (implies (and (pseudo-termp x) (alistp a) (ev (hyp-fn x) a)) (equal (ev x a) (ev (fn x) a))) is logically equivalent to the rule (implies (and (pseudo-termp x) (alistp a)) (equal (ev x a) (ev (new-fn x) a))) where (new-fn x) is defined to be (list 'if (hyp-fn x) (fn x) x). (If we're careful, we realize that this argument depends on making an extension of ev to an evaluator ev* that handles [if] and the functions manipulated by hyp-fn.) If we write 'term for the quotation of the present term, and if (hyp-fn 'term) and (fn 'term) are both terms, say hyp1 and term1, then by the previous argument we know it is sound to rewrite term to (if hyp1 term1 term). But since we have established in the current context that hyp1 is non-nil, we may simplify (if hyp1 term1 term) to term1, as desired. We now discuss the role of the [pseudo-termp] hypothesis. (Pseudo-termp x) checks that x has the shape of a term. Roughly speaking, it ensures that x is a symbol, a quoted constant, or a true list consisting of a lambda expression or symbol followed by some pseudo-terms. Among the properties of terms not checked by [pseudo-termp] are that variable symbols never begin with ampersand, lambda expressions are closed, and function symbols are applied to the correct number of arguments. See [pseudo-termp]. There are two possible roles for [pseudo-termp] in the development of a metatheorem: it may be used as the [guard] of the metafunction and/or hypothesis metafunction and it may be used as a hypothesis of the metatheorem. Generally speaking, the [pseudo-termp] hypothesis is included in a metatheorem only if it makes it easier to prove. The choice is yours. (An extreme example of this is when the metatheorem is invalid without the hypothesis!) We therefore address ourselves the question: should a metafunction have a [pseudo-termp] [guard]? A [pseudo-termp] [guard] for a metafunction, in connection with other considerations described below, improves the efficiency with which the metafunction is used by the simplifier. To make a metafunction maximally efficient you should (a) provide it with a [pseudo-termp] [guard] and exploit the [guard] when possible in coding the body of the function (see [guards-and-evaluation], especially the section on efficiency issues), (b) verify the [guard]s of the metafunction (see [verify-guards]), and (c) compile the metafunction (see [comp]). When these three steps have been taken the simplifier can evaluate (fn 'term1) by running the compiled ``primary code'' (see [guards-and-evaluation]) for fn directly in Common Lisp. (Note however that explicit compilation may be suppressed; see [compilation].) Before discussing efficiency issues further, let us review for a moment the general case in which we wish to evaluate (fn 'obj) for some :[logic] function. We must first ask whether the [guard]s of fn have been verified. If not, we must evaluate fn by executing its logic definition. This effectively checks the [guard]s of every subroutine and so can be slow. If, on the other hand, the [guard]s of fn have been verified, then we can run the primary code for fn, provided 'obj satisfies the [guard] of fn. So we must next evaluate the [guard] of fn on 'obj. If the [guard] is met, then we run the primary code for fn, otherwise we run the logic code. Now in the case of a metafunction for which the three steps above have been followed, we know the [guard] is (implied by) [pseudo-termp] and that it has been verified. Furthermore, we know without checking that the [guard] is met (because term1 is a term and hence 'term1 is a [pseudo-termp]). Hence, we can use the compiled primary code directly. We strongly recommend that you compile your metafunctions, as well as all their subroutines (unless explicit compilation is suppressed; see [compilation]). Guard verification is also recommended. Finally, we present a very simple example of the use of :meta rules, based on one provided by Robert Krug. This example illustrates a trick for avoiding undesired rewriting after applying a metafunction or any other form of rewriting. To elaborate: in general, the term t2 obtained by applying a metafunction to a term t1 is then handed immediately to the rewriter, which descends recursively through the arguments of function calls to rewrite t2 completely. But if t2 shares a lot of structure with t1, then it might not be worthwhile to rewrite t2 immediately. (A rewrite of t2 will occur anyhow the next time a goal is generated.) The trick involves avoiding this rewrite by wrapping t2 inside a call of [hide], which in turn is inside a call of a user-defined ``unhiding'' function, unhide. (defun unhide (x) (declare (xargs :guard t)) x) (defthm unhide-hide (equal (unhide (hide x)) x) :hints ((\"Goal\" :expand ((hide x))))) (in-theory (disable unhide)) (defun my-plus (x y) (+ x y)) (in-theory (disable my-plus)) (defevaluator evl evl-list ((my-plus x y) (binary-+ x y) (unhide x) (hide x))) (defun meta-fn (term) (declare (xargs :guard (pseudo-termp term))) (if (and (consp term) (equal (length term) 3) (equal (car term) 'my-plus)) `(UNHIDE (HIDE (BINARY-+ ,(cadr term) ,(caddr term)))) term)) (defthm my-meta-lemma (equal (evl term a) (evl (meta-fn term) a)) :hints ((\"Goal\" :in-theory (enable my-plus))) :rule-classes ((:meta :trigger-fns (my-plus)))) Notice that in the following (silly) conjecture, ACL2 initially does only does the simplification directed by the metafunction; a second goal is generated before the commuativity of addition can be applied. If the above calls of UNHIDE and HIDE had been stripped off, then Goal' would have been the term printed in Goal'' below. ACL2 !>(thm (equal (my-plus b a) ccc)) This simplifies, using the :meta rule MY-META-LEMMA and the :rewrite rule UNHIDE-HIDE, to Goal' (EQUAL (+ B A) CCC). This simplifies, using the :rewrite rule COMMUTATIVITY-OF-+, to Goal'' (EQUAL (+ A B) CCC). The discussion above probably suffices to make good use of this (UNHIDE (HIDE ...)) trick. However, we invite the reader who wishes to understand the trick in depth to evaluate the following form before submitting the [thm] form above. (trace$ (rewrite :entry (list (take 2 arglist)) :exit (list (car values))) (rewrite-with-lemma :entry (list (take 2 arglist)) :exit (take 2 values))) The following annotated subset of the trace output (which may appear a bit different depending on the underlying Common Lisp implementation) explains how the trick works. 2> (REWRITE ((MY-PLUS B A) NIL))> 3> (REWRITE-WITH-LEMMA ((MY-PLUS B A) (REWRITE-RULE (:META MY-META-LEMMA) 1822 NIL EQUAL META-FN NIL META NIL NIL)))> We apply the meta rule, then recursively rewrite the result, which is the (UNHIDE (HIDE ...)) term shown just below. 4> (REWRITE ((UNHIDE (HIDE (BINARY-+ B A))) ((A . A) (B . B))))> 5> (REWRITE ((HIDE (BINARY-+ B A)) ((A . A) (B . B))))> The HIDE protects its argument from being touched by the rewriter. <5 (REWRITE (HIDE (BINARY-+ B A)))> 5> (REWRITE-WITH-LEMMA ((UNHIDE (HIDE (BINARY-+ B A))) (REWRITE-RULE (:REWRITE UNHIDE-HIDE) 1806 NIL EQUAL (UNHIDE (HIDE X)) X ABBREVIATION NIL NIL)))> Now we apply UNHIDE-HIDE, then recursively rewrite its right-hand side in an environment where X is bound to (BINARY-+ B A). 6> (REWRITE (X ((X BINARY-+ B A))))> Notice that at this point X is cached, so REWRITE just returns (BINARY-+ B A). <6 (REWRITE (BINARY-+ B A))> <5 (REWRITE-WITH-LEMMA T (BINARY-+ B A))> <4 (REWRITE (BINARY-+ B A))> <3 (REWRITE-WITH-LEMMA T (BINARY-+ B A))> <2 (REWRITE (BINARY-+ B A))> Subtopics [Backchain-limit] Limiting the effort expended on relieving hypotheses [Case-split] Like force but immediately splits the top-level goal on the hypothesis [Evaluator-restrictions] Some restrictions on the use of evaluators in meta-level rules [Extended-metafunctions] State and context sensitive metafunctions [Force] Identity function used to force a hypothesis [Meta-extract] Meta reasoning using valid terms extracted from context or [world] [Meta-implicit-hypothesis] A potentially more efficient way of coding a hypothesis metafunction [Set-skip-meta-termp-checks] Skip output checks for [meta] functions and [clause-processor]s [Set-skip-meta-termp-checks!] Skip output checks non-[local]ly for [meta] functions and [clause-processor]s [Syntaxp] Attach a heuristic filter on a rule [Term-table] A table used to validate meta rules") (META-EXTRACT (META) "Meta reasoning using valid terms extracted from context or [world] For this advanced topic, we assume familiarity with metatheorems and metafunctions (see [meta]), as well as extended metafunctions (see [extended-metafunctions]). The capability described here --- so-called ``meta-extract hypotheses'' for a :[meta] or a :[clause-processor] rule --- provides an advanced form of meta-level reasoning that was initially designed largely by Sol Swords, who also provided a preliminary implementation. A meta rule or clause-processor rule may have so-called ``meta-extract'' hypotheses that take forms displayed below. Here evl is the evaluator, obj is an arbitrary term, mfc is the metafunction context (which is a variable other than the symbol STATE that represents the metafunction context; see [extended-metafunctions]), state is literally the symbol STATE, a is the second argument of evl in both arguments of the conclusion of the rule, and aa is an arbitrary term. (evl (meta-extract-contextual-fact obj mfc state) a) (evl (meta-extract-global-fact obj state) aa)) ; equivalent to the next form (evl (meta-extract-global-fact+ obj state state) aa) (evl (meta-extract-global-fact+ obj st state) aa) The first form is only legal for :meta rules for which the metafunction is an extended metafunction. The remaining forms are legal for both :meta rules and :clause-processor rules. Sol Swords has contributed a community book, clause-processors/meta-extract-user.lisp, that uses a Skolemization trick to allow one to use at most one meta-extract-global-fact+ hypothesis and at most one meta-extract-contextual-fact hypothesis. These additional hypotheses may be necessary in order to prove a proposed metatheorem or (for the second type of hypothesis above) clause-processor rule, in particular when the correctness of the metafunction depends on the correctness of utilities extracting formulas from the logical [world] or (for the first type) facts from the metafunction context (mfc). After the rule is proved, however, the meta-extract hypotheses have no effect on how the rule is applied during a proof. An argument for correctness of using meta-extract hypotheses is given in the ACL2 source code within a comment entitled ``Essay on Correctness of Meta Reasoning''. In the documentation below, we focus primarily on :[meta] rules, since the use of meta-extract-global-fact hypotheses in :[clause-processor] rules is entirely analogous. (At the end, though, we discuss the last of the four forms displayed above.) And for :meta rules we focus not on the application of rules but, rather, on how the use of meta-extract hypotheses allow you to prove correctness of metafunctions that use facts from the logical [world] or the metafunction context (mfc). Below we describe properties of meta-extract-contextual-fact and meta-extract-global-fact, but only after we illustrate their utility with an example. But even before we present that example, we first give a sense of how to think about these functions by showing a theorem that one can prove about the first of them. If this snippet doesn't help your intuition, then just skip over it and start with the example. (defevaluator evl evl-list ((binary-+ x y) (typespec-check x y))) (thm (implies (not (bad-atom (cdr (assoc-equal 'x alist)))) (equal (evl (meta-extract-contextual-fact (list :typeset 'x) mfc state) alist) (not (equal 0 ; indicates non-empty intersection (logand (type-set-quote ; type-set of a constant (cdr (assoc-equal 'x alist))) (mfc-ts-fn 'x mfc state nil))))))) The following example comes from the community book, books/clause-processors/meta-extract-simple-test.lisp (after it defines the evaluator), which presents very basic (and contrived) examples that nevertheless illustrate meta-extract hypotheses. (defthm plus-identity-2-meta (implies (and (nthmeta-ev (meta-extract-global-fact '(:formula bar-posp) state) (list (cons 'u (nthmeta-ev (cadr (cadr term)) a)))) (nthmeta-ev (meta-extract-contextual-fact `(:typeset ,(caddr term)) mfc state) a)) (equal (nthmeta-ev term a) (nthmeta-ev (plus-identity-2-metafn term mfc state) a))) :rule-classes ((:meta :trigger-fns (binary-+)))) The two hypotheses illustratate the two basic kinds of meta-extract hypotheses: applications of the evaluator to a call of meta-extract-global-fact and to a call of meta-extract-contextual-fact. Here is the definition of the metafunction used in the above rule, slightly simplified here from what is found in the above book (but adequate for proving the two events that follow it in the above book). (defun plus-identity-2-metafn (term mfc state) (declare (xargs :stobjs state :verify-guards nil)) (case-match term (('binary-+ ('bar &) y) (cond ((equal (meta-extract-formula 'bar-posp state) '(POSP (BAR U))) (if (ts= (mfc-ts y mfc state :forcep nil) *ts-character*) (cadr term) term)) (t term))) (& term))) This metafunction returns its input term unchanged except in the case that the term is of the form (binary-+ (bar x) y) and the following two conditions are met, in which case it returns (bar x). (1) (equal (meta-extract-formula 'bar-posp state) '(POSP (BAR U))) (2) (ts= (mfc-ts y mfc state :forcep nil) *ts-character*) So suppose that term is (list 'binary-+ (list 'bar x) y). We show how the meta-extract hypotheses together with (1) and (2) imply that the conclusion of the above :meta rule holds. Here is that conclusion after a bit of simplification. (equal (nthmeta-ev (list 'binary-+ (list 'bar x) y) a) (nthmeta-ev (list 'bar x) a)) This equality simplifies as follows using the evaluator properties of nthmeta-ev. (equal (binary-+ (bar (nthmeta-ev x a)) (nthmeta-ev y a)) (bar (nthmeta-ev x a))) Since a positive number plus a character is that number, it clearly suffices to show: (A) (posp (bar (nthmeta-ev x a))) (B) (characterp (nthmeta-ev y a)) It remains then to show that these follow from (1) and (2) together with the meta-extract hypotheses. First consider (A). We show that it is just a simplification of the first meta-extract hypothesis. (nthmeta-ev (meta-extract-global-fact '(:formula bar-posp) state) (list (cons 'u (nthmeta-ev (cadr (cadr term)) a)))) = {by our assumption that term is (list 'binary-+ (list 'bar x) y)} (nthmeta-ev (meta-extract-global-fact '(:formula bar-posp) state) (list (cons 'u (nthmeta-ev x a)))) = {by definition of meta-extract-global-fact, as discussed later} (nthmeta-ev (meta-extract-formula 'bar-posp state) (list (cons 'u (nthmeta-ev x a)))) = {by (1)} (nthmeta-ev '(posp (bar u)) (list (cons 'u (nthmeta-ev x a)))) = {by evaluator properties of nthmeta-ev} (posp (bar (nthmeta-ev x a))) Now consider (B). We show that it is just a simplification of the second meta-extract hypothesis. (nthmeta-ev (meta-extract-contextual-fact `(:typeset ,(caddr term)) mfc state) a) = {by our assumption that term is (list 'binary-+ (list 'bar x) y)} (nthmeta-ev (meta-extract-contextual-fact (list ':typeset y) mfc state) a) = {by definition of meta-extract-contextual-fact, as discussed later} (nthmeta-ev (list 'typespec-check (list 'quote (mfc-ts y mfc state :forcep nil)) y) a) = {by (2)} (nthmeta-ev (list 'typespec-check (list 'quote *ts-character*) y) a) = {by evaluator properties of nthmeta-ev} (typespec-check *ts-character* (nthmeta-ev y a)) = {by definition of typespec-check} (characterp (nthmeta-ev y a)) Note the use of :forcep nil above. All of the mfc-xx functions take a keyword argument :forcep. Calls of mfc-xx functions made on behalf of meta-extract-contextual-fact always use :forcep nil, so in order to reason about these calls in your own metafunctions, you will want to use :forcep nil. We have contemplated adding a utility like meta-extract-contextual-fact that allows forcing but returns a tag-tree (see [ttree]), and may do so if there is demand for it. Finally, we document what is provided logically by calls of meta-extract-global-fact and meta-extract-contextual-fact. Of course, you are invited to look at the definitions of these function in the ACL2 source code, or by using :[pe]. Note that both of these functions are non-executable (each of their bodies is inside a call of [non-exec]); their purpose is purely logical, not for execution. The functions return *t*, i.e., (quote t), in cases that they provide no information. First we consider the value of (meta-extract-global-fact obj state) for various values of obj. When we refer below to concepts like ``body'' and ``evaluation'', we refer to these with respect to the logical world of the input state. Case obj = (list :formula FN): The value reduces to the value of (meta-extract-formula FN state), which returns the ``formula'' of FN in the following sense. If FN is a function symbol with formals (X1 ... Xk), then the formula is the [constraint] on FN if FN is constrained or introduced by [defchoose], and otherwise is (equal (FN X1 ... Xk) BODY), where BODY is the (unsimplified) body of the definition of FN. Otherwise, if FN is the name of a theorem, the formula is just what is stored for that theorem. Otherwise, the formula is *t*. Case obj = (list :lemma FN N): Assume N is a natural number; otherwise, treat N as 0. If FN is a function symbol with more than N associated lemmas --- ``associated'' in the sense of being either a :[definition] rule for FN or a :[rewrite] rule for FN whose left-hand side has a top function symbol of FN --- then the value is the Nth such lemma (with zero-based indexing). Otherwise the value is *t*. Case obj = (list :fncall FN ARGLIST): Assume that FN is a :[logic]-mode function symbol and that ARGLIST is a true list of values of the same length as list of formal parameters for FN (i.e., as the input arity of FN). Also assume that the application of FN to actual parameter list ARGLIST returns a result (mv nil x). Let (QARG1 ... QARGk) be the result of quoting each element of ARGLIST, i.e., replacing each y in ARGLIST by the two-element list (quote y). Then the value is the term (equal (FN QARG1 ... QARGk) (quote x)). For any other values of obj, the value is *t*. Finally, the value of (meta-extract-contextual-fact obj mfc state) is as follows for various values of obj. Note a difference from the semantics of meta-extract-global-fact: below, the relevant logical world is the one stored in the metafunction context, mfc, not in the input state. Case obj = (list :typeset TERM ...): The value is the value of (typespec-check ts TERM), where ts is the value of (mfc-ts TERM mfc state :forcep nil :ttreep nil), and where (typespec-check ts val) is defined to be true when val has type-set ts. (Exception: If val satisfies bad-atom then typespec-check is true when ts is negative.) Case obj = (list :rw+ TERM ALIST OBJ EQUIV ...): We assume below that EQUIV is a symbol that represents an equivalence relation, where nil represents [equal], t represents [iff], and otherwise EQUIV represents itself (an equivalence relation in the current logical [world]). For any other EQUIV the value is *t*. Now let rhs be the value of (mfc-rw+ TERM ALIST OBJ EQUIV mfc state :forcep nil :ttreep nil). Then the value is the term (list 'equv (sublis-var ALIST TERM) rhs), where equv is the equivalence relation represented by EQUIV, and sublis-var is defined to substitute a variable-binding alist into a term. Case obj = (list :rw TERM OBJ EQUIV ...): The value is the same as above but for an ALIST of nil, i.e., for the case that obj is (list :rw+ TERM nil OBJ EQUIV ...). Case obj = (list :ap TERM ...): The value is (list 'not TERM) if (mfc-ap TERM mfc state :forcep nil) is true, else is *t*. Case obj = (list :relieve-hyp HYP ALIST RUNE TARGET BKPTR ...): The value is (sublis-var alist hyp) --- see above for a discussion of sublis-var --- if the following is true. (mfc-relieve-hyp hyp alist rune target bkptr mfc state :forcep nil :ttreep nil) Otherwise the value is *t*. If no case above applies, then the value is *t*. We conclude by considering the fourth of the four forms above (and implicitly, its special case represented by the third form above): (evl (meta-extract-global-fact+ obj st state) aa) The discussion above is for the function meta-extract-global-fact+, but assumes that the logical [world]s of st and state are equal; otherwise the value returned is *t*. Of course, since a call of meta-extract-global-fact expands to a corresponding call of meta-extract-global-fact+ in which the last two arguments are both state, that condition holds automatically for that case. But the state mentioned in the meta-extract hypotheses of a [meta] rule or [clause-processor] rule is in essence an initial state. In the case of a clause-processor rule, the clause-processor function may modify that initial state (say, by printing or modifying some state globals) without changing its world, and then pass that modified state to fncall-term. While fncall-term may produce a different result for this modified state than for the initial state, both are valid: the state used for heuristic purposes, such as determining whether guard-checking may cause an error. A useful instance of the hypothesis displayed above will be one in which st is that modified state.") (META-EXTRACT-CONTEXTUAL-FACT (POINTERS) "See [meta-extract].") (META-EXTRACT-FORMULA (POINTERS) "See [meta-extract].") (META-EXTRACT-GLOBAL-FACT (POINTERS) "See [meta-extract].") (META-EXTRACT-GLOBAL-FACT+ (POINTERS) "See [meta-extract].") (META-EXTRACT-RW+-TERM (POINTERS) "See [meta-extract].") (META-IMPLICIT-HYPOTHESIS (META) "A potentially more efficient way of coding a hypothesis metafunction We assume familiarity with [meta] rules. In this topic, we discuss a relatively advanced capability of meta reasoning in ACL2 that can increase its efficiency. Introduction In brief: if a metafunction application to a term, u, evaluates to a result of the form (if TEST NEW-TERM u), then TEST is treated as an ``implicit hypothesis,'' which must rewrite to true in order for the meta rule to simplify the input term. We now explain in more detail. Recall the general form of a meta rule: (implies (and (pseudo-termp x) ; this hyp is optional (alistp a) ; this hyp is optional (ev (hyp-fn x ...) a) ; this hyp is optional ; meta-extract hyps may also be included (see below) ) (equiv (ev x a) (ev (fn x ...) a))) When this rule is to be applied to a term, x, then (hyp-fn x ...) is evaluated to produce a term, which must rewrite to true in order to evaluate the call (fn x ...), which is then rewritten to a replacement for x. But it may be that these calls of hyp-fn and fn share a sub-computation. ACL2 provides the ``implicit hypothesis'' mechanism in order to share such a sub-computation. The next section illustrates how this mechanism works. The final section provides a precise specification of implicit hypotheses and how they are used in metareasoning. Example The following example is trivial but illustrates the sort of situation for which implicit hypotheses can be useful. First let us introduce a function and an evaluator (see [defevaluator]). (defun foo (x y) (+ x y)) (defevaluator evl evl-list ((if x y z) (foo x y) (binary-+ x y) (unary-- x) (acl2-numberp x) (not x))) Let us write a meta function and associated hypothesis metafunction that apply a common function, meta-helper, to a term, term, to return one of two multiple values: (mv nil term) in the case that there is no simplification; else (mv hyp new-term), where the following is a theorem: `(implies ,hyp (equal ,term ,new-term)). Of course, the following definition introduces a function whose calls can be evaluated very quickly; but for purposes of this example, let us pretend that calls of meta-helper take a great deal of time to evaluate. (defun meta-helper (term) ; PRETEND that his function is expensive to compute! (declare (xargs :guard (pseudo-termp term))) (case-match term (('foo x ('foo y ('unary-- x))) (declare (ignore x)) (mv `(acl2-numberp ,y) y)) (& (mv nil term)))) We can now define our meta function and hypothesis metafunction and prove a meta rule based on them. (defun meta-fn (term) (declare (xargs :guard (pseudo-termp term))) (mv-let (hyp new-term) (meta-helper term) (if hyp new-term term))) (defun meta-hyp-fn (term) (declare (xargs :guard (pseudo-termp term))) (mv-let (hyp new-term) (meta-helper term) (declare (ignore new-term)) (or hyp ''nil))) (defthm meta-fn-correct (implies (evl (meta-hyp-fn x) a) (equal (evl x a) (evl (meta-fn x) a))) :rule-classes ((:meta :trigger-fns (foo)))) In order to see this meta rule in action, let us disable foo and try a little test. (in-theory (disable foo)) (defthm meta-fn-correct-test (implies (acl2-numberp b) (equal (foo a (foo b (- a))) b))) Happily, the test succeeds, with the summary showing that our meta rule, meta-fn-correct, was indeed used in the proof. But if we first submit the form (trace$ meta-fn meta-hyp-fn meta-helper), we will see that meta-helper is called twice on the term (FOO A (FOO B (UNARY-- A))): once on behalf of meta-fn and once on behalf of meta-hyp-fn. This would be unfortunate if meta-helper were expensive to compute. So let us back up and try a different approach, which illustrates the idea of using an ``implicit hypothesis'' in order to avoid recomputation. This time, we avoid defining a hypothesis metafunction, but instead we define meta-fn to return a term of the form (if TEST NEW-TERM term). Here, TEST is `(acl2-numberp ,y); we call this an ``implicit hypothesis.'' :ubt! meta-fn (defun meta-fn (term) (declare (xargs :guard (pseudo-termp term))) (mv-let (hyp new-term) (meta-helper term) (if hyp ; the interesting case `(if ,hyp ,new-term ,term) term))) There is nothing remarkable in the proof of the corresponding meta rule. (defthm meta-fn-correct (equal (evl x a) (evl (meta-fn x) a)) :rule-classes ((:meta :trigger-fns (foo)))) Let us test our new implementation. If we first evaluate the form (trace$ meta-fn meta-helper), we will see that this time, meta-helper is called only once on the term (FOO A (FOO B (UNARY-- A))). (in-theory (disable foo)) (defthm meta-fn-correct-test (implies (acl2-numberp b) (equal (foo a (foo b (- a))) b))) Note that the following proof attempt fails but does not loop. Naively, one might expect it to loop, since the false branch of the IF term returned by meta-fn has the original (input) term as its false branch. However, ACL2 notices the special form (if TEST NEW-TERM term) of the term returned by calling meta-fn, and treats this result as though TEST is the term returned by a hypothesis metafunction and NEW-TERM is the term returned by the metafunction. (thm ; FAILS but does not loop! (equal (foo a (foo b (- a))) b)) Suppose that instead we had defined meta-fn as follows, that is, with the `then' and `else' branches swapped. (defun meta-fn (term) (declare (xargs :guard (pseudo-termp term))) (mv-let (hyp new-term) (meta-helper term) (if hyp ; the interesting case ; `(if (not ,hyp) ,term ,new-term) term))) Then the events above go through as before, up to the [thm] form. But that form loops, because the generated IF term no longer has the special form (if TEST NEW-TERM term). In the (likely rare) case that really wishes to allow an unresolved case split for which one branch is the original term, this swapping of branches is available to defeat the recognition of an implicit hypothesis. Precise specification Consider a meta rule: (implies (and (pseudo-termp x) ; this hyp is optional (alistp a) ; this hyp is optional (ev (hyp-fn x ...) a) ; this hyp is optional ; meta-extract hyps may also be included (see below) ) (equiv (ev x a) (ev (fn x ...) a))) Recall that when this rule is applied to a term, term, then a list of hypotheses is initially generated as follows, where each generated hypothesis must be rewritten to a non-nil value in order for the rule to fire. 1. If there is a hypothesis metafunction, hyp-fn, then let hyps be the list of hypothesis terms returned by the call of hyp-fn on term. More precisely, the term returned by the call of hyp-fn is flattened into a list of ``hypothesis terms,'' so that for example the (translated) conjunction (if a (if b c 'nil) 'nil) generates the list (a b c) of hypothesis terms. 2. Otherwise, let hyps be nil. When this rule is applied by calling fn on a term, term, we say that a term, test, is an ``implicit hypothesis'' if the value returned by that call of fn is a term of the form (if test new-term term): that is, test is the test of the resulting if term and the input term is the false branch of that if term. In this case, ACL2 recognizes test as an implicit hypothesis, which triggers two changes made in how this meta rule is applied. First, hyps is extended by the flattened list of hypotheses generated from test. Second, instead of applying hyp-fn to the original term, term, hyp-fn is applied to new-term.") (MIN (NUMBERS ACL2-BUILT-INS) "The smaller of two numbers (Min x y) is the smaller of the numbers x and y. The [guard] for min requires its arguments to be rational ([real], in ACL2(r)) numbers. Min is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun min (x y) (declare (xargs :guard (and (real/rationalp x) (real/rationalp y)))) (if (< x y) x y))") (MINIMAL-THEORY (THEORIES THEORY-FUNCTIONS) "A minimal theory to enable This [theory] (see [theories]) enables only a few built-in functions and executable counterparts. It can be useful when you want to formulate lemmas that rather immediately imply the theorem to be proved, by way of a :use hint (see [hints]), for example as follows. :use (lemma-1 lemma-2 lemma-3) :in-theory (union-theories '(f1 f2) (theory 'minimal-theory)) In this example, we expect the current goal to follow from lemmas lemma-1, lemma-2, and lemma-3 together with rules f1 and f2 and some obvious facts about built-in functions (such as the [definition] of [implies] and the :[executable-counterpart] of [car]). The :[in-theory] hint above is intended to speed up the proof by turning off all inessential rules.") (MINUSP (NUMBERS ACL2-BUILT-INS) "Test whether a number is negative (Minusp x) is true if and only if x < 0. The [guard] of minusp requires its argument to be a rational ([real], in ACL2(r)) number. Minusp is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun minusp (x) (declare (xargs :guard (real/rationalp x))) (< x 0))") (MISCELLANEOUS (ACL2) "A miscellany of documented functions and concepts (often cited in more accessible [documentation]) Perhaps as the system matures this section will become more structured. Subtopics [ACL2-customization] File of initial commands for ACL2 to run at [startup] [Case-split-limitations] A list of two ``numbers'' limiting the number of cases produced at once [Dead-events] Using proof supporters to identify dead code and unused theorems [Default-defun-mode] The default [defun-mode] of [defun]'d functions [Gc$] Invoke the garbage collector [Gcl] Tips on building and using ACL2 based on Gnu Common Lisp [Hints] Advice to the theorem proving process [Ld] The ACL2 read-eval-print loop, file loader, and [command] processor [Local-incompatibility] When non-local [events] won't replay in isolation [Ordinals] Ordinals in ACL2 [Quick-and-dirty-subsumption-replacement-step] (advanced topic) controlling a heuristic in the prover's clausifier [Reader] Reading expressions in the ACL2 read-eval-print loop [Set-case-split-limitations] Set the case-split-limitations [Set-prover-step-limit] Sets the step-limit used by the ACL2 prover [Specious-simplification] Nonproductive proof steps [Subversive-inductions] Why we restrict [encapsulate]d recursive functions [Subversive-recursions] Why we restrict [encapsulate]d recursive functions [Syntax] The syntax of ACL2 is that of Common Lisp [Term] The three senses of well-formed ACL2 expressions or formulas [Thm] Prove a theorem [Top-level] Evaluate a top-level form as a function body [Ttags-seen] List some declared trust tags (ttags) [Ttree] Tag-trees [Type-set] How type information is encoded in ACL2 [With-prover-step-limit] Limit the number of steps for proofs [With-prover-time-limit] Limit the time for proofs") (MOD (NUMBERS ACL2-BUILT-INS) "Remainder using [floor] ACL2 !>(mod 14 3) 2 ACL2 !>(mod -14 3) 1 ACL2 !>(mod 14 -3) -1 ACL2 !>(mod -14 -3) -2 ACL2 !>(mod -15 -3) 0 ACL2 !> (Mod i j) is that number k that (* j (floor i j)) added to k equals i. The [guard] for (mod i j) requires that i and j are rational ([real], in ACL2(r)) numbers and j is non-zero. Mod is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun mod (x y) (declare (xargs :guard (and (real/rationalp x) (real/rationalp y) (not (eql y 0))))) (- x (* (floor x y) y)))") (MOD-EXPT (NUMBERS ACL2-BUILT-INS) "Exponential function (mod-expt r i m) is the result of raising the number r to the integer power i and then taking the residue mod m. That is, (mod-expt r i m) is equal to (mod (expt r i) m). The [guard] for (mod-expt r i m) is that r is a rational number and i is an integer; if r is 0 then i is nonnegative; and m is a non-zero rational number. In some implementations (GCL Version 2.7.0 as of this writing), this function is highly optimized when r and i are natural numbers, not both zero, and m is a positive integer. For other Lisp implementations, consider using function mod-expt-fast, defined in the community book arithmetic-3/floor-mod/mod-expt-fast.lisp, which should still provide significantly improved performance over this function. Function: (defun mod-expt (base exp mod) (declare (xargs :guard (and (real/rationalp base) (integerp exp) (not (and (eql base 0) (< exp 0))) (real/rationalp mod) (not (eql mod 0))))) (mod (expt base exp) mod))") (MODE (POINTERS) "See [xargs] for keyword :mode.") (MODELING_IN_ACL2 (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Modeling in ACL2 [{IMAGE}] {IMAGE} Below we define mc(s,n) to be the function that single-steps n times from a given starting state, s. In Common Lisp, ``mc(s,n)'' is written (mc s n). (defun mc (s n) ; To step s n times: (if (zp n) ; If n is 0 s ; then return s (mc (single-step s) (- n 1)))) ; else step single-step(s) n-1 times. This is an example of a formal model in ACL2. [{IMAGE}]") (MODELS_IN_ENGINEERING (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Models in Engineering {IMAGE} Frequently, engineers use mathematical models. Use of such models frequently lead to better designs, faster completion of acceptable products, and reduced overall cost, because models allow the trained user to study the design before it is built and analyze its properties. Usually, testing and analyzing a model is cheaper and faster than fabricating and refabricating the product. {IMAGE}") (MODELS_OF_COMPUTER_HARDWARE_AND_SOFTWARE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Models of Computer Hardware and Software [{IMAGE}] {IMAGE} Computing machines, whether hardware or software or some combintation, are frequently modeled as ``state machines.'' To so model a computing machine we must represent its states as objects in our mathematical framework. Transitions are functions or relations on state objects. In what language shall we define these objects, functions, and relations? The mathematical languages we were taught in high school algebra, geometry, trignometry, and calculus are often inappropriate for modeling digital systems. They primarily let us talk about numbers and continuous functions. To see what kind of expressive power we need, take a closer look at what a typical state contains. [{IMAGE}]") (MONITOR (BREAK-REWRITE) "To monitor the attempted application of a rule name Example: (monitor '(:rewrite assoc-of-app) 't) :monitor (:rewrite assoc-of-app) t :monitor (:definition app) (equal (brr@ :target) '(app c d)) :monitor (:linear rule3) t General Form: (monitor rune term) where rune is a [rune] and term is a term, called the ``break condition.'' Rune must be a rune corresponding to a rule of class :[rewrite], :[definition], or :[linear]. When a [rune] is [monitor]ed any attempt to apply it may result in an interactive break in an ACL2 ``[wormhole] [state].'' There you will get a chance to see how the application proceeds. See [break-rewrite] for a description of the interactive loop entered. Whether an interactive break occurs depends on the value of the break condition expression associated with the [monitor]ed [rune]. NOTE: Some :rewrite rules are considered ``simple abbreviations''; see [simple]. These can be be monitored, but only at certain times during the proof. Monitoring is carried out by code inside the rewriter but abbreviation rules may be applied by a special purpose simplifier inside the so-called preprocess phase of a proof. If you desire to monitor an abbreviation rule, a warning will be printed suggesting that you may want to supply the hint :DO-NOT '(PREPROCESS); see [hints]. Without such a hint, an abbreviation rule can be applied during the preprocess phase of a proof, and no such application will cause an interactive break. To remove a [rune] from the list of [monitor]ed [rune]s, use unmonitor. To see which [rune]s are [monitor]ed and what their break conditions are, evaluate (monitored-runes). Monitor, unmonitor and monitored-runes are macros that expand into expressions involving state. While these macros appear to return the list of [monitor]ed [rune]s this is an illusion. They all print [monitor]ed [rune] information to the comment window and then return error triples (see [error-triples]) instructing ld to print nothing. It is impossible to return the list of [monitor]ed [rune]s because it exists only in the [wormhole] [state] with which you interact when a break occurs. This allows you to change the [monitor]ed [rune]s and their conditions during the course of a proof attempt without changing the [state] in which the the proof is being constructed. Unconditional break points are obtained by using the break condition t. We now discuss conditional break points. The break condition, expr, must be a term that contains no free variables other than state and that returns a single non-state result. In fact, the result should be nil, t, or a true list of commands to be fed to the resulting interactive break. Whenever the system attempts to use the associated rule, expr is evaluated in the [wormhole] interaction [state]. A break occurs only if the result of evaluating expr is non-nil. If the result is a true list, that list is appended to the front of standard-oi and hence is taken as the initial user commands issued to the interactive break. In order to develop effective break conditions it must be possible to access context sensitive information, i.e., information about the context in which the [monitor]ed [rune] is being tried. The [brr@] macro may be used in break conditions to access such information as the term being rewritten and the current governing assumptions. This information is not stored in the proof [state] but is transferred into the [wormhole] [state] when breaks occur. The macro form is (brr@ :sym) where :sym is one of several keyword symbols, including :target (the term being rewritten), :unify-subst (the substitution that instantiates the left-hand side of the conclusion of the rule so that it is the target term), and :[type-alist] (the governing assumptions). See [brr@]. For example, ACL2 !>:monitor (:rewrite assoc-of-app) (equal (brr@ :target) '(app a (app b c))) will monitor (:rewrite assoc-of-app) but will cause an interactive break only when the target term, the term being rewritten, is (app a (app b c)). Because break conditions are evaluated in the interaction environment, the user developing a break condition for a given [rune] can test candidate break conditions before installing them. For example, suppose an unconditional break has been installed on a [rune], that an interactive break has occurred and that the user has determined both that this particular application is uninteresting and that many more such applications will likely occur. An appropriate response would be to develop an expression that recognizes such applications and returns nil. Of course, the hard task is figuring out what makes the current application uninteresting. But once a candidate expression is developed, the user can evaluate it in the current context simply to confirm that it returns nil. Recall that when a break condition returns a non-nil true list that list is appended to the front of standard-oi. For example, ACL2 !>:monitor (:rewrite assoc-of-app) '(:go) will cause (:rewrite assoc-of-app) to be [monitor]ed and will make the break condition be '(:go). This break condition always evaluates the non-nil true list (:go). Thus, an interactive break will occur every time (:rewrite assoc-of-app) is tried. The break is fed the command :go. Now the command :go causes break-rewrite to (a) evaluate the attempt to apply the lemma, (b) print the result of that attempt, and (c) exit from the interactive break and let the proof attempt continue. Thus, in effect, the above :monitor merely ``traces'' the attempted applications of the [rune] but never causes an interactive break requiring input from the user. It is possible to use this feature to cause a conditional break where the effective break condition is tested after the lemma has been tried. For example: ACL2 !>:monitor (:rewrite lemma12) '(:unify-subst :eval$ nil :ok-if (or (not (brr@ :wonp)) (not (equal (brr@ :rewritten-rhs) '(foo a)))) :rewritten-rhs) causes the following behavior when (:rewrite lemma12) is tried. A break always occurs, but it is fed the commands above. The first, :unify-subst, causes break-rewrite to print out the unifying substitution. Then in response to :eval$ nil the lemma is tried but with all [rune]s temporarily [unmonitor]ed. Thus no breaks will occur during the rewriting of the hypotheses of the lemma. When the attempt has been made, control returns to break-rewrite (which will print the results of the attempt, i.e., whether the lemma was applied, if so what the result is, if not why it failed). The next command, the :ok-if with its following expression, is a conditional exit command. It means exit break-rewrite if either the attempt was unsuccessful, (not (brr@ :wonp)), or if the result of the rewrite is any term other than (foo a). If this condition is met, the break is exited and the remaining break commands are irrelevant. If this condition is not met then the next command, :rewritten-rhs, prints the result of the application (which in this contrived example is known to be (foo a)). Finally, the list of supplied commands is exhausted but break-rewrite expects more input. Therefore, it begins prompting the user for input. The end result, then, of the above :monitor command is that the [rune] in question is elaborately traced and interactive breaks occur whenever it rewrites its target to (foo a). We recognize that the above break condition is fairly arcane. We suspect that with experience we will develop some useful idioms. For example, it is straightforward now to define macros that monitor [rune]s in the ways suggested by the following names: trace-rune, break-if-target-is, and break-if-result-is. For example, the last could be defined as (defmacro break-if-result-is (rune term) `(monitor ',rune '(quote (:eval :ok-if (not (equal (brr@ :rewritten-rhs) ',term)))))) (Note however that the submitted term must be in translated form.) Since we don't have any experience with this kind of control on lemmas we thought it best to provide a general (if arcane) mechanism and hope that the ACL2 community will develop the special cases that we find most convenient.") (MONITORED-RUNES (BREAK-REWRITE) "Print the [monitor]ed [rune]s and their break conditions Example and General Form: :monitored-runes This macro prints a list, each element of which is of the form (rune expr), showing each [monitor]ed [rune] and its current break condition.") (MSG (IO ACL2-BUILT-INS) "Construct a ``message'' suitable for the ~@ directive of [fmt] See [fmt] for background on formatted printing with ACL2. We document msg precisely below, but first, we give an informal introduction and illustrate with an example. Suppose you are writing a program that is to do some printing. Typically, you will either pass the ACL2 state around (see [programming-with-state]) and use formatted printing functions that take the state as an argument (see [fmt])), or else you might avoid using state by calling the utility, [cw], to do you printing. Alternatively, you might print error messages upon encountering illegal situations; see [er]. But there are times where instead of printing immediately, you may prefer to pass messages around, for example to accumulate them before printing a final message. In such cases, it may be desirable to construct ``message'' objects to pass around. For example, consider the following pair of little programs. The first either performs a computation or prints an error, and the second calls the first on two inputs. (defun invert1 (x) (if (consp x) (cons (cdr x) (car x)) (prog2$ (cw \"ERROR: ~x0 expected a cons, but was given ~x1.~|\" 'invert1 x) nil))) (defun invert2 (x1 x2) (list (invert1 x1) (invert1 x2))) For example: ACL2 !>(invert1 '(3 . 4)) (4 . 3) ACL2 !>(invert1 'a) ERROR: INVERT1 expected a cons, but was given A. NIL ACL2 !>(invert2 '(3 . 4) '(5 . 6)) ((4 . 3) (6 . 5)) ACL2 !>(invert2 'a 'b) ERROR: INVERT1 expected a cons, but was given A. ERROR: INVERT1 expected a cons, but was given B. (NIL NIL) ACL2 !> Notice that when there are errors, there is no attempt to explain that these are due to a call of invert2. That could be fixed, of course, by arranging for invert2 to print its own error; but for complicated programs it can be awkward to coordinate printing from many sources. So let's try a different approach. This time, the first function returns two results. The first result is an ``error indicator'' --- either a message object or nil --- while the second is the computed value (only of interest when the first result is nil). Then the higher-level function can print a single error message that includes the error message(s) from the lower-level function, as shown below. (defun invert1a (x) (if (consp x) (mv nil (cons (cdr x) (car x))) (mv (msg \"ERROR: ~x0 expected a cons, but was given ~x1.~|\" 'invert1a x) nil))) (defun invert2a (x1 x2) (mv-let (erp1 y1) (invert1a x1) (mv-let (erp2 y2) (invert1a x2) (if erp1 (if erp2 (cw \"~x0 failed with two errors:~| ~@1 ~@2\" 'invert2a erp1 erp2) (cw \"~x0 failed with one error:~| ~@1\" 'invert2a erp1)) (if erp2 (cw \"~x0 failed with one error:~| ~@1\" 'invert2a erp2) (list y1 y2)))))) For example: ACL2 !>(invert2a '(3 . 4) '(5 . 6)) ((4 . 3) (6 . 5)) ACL2 !>(invert2a '(3 . 4) 'b) INVERT2A failed with one error: ERROR: INVERT1A expected a cons, but was given B. NIL ACL2 !>(invert2a 'a 'b) INVERT2A failed with two errors: ERROR: INVERT1A expected a cons, but was given A. ERROR: INVERT1A expected a cons, but was given B. NIL ACL2 !> If you study the example above, you might well understand msg. But we conclude with precise documentation. General Form: (msg str arg1 ... argk) where str is a string and k is at most 9. This macro returns a pair suitable for giving to the fmt directive ~@. Thus, suppose that #\\c is bound to the value of (msg str arg1 ... argk), where c is a character and k is at most 9. Then the fmt directive ~@c will print out the string, str, in the context of the alist in which the successive fmt variables #\\0, #\\1, ..., #\\k are bound to the successive elements of (arg1 ... argk).") (MUST-BE-EQUAL (MBE ACL2-BUILT-INS) "Attach code for execution The form (must-be-equal logic exec) evaluates to logic in the ACL2 logic but evaluates to exec in raw Lisp. The point is to be able to write one definition to reason about logically but another for evaluation. Please see [mbe] and see [mbt] for appropriate macros to use, rather than calling must-be-equal directly, since it is easy to commute the arguments of must-be-equal by accident. In essence, the guard for (must-be-equal x y) is (equal x y). However, note that must-be-equal is a macro: (must-be-equal logic exec) expands to (mbe1 exec logic), which expands to a call of [return-last].") (MUTUAL-RECURSION (EVENTS PROGRAMMING DEFUN) "Define some mutually recursive functions Example: (mutual-recursion (defun evenlp (x) (if (consp x) (oddlp (cdr x)) t)) (defun oddlp (x) (if (consp x) (evenlp (cdr x)) nil))) General Form: (mutual-recursion def1 ... defn) where each defi is a call of [defun], [defund], [defun-nx], or defund-nx. When mutually recursive functions are introduced it is necessary to do the termination analysis on the entire clique of definitions. Each [defun] form specifies its own measure, either with the :measure keyword xarg (see [xargs]) or by default to [ACL2-count]. When a function in the clique calls a function in the clique, the measure of the callee's actuals must be smaller than the measure of the caller's formals --- just as in the case of a simply recursive function. But with mutual recursion, the callee's actuals are measured as specified by the callee's [defun] while the caller's formals are measured as specified by the caller's [defun]. These two measures may be different but must be comparable in the sense that [o<] decreases through calls. If you want to specify :[hints] or :guard-hints (see [xargs]), you can put them in the [xargs] declaration of any of the [defun] forms, as the :[hints] from each form will be appended together, as will the [guard-hints] from each form. You may find it helpful to use a lexicographic order, the idea being to have a measure that returns a list of two arguments, where the first takes priority over the second. Here is an example. (include-book \"ordinals/lexicographic-ordering\" :dir :system) (encapsulate () (set-well-founded-relation l<) ; will be treated as LOCAL (mutual-recursion (defun foo (x) (declare (xargs :measure (list (acl2-count x) 1))) (bar x)) (defun bar (y) (declare (xargs :measure (list (acl2-count y) 0))) (if (zp y) y (foo (1- y)))))) The [guard] analysis must also be done for all of the functions at the same time. If any one of the [defun]s specifies the :[verify-guards] xarg to be nil, then [guard] verification is omitted for all of the functions. Similarly, if any one of the [defun]s specifies the :non-executable xarg to be t, or if any of the definitions uses [defun-nx] or defund-nx, then every one of the definitions will be treated as though it specifies a :non-executable xarg of t. Technical Note: Each defi above must be a call of [defun], [defund], [defun-nx], or defund-nx. In particular, it is not permitted for a defi to be an arbitrary form that macroexpands into a [defun] form. This is because mutual-recursion is itself a macro, and since macroexpansion occurs from the outside in, at the time (mutual-recursion def1 ... defk) is expanded the defi have not yet been macroexpanded. Suppose you have defined your own [defun]-like macro and wish to use it in a mutual-recursion expression. Well, you can't. (!) But you can define your own version of mutual-recursion that allows your [defun]-like form. Here is an example. Suppose you define (defmacro my-defun (&rest args) (my-defun-fn args)) where my-defun-fn takes the arguments of the my-defun form and produces from them a [defun] form. As noted above, you are not allowed to write (mutual-recursion (my-defun ...) ...). But you can define the macro my-mutual-recursion so that (my-mutual-recursion (my-defun ...) ... (my-defun ...)) expands into (mutual-recursion (defun ...) ... (defun ...)) by applying my-defun-fn to each of the arguments of my-mutual-recursion. (defun my-mutual-recursion-fn (lst) (declare (xargs :guard (alistp lst))) ; Each element of lst must be a consp (whose car, we assume, is always ; MY-DEFUN). We apply my-defun-fn to the arguments of each element and ; collect the resulting list of DEFUNs. (cond ((atom lst) nil) (t (cons (my-defun-fn (cdr (car lst))) (my-mutual-recursion-fn (cdr lst)))))) (defmacro my-mutual-recursion (&rest lst) ; Each element of lst must be a consp (whose car, we assume, is always ; MY-DEFUN). We obtain the DEFUN corresponding to each and list them ; all inside a MUTUAL-RECURSION form. (declare (xargs :guard (alistp lst))) (cons 'mutual-recursion (my-mutual-recursion-fn lst))). Subtopics [Defuns] An alternative to [mutual-recursion] [Set-bogus-mutual-recursion-ok] Allow unnecessary ``mutual recursion''") (MUTUAL-RECURSION-PROOF-EXAMPLE (TUTORIAL5-MISCELLANEOUS-EXAMPLES) "A small proof about mutually recursive functions Sometimes one wants to reason about mutually recursive functions. Although this is possible in ACL2, it can be a bit awkward. This example is intended to give some ideas about how one can go about such proofs. For an introduction to mutual recursion in ACL2, see [mutual-recursion]. We begin by defining two mutually recursive functions: one that collects the variables from a [term], the other that collects the variables from a list of [term]s. We actually imagine the [term] argument to be a pseudo-termp; see [pseudo-termp]. (mutual-recursion (defun free-vars1 (term ans) (cond ((atom term) (add-to-set-eq term ans)) ((fquotep term) ans) (t (free-vars1-lst (cdr term) ans)))) (defun free-vars1-lst (lst ans) (cond ((atom lst) ans) (t (free-vars1-lst (cdr lst) (free-vars1 (car lst) ans))))) ) Now suppose that we want to prove the following theorem. (defthm symbol-listp-free-vars1-try-1 (implies (and (pseudo-termp x) (symbol-listp ans)) (symbol-listp (free-vars1 x ans)))) Often ACL2 can generate a proof by induction based on the structure of definitions of function symbols occurring in the conjecture. In this case, ACL2 chooses to use an induction scheme suggested by (symbol-listp ans), and sadly, that doesn't work. If one were doing this proof with pencil and paper, one would be more likely to prove a combination of the conjecture above and an analogous conjecture about free-vars1-lst. Feel free to try a pencil and paper proof! Or you can read on, to see how one can get ACL2 to do such a proof after all. The trick is to define a function that suggests an appropriate induction. The induction suggested is based on the if-then-else structure of the function's definition, where inductive hypotheses are generated for recursive calls --- below we explain how that works for this function. (defun symbol-listp-free-vars1-induction (x ans) (if (atom x) ; then we just make sure x and ans aren't considered irrelevant: (list x ans) (list (symbol-listp-free-vars1-induction (car x) ans) (symbol-listp-free-vars1-induction (cdr x) ans) (symbol-listp-free-vars1-induction (cdr x) (free-vars1 (car x) ans))))) The if-then-else structure of this function generates two cases. In one case, (atom x) is true, and the theorem to be proved should be proved under no additional hypotheses except for (atom x); in other words, (atom x) gives us the base case of the induction. In the other case, (not (atom x)) is assumed together with three instances of the theorem to be proved, one for each recursive call. So, one instance substitutes (car x) for x; one substitutes (cdr x) for x; and the third substitutes (cdr x) for x and (free-vars1 (car x) ans) for ans. If you think about how you would go about a hand proof of the theorem to follow, you'll likely come up with a similar scheme. We now prove the two theorems together as a conjunction, because the inductive hypotheses for one are sometimes needed in the proof of the other (even when you do this proof on paper!). (defthm symbol-listp-free-vars1 (and (implies (and (pseudo-termp x) (symbol-listp ans)) (symbol-listp (free-vars1 x ans))) (implies (and (pseudo-term-listp x) (symbol-listp ans)) (symbol-listp (free-vars1-lst x ans)))) :hints ((\"Goal\" :induct (symbol-listp-free-vars1-induction x ans)))) The above works, but we conclude by illustrating a more efficient approach, in which we restrict to appropriate inductive hypotheses for each case. (ubt 'symbol-listp-free-vars1-induction) (defun symbol-listp-free-vars1-induction (flg x ans) ; Flg is nil if we are ``thinking'' of a single term. (if (atom x) ; whether x is a single term or a list of terms (list x ans) (if flg ; i.e., if x is a list of terms (list (symbol-listp-free-vars1-induction nil (car x) ans) (symbol-listp-free-vars1-induction t (cdr x) (free-vars1 (car x) ans))) (symbol-listp-free-vars1-induction t (cdr x) ans)))) We now state the theorem as a conditional, so that it can be proved nicely using the [induction] scheme that we have just coded. The prover will not store an [if] [term] as a [rewrite] rule, but that's OK (provided we tell it not to try), because we're going to derive the corollaries of interest later and make them into [rewrite] rules. (defthm symbol-listp-free-vars1-flg (if flg (implies (and (pseudo-term-listp x) (symbol-listp ans)) (symbol-listp (free-vars1-lst x ans))) (implies (and (pseudo-termp x) (symbol-listp ans)) (symbol-listp (free-vars1 x ans)))) :hints ((\"Goal\" :induct (symbol-listp-free-vars1-induction flg x ans))) :rule-classes nil) And finally, we may derive the theorems we are interested in as immediate corollaries. (defthm symbol-listp-free-vars1 (implies (and (pseudo-termp x) (symbol-listp ans)) (symbol-listp (free-vars1 x ans))) :hints ((\"Goal\" :by (:instance symbol-listp-free-vars1-flg (flg nil))))) (defthm symbol-listp-free-vars1-lst (implies (and (pseudo-term-listp x) (symbol-listp ans)) (symbol-listp (free-vars1-lst x ans))) :hints ((\"Goal\" :by (:instance symbol-listp-free-vars1-flg (flg t))))) You may find [community-books] that help you to automate this kind of reasoning about mutually recursive functions. See for example [make-flag].") (MV (BASICS ACL2-BUILT-INS) "Returning a multiple value Mv is the mechanism provided by ACL2 for returning two or more values. Logically, (mv x1 x2 ... xn) is the same as (list x1 x2 ... xn), a list of the indicated values. However, ACL2 avoids the cost of building this list structure, with the cost that mv may only be used in a certain style in definitions: if a function ever returns using mv (either directly, or by calling another function that returns a multiple value), then this function must always return the same number of values. For more explanation of the multiple value mechanism, see [mv-let]. Also see [mv-list] for a way to convert a multiple value into an ordinary list. ACL2 does not support the Common Lisp construct values, whose logical meaning seems difficult to characterize. Mv is the ACL2 analogue of that construct. Subtopics [Mv-let] Calling multi-valued ACL2 functions [Mv-list] Converting multiple-valued result to a single-valued list [Mv-nth] The mv-nth element (zero-based) of a list [Mv?] Return one or more values [Mv?-let] Calling possibly multi-valued ACL2 functions") (MV-LET (MV ACL2-BUILT-INS) "Calling multi-valued ACL2 functions Example Form: (mv-let (x y z) ; local variables (mv 1 2 3) ; multi-valued expression (declare (ignore y)) ; optional declarations (cons x z)) ; body The form above binds the three ``local variables,'' x, y, and z, to the three results returned by the multi-valued expression and then evaluates the body. The result is '(1 . 3). The second local, y, is [declare]d ignored. The multi-valued expression can be any ACL2 expression that returns k results, where k is the number of local variables listed. Often however it is simply the application of a k-valued function. Mv-let is the standard way to invoke a multi-valued function when the caller must manipulate the vector of results returned. General Form: (mv-let (var1 ... vark) term body) or (mv-let (var1 ... vark) term (declare ...) ... (declare ...) body) where the vari are distinct variables, term is a term that returns k results and mentions only variables bound in the environment containing the mv-let expression, and body is a term mentioning only the vari and variables bound in the environment containing the mv-let. Each vari must occur in body unless it is [declare]d ignored or ignorable in one of the optional [declare] forms, unless this requirement is turned off; see [set-ignore-ok]. The value of the mv-let term is the result of evaluating body in an environment in which the vari are bound, in order, to the k results obtained by evaluating term in the environment containing the mv-let. Here is an extended example that illustrates both the definition of a multi-valued function and the use of mv-let to call it. Consider a simple binary tree whose interior nodes are [cons]es and whose leaves are non-[cons]es. Suppose we often need to know the number, n, of interior nodes of such a tree; the list, syms, of symbols that occur as leaves; and the list, ints, of integers that occur as leaves. (Observe that there may be leaves that are neither symbols nor integers.) Using a multi-valued function we can collect all three results in one pass. Here is the first of two definitions of the desired function. This definition is ``primitive recursive'' in that it has only one argument and that argument is reduced in size on every recursion. (defun count-and-collect (x) ; We return three results, (mv n syms ints) as described above. (cond ((atom x) ; X is a leaf. Thus, there are 0 interior nodes, and depending on ; whether x is a symbol, an integer, or something else, we return ; the list containing x in as the appropriate result. (cond ((symbolp x) (mv 0 (list x) nil)) ((integerp x)(mv 0 nil (list x))) (t (mv 0 nil nil)))) (t ; X is an interior node. First we process the car, binding n1, syms1, and ; ints1 to the answers. (mv-let (n1 syms1 ints1) (count-and-collect (car x)) ; Next we process the cdr, binding n2, syms2, and ints2. (mv-let (n2 syms2 ints2) (count-and-collect (car x)) ; Finally, we compute the answer for x from those obtained for its car ; and cdr, remembering to increment the node count by one for x itself. (mv (1+ (+ n1 n2)) (append syms1 syms2) (append ints1 ints2))))))) This use of a multiple value to ``do several things at once'' is very common in ACL2. However, the function above is inefficient because it [append]s syms1 to syms2 and ints1 to ints2, copying the list structures of syms1 and ints1 in the process. By adding ``accumulators'' to the function, we can make the code more efficient. (defun count-and-collect1 (x n syms ints) (cond ((atom x) (cond ((symbolp x) (mv n (cons x syms) ints)) ((integerp x) (mv n syms (cons x ints))) (t (mv n syms ints)))) (t (mv-let (n2 syms2 ints2) (count-and-collect1 (cdr x) (1+ n) syms ints) (count-and-collect1 (car x) n2 syms2 ints2))))) We claim that (count-and-collect x) returns the same triple of results as (count-and-collect1 x 0 nil nil). The reader is urged to study this claim until convinced that it is true and that the latter method of computing the results is more efficient. One might try proving the theorem (defthm count-and-collect-theorem (equal (count-and-collect1 x 0 nil nil) (count-and-collect x))). Hint: the inductive proof requires attacking a more general theorem. ACL2 does not support the Common Lisp construct multiple-value-bind, whose logical meaning seems difficult to characterize. Mv-let is the ACL2 analogue of that construct. Also see [mv] and see [mv-list].") (MV-LIST (MV ACL2-BUILT-INS) "Converting multiple-valued result to a single-valued list Example Forms: ; Returns the list (3 4): (mv-list 2 (mv 3 4)) ; Returns a list containing the three values returned by var-fn-count: (mv-list 3 (var-fn-count '(cons (binary-+ x y) z) nil)) General form: (mv-list n term) Logically, (mv-list n term) is just term; that is, in the logic mv-list simply returns its second argument. However, the evaluation of a call of mv-list on explicit values always results in a single value, which is a (null-terminated) list. For evaluation, the term n above (the first argument to an mv-list call) must ``essentially'' (see below) be an integer not less than 2, where that integer is the number of values returned by the evaluation of term (the second argument to that mv-list call). We say ``essentially'' above because it suffices that the translation of n to a term (see [trans]) be of the form (quote k), where k is an integer greater than 1. So for example, if term above returns three values, then n can be the expression 3, or (quote 3), or even (mac 3) if mac is a macro defined by (defmacro mac (x) x). But n cannot be (+ 1 2), because even though that expression evaluates to 3, nevertheless it translates to (binary-+ '1 '2), not to (quote 3). Mv-list is the ACL2 analogue of the Common Lisp construct multiple-value-list. Function: (defun mv-list (input-arity x) (declare (xargs :guard t) (ignore input-arity)) x)") (MV-NTH (MV ACL2-BUILT-INS) "The mv-nth element (zero-based) of a list (Mv-nth n l) is the nth element of l, zero-based. If n is greater than or equal to the length of l, then mv-nth returns nil. (Mv-nth n l) has a [guard] that n is a non-negative integer. Mv-nth is equivalent to the Common Lisp function [nth] (although without the guard condition that the list is a [true-listp]), but is used by ACL2 to access the nth value returned by a multiply valued expression. For example, the following are logically equivalent: (mv-let (erp val state) (read-object ch state) (value (list erp val))) and (let ((erp (mv-nth 0 (read-object ch state))) (val (mv-nth 1 (read-object ch state))) (state (mv-nth 2 (read-object ch state)))) (value (list erp val))) To see the ACL2 definition of mv-nth, see [pf]. If EXPR is an expression that is multiply valued, then the form (mv-nth n EXPR) is illegal both in definitions and in forms submitted directly to the ACL2 loop. Indeed, EXPR cannot be passed as an argument to any function (mv-nth or otherwise) in such an evaluation context. The reason is that ACL2 code compiled for execution does not actually create a list for multiple value return; for example, the read-object call above logically returns a list of length 3, but when evaluated, it instead stores its three returned values without constructing a list. In such cases you can use mv-nth to access the corresponding list by using mv-list, writing (mv-nth n (mv-list k EXPR)) for suitable k, where mv-list converts a multiple value result into the corresponding list; see [mv-list].") (MV? (MV ACL2-BUILT-INS) "Return one or more values Mv? is designed to work with mv?-let, generalizing how [mv] works with [mv-let] by allowing the binding of a single variable. For example, the following form is legal. (mv?-let (y) (mv? (f x)) (declare (type integer y)) (g x y z)) The expression above is equivalent to the following expression, because (mv? form) expands to form for any expression, form. (let ((y (f x))) (declare (type integer y)) (g x y z)) Logically, (mv? x) is the same as x, while (mv? v1 v2 ...) is the same as (list v1 v2 ...). Also see [mv] and see [mv?-let].") (MV?-LET (MV ACL2-BUILT-INS) "Calling possibly multi-valued ACL2 functions Mv?-let is a macro that extends the macro [mv-let] by allowing a single variable to be bound. Thus, the syntax is the same as that of [mv-let] except that mv?-let is permitted to bind a single variable to a form that produces a single value. The macros mv?-let and [mv?] are provided to facilitate the writing of macros that traffic in expressions that could return one or more (multiple) values. For example, the form (mv?-let (y) (f x) (declare (type integer y)) (g x y z)) is equivalent to the following form. (let ((y (f x))) (declare (type integer y)) (g x y z)) Calls of mv?-let and of [mv-let] are equivalent when the first argument contains at least two variables; see [mv-let] for documentation. In the case of binding a single variable, the general form is (mv?-let (var) term (declare ...) ... (declare ...) body) and this is equivalent to the following form (see [let]). (let ((var term)) (declare ...) ... (declare ...) body) Also see [mv?].") (NAME (EVENTS) "Syntactic rules on logical names Examples Counter-Examples PRIMEP 91 (not a symbolp) F-AC-23 :CHK-LIST (in KEYWORD package) 1AX *PACKAGE* (in the Lisp Package) |Prime Number| 1E3 (not a symbolp) Many different ACL2 entities have names, e.g., functions, macros, variables, constants, packages, theorems, [theories], etc. Package names are strings. All other names are symbols and may not be in the \"KEYWORD\" package. Moreover, names of functions, macros, constrained functions, and constants, other than those that are predefined, must not be in the ``main Lisp package'' (which is (\"LISP\" or \"COMMON-LISP\", according to whether we are following CLTL1 or CLTL2). An analogous restriction on variables is given below. T, nil, and all names above except those that begin with ampersand (&) are names of variables or constants. T, nil, and those names beginning and ending with star (*) are constants. All other such names are variables. Note that names that start with ampersand, such as &rest, may be lambda list keywords and are reserved for such use whether or not they are in the CLTL constant lambda-list-keywords. (See pg 82 of CLTL2.) That is, these may not be used as variables. Unlike constants, variables may be in the main Lisp package as long as they are in the original list of imports from that package to ACL2, the list *common-lisp-symbols-from-main-lisp-package*, and do not belong to a list of symbols that are potentially ``global.'' This latter list is the value of *common-lisp-specials-and-constants*. Our restrictions pertaining to the main Lisp package take into account that some symbols, e.g., lambda-list-keywords and boole-c2, are ``special.'' Permitting them to be bound could have harmful effects. In addition, the Common Lisp language does not allow certain manipulations with many symbols of that package. So, we stay away from them, except for allowing certain variables as indicated above.") (NAME_THE_FORMULA_ABOVE (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Name the Formula Above When the theorem prover explicitly assigns a name, like *1, to a formula, it has decided to prove the formula by induction.") (NAT-LISTP (NUMBERS LISTS ACL2-BUILT-INS) "Recognizer for a true list of natural numbers The predicate nat-listp tests whether its argument is a true list of natural numbers. Function: (defun nat-listp (l) (declare (xargs :guard t)) (cond ((atom l) (eq l nil)) (t (and (natp (car l)) (nat-listp (cdr l))))))") (NATP (NUMBERS ACL2-BUILT-INS) "A recognizer for the natural numbers The natural numbers is the set of all non-negative integers, {0,1,2,3,...}. Natp returns t if and only its argument is a natural number, and nil otherwise. The community book [arithmetic/natp-posp] has some lightweight rules for reasoning about posp and natp, and is included in the [arithmetic-1] library. For a somewhat heavier and more comprehensive alternative, you may wish to instead see the [arith-equivs] book. Function: (defun natp (x) (declare (xargs :guard t)) (and (integerp x) (<= 0 x)))") (NESTED-STOBJS (STOBJ) "Using [stobj]s that contain stobjs For this topic we assume that you already understand the basics of single-threaded objects in ACL2. See [stobj], and in particular, see [defstobj]. The latter topic mentions briefly that a stobj field can itself be a stobj or an array of stobjs. That discussion is the subject of the present [documentation] topic. Our presentation is in four sections. First we augment the documentation for [defstobj] by explaining how stobjs may be specified for fields in a new stobj definition. Then we explain an aliasing problem, which accounts for a prohibition against making direct calls to accessors and updaters involving stobj fields of stobjs. Next, we introduce an ACL2 primitive, stobj-let, which provides the only way to read and write stobj components of stobjs. The final section provides precise documentation for stobj-let. See also ACL2 community book demos/modeling/nested-stobj-toy-isa.lisp for a worked example, which applies nested stobj structures to the problem of defining interpreters. A variety of small additional examples may be found in ACL2 community book misc/nested-stobj-tests.lisp. For further discussion, you are welcome to read the ``Essay on Nested Stobjs'', a long comment in ACL2 source file other-events.lisp. However, this documentation topic is intended to be self-contained for those familiar with [stobj]s. SECTION: Extension of [defstobj] to permit [stobj]s within stobjs Recall that the :type keyword of a [defstobj] field descriptor can be a ``type-indicator'' that specifies the type of the field as a type-spec (see [type-spec]). For example, the following specifies an integer field and a field that is an array of bytes. (defstobj st (int-field :type integer :initially 0) (ar-field :type (array unsigned-byte (10)) :initially 0)) But the :type of a stobj field descriptor may instead be based on a stobj. For example, the following sequence of three [events] is legal. The first field descriptor of top, named sub1-field, illustrates one new kind of value for :type: the name of a previously-introduced stobj, which here is sub1. The second field descriptor of top, named sub2-ar-field, illustrates the other new kind of value for :type: an array whose elements are specified by the name of a previously-introduced stobj, in this case, the stobj sub2. (defstobj sub1 fld1) (defstobj sub2 fld2) (defstobj top (sub1-field :type sub1) (sub2-ar-field :type (array sub2 (10)))) The :initially keyword is illegal for fields whose :type is a stobj or an array of stobjs. Each such initial value is provided by a corresponding call of the stobj creator for that stobj. In particular, in the case of an array of stobjs, the stobj creator is called once for each element of the array, so that the array elements are distinct. For example, each element of sub2-ar-field in the example above is initially provided by a separate call of create-sub2. Each initial element is thus unique, and in particular is distinct from the initial global value of the stobj. Similarly, the initial global stobj for sub1 is distinct from the initial sub1-field field of the global stobj for top, as these result from separate calls of create-sub1. When a stobj is used in a field of another stobj, we may refer to the former field as a ``child stobj'' and the latter stobj as a ``parent stobj''. So in the example above, sub1-field is a child stobj of type sub1 for parent stobj top, and sub2-ar-field is an array of child stobjs of type sub2 for parent stobj top. A child stobj has the same structural shape as the global stobj of its type, but as explained above, these are distinct structures. We follow standard terminology by saying ``isomorphic'' to indicate the same structural shape. So for example, (the value of) sub1-field is isomorphic to sub1, though these are distinct structures. ACL2 enforces the following restriction, which can allow for greater efficiency in the raw Lisp code generated for stobj-let forms, as per the discussion below about clearing memoization tables. If the parent stobj is introduced by [defstobj] using keyword argument :non-memoizable t, then this is required to have been the case for every child stobj as well. SECTION: An aliasing problem Before introducing stobj-let below, we provide motivation for this ACL2 primitive. Consider the following [events]. (defstobj child fld) (defstobj parent (fld2 :type child)) Now suppose we could evaluate the following code, to be run immediately after admitting the two [defstobj] events above. (let* ((child (fld2 parent)) (child (update-fld 3 child))) (mv child parent)) Now logically there is no change to parent: parent is passed through unchanged. We can indeed prove that fact! (thm (equal (mv-nth 1 (let* ((child (fld2 parent)) (child (update-fld 3 child))) (mv child parent))) parent)) But recall that stobjs are updated with destructive assignments. That is, we really are updating (fld2 parent) to be the new value of child, whether this is explained logically or not. Thus, evaluation of the above [let*] form does in fact change the actual global stobj, parent. (Aside: Here is an explanation involving raw Lisp, for those who might find this useful. We escape to raw Lisp and execute the following; note that *the-live-parent* is the Lisp variable representing the global value of parent. (let ((parent *the-live-parent*)) (let* ((child (fld2 parent)) (child (update-fld 4 child))) (mv child parent))) Then, in raw Lisp, (fld (fld2 *the-live-parent*)) evaluates to 4, illustrating the destructive update. End of Aside.) Such aliasing can permit a change to a child stobj to cause a logically-inexplicable change to the parent stobj. Similarly, unfettered accessing of stobj fields can result in logically inexplicable changes to the child stobj when the parent stobj is changed. Thus, ACL2 disallows direct calls of stobj accessors and updaters for fields whose :type is a stobj or an array of stobjs. Instead, ACL2 provides stobj-let for reading and writing such fields in a sound manner. SECTION: Accessing and updating stobj fields of stobjs using stobj-let ACL2 provides a primitive, stobj-let, to access and update stobj fields of stobjs, in a manner that avoids the aliasing problem discussed above. In this section we provide an informal introduction to stobj-let, using examples, to be followed in the next section by precise documentation. We begin by returning to a slight variant of the example above. (defstobj child fld) (defstobj parent (fld2 :type child) fld3) The following form returns the result of updating the fld2 field of parent, which is a stobj isomorphic to child, to have a value of 3. Below we explain the terms ``bindings'', ``producer variables'', ``producer'', and ``consumer'', as well as how to understand this form. (stobj-let ((child (fld2 parent))) ; bindings (child) ; producer variable(s) (update-fld 3 child) ; producer (update-fld3 'a parent)) ; consumer The four lines under ``stobj-let'' just above can be understood as follows. * Bindings: Bind child to (fld2 parent). * Producer variable(s) and producer: Then bind the variable, child, to the value of the producer, (update-fld 3 child). * Implicit update of parent: Update fld2 of parent with the producer variable, child. * Consumer: Finally, return (update-fld3 'a parent). Thus, the logical expansion of the stobj-let form above is the following expression, though this is approximate (see below). (let ((child (fld2 parent))) ; bindings (let ((child (update-fld 3 child))) ; bind producer vars to producer (let ((parent (update-fld2 child parent))) ; implicit update of parent (update-fld3 'a parent)))) The bindings always bind distinct names to child stobjs of a unique parent stobj, where the child stobj corresponds to the :type associated with the indicated accessor in the [defstobj] form for the parent stobj. Thus in this case, for the unique binding, variable child is bound to the stobj of `type' child for accessor fld2 of the parent stobj, parent. We refer to child from the bindings as a ``stobj-let-bound variable''. Note also that the ``implicit extra step'' mentioned above is generated by macroexpansion of stobj-let; it logically updates the parent with new child values, just before calling the consumer. Implementation note for [hons-enabled] ACL2 executables (which are built by default): Destructive updating in raw Lisp lets us omit this implicit extra step, though the raw Lisp code generated for stobj-let will clear the memoization table for every function taking the parent stobj as an input, if any child stobj bound in the bindings is among the producer variables --- unless the parent stobj was introduced by [defstobj] using keyword argument :non-memoizable t. The form above is equivalent to the form displayed just below, which differs only in specifying an explicit stobj updater corresponding to the stobj accessor, fld2. Here we show the default updater name, whose name has \"UPDATE-\" prepended to the name of the accessor. But if the :RENAMING field of the defstobj event specified a different updater name corresponding to fld2, then that would need to be included where we have added update-fld2 below. (stobj-let ((child (fld2 parent) update-fld2)) ; bindings, including updater(s) (child) ; producer variables (update-fld 3 child) ; producer (update-fld3 'a parent)) ; consumer You can experiment using :[trans1] to see the single-step macroexpansion of a stobj-let form in the logic. For example, here is how that works for a stobj-let form that binds three fields and updates two of them. Notice that because more than one field is updated, an [mv-let] form is generated to bind the two fields to their values returned by the producer, rather than a [let] form as previously generated. First, let's introduce some events. (defstobj child1 child1-fld) (defstobj child2 child2-fld) (defstobj child3 child3-fld) (defstobj mom (fld1 :type child1) (fld2 :type child2) (fld3 :type child3)) ; Silly stub: (defun update-last-op (op mom) (declare (xargs :stobjs mom)) (declare (ignore op)) mom) (defun new-mom (mom) (declare (xargs :stobjs mom)) (stobj-let ((child1 (fld1 mom)) (child2 (fld2 mom)) (child3 (fld3 mom))) (child1 child3) (let* ((child1 (update-child1-fld 'one child1)) (child3 (update-child3-fld 'three child3))) (mv child1 child3)) (update-last-op 'my-compute mom))) Now let's look at the single-step macroexpansion of the above stobj-let form. ACL2 !>:trans1 (stobj-let ((child1 (fld1 mom)) (child2 (fld2 mom)) (child3 (fld3 mom))) (child1 child3) (let* ((child1 (update-child1-fld 'one child1)) (child3 (update-child3-fld 'three child3))) (mv child1 child3)) (update-last-op 'my-compute mom)) (PROGN$ (LET ((CHILD1 (FLD1 MOM)) (CHILD2 (FLD2 MOM)) (CHILD3 (FLD3 MOM))) (DECLARE (IGNORABLE CHILD1 CHILD2 CHILD3)) (MV-LET (CHILD1 CHILD3) (CHECK-VARS-NOT-FREE (MOM) (LET* ((CHILD1 (UPDATE-CHILD1-FLD 'ONE CHILD1)) (CHILD3 (UPDATE-CHILD3-FLD 'THREE CHILD3))) (MV CHILD1 CHILD3))) (LET* ((MOM (UPDATE-FLD1 CHILD1 MOM)) (MOM (UPDATE-FLD3 CHILD3 MOM))) (CHECK-VARS-NOT-FREE (CHILD1 CHILD2 CHILD3) (UPDATE-LAST-OP 'MY-COMPUTE MOM)))))) ACL2 !> If you try to evaluate a stobj-let form directly in the top-level loop, rather than from within a function body, you will get an error. The example above illustrates how stobj-let may be used in function bodies; here is another example, presented using an edited log. ACL2 !>(defstobj child fld) Summary Form: ( DEFSTOBJ CHILD ...) Rules: NIL Time: 0.02 seconds (prove: 0.00, print: 0.00, other: 0.02) CHILD ACL2 !>(defstobj parent (fld2 :type child) fld3) Summary Form: ( DEFSTOBJ PARENT ...) Rules: NIL Time: 0.02 seconds (prove: 0.00, print: 0.00, other: 0.02) PARENT ACL2 !>(defun f (parent) (declare (xargs :stobjs parent)) (stobj-let ((child (fld2 parent))) ; bindings (child) ; producer variables (update-fld 3 child) ; producer (update-fld3 'a parent))) ; consumer [[output omitted]] F ACL2 !>(f parent) ACL2 !>(defun check-f (parent) ; returns the value of the field of the child stobj (declare (xargs :stobjs parent)) (stobj-let ((child (fld2 parent))) ; bindings (val) ; producer variables (fld child) ; producer val)) ; consumer [[output omitted]] CHECK-F ACL2 !>(check-f parent) 3 ACL2 !> Notice that the second function defined above, check-f, uses a stobj-let form that returns an ordinary value: it reads a value from a child stobj, but does not write to the child stobj, as indicated by the lack of a child stobj among the producer variables. So for that stobj-let form, there is no implicit extra step. We labeled a stobj-let expansion above as ``approximate'' for two reasons, which we give here informally. (Now you know how to apply :[trans1] to that stobj-let call to see the precise expansion.) First, stobj-let declares the stobj-let-bound variables to be ignorable for the top let bindings. Second, and more importantly, stobj-let imposes the following restrictions on the producer and consumer, to avoid the aliasing problem: it disallows references to the parent stobj in the producer and it also disallows references to any bound stobj (i.e., bound in the bindings) in the consumer. We conclude this section with examples based on a slight variation of the nested stobj example from the first section above. These events can also be found in ACL2 community book misc/nested-stobj-tests.lisp, immediately under the following comment: ; As promised in :doc stobj-let, we begin with an example from that :doc. Note that some lemmas were needed in order to complete the [guard] proof for the function update-top, which may be found in the above file; they are omitted below. First we introduce three stobjs. (defstobj kid1 fld1) (defstobj kid2 fld2) (defstobj mom (kid1-field :type kid1) (kid2-ar-field :type (array kid2 (5))) last-op) The next function takes a given index and a mom stobj, and swaps the value stored in the stobj in mom's kid2-ar-field array at that index with the value stored in the stobj in mom's kid1-field field. (defun mom-swap-fields (index mom) (declare (xargs :stobjs mom :guard (and (natp index) (< index (kid2-ar-field-length mom))))) (stobj-let ((kid1 (kid1-field mom)) (kid2 (kid2-ar-fieldi index mom))) (kid1 kid2) (let* ((val1 (fld1 kid1)) (val2 (fld2 kid2)) (kid1 (update-fld1 val2 kid1)) (kid2 (update-fld2 val1 kid2))) (mv kid1 kid2)) (update-last-op 'swap mom))) Function mom.kid1-fld1 stores a given value in the given mom's kid1-fld1 field. (defun mom.kid1-fld1 (val mom) (declare (xargs :stobjs mom)) (stobj-let ((kid1 (kid1-field mom))) (kid1) (update-fld1 val kid1) (update-last-op val mom))) We next combine the two functions above, according to an op argument, as indicated by the following definition. (defun update-mom (op mom) (declare (xargs :stobjs mom)) (cond ((and (consp op) (eq (car op) 'swap) (natp (cdr op)) (< (cdr op) (kid2-ar-field-length mom))) (mom-swap-fields (cdr op) mom)) (t (mom.kid1-fld1 op mom)))) The following checker function uses a stobj-let form like the ones above, a major difference being that the producer variable is not a stobj, since the producer does not modify any stobjs. (defun check-update-mom (index val1 val2 last-op mom) (declare (xargs :stobjs mom :mode :program :guard (or (null index) (and (natp index) (< index (kid2-ar-field-length mom)))))) (and (equal (last-op mom) last-op) (stobj-let ((kid1 (kid1-field mom)) (kid2 (kid2-ar-fieldi index mom))) (val) ; producer variables (and (equal val1 (fld1 kid1)) (equal val2 (fld2 kid2))) val))) Now let us run our update function to populate some fields within the mom stobj. (let* ((mom ; set mom to (3 (x0 x1 x2 x3 x4)) (update-mom 3 mom)) (mom ; set mom to (x1 (x0 3 x2 x3 x4)) (update-mom '(swap . 1) mom)) (mom ; set mom to (7 (x0 3 x2 x3 x4)) (update-mom 7 mom)) (mom ; set mom to (x0 (7 3 x2 x3 x4)) (update-mom '(swap . 0) mom)) (mom ; set mom to (5 (7 3 x2 x3 x4)) (update-mom 5 mom)) (mom ; set mom to (7 (5 3 x2 x3 x4)) (update-mom '(swap . 0) mom))) mom) Are the above values of 7, 5, and 3 as expected, with a last operation being a swap? Yes! ACL2 !>(and (check-update-mom 0 7 5 'swap mom) (check-update-mom 1 7 3 'swap mom)) T ACL2 !> Notice that above, we never tried to access two different entries of the array. This can be done, but we need to bind two different stobjs to those fields. Fortunately, congruent stobjs make this possible; see [defstobj], in particular the discussion of congruent stobjs. Since we want to bind two stobjs to values in the array that are isomorphic to the stobj kid2, we introduce a stobj congruent to kid2. (defstobj kid2a fld2a :congruent-to kid2) Then we can define our swapping function as follows. The [guard] proof obligation includes the requirement that the two indices be distinct, again to avoid an aliasing problem. (defun mom-swap-indices (i1 i2 mom) (declare (xargs :stobjs mom :guard (and (natp i1) (< i1 (kid2-ar-field-length mom)) (natp i2) (< i2 (kid2-ar-field-length mom)) (not (equal i1 i2))))) (stobj-let ((kid2 (kid2-ar-fieldi i1 mom)) (kid2a (kid2-ar-fieldi i2 mom))) (kid2 kid2a) (let* ((val2 (fld2 kid2)) (val2a (fld2 kid2a)) (kid2 (update-fld2 val2a kid2)) (kid2a (update-fld2 val2 kid2a))) (mv kid2 kid2a)) mom)) The aforementioned community book, misc/nested-stobj-tests.lisp, contains a corresponding checker immediately following this definition. SECTION: Precise documentation for stobj-let General Form: (stobj-let BINDINGS PRODUCER-VARIABLES PRODUCER CONSUMER) where PRODUCER-VARIABLES is a non-empty true list of legal variable names without duplicates, PRODUCER and CONSUMER are expressions, and BINDINGS is a list subject to the following requirements. BINDINGS is a non-empty true list of tuples, each of which has the form (VAR ACCESSOR) or (VAR ACCESSOR UPDATER). There is a stobj name, ST, previously introduced by [defstobj] (not [defabsstobj]), such that each accessor is of the form (ACC ST) or (ACCi I ST), with the same stobj name (ST) for each binding. In the case (ACC ST), ACC is the accessor for a non-array field of ST. In the case (ACCi I ST), ACCi is the accessor for an array field of ST, and I is either a variable, a natural number, a list (quote N) where N is a natural number, or a symbol introduced by [defconst]. If UPDATER is supplied, then it is a symbol that is the name of the stobj updater for the field of ST accessed by ACCESSOR. If UPDATER is not supplied, then for the discussion below we consider it to be, implicitly, the symbol in the same package as the function symbol of ACCESSOR (i.e., ACC or ACCi), obtained by prepending the string \"UPDATE-\" to the [symbol-name] of that function symbol. Finally, ACCESSOR has a [signature] specifying a return value that is either ST or is stobj that is congruent to ST. If the conditions above are met, then the General Form expands to the one of the following expressions, depending on whether the list PRODUCER-VARIABLES has one member or more than one member, respectively. (But see below for extra code that may be inserted if there are stobj array accesses in BINDINGS.) Here we write STOBJ-LET-BOUND-VARS for the list of variables VAR discussed above, i.e., for (strip-cars BINDINGS). And, we write UPDATES for the result of mapping through PRODUCER-VARIABLES and, for each variable VAR that has a binding (VAR ACCESSOR UPDATER) in BINDINGS (where UPDATER may be implicit, as discussed above), collect into UPDATES the tuple (ST (UPDATER VAR ST)). For PRODUCER-VARIABLES = (PRODUCER-VAR): (let BINDINGS (declare (ignorable . STOBJ-LET-BOUND-VARIABLES)) (let ((PRODUCER-VAR PRODUCER)) (let* UPDATES CONSUMER))) Otherwise: (let BINDINGS (declare (ignorable . STOBJ-LET-BOUND-VARIABLES)) (mv-let PRODUCER-VARS PRODUCER (let* UPDATES CONSUMER))) Moreover, ACL2 places restrictions on the resulting expression: ST must not occur free in PRODUCER, and every variable in STOBJ-LET-BOUND-VARIABLES must not occur free in CONSUMER. Stobj-let forms can be evaluated using ordinary objects in theorem contexts, much as any form. They can also, of course, appear in function bodies. However, a stobj-let form cannot be evaluated directly in the top-level loop or other top-level contexts for execution (such as during [make-event] expansion). Finally, let FORM denote the form displayed above (either case). We explain how FORM is actually replaced by an expression of the form (PROGN$ ... FORM). This expression generates an extra [guard] proof obligation, which guarantees that no aliasing occurs from binding two stobj-let-bound variables to the same array access. So fix a stobj array accessor ACCi for which some stobj is bound to (ACCi I ST) in BINDINGS; we define an expression ACCi-CHECK as follows. Collect up all such index expressions I, where if I is of the form (quote N) then replace I by N. If the resulting list of index expressions for ACCi consists solely of distinct numbers, or if it is of length 1, then no extra check is generated for ACCi. Otherwise, let ACCi-CHECK be the form (chk-no-duplicatesp (list I1 ... Ik)), where I1, ..., Ik are the index expressions for ACCi. Note: chk-no-duplicatesp is a function that returns nil, but has a [guard] that its argument is an [eqlable-listp] that satisfies [no-duplicatesp]. Finally, FORM is replaced by (PROGN$ CHK1 ... CHKn FORM), where the CHKm range over all of the above ACCi-CHECK.") (NEVER-MEMOIZE (MEMOIZE) "Mark a function as unsafe to memoize. Logically, this function just returns nil. But execution of (never-memoize fn) records that fn must never be memoized, so that any attempt to memoize fn will fail. Any function can be marked as unsafe to memoize; in fact, fn need not even be defined at the time it is marked. This is useful for prohibiting the memoization of functions that are known to involve destructive functions like nreverse.") (NFIX (NUMBERS ACL2-BUILT-INS) "Coerce to a natural number Nfix simply returns any natural number argument unchanged, returning 0 on an argument that is not a natural number. Also see [ifix], see [rfix], see [realfix], and see [fix] for analogous functions that coerce to an integer, a rational number, a real, and a number, respectively. Nfix has a [guard] of t. Function: (defun nfix (x) (declare (xargs :guard t)) (if (and (integerp x) (>= x 0)) x 0))") (NIL-GOAL (DEBUGGING) "How to proceed when the prover generates a goal of nil At the end of a failed proof, one typically sees so-called ``key checkpoints'' (see [set-gag-mode]). These may be annotated as follows. [NOTE: A goal of NIL was generated. See :DOC nil-goal.] This [documentation] topic gives some ideas about how to think about the situation described by that message: some goal has reduced to nil. Suppose then that you see the above NOTE. If you look back at the proof log, even with [gag-mode] enabled, you will see a message saying that a goal of NIL ``has been generated''. This may indicate that the original goal is not a theorem, since most of the prover's activity is to replace a goal by an equivalent conjunction of its child subgoals. However, if some ancestor of the nil goal has undergone a process other than simplification or destructor elimination --- fertilization (heuristic use of equalities), generalization, or elimination of irrelevance --- then it is quite possible that the prover got to the nil goal by replacing a goal by a stronger (and perhaps false) conjunction of child subgoals. At present, if you are using [gag-mode] (the default) then you will need to issue the command :[pso] (``Print Saved Output'') if you want to see whether the situation above has occurred. However, that might not be necessary. A good rule of thumb is that if the nil goal is under more than one level of induction (e.g., with a prefix ``*i.j'' such as ``Subgoal *1.1/2.2''), then there is some likelihood that the situation above did indeed occur, and you can spend your time and energy looking at the key checkpoints printed in the summary to see if they suggest useful [rewrite] rules to prove. On the other hand, if the nil goal is at the top level (e.g. with a name not starting with ``*'', such as ``Subgoal 3.2''), then the original conjecture is probably not a theorem. If you do not quickly see why that is the case, then you might find it useful to issue the command :[pso] to see which case reduced to nil, in order to get insight about how the theorem might be falsified.") (NINTH (NTH ACL2-BUILT-INS) "Ninth member of the list See any Common Lisp documentation for details.") (NO-DUPLICATESP (LISTS ACL2-BUILT-INS) "Check for duplicates in a list General Forms: (no-duplicatesp x) (no-duplicatesp x :test 'eql) ; same as above (eql as equality test) (no-duplicatesp x :test 'eq) ; same, but eq is equality test (no-duplicatesp x :test 'equal) ; same, but equal is equality test (no-duplicatesp lst) is true if and only if no member of lst occurs twice in lst. The optional keyword, :TEST, has no effect logically, but provides the test (default [eql]) used for comparing elements of lst. The [guard] for a call of no-duplicatesp depends on the test. In all cases, the argument must satisfy [true-listp]. If the test is [eql], then the argument must satisfy [eqlable-listp]. If the test is [eq], then the argument must satisfy [symbol-listp]. See [equality-variants] for a discussion of the relation between no-duplicatesp and its variants: (no-duplicatesp-eq x lst) is equivalent to (no-duplicatesp x lst :test 'eq); (no-duplicatesp-equal x lst) is equivalent to (no-duplicatesp x lst :test 'equal). In particular, reasoning about any of these primitives reduces to reasoning about the function no-duplicatesp-equal. Function: (defun no-duplicatesp-equal (l) (declare (xargs :guard (true-listp l))) (cond ((endp l) t) ((member-equal (car l) (cdr l)) nil) (t (no-duplicatesp-equal (cdr l)))))") (NO-DUPLICATESP-EQ (POINTERS) "See [no-duplicatesp].") (NO-DUPLICATESP-EQUAL (POINTERS) "See [no-duplicatesp].") (NO-THANKS (POINTERS) "See [hints] for keyword :no-thanks.") (NON-EXEC (GUARD ACL2-BUILT-INS) "Mark code as non-executable Non-exec is a macro such that logically, (non-exec x) is equal to x. However, the argument to a call of non-exec need not obey the usual syntactic restrictions for executable code, and indeed, evaluation of a call of non-exec will result in an error. Moreover, for any form occurring in the body of a function (see [defun]) that is a call of non-exec, no guard proof obligations are generated for that form. The following example, although rather contrived, illustrates the use of non-exec. One can imagine a less contrived example that efficiently computes return values for a small number of fixed inputs and, for other inputs, returns something logically ``consistent'' with those return values. (defun double (x) (case x (1 2) (2 4) (3 6) (otherwise (non-exec (* 2 x))))) We can prove that double is compliant with Common Lisp (see [guard]) and that it always computes (* 2 x). (verify-guards double) (thm (equal (double x) (* 2 x))) We can evaluate double on the specified arguments. But a call of non-exec results in an error message that reports the form that was supplied to non-exec. ACL2 !>(double 3) 6 ACL2 !>(double 10) ACL2 Error in TOP-LEVEL: ACL2 has been instructed to cause an error because of an attempt to evaluate the following form (see :DOC non- exec): (* 2 X). To debug see :DOC print-gv, see :DOC trace, and see :DOC wet. ACL2 !> During proofs, the error is silent; it is ``caught'' by the proof mechanism and generally results in the introduction of a call of [hide] during a proof. Also see [defun-nx] for a utility that makes every call of a function non-executable, rather than a specified form. The following examples contrast non-exec with [defun-nx], in particular illustratating the role of [non-exec] in avoiding guard proof obligations. ; Guard verification fails: (defun-nx f1 (x) (declare (xargs :guard t)) (car x)) ; Guard verification succeeds after changing the guard above: (defun-nx f1 (x) (declare (xargs :guard (consp x))) (car x)) ; Guard verification succeeds: (defun f2 (x) (declare (xargs :guard t)) (non-exec (car x))) ; Evaluating (g1) prints \"Hello\" before signaling an error. (defun g1 () (f1 (cw \"Hello\"))) ; Evaluating (g2) does not print before signaling an error. (defun g2 () (non-exec (cw \"Hello\"))) ; Evaluating (h1) gives a guard violation for taking reciprocal of 0. (defun h1 () (f1 (/ 1 0))) ; Evaluating (h2) does not take a reciprocal, hence there is no guard ; violation for that; we just get the error expected from using non-exec. (defun h2 () (non-exec (/ 0)))") (NON-EXECUTABLE (POINTERS) "See [xargs] for keyword :non-executable.") (NON-LINEAR-ARITHMETIC (LINEAR) "Non-linear Arithmetic This documentation topic is divided into two parts. We first discuss the practical aspect of how to use the non-linear arithmetic extension to ACL2, and then the theory behind it. We assume that the reader is familiar with the material in [linear-arithmetic] and that on :[linear] rules. We begin our discussion of how to use non-linear arithmetic with a simple example. Assume that we wish to prove: (thm (implies (and (rationalp x) (rationalp y) (rationalp z) (< 0 y) (< x (* y z))) (< (floor x y) z))) Note that (floor x y) <= (/ x y). Note also that if we divide both sides of x < (* y z) by y, since 0 < y, we obtain (/ x y) < z. By chaining these two inequalities together, we get the inequality we desired to prove. We now proceed with our example session: (skip-proofs (progn ; Since the truth of this theorem depends on the linear properties ; of floor, we will need the linear lemma: (defthm floor-bounds-1 (implies (and (rationalp x) (rationalp y)) (and (< (+ (/ x y) -1) (floor x y)) (<= (floor x y) (/ x y)))) :rule-classes ((:linear :trigger-terms ((floor x y))))) ; We now disable floor, so that the linear lemma will be used. (in-theory (disable floor)) ; We create five rewrite rules which we will use during non-linear ; arithmetic. The necessity for these is due to one of the differences in ; ACL2's behaviour when non-linear arithmetic is turned on. Although ; the conclusions of linear lemmas have always been rewritten before ; they are used, now, when non-linear arithmetic is turned on, the ; conclusions are rewritten under a different theory than under ``normal'' ; rewriting. This theory is also used in other, similar, circumstances ; described below. (defthm |arith (* -1 x)| (equal (* -1 x) (- x))) (defthm |arith (* 1 x)| (equal (* 1 x) (fix x))) (defthm |arith (* x (/ x) y)| (equal (* x (/ x) y) (if (equal (fix x) 0) 0 (fix y)))) (defthm |arith (* y x)| (equal (* y x) (* x y))) (defthm |arith (fix x)| (implies (acl2-numberp x) (equal (fix x) x)))) ) ; End skip-proofs. ; We disable the above rewrite rules from normal use. (in-theory (disable |arith (* -1 x)| |arith (* 1 x)| |arith (* x (/ x) y)| |arith (* y x)| |arith (fix x)|)) ; We create an arithmetic-theory. Note that we must give a quoted ; constant for the theory --- none of the normal [theory-functions] ; are applicable to in-arithmetic-theory. (in-arithmetic-theory '(|arith (* -1 x)| |arith (* 1 x)| |arith (* x (/ x) y)| |arith (* y x)| |arith (fix x)|)) ; We turn non-linear arithmetic on. (set-non-linearp t) ; We can now go ahead and prove our theorem. (thm (implies (and (rationalp x) (rationalp y) (rationalp z) (< 0 y) (< x (* y z))) (< (floor x y) z))) The above example illustrates the two practical requirements for using non-linear arithmetic in ACL2. First, one must set up an arithmetic-theory. Usually, one would not set up an arithmetic-theory on one's own but would instead load a library book or books which do so. Second, one must turn the non-linear arithmetic extension on. This one must do explicitly --- no book can do this for you. For a brief discussion of why this is so, even though (set-non-linearp t) is an embeddable event, see [ACL2-defaults-table] (in particular, the final paragraph). (Note that (set-non-linearp t) modifies the acl2-defaults-table.) Also see [set-non-linearp], see [embedded-event-form], and see [events]. You can also enable non-linear arithmetic with the hint :nonlinearp t. See [hints]. We, in fact, recommend the use of a hint which will enable nonlinear arithmetic only when the goal has stabilized under rewriting. Using [default-hints] can make this easier. (defun nonlinearp-default-hint (stable-under-simplificationp hist pspv) (cond (stable-under-simplificationp (if (not (access rewrite-constant (access prove-spec-var pspv :rewrite-constant) :nonlinearp)) '(:computed-hint-replacement t :nonlinearp t) nil)) ((access rewrite-constant (access prove-spec-var pspv :rewrite-constant) :nonlinearp) (if (not (equal (caar hist) 'SETTLED-DOWN-CLAUSE)) '(:computed-hint-replacement t :nonlinearp nil) nil)) (t nil))) (set-default-hints '((nonlinearp-default-hint stable-under-simplificationp hist pspv))) This has proven to be a helpful strategy which allows faster proof times. We now proceed to briefly describe the theory behind the non-linear extension to ACL2. In [linear-arithmetic] it was stated that, ``[L]inear polynomial inequalities can be combined by cross-multiplication and addition to permit the deduction of a third inequality....'' That is, if 0 < poly1, 0 < poly2, and c and d are positive rational constants, then 0 < c*poly1 + d*poly2. Similarly, given the above, 0 < poly1*poly2. In the linear arithmetic case, we are taking advantage of the facts that multiplication by a positive rational constant does not change the sign of a polynomial and that the sum of two positive polynomials is itself positive. In the non-linear arithmetic case, we are using the fact that the product of two positive polynomials is itself positive. For example, suppose we have the three assumptions: p1: 3*x*y + 7*a < 4 p2: 3 < 2*x or p2': 0 < -3 + 2*x p3: 1 < y or p3': 0 < -1 + y, and we wish to prove that a < 0. As described elsewhere (see [linear-arithmetic]), we proceed by assuming the negation of our goal: p4: 0 <= a, and looking for a contradiction. There are no cancellations which can be performed by linear arithmetic in the above situation. (Recall that two polynomials are cancelled against each other only when they have the same largest unknown.) However, p1 has a product as its largest unknown, and for each of the factors of that product there is a poly that has that factor as a largest unknown. When non-linear arithmetic is enabled, ACL2 will therefore multiply p1' and p2' obtaining p5: 0 < 3 + -2*x + -3*y + 2*x*y. The addition of this polynomial will allow cancelation to continue and, in this case, we will prove our goal. Thus, just as ACL2 adds two polynomials together when they have the same largest unknown of opposite signs in order to create a new ``smaller'' polynomial; so ACL2 multiplies polynomials together when the product of their largest unknowns is itself the largest unknown of another polynomial. As the use of :[linear] lemmas to further seed the arithmetic database may allow cancellation to proceed, so may the use of non-linear arithmetic. This multiplication of polynomials is the motivation for an arithmetic-theory distinct from than the normal one. Because this may be done so often, and because the individual factors have presumably already been rewritten, it is important that this be done in an efficient way. The use of a small, specialized, theory helps avoid the repeated application of rewrite rules to already stabilized terms. Subtopics [Set-non-linearp] To turn on or off non-linear arithmetic reasoning") (NONLINEARP (POINTERS) "See [hints] for keyword :nonlinearp.") (NONNEGATIVE-INTEGER-QUOTIENT (NUMBERS ACL2-BUILT-INS) "Natural number division function Example Forms: (nonnegative-integer-quotient 14 3) ; equals 4 (nonnegative-integer-quotient 15 3) ; equals 5 (nonnegative-integer-quotient i j) returns the integer quotient of the integers i and (non-zero) j, i.e., the largest k such that (* j k) is less than or equal to i. Also see [floor], see [ceiling] and see [truncate], which are derived from this function and apply to rational numbers. The [guard] of (nonnegative-integer-quotient i j) requires that i is a nonnegative integer and j is a positive integer. Function: (defun nonnegative-integer-quotient (i j) (declare (xargs :guard (and (integerp i) (not (< i 0)) (integerp j) (< 0 j)))) (if (or (= (nfix j) 0) (< (ifix i) j)) 0 (+ 1 (nonnegative-integer-quotient (- i j) j))))") (NONTAUTOLOGICAL_SUBGOALS (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS) "Prover output omits some details The theorem prover's proof output is intended to suggest an outline of the reasoning process employed by its proof engine, which is virtually always more than is necessary for the ACL2 user. In particular, the output often omits subgoals that are sufficiently trivial, including tautologies.") (NORMALIZE (POINTERS) "See [xargs] for keyword :normalize.") (NORMED (HONS) "Normed objects are ACL2 Objects that are \"canonical\" or \"unique\" in a certain sense. In Common Lisp, we can tell whether an ACL2 object is normed or not, but there is no way for an ordinary ACL2 function to see whether an object is normed. Hence, whether or not an object is normed is an implementation-level concept. The fundamental property of normed objects is that if A and B are both normed, then (equal A B) holds if and only if (eql A B) holds. For strings and conses, (eql A B) holds only when (eq A B), so any normed conses or strings are [equal] precisely when they are [eq]. The potential benefits of having normed objects include: constant-time equality comparisons, reduced memory usage, fast association lists, and function memoization. Note that in our implementation, all symbols, characters, and numbers are automatically normed, and whenever a cons is normed its car and cdr must also be normed. The Meaning of Normed in Common Lisp. Recall that the ACL2 Objects are certain \"good\" Common Lisp symbols, characters, strings, and numbers, and the conses which can be recursively formed from these good atoms. Not all properties of these objects are visible in the ACL2 logic. An example of an invisible property is the pointer identity of an object. For example, suppose we write the following. (defconst *x* (cons 1 2)) (defconst *y* (cons 1 2)) In Common Lisp, [cons] is guaranteed to provide a new pair that is distinct from any previously created pair, so we know that *x* and *y* will be distinct objects and we will be able to tell them apart from one another using eq. But this difference is not visible in the ACL2 logic, and no ACL2 function can tell *x* apart from *y*. The normed-ness of an object is a similarly invisible property. In Common Lisp, invisible to ACL2, we maintain a data structure called a \"Hons Space\" that records which objects are normed. So, being normed is not an intrinsic property of an object, but instead is determined by whether the object is mentioned in this Hons Space. Notes about Garbage Collection. The Hons Space includes tables with pointers to every normed cons and string. One consequence of this is that normed objects cannot be reclaimed by Lisp's ordinary garbage collector, even after they have become unreachable from the perspective of an ACL2 program. For CCL and GCL users only, [hons-wash] is a special kind of garbage collection that allows normed conses to be reclaimed. For other Lisps, the only option is to occasionally, manually clear out these Hons Space tables with [hons-clear].") (NOT (BASICS ACL2-BUILT-INS) "Logical negation Not is the ACL2 negation function. The negation of nil is t and the negation of anything else is nil. Not is a Common Lisp function. See any Common Lisp documentation for more information. Function: (defun not (p) (declare (xargs :guard t)) (if p nil t))") (NOTE-2-0 (RELEASE-NOTES) "ACL2 Version 2.0 (July, 1997) Notes This is the first version of ACL2 released under the copyright of the University of Texas (UT). Future releases of ACL2 will be made from UT rather than Computational Logic, Inc. (CLI). Version 2.0 is just Version 1.9 as released by CLI, with a few bugs fixed. A bug causing an infinite loop was fixed in functional instantiation. The bug manifested itself when two conditions occurred simultaneously: First, the functional substitution replaces a function symbol, e.g., FOO, with a LAMBDA expression containing a free variable (a variable not among in the LAMBDA formals). And, second, in one of the constraints being instantiated there is a call of the function symbol FOO within the scope of another LAMBDA expression. Unless you used such a functional substitution, this bug fix will not affect you. Less important notes: The implementation of PRINC$ was changed so that it was no longer sensitive to the external setting of *print-base* and other Common Lisp special variables. Typographical errors were fixed in the documentation.") (NOTE-2-1 (RELEASE-NOTES) "ACL2 Version 2.1 (December, 1997) Notes The identity function [case-split] has been added. It is similar to [force] but causes an immediate split of the top-level goal on whether the indicated hypothesis is true. Less important notes: Minor bugs in the documentation were fixed.") (NOTE-2-2 (RELEASE-NOTES) "ACL2 Version 2.2 (August, 1998) Notes Important changes: A bug was fixed in the compile command, :comp. The compiled code produced by :comp in previous versions could be wildly incorrect because of a confusion between the printer and the reader regarding what was the current Lisp *package*. This bug could manifest itself only if you used the :comp command to compile previously uncompiled functions while the current package was different from \"ACL2\". What happened in that situation depended upon what symbols were imported into your current package. The most likely behavior is that the compiler would break or complain or the resulting compiled code would call functions that did not exist. There have been no other important changes to the code. However, this release contains some useful new books, notably those on the books subdirectories cli-misc and ihs. Both have README files. The ihs books provide support for integer hardware specifications. These books were crucial to Bishop Brock's successful modeling of the Motorola CAP. We thank Bishop for producing them and we thank all those who worked so hard to get these books released. We highly recommend the ihs books to those modeling ALUs and other arithmetic components of microprocessors or programming languages. In previous versions of ACL2, the arithmetic books, found on books/arithmetic/, included the addition of several unproved axioms stating properties of the rationals that we believed could be derived from our ``official'' axioms but which we had not mechanically proved. The axioms were found in the book rationals-with-axioms.lisp, which was then used in the uppermost arithmetic books top.lisp and top-with-meta.lisp. John Cowles has now provided us with ACL2 proofs of those ``axioms'' and so in this release you will find both rationals-with-axioms.lisp and rationals-with-axioms-proved.lisp. The former is provided for compatibility's sake. The latter is identical but contains defthms where the former contains defaxioms. The top-most books have been rebuilt using ``-axioms-proved'' book. Thanks John. Less important notes: Bishop Brock found a bug in translated-acl2-unwind-protectp4. Jun Sawada reported a bug in linear arithmetic that caused us not to prove certain trivial theorems concluding with (not (equal i j)). We have fixed both. We now prohibit definitions that call certain event commands such as DEFTHM and TABLE because our Common Lisp implementations of them differ from their ACL2 meanings (so that compiled books can be loaded correctly and efficiently). Minor bugs in the documentation were fixed.") (NOTE-2-3 (RELEASE-NOTES) "ACL2 Version 2.3 (October, 1998) Notes Important changes: Versions of ACL2 preceding this one contain a subtle soundness bug! We found a flaw in our detection of [subversive-recursions]. The bug allowed some subversive recursions to slip through undetected. We believe it would have been difficult to have exploited this flaw inadvertently. In particular, the following five conditions are necessary. (1) Introduce a constrained function, say f, via an encapsulate. (2) In the same encapsulation, define a clique of mutually recursive functions. This clique must be non-local and in :logic mode. (3) In that mutually recursive clique, use the constrained function f (perhaps indirectly) so that the termination argument for the clique depends on properties of the witness for f. Thus, f or some other function dependent upon f, must be used in an argument in a recursive call or in a term governing a recursive call. Furthermore, the use of f must be such that the termination proof cannot be done without exploiting properties of the witness for f. Other uses of the constrained functions in the clique are ok. (4) Fail to include the exploited properties of f among the constraints of the encapsulation. (5) Later, outside the encapsulation, explicitly use a functional instantiation in which f is replaced by a function not enjoying the crucial properties. See [subversive-recursions] for details. Less important notes: We have begun to write some introductory tutorial material for those who wish to learn to program in ACL2. Most of this material is HTML-based. See the Hyper-Card on the ACL2 home page. The documentation of [verify-guards] was improved to explain why one might wish to verify the ``guards'' of a defthm event. The missing documentation was noticed by John Cowles. A bug was fixed in cross fertilization. The bug caused the system to report that it had substituted one term for another when in fact no substitution occurred. The bug was noticed by Bill McCune.") (NOTE-2-4 (RELEASE-NOTES) "ACL2 Version 2.4 (August, 1999) Notes Important changes: We corrected a soundness bug in Version 2.3 related to the handling of [immediate-force-modep]. The bad behavior was noticed by Robert Krug. Thanks! We corrected a bug that permitted [verify-guards] to accept a function even though a subfunction had not yet had its guards verified. Thanks to John Cowles for noticing this. User defined single-threaded objects are now supported. See [stobj]. Less important notes: We corrected a bug that prevented the intended expansion of some recursive function calls. We changed the handling of the primitive function [illegal], which is logically defined to be nil but which is programmed to signal an error, so that when it is evaluated as part of a proof, it does not signal an error. The old handling of the function prevented some guard proofs involving [the] or [let]s with internal declarations. We corrected a bug that permitted some LOCAL DEFAXIOM events to slip into certified books. We corrected a bug that prevented the correct undoing of certain DEFPKG forms. Changes were made to support CMU Lisp. Pete Manolios helped with these changes. Changes were made to make the make files more compatible with Allegro Common Lisp. Jun Sawada, who has been a great help with keeping ACL2 up and running at UT on various platforms, was especially helpful. Thanks Jun.") (NOTE-2-5 (RELEASE-NOTES) "ACL2 Version 2.5 (June, 2000) Notes Important Changes: Concurrent with the release of ACL2 Version 2.5 is the publication of two books about ACL2. See the ``Books and Papers about ACL2 and Its Applications'' on the ACL2 Home Page. The books subdirectory now contains many new certifiable books, including solutions to the exercises in the two published books and full scripts for the case studies. See books/README.html. Improved Unix Makefile support for book certification has also been written. See books/README.html. The list of symbols in *acl2-exports* has been considerably expanded. If you have packages built by importing *acl2-exports* you might want to look carefully at the new value of that constant. The new value includes all :logic mode functions as of Version 2.5, as well as all documented macros and all built-in theorem names. [Include-book] and [certify-book] were modified to have some additional keyword arguments. It is possible to certify a book containing [defaxiom] and/or [skip-proofs] events and get warning messages or errors signaled, according to the settings of these new flags. In addition, it is possible to specify in include-book whether the book must be certified (under penalty of error if not). The default values of these new arguments cause warnings to be printed rather than errors signaled. The above change involved altering the form of certificate files. When books certified under previous versions are included, more warnings will be generated because these books are considered possibly to contain defaxiom and/or skip-proofs events. We anticipate further changes to this aspect of books and consider the current mechanisms (for controlling whether warnings or errors are signaled) just a prototype. See also the discussion below of ``soundness related'' warnings. Your suggestions are welcome. A discrepancy between ACL2 and Common Lisp was fixed, having to do with declare ignore. In past versions of ACL2, a formal parameter of a defun was considered ignored if it was not used in the body, the guard or the measure of the defun. That meant that a variable used only in the guard could not be declared ignored in ACL2; but some Common Lisp compilers would complain because the variable was not used in the body. Now, ACL2 considers a variable ignored if it is not used in the body. ACL2 can now be built in releases 5.0 and later of Allegro Common Lisp. (Other releases of Allegro Common Lisp and of other lisps continue to be supported as well.) This includes Allegro Common Lisp running on Windows 98 platforms. John Cowles helped us do some testing and answered questions for us. Thanks John! We incorporated Ruben Gamboa's changes to allow the building of a variant, ACL2(r), of ACL2, in which the user can reason about the real numbers using non-standard analysis. See [real]. Note that ACL2(r) and ACL2 have different underlying theories, and books certified in one system may not be included in the other. For backward compatibility and to ensure a smooth transition, ACL2 is built by default, not ACL2(r). This is a compile-time switch; see the makefile for instructions. There should be no changes to ACL2 resulting from the capability of building ACL2(r) from the same sources. Also see [acknowledgments] for more on the history of ACL2(r). A large number of bugs (some affecting soundness) were fixed, and many small new features were added. See below. Less Important Changes: Some warnings are now considered ``soundness related,'' namely, those that advise you that an uncertified book has been included or that a book containing DEFAXIOM or SKIP-PROOFS events. (Technically, DEFAXIOMs do not imperil soundness in the proof- theoretic sense, though they may imperil the validity of theorems. But you sould know when a book has added an axiom to your logic!) In previous versions of ACL2, all warnings were inhibited if the token warning was included in the argument to [set-inhibit-output-lst]. Now, soundness related warnings are printed even if warnings have been inhibited. To inhibit all warnings, supply the token warning! to set-inhibit-output-lst. Several bugs in [defstobj] were fixed, relating to the possibility that some of the subfunctions introduced by the defstobj were already defined. :[Puff] no longer tries to expand [defstobj] events. Previously, the attempt would cause a hard error. A soundness bug was fixed. The bug might have been exercised if you had an alternative definition (implies hyps (equiv (fn ...) body)) in which equiv is an equivalence relation other than EQUAL. In this case, calls of fn might have been expanded to body in places that were not equiv-hittable. An obscure soundness bug was fixed. The bug was exercised only if you had a metafunction with a computed hypothesis (i.e., a ``meta hypothesis function''), the hypothesis contained a free variable, i.e., a variable not involved in the term being rewritten, and the free variable occurred in the output of the metafunction. The possibility of this bug was brought to our attention by Robert Krug. We fixed a bug in the handling of hide related to the question of whether a variable symbol occurs in a term. The old code did not find the variable and could cause the system to throw away a hypothesis about it on the grounds that it was never mentioned. Rob Sumners helped discover this problem. The handling of :[elim] rules was generalized, permitting arbitrary known equivalence relations instead of merely equal in the concluding equality. The printing of runes (rule names; see [rune]) used has been made \"deterministic,\" both in proof output and in proof attempt summaries, by sorting the runes before printing. The handling of free variables has been improved for hypotheses such as (< 0 X), and more generally, any hypotheses involving a comparison with 0 (even for example (< X 1) where X is known to be an integer, which is handled as (<= X 0)). Thanks to Robert Krug for bringing relevant examples to our attention. A new value, :comp, has been implemented for the :load-compiled-file keyword of [include-book]. If this value is supplied, then a compiled file will always be loaded, even if that requires creating the compiled file first. The event include-book now generates a warning when a compiled file is expected but not found (see [include-book]). Formerly, it only did so when executed at the top level; it failed to generate the warning when executed on behalf of a surrounding include-book command. Certain redefinition warnings generated by Allegro Common Lisp have been eliminated. A new key has been implemented for the [ACL2-defaults-table], :bogus-mutual-recursion-ok, set with :[set-bogus-mutual-recursion-ok]. Thanks to David Russinoff for pointing out the utility of such a key. A bug was fixed in [defun-sk] that prevented its generated events from being accepted when guard verification is being performed. Thanks to Bill Young for bringing this problem to our attention. A second bug was brought to our attention by Pete Manolios, which was causing certain [defun-sk] events to be rejected. That problem has been fixed, and an \"Infected\" warning has also been eliminated. The command [good-bye] now works with Allegro Common Lisp. A low-level bug was fixed that could, for example, cause an error such as \"Error: Expected 5 args but received 4 args\" when interrupting a local event. A bug has been fixed in the [proof-checker] related to definition expansion. Thanks to Pete Manolios for bringing this to our attention with a simple example. A bug has been fixed related to the :[bdd] hint in the presence of [equivalence] relations. Thanks to Pete Manolios for bringing this to our attention with a simple example. The functions [position] and [position-equal] formerly required the second argument to be a true list. In accordance with Common Lisp, we now also allow the second argument to be a string. This could cause earlier proofs about these functions to fail unless [true-listp] is known to hold where necessary. Robert Krug wrote a patch, which has been incorporated, to prevent certain infinite loops that can arise in linear arithmetic. Thanks, Robert! The macro [let*] no longer requires the bound variables to be distinct. An obscure bug was fixed related to congruence rules. The bug would sometimes cause ACL2 to behave as though no rules (other than equality) were available for some argument positions. Thanks to Pete Manolios for bringing this bug to our attention. Documentation topics have been added for [hard-error] and [prog2$], and the documentation for [illegal] has been improved. Thanks to Rob Sumners for a useful suggestion in the examples in documentation for prog2$ and a fix in documentation for [sublis]. The event form [certify-book] was made more secure, in that it can now catch attempts to write a book to disk during its certification. Thanks to Rob Sumners for pointing out the insecurity of the existing mechanism. A Y2K problem was fixed with our applicative handling of dates. Accessors and updaters for [stobj]s have been made more efficient when the underlying lisp is Allegro Common Lisp, by the use of appropriate simple array declarations. A raw Lisp break had been possible when a certified book that had no guard verification was included in a session after ([set-verify-guards-eagerness] 2). This has been fixed. The keyword command :[comp] can now be used to compile only raw Lisp functions, excluding executable counterparts, by supplying the argument :raw. Rewrite rule nth-of-character-listp was removed from source file axioms.lisp since it is essentially subsumed by characterp-nth. Printing has been sped up. In one example the improvement was over 50% in both Allegro and GCL. We now allow printing in a \"downcase\" mode, where symbols are printed in lower case. All printing functions except print-object$ now print characters in lower case for a symbol when the ACL2 state global variable print-case has value :downcase and vertical bars are not necessary for printing that symbol. See [io] for a discussion of the macros acl2-print-case and set-acl2-print-case. The default printing remains unchanged, i.e., symbols are printed in upper case when vertical bars are not required. A low-level printing function (prin1$) was modified so that it is not sensitive to various Common Lisp globals related to printing. So for example, the function [fmt] is no longer sensitive to the value of Common Lisp global *print-case*. (The preceding paragraph explains how to control the case for printing in ACL2.) The definition of [array1p] was fixed so that the :maximum-length of an array must be strictly greater than the number specified in the :dimensions field; they may no longer be equal. This was always the intention; the documentation (see [arrays]) has remained unchanged. The corresponding change was also made to [array2p]. Allegro Common Lisp formerly caused an error when [compress1] was called on an array where the numbers above were equal; now, we get a guard violation instead, which is appropriate. In the context of theories, a name now represents not just the corresponding :definition [rune], as it has done in earlier versions of ACL2, but also the corresponding :[induction] rune. See [theories] for a discussion of runic designators. Most users will rarely, if ever, notice this change. One situation where this change will make a difference is after executing (in-theory (current-theory 'foo)) followed by (in-theory (enable bar)), where function bar is introduced after event foo, and bar is recursively defined. The latter [in-theory] form now enables the rune (:induction bar), which implies that the prover can use the induction scheme stored at definition time for bar. Formerly, the rune (:induction bar) was not enabled by (in-theory (enable bar)), and hence the induction scheme for bar was ignored even when explicit :induct hints were supplied. You may now supply [xargs] keyword pair :normalize nil in order to prevent certain definitions from ``hanging'' when there are many if-subexpressions. see [defun]. We now translate type declarations of real into guards, as we have already done for other types such as rational. For example, (declare (type real x)) generates the [guard] (rationalp x). See [type-spec]. The theorem prover now behaves reasonably under the combination of specifying a value of t both for :[otf-flg] and for a hint :do-not-induct. Previously, it aborted the first time it would have otherwise pushed a goal for induction, but now, it will continue and wait until all induction subgoals have been pushed before it aborts. We changed slightly the definition of [round]. However, we believe that the new definition is equivalent to the old. The definition of Common Lisp function [substitute] has been added. The following changes have been made in the use of file names within ACL2. We thank Warren Hunt and John Cowles for running some tests of these changes on Macintosh and Windows 98 platforms (respectively). (1) Names of directories and files now use a syntax like that used for Unix (trademark of AT&T), where directories are separated using the ``/'' character even when the operating system is not Unix or Linux. See [pathname]. ACL2 also continues to support its notion of structured pathnames from Version 2.4 and before, but might not do so in future releases and hence no longer documents such syntax. (2) The command :[set-cbd] may now take a relative pathname as an argument. (3) When the macro [ld] is given a file name as a value for [standard-oi], then if that file name is a relative pathname it refers to the result of prepending the connected book directory (see [pathname], see [cbd], and see [set-cbd]) in order to obtain an absolute pathname. Simiarly for the ld specials [standard-co] and [proofs-co]. It is no longer necessary to issue :[set-state-ok] t if you include a [stobj] declaration for [state], for example: (declare (xargs :stobjs state)) See [declare-stobjs]. The [proof-checker] has been cleaned up a bit, including the documentation and the capability (once again) to define pc-macro commands (see [define-pc-macro]) and proof-checker meta commands (see [define-pc-meta]). Recall that events generate summaries that include a line beginning with ``Warnings:'', which is followed (on the same line) by zero or more brief strings that summarize the warnings generated by that event. Formerly, this warnings summary for an [encapsulate] or [include-book] event did not include the summary strings for warnings generated by subsidiary events. This has been fixed. Macro [cw] has been documented and now expands to a call of a ;[logic] mode function. See [cw] for a way to print to the screen without having to involve the ACL2 [state]. Thanks to Rob Sumners for suggesting that we document this useful utility. Functions duplicates, add-to-set-equal, intersection-eq, evens, and odds are now :[logic] mode functions.") (NOTE-2-5{R} (RELEASE-NOTES) "ACL2 Version 2.5(r) (June, 2000) Notes Important changes to non-standard version: Please see [note-2-5] for changes to Version 2.5 of ACL2. We hope to write more documentation for ACL2(r) in the future.") (NOTE-2-6 (RELEASE-NOTES) "ACL2 Version 2.6 (November, 2001) Notes Because of the large number of modifications, we have divided up the Version 2.6 notes into the following subtopics. * New functionality (see [note-2-6-new-functionality]) * Changes in proof engine (see [note-2-6-proofs]) * Changes in rules and definitions (see [note-2-6-rules]) * Guard-related changes (see [note-2-6-guards]) * Proof-checker changes (see [note-2-6-proof-checker]) * System-level changes (see [note-2-6-system]) * Other (minor) changes (see [note-2-6-other]) Subtopics [Note-2-6-guards] ACL2 Version 2.6 Notes on Guard-related Changes [Note-2-6-new-functionality] ACL2 Version 2.6 Notes on New Functionality [Note-2-6-other] ACL2 Version 2.6 Notes on Other (Minor) Changes [Note-2-6-proof-checker] ACL2 Version 2.6 Notes on Proof-checker Changes [Note-2-6-proofs] ACL2 Version 2.6 Notes on Changes in Proof Engine [Note-2-6-rules] ACL2 Version 2.6 Notes on Changes in Rules and Constants [Note-2-6-system] ACL2 Version 2.6 Notes on System-level Changes") (NOTE-2-6-GUARDS (NOTE-2-6) "ACL2 Version 2.6 Notes on Guard-related Changes When you [declare] that a function treats certain formals as :[stobj]s, the [guard] of the function is automatically extended to include the corresponding stobj-recognizer calls. For example, if a definition includes (declare (xargs :stobjs (ST))) then the guard of the function is changed by the addition of the conjunct (ST-P ST). One impact of this is that if you use the built-in ACL2 [state] as a formal parameter of a function, (STATE-P STATE) is added to the guard. This may introduce a guard where there was none in previous versions of the system. In older versions, therefore, no attempt would be made to [verify-guards], while in the new version, we would attempt guard verification. You may wish to add (declare (xargs :verify-guards nil)) to such definitions. A related change affects users who do not use stobjs or state. In previous versions of the system --- as now --- a type declaration extended the guard you provided explicitly. Thus, if you wrote (declare (type integer n)) then (INTEGERP n) was added to your guard. This is still the case and :stobjs recognizers are similarly added. But in older versions of the system we ``added'' the conjuncts without checking whether they were already present in the guard you provided. This sometimes produced such guards as (and (integerp n) (integerp n)) where the first was produced by your type declaration and the second was your :guard. We now eliminate redundant conjuncts; this may rearrange the order of the conjuncts. The guard conjectures for functions using stobjs have been simplified somewhat by taking advantage of the syntactic restrictions checked for single-threaded objects. The following functions have been modified so that character and string arguments are restricted to standard characters. (See [standard-char-p] and see [standard-char-listp].) [upper-case-p] [lower-case-p] [char-upcase] [char-downcase] string-downcase1 [string-downcase] string-upcase1 [string-upcase] [char-equal] string-equal1 [string-equal] Also, function [standard-string-alistp] replaces function string-alistp, with concomitant changes in the guard to [assoc-string-equal], and in variable *acl2-exports*. Also, lemma standard-string-alistp-forward-to-alistp replaces lemma string-alistp-forward-to-alistp. There is a new lemma standard-char-p-nth, which has also been added to *acl2-exports*. The guard had been inadvertently omitted from the definition of the function [substitute] (and its subroutine substitute-ac). This omission has been corrected; also, the guard is slightly stronger than the documentation had claimed (and that has been corrected).") (NOTE-2-6-NEW-FUNCTIONALITY (NOTE-2-6) "ACL2 Version 2.6 Notes on New Functionality A fundamental change is the provision of the ``nu-rewriter'' for simplifying expressions composed of NTH, UPDATE-NTH, and UPDATE-NTH-ARRAY applications and LET expressions and other calls of non-recursive functions or LAMBDA expressions involving those symbols. The nu-rewriter applies the obvious rewrite rule for (NTH i (UPDATE-NTH j v s)) and the analogous rule for UPDATE-NTH-ARRAY. See nu-rewriter. The nu-rewriter can be enabled with set-nu-rewriter-mode. A new flag has been added to the xargs of [defun] permitting the declaration that the function is non-executable. The usage is (declare (xargs :non-executable t)) and the effect is that the function has no executable counterpart. On the positive side: the function is permitted to use single-threaded object names and functions arbitrarily, as in theorems rather than as in executable definitions. Such functions are not permitted to declare any names :[stobj]s but accessors, etc., may be used, just as in theorems. A new flag has been added to permit the system to abbreviate output by introducing LET* notation identifying common subterms. The formula being proved is not affected; this flag changes its displayed form only. See [set-let*-abstractionp]. A ``raw mode'' has been added, primarily for faster loading of applications. see [set-raw-mode]. Functions [alphorder] and [lexorder] have been put in :[logic] mode. Lexorder is now a total order ordering of the ACL2 universe, and theorems are included to that effect. Thanks to Pete Manolios for suggesting the idea and providing events to use, and to Rob Sumners for assistance with some modifications. See also the new book books/misc/total-order for an irreflexive total order. The ACL2 user can now make system calls to the host operating system. See [sys-call] and see [sys-call-status]. Thanks to Rob Sumners for working out this idea with Pete Manolios and Robert Krug, who we also thank, and for working out the implementation with us. It is no longer required to use absolute [pathname]s in [include-book] forms that have been executed before a [certify-book]. Any relative pathname strings in such contexts will be expanded into absolute pathnames before they are saved in the [portcullis] of the [certificate] of the book being certified. ACL2 can now be built on top of Allegro Common Lisp 6.0, and also on Windows platforms on top of Allegro Common Lisp and GCL. Thanks to Pete Manolios and Vinay K. Siddhavanahalli for their help with Windows. Rob Sumners has designed and provided an initial implementation for two improvements to [defstobj] (also see [stobj]). First, array fields can now be resized. Resize and length functions are provided for array fields, which can be used to resize stobj array fields dynamically. The recognizers for array fields have been simplified to accommodate this change, so that they only check that each element of the array field has the specified type. Second, performance has been improved for stobjs with a large number of fields, by changing their Common Lisp implementation to store the fields in a simple vector instead of a list. Now [stobj]s may be bound locally; see [with-local-stobj]. Thanks to Rob Sumners, who encouraged us to implement this capability, was an early user of it, and participated usefully in discussions on its design. New functions [fms!], [fmt!], and [fmt1!] are the same as their respective functions without the ``!,'' except that the ``!'' functions are guaranteed to print forms that can be read back in (at a slight readability cost). We added [extended-metafunctions], metafunctions which allow [state] and context sensitive rewriting to some extent. We thank Robert Krug for pushing for and on this idea. The documentation has been improved. In particular, a new documentation topic provides a gentle introduction to ACL2 [arrays] --- see [arrays-example] --- and additional documentation has been provided for getting started with proof trees in emacs --- see [proof-tree]. New Makefile targets fasl and o have been added to the books/ directory of the distribution. For example, you might first certify books using an ACL2 built on top of GCL (which creates compiled files with suffix o). Then, when standing in the books/ directory, you might execute the command make fasl ACL2=my-allegro-acl2 which will create compiled (.fasl) files for Allegro Common Lisp, assuming that my-allegro-acl2 starts up an ACL2 built on that Common Lisp. The macro [let*] now allows variables to be declared ignored. See [let*] and see [let]. The user may now control backchaining. This feature was designed and primarily implemented by Robert Krug (though the authors of ACL2 are resposible for any errors); thanks, Robert! See [backchain-limit]. It is now possible to ``slow down'' the rate at which case splits are generated by the simplifier. See [set-case-split-limitations]. Accesses to [stobj]s using [nth] or [update-nth] are now displayed using symbolic constants instead of numeric indices. For example, given the event (defstobj foo a b :renaming ((b c))) then the term (nth 0 foo) will be displayed (for example, during proofs) as (nth *a* foo) while (nth 1 foo) will be displayed as (nth *c* foo). The [defstobj] event now correspondingly introduces a [defconst] event for each field accessor function, introducing a constant whose name is obtained from the accessor's name by prefixing and suffixin a ``*,'' as in the example above: accessor a generates (defconst *a* 0) and accessor c generates (defconst *c* 1). See [nth-aliases-table] for how to extend this feature for alternate names of [stobj]s. Computed hints have been improved. It is now possible to detect within a computed hint whether the goal clause is stable under simplification; it is also possible for a computed hint to change the list of available hints. See [computed-hints]. It is now possible to provide ``default hints'' that are appended to the hints explicitly provided. See [set-default-hints]. Using computed hints (see [computed-hints]) and default hints (see [set-default-hints]) it is possible to implement a book that supports ``priority phased simplification.'' Using this book you can assign priorities to your rules and cause the theorem prover to simplify each goal maximally under all the rules of one priority before enabling rules of the next priority. See books/misc/priorities.lisp. The macro [defabbrev] has been improved to allow [declare] forms and documentation strings and to do more error-checking. Thanks to Rob Sumners for designing this enhancement and providing the first implementation. See [defabbrev]. Further changes were made to support CMU Lisp. Wolfhard Buss helped with these changes. A new table was added that is used when printing proof output, so that nests of right-associated calls of a binary function are replaced by corresponding macro calls, as has been the case for [binary-+] and [+], [binary-append] and [append], and so on. See [add-binop]. Operators [logand], [logior], [logxor], and [logeqv] are now macros (formerly, they were functions) that call corresponding binary functions (e.g., binary-logand) defined in source file \"axioms.lisp\". Thanks to Rob Sumners for this enhancement. Proof output will however continue to show calls of [logand], [logior], [logxor], and [logeqv]. Function ([allocate-fixnum-range] fixnum-lo fixnum-hi) sets aside more \"permanent\" fixnums in GCL. ACL2 now runs under CLISP. Thanks to Wolfhard Buss and Sam Steingold for their assistance with the port. Michael ``Bogo'' Bogomolny has created a search engine, accessible from the ACL2 home page. For that purpose he modified the HTML translator to create one file per topic (a good idea in any case). Thanks, Bogo! An emacs file of potential (but optional) use for ACL2 users may be found in emacs/emacs-acl2.el. In particular, this file supports the use of proof trees (see [proof-tree]). Some [books] have been added or modified. In particular, Robert Krug has contributed books/arithmetic-2/, which provides an alternative to the existing collection of books about arithmetic, books/arithmetic/. For a discussion of the distributed books see the link to README.html in the installation instructions.") (NOTE-2-6-OTHER (NOTE-2-6) "ACL2 Version 2.6 Notes on Other (Minor) Changes Warning strings are now case-insensitive. See [set-inhibit-warnings]. ACL2 causes a warning when an [in-theory] hint or event causes a 0-ary function's definition to be disabled but its :[executable-counterpart] to be enabled. A minor modification has been made to [defstobj] that can have a positive impact on performance in Allegro Common Lisp. (For Lisp hackers: the stobj name was formerly declared special, and that was disabling Allegro's tail-merging routing for compilation of some recursive functions using stobjs.) The downside is that stobj names can no longer be evaluated in raw Lisp. However, raw Lisp is not the right place to be evaluating ACL2 forms anyhow; see [set-raw-mode]. We thank Rob Sumners for bringing this issue to our attention. Before Version 2.6, there has been the following problem with [defstub] and [encapsulate] in the case that the current package is not the ACL2 package. If a [signature] was specified using the symbol =>, then that symbol had have been imported into the current package from the ACL2 package when the current package was defined. There are no longer any package restrictions on the use of =>. Thanks to John Cowles for bringing this problem to our attention. Bugs in [defun-sk] have been fixed. Defun-sk forms introducing functions of no arguments were failing to be admitted, for example: (defun-sk always-p1 () (forall (x) (p1 x))). Thanks to John Cowles for bringing this problem to our attention. Also, defun-sk failed on an example in the documentation (see [tutorial4-defun-sk-example]), as pointed out by Matyas Sustik; this bug has been fixed as well. The trace mechanism has been fixed to handle [stobj]s, and to avoid the printing of so-called enabled structures. The [brr] command :type-alist now produces more readable output. An [include-book] of an uncertified book no longer loads an associated compiled file. We added a few checks to make sure that the underlying lisp is suitable, for example checking that the reader is case-insensitive and reads in symbols with upper-case names where appropriate. We now warn when forcing (see [force]) or immediate force mode (see [immediate-force-modep]) change state between enabled and disabled. Also see [enable-immediate-force-modep] and see [disable-immediate-force-modep] for information about these new macros, which may be used to control immediate force mode. We have eliminated the use of a low-level raw Lisp constant, *most-recent-multiplicity*. Our test suite saw a speed-up of approximately 2% as a result for an ACL2 image built on GCL (but no significant speed-up for an ACL2 image built on Allegro Common Lisp). We thank Rob Sumners for suggesting this improvement. Fixnum declarations are now realized as (signed-byte 29) instead of (signed-byte 27). We check that the underlying Common Lisp recognizes objects of type (signed-byte 29) as fixnums, with the exception of CLISP, which is said to have an efficient bignum implementation. A new documentation topic [functional-instantiation-example] illustrates functional instantiation. A bug has been fixed in the monitoring of runes (see [monitor]). Thanks to Dave Greve for sending an example that clearly showed the problem. A warning is now issued when it is detected that a :[type-prescription] rule may not be as strong as it appears because it is not sufficient to prove itself by type reasoning. An error is caused for rules of class :[meta] when the function symbol IF is among the :trigger-fns. (IF was ignored anyhow; the point of this change is to avoid misleading the user.) A minor bug has been fixed in :[pr], evident for example if this command was applied to IF. A minor hole in :[set-bogus-mutual-recursion-ok] did not permit the acceptance of [mutual-recursion] forms that include constant function definitions. This has been fixed. Thanks to Eric Smith for coming up with a simple example illustrating the problem. The temporary files \"TMP.lisp\" and \"TMP1.lisp\" written out by :[comp] are now written to the connected book directory (see [cbd]). Previously, the Allegro compiler was not eliminating tail recursion for executable counterparts of functions, because of the way one of its flags had been set. As a result, calls of functions whose guards had not been verified could run out of stack space when this was not necessary. This situation has been fixed. Executable counterparts could have slow array accesses. This has been fixed (specifically, constants are no longer replaced with their values in the definitions of executable counterparts). Various improvements have been made to the documentation. Thanks in particular to Eric Smith for pointing out a numbers of places where fixes were in order. File \"mcl-acl2-startup.lisp\" has been updated, thanks to feedback from Philippe Georgelin. Inefficiencies in GCL fixnum computations were remedied for macros +f and *f. Thanks to Rob Sumners for pointing out this issue.") (NOTE-2-6-PROOF-CHECKER (NOTE-2-6) "ACL2 Version 2.6 Notes on Proof-checker Changes The proof-checker command =, when used with no arguments, now reports which hypothesis is being used. The output from [proof-checker] command type-alist has been improved. A slight change has been made to the [proof-checker] for commands promote, casesplit, equiv, and =, so that terms of the form (if x nil y) are recognized as conjunctions, (and (not x) y). Thanks to Pete Manolios for suggesting that we consider such a change. There is a new [proof-checker] command print-all-concs that prints all the conclusions of the unproved goals. A new [proof-checker] command, runes, has been added. It reports the [rune]s that have participated in the interactive proof up to the current point.") (NOTE-2-6-PROOFS (NOTE-2-6) "ACL2 Version 2.6 Notes on Changes in Proof Engine Certain optimizations are performed when converting terms to clausal form. For example, (< 0 1) is known to be t, (HARD-ERROR ctx str alist) is known to be nil, and (INTEGERP n) is known to imply (RATIONALP n). In earlier versions of ACL2, the conversion of a term to clausal form expanded LAMBDA applications. That may no longer occur. Some proofs may slow down (or fail) because your LAMBDA-expressions are not expanded away when you ``expected'' them to be. Robert Krug found a soundness bug in our linear arithmetic package. The bug was caused by the derivation of an equation from two inequalities without taking adequate precautions to ensure that both sides of the inequalities were numeric. Robert also kindly provided a fix which we adopted. Thanks Robert! We fixed a bug that could prevent the application of a metatheorem. A bug has been fixed that had caused bogus forcing rounds (see [forcing-round]). The bug could occur when the hypothesis of a rule was forced (see [force]) before the prover decided to start over and prove the original goal by induction. Thanks to Rob Sumners for drawing our attention to this problem. Some low-level fixes have been made that prevent certain infinite loops, based on reports by users. We thank Yunja Choi, Matt Wilding, and Pete Manolios for reporting such problems. An obscure potential soundness hole has been fixed by redoing the way evaluation takes place in the ACL2 loop and during theorem proving. We expect that users will see no difference based on this change. (Those interested in the details can see the long comment ``Essay on Evaluation in ACL2'' in source file interface-raw.lisp.) A small change was made in computation for a heuristic that controls backchaining. This will speed up proofs dramatically in a very few cases but should have a very small impact in general. The simplifier has been modified to avoid eliminating hypotheses of goals that can be established by contextual (specifically, type-set) reasoning alone. We believe that this change will generally strengthen ACL2's reasoning engine, although on rare occasions a lemma that formerly was provable may require user assistance. Thanks to Robert Krug for suggesting this change and providing its implementation. Case splits are now limited, by default. This may allow some proof attempts to provide output where previously the prover would appear to ``go out to lunch.'' For a more complete discussion, including instructions for how users can control case splitting, see [set-case-split-limitations]. A bug has been fixed in the handling of :[type-prescription] rules by the [bdd] package. Thanks to Rob Sumners for discovering this bug and supplying a helpful example. ACL2 may now use the built-in induction scheme for a function symbol even if that function symbol is disabled. Formerly, if a function symbol was disabled then its induction scheme was only considered if an explicit induction hint was supplied, other than :induct t. We eliminated the rule-class linear-alias. This rule class was seldom used and complicated the linear arithmetic decision procedure in ways that made it difficult to extend to handle some non-linear special cases. The only use of the rule-class that we know of was in our own nqthm books, which were an attempt to provide an embedding of the Nqthm logic and theorem prover into ACL2. But that facility was also practically never used, as far as we know. So both linear-alias rules and the nqthm books have been eliminated. In earlier versions of ACL2, when the IF-form of (AND p q) was assumed true -- as when rewriting the alpha expression in (IF (AND p q) alpha beta) -- the assumption mechanism did not deduce that p and q are true, only that their conjunction, in its IF-form, is true. This has long been known as a deficiency in both ACL2 and the earlier Nqthm but it was tedious to do better when one considered the full range of IF-forms one might encounter in the test of another IF. Rather than code all the cases, we just waited until clausification got rid of them. Robert Krug developed a pretty nice treatment of the general case and we added it in this version. This also involved a surprising number of changes elsewhere in the system because the improved handling of assumptions caused the theorem prover often to ``erase'' hypotheses provided by :use hints because it could simplify them to t. Thank you Robert! In response to a suggestion from Robert Krug, we added mfc-ap so that extended metafunctions can take advantage of linear arithmetic. See [extended-metafunctions]. There is less delay in printing goals. In previous versions, a goal was not printed until its subgoals were created (or the goal was proved). Now, the goal is printed essentially as soon as it is created. A small technical change has been made in the function [term-order], to give priority on the function symbol count over the weighting of constants. So for example, while previously the term (f) preceded the constant 2, that is no longer the case. If this change is noticed at all, it will probably be noticed in how so-called permutative rewrite rules are applied; see [loop-stopper]. Thanks to Robert Krug for suggesting this improvement and providing part of the implemtation.") (NOTE-2-6-RULES (NOTE-2-6) "ACL2 Version 2.6 Notes on Changes in Rules and Constants The following symbols have been added to the list constant *common-lisp-specials-and-constants*: REPLACE, FILL, CHARACTER, =, BREAK, and PRIN1. This was done in support of ports to Allegro 6.0 and Windows platforms (see [note-2-6-new-functionality]). The list of symbols in *acl2-exports* has been modified, for example to include show-accumulated-persistence and the legal arguments to [set-inhibit-output-lst]. Functions [zp] and [zip] are now handled slightly differently. They are are now disabled, but each comes with a :[rewrite] rule that allows their expansion on non-variable terms, and also with a :[compound-recognizer] rule that avoids the need for opening up these functions when applied to variables. The resulting behavior should be very similar to the behavior of previous versions, except that case splits will be avoided when these functions are applied to variables. Function [standard-string-alistp] replaces function string-alistp. For further discussion, see [note-2-6-guards]. Rules of class :[rewrite] whose conclusion is a term of the form (equal lhs rhs) have always been stored in the expected way: lhs rewrites to rhs. This way of storing :rewrite rules has been extended to allow [=], [eq], or [eql] in place of [equal]. Rewrite rule nth-update-nth, in source file axioms.lisp, has been strengthened. A new rewrite rule equal-constant-+ has been added to the book arithmetic/equalities. This should generally be a beneficial change, but existing proofs involving the arithmetic books could conceivably be affected. Function [symbol-package-name] and constant *main-lisp-package-name* have undergone small changes. This change should rarely be noticed by users and is discussed elsewhere; see [note-2-6-system]. We mention here that proofs involving [stobj]s may need to be modified because of changes in auxiliary functions generated by [defstobj]. (These changes were made in support of a new resizing capability, mentioned elsewhere in these release notes; see [note-2-6-new-functionality]. In the distributed book directory books/arithmetic/, the book rationals-with-axioms-proved.lisp has been renamed rationals.lisp. (ACL2(r) only) Rewrite rules realp-+, realp-*, realp-unary--, and realp-unary-/ have been added in analogy to existing rules rationalp-+, rationalp-*, rationalp-unary--, and rationalp-unary-/. Thanks to Jun Sawada for suggesting this change. The definition of [aref1] has been modified slightly. Previously, if *my-a* were an array then (aref1 'some-name *my-a* :header) would evaluate to the cdr of the [header] of *my-a* rather than to its [default]. See [arrays]. Changes have been made in the ihs books, based on suggestions from Jun Sawada, that support its use with ACL2(r) (see [real]). The primary change is to replace calls of [rationalp] with calls of [real/rationalp], which should have no effect on users of standard ACL2.") (NOTE-2-6-SYSTEM (NOTE-2-6) "ACL2 Version 2.6 Notes on System-level Changes We modified the tracking of [skip-proofs] events and the use of [state] global ld-skip-proofsp in order to avoid some soundness issues. For example, [skip-proofs] events buried in locally-included books are now tracked. The ``Essay on Skip-proofs'' in source file axioms.lisp gives several examples of dicey behavior that is no longer supported. We fixed a problem with some of the makefiles, so that recursive invocations of `make' now use the version of `make' specified on the command line. Files were fixed to help non-Unix/Linux users with book certification. Thanks to John Cowles for finding some problems and suggesting fixes to books/certify-numbers.lisp, books/arithmetic/certify.lsp, and books/cowles/certify.lsp. We thank Scott Burson for noticing and fixing some other such problems. Moreover, a bdd test was being ignored entirely in Version 2.5; this problem has been fixed as well. A minor change in system function save-acl2-in-allegro will allow this function to continue to work in Allegro CL versions starting (someday) with 10.0. Thanks to Art Flatau for suggesting such a fix. The books/case-studies/ directory has been removed. These books are in support of the first (1998) ACL2 workshop, and are accessible via the {ACL2 home page | http://www.cs.utexas.edu/users/moore/acl2/}. Also, the books/cli-misc directory has been renamed books/misc, and the books/nqthm directory has been removed. The notion of ACL2 version has been slightly modified to catch unsoundness due to implementation dependencies. See [version]. Another change to eliminate such unsoundness is that built-in symbols now have a [symbol-package-name] of \"COMMON-LISP\"; formerly, this string was \"LISP\" for ACL2 images built on GCL. See [symbol-package-name]. At a low level, the (undocumented) constant *main-lisp-package-name* is now \"COMMON-LISP\"; before, it was \"LISP\" for GCL.") (NOTE-2-6{R} (RELEASE-NOTES) "ACL2 Version 2.6(r) (November, 2001) Notes Important changes to non-standard version: None since Version 2.5. Please see [note-2-6] for changes to Version 2.6 of ACL2. We hope to write more documentation for ACL2(r) in the future.") (NOTE-2-7 (RELEASE-NOTES) "ACL2 Version 2.7 (November, 2002) Notes The Version_2.7 notes are divided into the subtopics below. Here we give only a brief summary of a few of the changes that seem most likely to impact existing proofs. Not included in this brief summary, but included in the subtopics, are descriptions of improvements (including bug fixes and new functionality) that should not get in the way of existing proof efforts. In particular, please see [note-2-7-new-functionality] for discussion of a number of new features that you may find useful. Acknowledgements and elaboration, as well as other changes, can be found in the subtopics listed below. Bug fixes (see [note-2-7-bug-fixes]) * Three soundness bugs were fixed. These bugs were probably rarely hit, so users may well not notice these changes. * [Certify-book] now requires :skip-proofs-ok t (respectively, :defaxioms-okp t) if there are [skip-proofs] (respectively, [defaxiom]) events in the book or any included sub-books. * When :by hints refer to a definition, they now use the original body of that definition rather than the simplfied (``normalized'') body. * When [ld] is applied to a stringp file name, it now temporarily sets the connected book directory (see [cbd]) to the directory of that file while evaluating forms in that file. New functionality (see [note-2-7-new-functionality]) * ACL2 now works harder to apply :[rewrite] and :[linear] rules with free variables in the hypotheses. See [note-2-7-new-functionality], in particular its first two paragraphs, for details. [Forward-chaining] also does more with free variables. Changes in proof engine (see [note-2-7-proofs]) * Some prover heuristics have changed slightly. Among other consequences, this can cause subgoal [hints] to change. For example, suppose that the Version_2.6 proof of a particular theorem generated \"Subgoal 2\" and \"Subgoal 1\" while Version_2.7 only generates the second of these. Then a subgoal hint attached to \"Subgoal 1\" in Version_2.6 would have to be attached to \"Goal'\" in Version_2.7. (See [goal-spec].) The full topic has details (see [note-2-7-proofs]). Changes in rules and definitions (see [note-2-7-rules]) * The package name of a generated variable has changed for [defcong]. Guard-related changes (see [note-2-7-guards]) * [Guard] verification formerly succeeded in a few cases where it should have failed. * Guards generated from type declarations now use functions signed-byte-p and unsigned-byte-p, now defined in source file axioms.lisp and formerly defined rather similarly under books/ihs/. Proof-checker changes (see [note-2-7-proof-checker]) * See the above doc topic. System-level changes (see [note-2-7-system]) * See the above doc topic. Other changes (see [note-2-7-other]) * A new [table], [invisible-fns-table], takes the place of the handling of invisible functions in the [ACL2-defaults-table], * The [theory-invariant] event has been modified so that the default action is an error rather than a warning. * Proof output that reports destructor elimination no longer uses the word ``generalizing''. Again, please proceed to the subtopics for more thorough release notes. Subtopics [Note-2-7-bug-fixes] ACL2 Version 2.7 Notes on Bug Fixes [Note-2-7-guards] ACL2 Version 2.7 Notes on Guard-related Changes [Note-2-7-new-functionality] ACL2 Version 2.7 Notes on New Functionality [Note-2-7-other] ACL2 Version 2.7 Notes on Miscellaneous Changes [Note-2-7-proof-checker] ACL2 Version 2.7 Notes on Proof-checker Changes [Note-2-7-proofs] ACL2 Version 2.7 Notes on Changes in Proof Engine [Note-2-7-rules] ACL2 Version 2.7 Notes on Changes in Rules and Constants [Note-2-7-system] ACL2 Version 2.7 Notes on System-level Changes") (NOTE-2-7-BUG-FIXES (NOTE-2-7) "ACL2 Version 2.7 Notes on Bug Fixes Francisco J. Martin-Mateos emailed us a soundness bug (!) in our handling of functional instantiation (for example see [functional-instantiation-example]). We are grateful for that email, which clearly illustrated the problem. It is included just below the definition of push-clause in ACL2 source file prove.lisp, where we have fixed the bug. This bug was fixed in a re-release of Version 2.6 in February, 2002. Rob Sumners emailed us a soundness bug (!) in function commutative-p1, which is used by the ACL2 [bdd] package. We are grateful for his help; his email gave a proof of nil and also pointed to the problem function. This bug was fixed in a re-release of Version 2.6 in February, 2002. We discovered and fixed a soundness bug illustrated by the book below, which was certifiable in Version 2.6 and ends in a proof of nil. The event (verify-guards foo) should have been rejected, because foo calls a function whose guards have not been verified, namely, bar. However, ACL2 did not notice the call of function bar in the body of foo because it was looking in the simplified (normalized) body of foo rather than in the original body of foo. During processing of the book below, the logical definition of zp is used before (verify-guards foo), and (zp -3) reduces to t in the logic. After (verify-guards foo), ACL2 simplifies (foo -3) by going into raw Lisp, where (zp -3) is evaluated and reduces to nil. (in-package \"ACL2\") (defun bar (x) (zp x)) (defthm zp-false-on-negatives (implies (< x 0) (bar x)) :rule-classes :type-prescription) (defun foo (x) (declare (xargs :guard (rationalp x) :verify-guards nil)) (if (< x 0) (if (bar x) 0 1) ; simplified body reduces this line to 0 17)) (defthm foo-of-minus-3-is-0 (equal (foo -3) 0) :rule-classes nil) (verify-guards foo) (defthm foo-of-minus-3-is-1 (equal (foo -3) 1) :rule-classes nil) (defthm bug nil :rule-classes nil :hints ((\"Goal\" :use (foo-of-minus-3-is-0 foo-of-minus-3-is-1)))) The above bug exploited the fact that [zp] has a different definition in raw Lisp than in the logic for arguments that violate its guard). The following example caused a hard error in raw Lisp, though not a soundness error. (in-package \"ACL2\") (defun bar (x) (cons (car x) (car x))) (defun foo (x) (declare (xargs :guard t :verify-guards nil)) (if (bar x) x nil)) (verify-guards foo) (defthm bug (equal (foo 3) t) :rule-classes nil) We have made a minor change to the notion of the formula of a function symbol, related to the change above, which however is unlikely to be noticeable. In order to make it harder to hit problems like the guard problem above, we have slighly modified the raw Lisp definition of [zp]. A [break-rewrite] command, :ancestors, was broken, but has been fixed. Thanks to Eric Smith for bringing the problem to our attention, and to Robert Krug for supplying the final part of the fix. Some [proof-checker] commands caused errors when all goals have already been proved. This has been fixed. Thanks to Matt Wilding for reporting this bug. Fixed a bug in :[comp]. When compiling uncompiled functions with very large definitions, ACL2 was inserted a backslash (\\) character into generated files. Fixed the :type-alist :[brr] command (see [brr-commands]), whose output was difficult to read when typed after an :eval.. Fixed some clumsy handling of errors when including an uncertified book, for example, with the error message when including an uncertified book with a bad [deftheory] event. Thanks to Eric Smith for pointing out this problem. Two modifications to [certify-book] now cause it to reflect natural expectations with respect to soundness. First, it now has default values of nil instead of t for keyword arguments :skip-proofs-okp and :defaxioms-okp. Thanks to Robert Krug for suggesting this change and the ACL2 seminar at the University of Texas for discussing it. Second, when :skip-proofs-okp (respectively, :defaxioms-okp) is nil, either explicitly or by default, then [skip-proofs] commands (respectively, [defaxiom] events) are disallowed inside any included books, regardless of the keyword parameters passed to [include-book]. This had not been the case for previous versions of ACL2, regardless of the values of :skip-proofs-okp or :defaxioms-okp passed to [include-book]. Improved warnings and errors for [certify-book] and [include-book] to mention the [portcullis] as a possible source of [skip-proofs] and [defaxiom]s. ACL2 formerly caused an error when [hints] in a :[corollary] were not well-formed. This situation could arise as follows when certifying a book. A lemma FOO is proved [local]ly to the book (or, is present in a sub-book that is included locally). The :corollary of a subsequent theorem, BAR, disables that rule in a hint. When BAR is proved, this is not a problem. But [certify-book] makes a second pass after processing the events in a book: it essentially does an [include-book]. During the include-book pass, FOO is not known (because it was [local]), and therefore ACL2 fails to process the [disable] of FOO in an [in-theory] hint. The fix is that during [include-book], [hints] are ignored in corollaries just as they have been for the main theorem (or definition). It was possible for guard verification to succeed where it should have failed. We have fixed the bug (which was in source function (ironically named!) fcons-term-smart). Thanks to Robert Krug for sending us an example of bungled guard verification. It turns out that this bug was also present in Version_2.6. The [proof-checker] command = has been improved. Formerly, it could fail to apply when certain [implies] terms were in the context. Thanks to Pete Manolios for bringing this problem to our attention. The command [add-binop] failed to work. This has been fixed. Thanks to Rob Sumners for pointing out this problem. Also see [note-2-7-other] for a discussion of how this and another [table] are no longer part of the [ACL2-defaults-table]. Book certification could cause a segmentation fault in cases where the certification world (see [certify-book]) has a very large number of events. This has been fixed. We now allow empty :use [hints] and empty hints, as requested by Eric Smith. Examples: (\"Goal\" :use ()) (\"Goal\") A large [mutual-recursion] nest could cause a stack overflow when executing either :pr FN, :pr! FN, or :monitor (:definition FN) t, where FN is in that large mutual recursion nest. This has been fixed (implementation detail: function actual-props has been made tail-recursive). NOTE: If you just want the definition of FN, :[pf] FN can be much faster than :[pr] FN if FN is in a large [mutual-recursion]. Hard Lisp errors could occur when including uncertified books. This has been fixed; ACL2 now does syntax-checking formerly omitted when including uncertified books. Previously, the evaluation of [defstobj] and [mutual-recursion] forms could cause ``undefined'' warnings when the form was compiled. This has been fixed. Thanks to Eric Smith for bring a mutual-recursion example to our attention. A bug has been fixed in the syntactic check for valid :[loop-stopper] values. Formerly, valid :loop-stopper values were erroneously restricted to lists of length at most 2 (a minor problem, since these lists typically have length 1), and the function symbol(s) need not have been defined in the current ACL2 [world]. Thanks to Eric Smith for sending an example to demonstrate the latter problem. Functions definitions that are :non-executable (see [xargs]) had never been recognized as redundant, but this has been fixed. Thanks to Vernon Austel for pointing out this problem. Compilation using :[comp] now compiles user-defined :[program] mode functions. Formerly only :[logic] mode functions could be compiled using :comp. Handling of :by hints has been improved in essentially three ways. The primary change is that now, when the current goal exactly matches the supplied lemma instance, the subsumption test will always succeeds (see [hints], in particular the discussion of :by). Second, certain proof failures involving :by [hints] were failing silently, with duplicate messages ``As indicated by the hint, this goal is subsumed by....'' This could happen when the original goal was among the goals generated by applying the hint. This problem has been fixed by no longer considering this proof step to be specious (see [specious-simplification]). Third and finally, when the [lemma-instance] refers to a definition, the original body of that definition is used rather than the simplfied (``normalized'') body. In addition to the obove, we now recognize more cases of specious simplification (see [specious-simplification]). Thanks to Eric Smith for bringing this issue to our attention. Fixed building of ACL2 under CLISP so that (1) the appropriate ACL2 startup message is printed out when ACL2 starts up, and (2) the lisp process supplied to make, e.g., LISP=/usr/bin/clisp, is the one written out to the saved ACL2 file. Thanks to Dave Greve and Noah Friedman for suggesting (2). Also, ACL2 now works with CLISP 2.30. We have accommodated a change in CLISP's handling of streams and its package-locking mechanism, as well as certain non-standard characters that formerly could cause CLISP 2.30 to break, even when those characters are in comments. Eliminated compiler warnings for CMU Lisp. Fixed an incorrect error supplied when book certification proceeded so quickly that the file write dates of the book (.lisp file) and the corresponding compiled file are equal. Now that error only occurs if the compiled file has a strictly earlier write date, which probably should never happen. Fixed an infinite loop when executing make clean-books (and hence `make' with targets that call clean-books, namely, certify-books-fresh, regression-fresh, and regression-nonstd-fresh), which could occur when any subdirectories of books/ are missing --- even workshops/, which is intended to be optional. Thanks to Pete Manolios for pointing out this bug. The [include-book] command now works properly even when filenames, or their directories or parent directories (etc.) are links. Thanks to Matt Wilding for pointing out this problem. The commands :[puff] :[puff*] have been fixed. Formerly, there was a bug when :puff or :puff* caused the execution of an [include-book] for an absolute [pathname], P, that was other than the current connected book directory (see [cbd]). When including P, any subsidiary [include-book] with a relative pathname would be erroneously considered relative to the current [cbd] rather than relative to the directory of P. Thanks to Pete Manolios and Matt Wilding for pointing out this problem. It had been possible in a ``large'' ACL2 image to call [verify-termination] successfully on built-in function [sys-call], with undesirable results. This hole has been plugged. Thanks to Rob Sumners for pointing out this problem. The new function [gc$] must also stay in :[program] mode. ACL2 no longer warns when certifying a book based on [local] functions whose [guard]s have not yet been verified. Thanks to Pete Manolios for pointing out this issue. An occasional ``slow array warning'' had been possible during proofs. The following sequence shows how to evoke that warning in previous versions. (in-theory (disable binary-append)) (in-theory (enable binary-append)) (in-theory (disable binary-append)) (ubt 2) (thm (equal (car (cons x y)) x)) (See [note-2-7-other] for a discussion of a change to [compress1] in support of this fix; however, users should not need to read that discussion.) The raw Lisp code for [defchoose] had a small bug, which was only evidenced in CLISP implementations as far as we know. It has been fixed. When [ld] is applied to a stringp file name, it now temporarily sets the connected book directory (see [cbd]) to the directory of that file while evaluating forms in that file. To see the effect of this change, imagine a subdirectory \"sub\" of the current directory, and imagine executing (ld \"sub/foo.lisp\"), where file foo.lisp contains the form (include-book \"bar\"). Presumably the intention was to consider the file bar.lisp in the same directory, sub/, as foo.lisp. Ld now honors that intention, but in previous versions \"bar.lisp\" would have been a reference to a file in the current directory, not in sub/. For users of run-acl2 [perhaps there are none!]: A fix has been provided by a Debian user via Camm Maguire so that acl2-mode anyone using that?] will work in Xemacs, which apparently uses variable lisp-mode-shared-map rather than shared-lisp-mode-map. ACL2 has, for a long time (always?), had a mechanism for avoiding re-proving [constraint]s generated by :functional-instance [lemma-instance]s in :use and :by hints. But this mechanism had not applied to defined (as opposed to constrained) functions. This has been fixed. Thanks to Francisco J. Martin-Mateos (ChesKo) for pointing out this problem by sending a clear example.") (NOTE-2-7-GUARDS (NOTE-2-7) "ACL2 Version 2.7 Notes on Guard-related Changes It was possible for guard verification to succeed where it should have failed. See the discussion under [note-2-7-bug-fixes]. There have been changes in the guards generated from type declarations for the following cases. Thanks to Dave Greve and Matt Wilding for suggesting such changes. (type (signed-byte n) val) (type (unsigned-byte n) val) (type (integer m n) val) The following examples illustrate the changes. (type (signed-byte 4) x) ==> [old] (AND (INTEGERP X) (<= -8 X) (<= X 7)) ==> [new] (SIGNED-BYTE-P 4 X) (type (unsigned-byte 4) x) ==> [old] (AND (INTEGERP X) (<= 0 X) (<= X 15)) ==> [new] (UNSIGNED-BYTE-P 4 X)") (NOTE-2-7-NEW-FUNCTIONALITY (NOTE-2-7) "ACL2 Version 2.7 Notes on New Functionality ACL2 now has a more powerful technique for relieving a :[rewrite] or :[linear] rule's hypothesis that contains free variables. A new [documentation] section has been written describing the handling free variables in rules; see [free-variables]. In brief, the primary change is that when a free-variable match for the current hypothesis fails to allow subsequent hypotheses to be relieved, then additional matches may be attempted until they have all been tried. Also see [rule-classes] (discussion of :match-free). Also see [set-match-free-error], see [set-match-free-default], and see [add-match-free-override] for interfaces provided to the user for controlling the way ACL2 deals with free variables in hypotheses. We thank Rob Sumners for several helpful discussions about the designs of those interfaces, as well as Eric Smith and Robert Krug for helpful related discussions. Robert Krug also found a performance bug in a preliminary version, for which we are grateful. WARNING: Book certification attempts may take much longer now that, by default, ACL2 looks for more free variable matches (see paragraph just above). You can get the old behavior by inserting the form (set-match-free-default :once) just after the initial [in-package] form. However, rules from included books that have free variables can still slow down certification. This can be fixed by inserting (add-match-free-override :once t) before the first event in the file that generates a proof. [Forward-chaining] has been made more powerful in the presence of free variables (see [free-variables]), thanks to a contribution by Erik Reeber. Both before and now, when an attempt is made to relieve (prove) a hypothesis of a :forward-chaining rule in the case that at least one variable in that hypothesis is not yet bound, ACL2 looks in the current context for an instance of that hypothesis. If it finds one, then it binds the unbound variables and continues to the next hyopothesis. What is new is that ACL2 can now looks for multiple instances of that hypothesis. Consider the following example; an explanation is below. (encapsulate (((op * *) => *)) (local (defun op (x y) (< x y))) (defthm transitivity-of-op (implies (and (op x y) (op y z)) (op x z)) :rule-classes :forward-chaining)) ; fails in Version_2.6; succeeds in in Version_2.7 (thm (implies (and (op a b) (op b c) (op b e)) (op a c))) Before Version_2.7, the proof of the thm above fails. When the :forward-chaining rule transitivity-of-op binds x to a and y to b, it then looks for an instance of (op y z) in the current context, with y bound to b but z unbound. It happens to find (op b e) before (op b c), and it then adds (op a e) to the context. But starting with Version_2.7, it continues to look for additional instances and finds (op b c) in the context as well, chaining forward to (op a c) and thus proving the theorem. A new macro, [bind-free], provides a simple way to get much or most of the power of [meta]functions. Thanks to Eric Smith for coming up with the idea and to Robert Krug for providing an implementation (which we modified only very slightly) and documentation. See [bind-free] and see [bind-free-examples]. With the addition of [bind-free] (mentioned above), [syntaxp] has become a macro, although that change should be transparent to the user. More importantly, the argument of syntaxp may now refer to variables mfc and state, giving syntaxp some of the power of extended metafunctions; see [syntaxp] and see [extended-metafunctions]. Thanks to Robert Krug for implementing that extension. Also, the argument of [syntaxp] may now include calls of :[program] mode functions. See [syntaxp] and see [syntaxp-examples] (thanks to Robert Krug for updating the former and creating the latter documentation). The linear-arithmetic decision procedure (see [linear-arithmetic]) has now been extended so that ACL2 can reason about non-linear arithmetic as well (see [non-linear-arithmetic] for how to turn on this feature). We thank Robert Krug for the initial implementation of this, and Eric Smith for finding a couple of bugs in it. Some [trace] utilities have been made available in the ACL2 loop. * Function [trace$] (and also [untrace$]) calls the corresponding underlying Lisp routine trace (and untrace), which however continues (as it has for some time) to be enhanced for GCL and Allegro CL. * Macro [open-trace-file] causes trace output to go to a specified file. Macro [close-trace-file] causes trace output to go to the screen (which is the default). * Macro with-error-trace (or, wet for short) causes a backtrace to be written out for many failures, including guard violations. See [trace], see [trace$], and see :DOC wet [** NOTE: eliminated after Version 3.3]. A new [theory], [minimal-theory] has been provided (see [theories]). It can be particularly useful for speeding up proofs involving :use [hints]. New [events] [defund] and [defthmd] behave exactly like [defun] and [defthm], respectively, except that these new events disable the new name. The new macro [with-output] can be used to suppress output that would normally result from evaluation of a form. The form ([pstack]) can give the user an idea of what the prover has been up to during a proof, or after a user-aborted proof. Moreover, by evaluating (verbose-pstack t) (see [verbose-pstack]) one can get [trace]-like information about prover functions, including time summaries, printed to the screen during a proof. Thanks to Bill Legato and Robert Krug for initiating this work and to Robert for providing some initial implementation. The new command :[comp-gcl] is identical in functionality, except that it always leaves .c and .h files when compiling in GCL. Thanks to Rob Sumners and Vernon Austel for suggesting such a capability. The macro [e/d] provides a convenient way to [enable] some rules and [disable] others. It was formerly in a book supplied with the distribution, books/ihs/ihs-init.lisp, written by Bishop Brock (who we thank for providing this useful macro). New distributed books include those in books/ordinals/, books/rtl/rel3/, and books/misc/simplify-defuns.lisp (which is documented in books/misc/simplify-defuns.txt). The :expand hint now accepts a special value, :LAMBDAS, that tells the ACL2 rewriter to expand all lambda applications ([let] expressions). See [hints]. A new function [zpf] has been added as fast test against 0 for nonnegative fixnums. A new macro [gc$] allows the user to call the garbage collector of the underlying Common Lisp. Thanks to Rob Sumners for suggesting this feature. It is now possible to [monitor] [simple] (abbreviation) rules. However, as a warning explains, they are still not considered monitored during preprocessing; see [monitor]. Thanks to Robert Krug for providing this improvement. The second argument of [certify-book], if supplied, formerly had to be either t or a non-negative integer. Now it can be the symbol ?, in the ACL2 package, indicating that the usual check should be suppressed on the number of commands that have been executed to create the world in which [certify-book] was called.") (NOTE-2-7-OTHER (NOTE-2-7) "ACL2 Version 2.7 Notes on Miscellaneous Changes Made several minor [documentation] improvements. We are grateful to Eric Smith for suggesting (most of) these. Improved (show-bdd) (see [bdd]) to give more useful feedback when there are ``leaf'' terms not known to be Boolean. Sped up processing of large mutual-recursion nests. In one large example the speedup was roughly two orders of magnitude. Modified event printing so that if both 'prove and 'event are inhibited, then events are no longer printed on behalf of [certify-book], [encapsulate], or [defstobj]. Thanks to Eric Smith for prompting consideration of such a change. The following technical change was made to support with-error-trace and wet (see [note-2-7-new-functionality]), but may be of interest to those who do low-level programming using the ACL2 logical [world]. The 'unnormalized-body property is now stored not only for functions defined in :[logic] mode, but also for functions defined by the user in :[program] mode. (:Program mode Functions built into ACL2 still have their 'unnormalized-body property omitted, in order to save space.) The handling of ``invisible'' functions for purposes of controlling rewriting (see [loop-stopper]) has been moved to a new table; see [invisible-fns-table]. Macros that access and modify this table are called ``...-invisible-fns-table'' in place of their former names, ``...-invisible-fns-alist.'' This feature was formerly implemented in the [ACL2-defaults-table], which prevented a book from exporting lists of invisible functions intended to work with the [rewrite] rules developed in the book. Thanks to Eric Smith and Rob Sumners for suggesting this change. See [set-invisible-fns-table] (formerly set-invisible-fns-alist), and also see [add-invisible-fns] and see [remove-invisible-fns], which provides ways to incrementally add to and remove from this table, respectively. The handling of printing binary function call nests using macros (See [add-binop]) has also been moved out of the [ACL2-defaults-table] as suggested by Eric and Rob, but this feature didn't work anyhow (see [note-2-7-bug-fixes]). Incidentally, the symbols binop-table, [add-binop], and [remove-binop] have all been added to the list *acl2-exports* (see [ACL2-user]), [add-invisible-fns] and [remove-invisible-fns] have been added to that list, and set-invisible-fns-alist has been replaced in that list by [set-invisible-fns-table]. Function invisible-fns-alistp is no longer defined and has been removed from *acl2-exports*. We now enforce the stated restriction on the pairings in macro-aliases-table (see [macro-aliases-table]), namely, that it associates names of macros with names of funcions (with respect to the current ACL2 logical [world]). We make a similar requirement on [invisible-fns-table]. The [theory-invariant] event has been modified so that the default action is an error rather than a warning. Thanks to Eric Smith for suggesting this change. Also, the value returned upon successful execution of a [theory-invariant] event is now the key. Proof output that reports destructor elimination no longer uses the word ``generalizing''. This small change may help in browsing proof output, since now ``generaliz'' takes you to true uses of generalization. Thanks to Matyas Sustik for suggesting such a change. The command :[pl] now prints an abbreviated controller-alist for ;[definition] rules. Formerly the output from :pl could be overwhelming when the supplied function was part of a large [mutual-recursion] nest. The defaults for keyword parameters of [certify-book] have changed. See [note-2-7-bug-fixes], in particular, the discussion there of two modifications to certify-book. Technical changes have been made to [compress1] and [compress2] that should usually be invisible to users. The next paragraph describes them in detail, only for competeness (i.e., that description can be ignored by most users). But first, here is an example showing an effect on users. The slow array warning was not there previously. Notice that the warning only arises if the event form is changed. The solution is to be sure that redundant [defconst] forms are syntactically identical. ACL2 !>(defconst *a* (compress1 'demo '((:header :dimensions (5) :maximum-length 15 :default uninitialized :name demo) (1 . one) (0 . zero)))) Summary Form: ( DEFCONST *A* ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) *A* ACL2 !>(aref1 'demo *a* 0) ZERO ACL2 !>(defconst *a* (compress1 'demo '((:header :dimensions (5) :maximum-length 15 :default uninitialized :name demo) (1 . one) (0 . zero)))) This event is redundant. See :DOC redundant-events. Summary Form: ( DEFCONST *A* ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) :REDUNDANT ACL2 !>(aref1 'demo *a* 0) ZERO ACL2 !>(defconst *a* (compress1 'demo '((:header :dimensions (5) :maximum-length 15 :default uninitialized :name demo) (0 . zero) (1 . one)))) This event is redundant. See :DOC redundant-events. Summary Form: ( DEFCONST *A* ...) Rules: NIL Warnings: None Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) :REDUNDANT ACL2 !>(aref1 'demo *a* 0) ********************************************************** Slow Array Access! A call of AREF1 on an array named DEMO is being executed slowly. See :DOC slow-array-warning ********************************************************** ZERO ACL2 !> As before, the von Neumann structure stored in the 'acl2-array property of the array name contains the array list object in its [car]. However, previously it was the case that compress1 and compress2 did not update that car when its new value would be equal to its old value. This was done largely in support of some type-set tables defined using [defconst] in type-set-b.lisp. The new versions of [compress1] and [compress2] are simpler in that no such exception is made in the case of equal lists, although instead the entire compression process is short-circuited when the input array list object is [eq] to the car of the 'acl2-array property. This change was made because the equality test was causing a ``slow array access'' warning to be printed in rare cases during proofs, as described elswhere (see [note-2-7-bug-fixes]). We no longer distribute documentation specific to Lucid Emacs. The Info documentation in directory doc/EMACS/ works well both for Gnu Emacs and XEmacs. A little-advertised macro, value, has long been allowed for top-level forms in [books]; see [embedded-event-form]. This has been replaced by a new macro, value-triple. The two have the same semantics at the top-level of books, where [state] is ``live''. However, value-triple should be used at the top-level of a book, while value should be used in function definitions (as before). This change eliminates a warning put out by the Allegro Common Lisp compiler for top-level value forms in [books].") (NOTE-2-7-PROOF-CHECKER (NOTE-2-7) "ACL2 Version 2.7 Notes on Proof-checker Changes Output from the [proof-checker] can now be inhibited by supplying the symbol proof-checker in the list given to [set-inhibit-output-lst].") (NOTE-2-7-PROOFS (NOTE-2-7) "ACL2 Version 2.7 Notes on Changes in Proof Engine An improvement in the linear arithmetic heuristics has been provided by Robert Krug. For information about this change, search for the comment in add-linear-lemma (file rewrite.lisp) that begins as follows. ; Previous to Version_2.7, we just went ahead and used the result of Thanks, Robert! Also thanks to Eric Smith for providing a motivating example. The non-linear-arithmetic addition (see [non-linear-arithmetic]) led to several small changes in the linear-arithmetic decision procedure (see [linear-arithmetic]). Two of these changes could affect existing proofs. First, when we are setting up the initial arithmetic database (which we call the ``pot-lst''), we have always scanned it to see if there were any pairs of inequalities from which we could derive a previously unknown equality. In some cases we added this equality to the clause and in others we used it to rewrite the clause, substituting one side of the equality for the other throughout the clause. Previously, the heuristics that we used to determine whether we performed the substitution differed from those used in several other places in the code. This has now been regularized, and similar heuristics are now used throughout the code. The second change to the linear-arithmetic decision procedure is that we now explicitly add inequalities derived from type reasoning to the pot-lst. Previously, we performed cancellations against these inequalities without adding them to the pot-lst. This change results in there being more inequalities in the pot-lst than before, and so more chances for there to be a pair of inequalities from which an equality can be derived. In effect, certain simple consequences of the current goal (see [type-set]) may now be added as hypotheses of the goal or used to peform equality substitutions. A slight improvement has been made to the way certain rewrite rules are stored. It was already the case that a rewrite rule rule whose conclusion C is not a call of a known equivalence relation (or [eq], [eql], or [=]) is stored as (iff C t), except that if ACL2 can determine (using its [type-set] mechanism) that C is Boolean, then the rule is stored as (equal C t). The iprovement is that if C and C' are Boolean, then a rule stated as (iff C C') is stored as (equal C C'). Thanks to Pete Manolios for providing an example that led us to consider this improvement. The heuristic use of equalities (fertilization) has been modified. Previously, ACL2 would sometimes substitute using an equality but keep the equality, and then undo the substitution by using the equality again. Now, when ACL2 keeps an equality after using it, it puts the equality inside a call of [hide]. Descendents of that goal that are unchanged by simplification will have this call of [hide] removed so that the equality can once again contribute to the proof. This change can cause some proofs to succeed that otherwise would fail. In the unlikely event that a proof fails that formerly succeeded, the following hint on \"Goal\" may fix the problem (see [hints]): :expand ((:free (x) (hide x))) We have refined the heuristics employed when an [if] form is assumed true or false. Our previous attempt (see [note-2-6-proofs] for the original announcement) was not as general as we had believed. We have also improved some low-level code responsible for rewriting IF expressions. In earlier versions of ACL2, it was possible to have the truth or falsity of an IF expression explicitly recorded in the type-alist, and yet not use this information during rewriting. This problem has been corrected. Thanks to Robert Krug for noticing this problem and implementing the fix. We have sped up the rewriter in some cases where there are large collections of mutually-recursive functions (see [mutual-recursion]). (Implementation notes: technically, we have modified the way function being-openedp operates on the fnstack, and we have modified *current-acl2-world-key-ordering* as described in the essay above its definition.) [Forward-chaining] is now done in the preprocessing phase of proof attempts (see the discussion of :DO-NOT --- see [hints]). This is part of a technical change, made in support of translation of type declarations to [guard]s (see [note-2-7-guards]). Previously, whenever ACL2 checked for [built-in-clause]s, it then looked for a contradiction using [type-set] reasoning if it did not find a suitable built-in clause. The change is to perform forward-chaining in such cases (i.e., when a built-in clause is not found). A couple of changes have been made in the generation of goals for [forcing-round]s. Thanks to Eric Smith for bringing issues to our attention that led to these changes. For one, [guard]s are no longer relevant in such goal generation. Formerly, the addition of a guard could make a proof fail that otherwise succeeded. Secondly, contextual information is now always kept when it involves a constrained constant, i.e., a zero-ary function introduced in the signature of an [encapsulate].") (NOTE-2-7-RULES (NOTE-2-7) "ACL2 Version 2.7 Notes on Changes in Rules and Constants The [defcong] macro has been slightly changed. The difference is that the variable generated with suffix -EQUIV will now be in the same package as the name of the variable from which it is generated, rather than always belonging to the ACL2 package. Thanks to Hanbing Liu for suggesting this change. (Note that a couple of books have been modified to accommodate this change, e.g., books/finite-set-theory/set-theory.) In Version_2.6, a change was made for rules of class :[rewrite] whose conclusion is a term of the form (EQV lhs rhs), where EQV is [=], [eq], or [eql]: the rule was stored as though EQV were [equal]. (See [note-2-6-rules].) This change has been extended to rules of class :[definition].") (NOTE-2-7-SYSTEM (NOTE-2-7) "ACL2 Version 2.7 Notes on System-level Changes ACL2 now runs (once again) under LispWorks, specifically, LispWorks 4.2.0. However, we needed a patch, which presumably will be unnecessary after 4.2.7. From LispWorks support: Users with LispWorks4.2.7 should ask us at lisp-support@xanalys.com for the transform-if-node patch. It will be helpful if they quote (Lisp Support Call #11372) when doing so. Also, they must send a bug form generated from their LispWorks image: instructions at http://www.lispworks.com/support/bug-report.html. File books/Makefile-generic has been improved so that failed attempts to certify a book will cause the `make' to fail. Previously, an existing .cert file was left in place, and that sufficed for the `make' to be considered a success. Now, the old .cert file is first removed when recertification is found to be necessary. A change has been made to source file acl2.lisp to accommodate GCL 2.4.3. (ACL2 Version 2.6 does not work with some versions of GCL 2.4.3.) The error message has been improved when certain forms are typed to raw Lisp and the ACL2 loop has never been entered (with ([lp])). The following symbols in the ACL2 package have been made untouchable, meaning that they are not available to the user: ev-fncall, ev, ev-lst, ev-acl2-unwind-protect, ev-fncall!, and user-stobj-alist-safe. The reason is that these functions can not be called safely except under certain restrictions. If you want to call the ACL2 evaluator, consider using the built-in system functions trans-eval or simple-translate-and-eval. CLISP Version_2.30 implements a notion of ``locking'' the \"LISP\" package that is incompatible with building ACL2. (CLISP Version_2.27 does not appear to have had this feature.) We have gotten around this problem by unlocking the \"LISP\" package in ACL2 images built on such CLISPs. Automatic proclaiming for GCL, which has (for a long time) been done for functions in compiled books, has been improved. Formerly, the only time a non-trivial output type (i.e., other than t) was inferred was when macroexpansion produced an explicit call of [the]. Now, [if] expressions can also generate non-t output types. Consider the following example. (defmacro the-fixnum (n) (list 'the '(signed-byte 29) n)) (defmacro 1+f (x) (list 'the-fixnum (list '1+ (list 'the-fixnum x)))) (defun foo (x) (declare (type (unsigned-byte 27) x)) (if (zp x) 0 (1+f (foo (1-f x))))) Formerly, the proclaim forms for foo, before and after this improvement, are as shown below. (PROCLAIM '(FTYPE (FUNCTION ((UNSIGNED-BYTE 27)) T) FOO)) ;old (PROCLAIM '(FTYPE (FUNCTION ((UNSIGNED-BYTE 27)) (SIGNED-BYTE 29)) FOO)) ;new Compiler info messages sent to error stream were eliminated for CMUCL.") (NOTE-2-7{R} (RELEASE-NOTES) "ACL2 Version 2.7(r) (November, 2002) Notes In source file axioms.lisp, in order for proofs to succeed, (make proofs), the definitions of [ACL2-count] and explode-atom have been modified slightly, and lemma standard-numberp-one [modified after Version_3.4 to become standardp-one] has been given :rule-classes nil. All [skip-proofs] forms have been eliminated from the nonstd books, thanks to Ruben Gamboa. The directory books/sqrt/, which was intended for ACL2(r), has been moved to books/nonstd/sqrt/ and added as appropriate to books/nonstd/Makefile. Please see [note-2-7] for changes to Version_2.7 of ACL2.") (NOTE-2-8 (RELEASE-NOTES) "ACL2 Version 2.8 (March, 2004) Notes BRIEF SUMMARY. The Version_2.8 notes are divided into the indicated subtopics. Here we give only a brief summary of just a few of the major new features and changes that seem most likely to impact existing proofs. Not included in this brief summary, but included in the subtopics, are descriptions of many improvements (including bug fixes and new functionality) that should not get in the way of existing proof efforts. In the description below we also omit discussion of changes that will become clear by way of error messages if they affect you. In particular, please see [note-2-8-new-functionality] for discussion of a number of new features that you may find useful. Acknowledgements and elaboration, as well as other changes, can be found in the subtopics listed below. Some of the bug fixes (see [note-2-8-bug-fixes]) * Some soundness bugs were fixed. * The handling of free variables in hypotheses (see [free-variables]) of rewrite and linear rules had a bug that prevented some proofs from going through. Now that this bug has been fixed, you may find some proofs running much more slowly than before. You can use [accumulated-persistence] and [add-match-free-override] to remedy this situation; see [note-2-8-bug-fixes] for details. * The [default-hints] in the current logical [world] are no longer ignored by [verify-guards]. * Forms violating guard-checking such as (defconst *silly* (car 3)) are now allowed in [books]. Some of the new functionality (see [note-2-8-new-functionality]) * WARNING: You may find that control-d (in emacs, control-c control-d) can throw you completely out of Lisp where it had not formerly done so. * ACL2 now starts up inside the ACL2 loop --- that is, ([lp]) is executed automatically --- when built on CLISP or Allegro CL. This was already the case for GCL and CMUCL, and it still is not true for LispWorks. * See [note-2-8-ordinals] for a discussion of a significant change in ordinal represtation, and in particular, for how to preserve existing proofs that depend on the previous ordinal representation. * Macros [mbe] (``must be equal''), [mbt] (``must be true''), and [defexec] have been introduced, which allow the user to attach alternate executable definitions to functions. * The user can now control multiple matching for free variables in hypotheses for :[forward-chaining] rules, as has already been supported for :[rewrite] and :[linear] rules. * It is no longer necessary to specify (set-match-free-error nil) in order to avoid errors when a rule with free variables in its hypotheses is missing the :match-free field. * The form (break-on-error) causes, at least for most Lisps, entry into the Lisp debugger whenever ACL2 causes an error. * A new [table] has been provided so that advanced users can override the built-in untranslate functionality. See [user-defined-functions-table]. * The [pstack] (`process [prover] stack'') mechanism, formerly denoted checkpoints, has been improved. One of these improvements is to show actual parameters with (pstack t) rather than formals. * The [defstobj] event is now allowed to take an :inline argument, which can speed up execution. * Macro [cw-gstack] no longer takes arguments for the gstack or [state]. To print terms in full rather than abbreviated: (cw-gstack :evisc-tuple nil). * The [include-book] event now has an additional (optional) keyword, :dir. In particular, (include-book \"foo/bar\" :dir :system) will include the indicated book after prepending the path of the built-in books/ directory. You will probably not find :dir :system to be useful if you move the executable image or distributed books; see [include-book], in particular its ``soundness warning''. * The printing of results in raw mode (see [set-raw-mode]) may now be partially controlled by the user: see [add-raw-arity]. * For those using Unix/Linux `make': A cert.acl2 file can contain forms to be evaluated before an appropriate [certify-book] command is invoked automatically (not included in cert.acl2). Some of the changes in the proof engine (see [note-2-8-proofs]) * ACL2 now prevents certain rewriting loops; see [rewrite-stack-limit]. * Small changes have been made to heuristics for controlling rewriting during proofs by induction and in handling certain ``weak'' [compound-recognizer] rules. * The handling of free variables in a hypothesis of a [rewrite] rule (see [free-variables]) has been improved in the case that the hypothesis is of the form (equiv x y), where equiv is a known equivalence relation (see [equivalence]). * We have modified how the ACL2 simplifier handles the application of a defined function symbol to constant arguments, by avoiding the introduction of [hide] when evaluation fails if the term can be rewritten. * The generation of \"Goal\" for recursive (and mutually-recursive) definitions now uses the subsumption/replacement limitation (default 500). See [case-split-limitations]. * Default hints now apply to hints given in definitions, not just theorems. See [default-hints]. * Linear arithmetic now uses the conclusions of [forward-chaining] rules, and [type-set] now uses a small amount of linear reasoning when deciding inequalities. Some of the changes in rules, definitions, and constants (see [note-2-8-rules]) * See the above doc topic. Guard-related changes are described in see [note-2-8-bug-fixes] Some of the proof-checker changes (see [note-2-8-proof-checker]) * Added new [proof-checker] commands wrap1, wrap, and wrap-induct, to combine multiple conjuncts or goals. * The type-alist command now takes optional arguments that control whether or not the governors and/or conclusion are used in computing the context. Some of the system-level changes (see [note-2-8-system]) * ACL2 now runs on OpenMCL and on MCL 5.0. Some of the other changes (see [note-2-8-other]) * Emacs file emacs/emacs-acl2.el has been updated (see [note-2-8-other] for details). * When :pl is given a term other than a symbol, it will print all rewrite rules that match that term. * A new function, [pkg-witness], returns a symbol in the given package. * The list constant *acl2-exports* has been extended. * A new release of the rtl library has been included: books/rtl/rel4/. See the README file in that directory. Again, please proceed to the subtopics for more thorough release notes. Subtopics [Note-2-8-bug-fixes] ACL2 Version 2.8 Notes on Bug Fixes [Note-2-8-guards] ACL2 Version 2.8 Notes on Guard-related Changes [Note-2-8-new-functionality] ACL2 Version 2.8 Notes on New Functionality [Note-2-8-ordinals] ACL2 Version 2.8 Notes on Changes to the Ordinals [Note-2-8-other] ACL2 Version 2.8 Notes on Miscellaneous Changes [Note-2-8-proof-checker] ACL2 Version 2.8 Notes on Proof-checker Changes [Note-2-8-proofs] ACL2 Version 2.8 Notes on Changes in Proof Engine [Note-2-8-rules] ACL2 Version 2.8 Notes on Changes in Rules, Definitions, and Constants [Note-2-8-system] ACL2 Version 2.8 Notes on System-level Changes") (NOTE-2-8-BUG-FIXES (NOTE-2-8) "ACL2 Version 2.8 Notes on Bug Fixes We have fixed a soundness bug in the tautology checker's handling of expressions of the form (not (not x)). This bug has gone back at least as far as Version_2.4. All of the regression tests passed after the fix, without modification. So we hope that this bug has rarely bitten anyone. Thanks to Qiang Zhang for sending us a proof of nil that led us to this fix: (thm (equal (and p q) (not (or (not p) (not q))))). And thanks to Matyas Sustik for an observation that led to an improvement of our initial fix. The preceding version (2.7) introduced a soundness bug in handling of ACL2 [arrays], in which functions [compress1] and [compress2] were returning the input alist rather than compressing it appropriately. Here is a proof of nil that no longer succeeds, based on a bug report from Warren Hunt, who we thank for bringing this problem to our atttention. (defthm bad (not (let* ((ar2 (aset1 'my-array ar1 3 10)) (ar3 (compress1 'my-array ar2)) (ar4 (reverse (reverse ar2))) (ar5 (compress1 'my-array ar4))) (and (equal ar2 ar4) (not (equal ar3 ar5))))) :rule-classes nil) (defthm contradiction nil :rule-classes nil :hints ((\"Goal\" :use ((:instance bad (ar1 (compress1 'my-array '((3 . 5) (:HEADER :DIMENSIONS (5) :MAXIMUM-LENGTH 6 :DEFAULT 0 :NAME MY-ARRAY))))))))) On a related note, a new function [flush-compress] can be used for subtle control of under-the-hood raw Lisp support for fast array access, although we expect it to be very rare that users need this extra support. Previous versions have had two soundness bugs that can occur when using the [proof-checker]: * The first bug pertains to the expand command, and hence x and x-dumb commands (which call expand); see [proof-checker-commands]. The bug can occur when applying the above commands when the current term is a call of a constrained function symbol for which there is a :[definition] rule. Now, the expand command will succeed only when the function symbol of the current term is a defined function symbol, in which case the original definition is always used, in analogy to how the :expand hint works in the prover; see [hints]. Thanks to John Erickson for sending an example that led us to wonder if there might be a soundness problem. * The second bug pertains to the s command (and commands that call it, e.g., s-prop). The proof-checker forms a context out of the top-level hypotheses and the if-terms governing the current term. If there is a contradiction in the top-level hypotheses, the proof-checker can appropriately consider the goal to be proved, and it does so. But formerly, the criterion was weaker: the contradiction could involve the combination of the top-level hypotheses and if-term governors. Thanks to Rob Sumners for noticing this bug. A soundness bug could be provoked in some Lisps by applying [defpkg] to the empty string. This has been disallowed. We fixed a soundness bug related to packages caused by a failure to track axioms introduced [local]ly on behalf of [defpkg] events. See [hidden-death-package]. We fixed a soundness bug caused by a failure to check that a :[type-prescription] rule can be processed when proofs are skipped or under a [defequiv] event. The former case can occur when processing an [encapsulate] or [include-book] event, where the rule could depend on a [local] :[compound-recognizer] rule preceding the proposed :[type-prescription] rule under the same [encapsulate] or [include-book] event. See [local-incompatibility] for such an example. We fixed a potential soundness bug relating to reclassifying a :program mode function to :logic mode (as done by [verify-termination] or the submission of an appropriate ``redundant'' definition) without adequate checking that [stobj] usage was identical. Allegedly redundant definitions must now preserve the stobjs declaration as well as the formals, body, guard and type declarations. We thank Vernon Austel for pointing out this problem. It was possible to get a raw Lisp error by introducing a [local]ly defined function with [guard] verification inhibited and then subsequently introducing the same definition non-locally without that inhibition. The following example will clarify. (encapsulate nil (local (defun foo (x) (declare (xargs :guard t :verify-guards nil)) (car x))) (defun foo (x) (declare (xargs :guard t)) (car x))) ; The following causes a raw lisp error because ACL2 runs the Common Lisp ; definition of foo, because it thinks that foo's guard of t was verified. (thm (equal (foo 3) xxx)) Thanks to Jared Davis for bringing this problem to our attention. We are particularly grateful to Jared because his example exploited this bug by applying it to a function defined using [mbe] (introduced in this same version, 2.8), in order to prove nil! The sort of error message shown below can legitimately occur when certifying a book in a certification world where there was an [include-book] command with a relative pathname (see [pathname]). However, it was occurring more often than necessary. This has been fixed. ACL2 Error in (CERTIFY-BOOK \"foo\" ...): The certification world has include-book commands for book \"bar\" that correspond to different full pathnames, namely \"/u/dir1/bar\" and \"/u/dir2/bar\". ACL2 cannot currently certify a book in such a world. To work around this problem, use an absolute pathname for at least one of these books (see :DOC pathname). Bugs were fixed in [with-output], in particular related to the use of values :all. Also, documentation for with-output has been improved. Thanks to Vernon Austel for pointing out the bugs. Fixed a lisp error occurring when bash proof-checker command was given illegal syntax, e.g., (bash ((\"Goal\" :in-theory (enable binary-append)))) instead of (bash (\"Goal\" :in-theory (enable binary-append))). We added an appropriate guard to [find-rules-of-rune], which will avoid hard lisp errors when this function is called on non-[rune] arguments. Thanks to Eric Smith for pointing out this issue. It was possible for a redundant [include-book] form (see [redundant-events]) to leave a [command] in the ACL2 logical [world] and to cause (re-)loading of a compiled file. These behaviors have been fixed. In particular, if book1 has already been included in the current ACL2 [world] and (include-book \"book1\") occurs in book2, then the compiled file for book1 will not be loaded again when book2 is included. Thanks to Dave Greve for bringing our attention to these problems, and to Eric Smith for bringing up a special case earlier (where \"//\" occurred in the book name). The summary printed at the end of a proof had not listed :[induction] rules used in a proof. This has been corrected. The use of proof trees in emacs redefined `control-c control-c' in such a way that in telnet mode, the telnet session was interrupted and perhaps could not be continued. This has been fixed. Source function load-theory-into-enabled-structure contained a guard-violating call of [compress1]. Thanks to Vernon Austel for bringing this problem to our attention; even though this bug was benign (as he pointed out), we like keeping the source code free of guard violations. A number of proof-checker atomic macros caused a hard error when all goals have already been proved. This has been fixed. Thanks to John Erickson for sending an example of the issue. A bug has been fixed in [add-match-free-override]. Formerly, a [table] [guard] violation occurred when calling [add-match-free-override] more than once with first argument other than :clear. Defininitions of functions involving large constants could cause stack overflows. This has been fixed, at least in some of the most egregious cases (by making a source function fn-count-evg tail-recursive). Thanks to Jared Davis for bringing this problem to our attention. Evaluation of computed hints could cause stack overflows. This has been fixed. Thanks to Eric Smith for bringing this problem to our attention. Evaluation of :[monitor] on :[definition] [rune]s is now fast even if the specified function is part of a very large [mutual-recursion] nest. Thanks to Eric Smith for sending an example showing that this wasn't always the case. Fixed a bug in books/bdd/cbf.lisp that was causing certification of distributed bdd books to fail when the connected book directory (see [cbd]) differs from the current working directory. Thanks to Scott Guthery for bringing this bug to our attention and supplying a helpful log. Duplicate rule names have been eliminated from warnings generated upon the use of enabled :[rewrite] or :[definition] rules. Thanks to Eric Smith for pointing out this problem. The trace utilities (see [trace]), as modified for GCL and Allegro Common Lisp, had failed to show more than the first return value for so-called ``*1*'' functions (essentially, [executable-counterpart] functions) when they were returning multiple values (via [mv]). This has been fixed. Thanks to Erik Reeber for pointing out this problem. Also, it is now possible to refer to arglist in [trace$] forms when ACL2 is built on GCL, not just when ACL2 is built on Allegro Common Lisp. Uses of [hide] introduced during proofs by failed attempts to evaluate constrained functions (see [hide]) are now tracked, so that the [rune] (:DEFINITION HIDE) will show up in the summary. The following bug, introduced back in Version 2.7, has been fixed. The bug applied only to GCL and may well not have affected anyone. But the function proclamation computed by ACL2 for compilation usually had an output type of nil where it should have been t. The macro [gc$] had a bug exhibited when it was supplied one or more arguments. This has been fixed. The macro [defabbrev] broke when supplied a string and no documentation, e.g., (defabbrev foo () \"\"). Thanks to Rob Sumners for noticing this problem and providing a fix, which we have incorporated. For ACL2 executables built on Allegro Common Lisp, a Lisp error occurred when [trace$] was called on other than a defined function symbol. Now ACL2 prints a more useful error message. The proof-checker no longer accepts a ([verify]) command when some function symbol in the original goal no longer exists in the current ACL2 logical [world]. Thanks to John Erickson for bringing this issue to our attention. The function ld-redefinition-action may now be called by the user. Thanks to Vernon Austel for suggesting that we remove this symbol from the list of so-called untouchables. The handling of free variables in hypotheses (see [free-variables]) of rewrite and linear rules had a bug that prevented some proofs from going through. Here is a simple example, essentially provided by Diana Moisuc, who we thank for bringing this issue to our attention. The proof of the [thm] below had failed, but now will succeed. This particular bug prevented, for example, the :all behavior from occurring when the first hypothesis of the rule does not have free variables. NOTE: Now that this bug has been fixed, you may find some proofs running much more slowly than before. You can use [accumulated-persistence] to locate rules that are slowing down your proofs because of excessive attention to free variables, and then execute [add-match-free-override] for those rules (or, just change the rules themselves to specify :once in the :[rule-classes]). (defstub foo1 (* ) => *) (skip-proofs (defthm aux-foo1 (implies (and (integerp a) (integerp i) (equal (foo1 0) (list 0 i))) (equal (foo1 a) (list 0 (+ a i)))) :rule-classes ((:rewrite :match-free :all)))) (thm (implies (and (integerp i) (integerp a) (equal (foo1 0) (list 0 i))) (equal (foo1 a) (list 0 (+ a i))))) Formerly, creation of large arrays could cause an error in the underlying Common Lisp implementation without helpful messages for the user. Now, we check Common Lisp restrictions on arrays and print a helpful error message if they are violated, namely: each dimension must be less than the value of Common Lisp constant array-dimension-limit, and the product of the dimensions must be less than the value of Common Lisp constant array-total-size-limit. Thanks to Warren Hunt for bringing this issue to our attention. Note: this change also removes a former restriction of [stobj] array fields to size smaller than 2^28-1, provided the underlying Lisp can support larger arrays. The [default-hints] in the current logical [world] were ignored by [verify-guards]. This has been fixed. Thanks to Jared Davis for pointing out this bug and sending a helpful example. The [brr] mechanism has been cleaned up in order to avoid hard errors and infinite loops that can arrive when typing interrupts (control-c) or end-of-files (control-d) inside the [brr] loop. Thanks to Dave Greve, Olga Matlin, Eric Smith, and Serita Van Groningen for bringing this issue to our attention. As a byproduct, if you type control-d (or if inside emacs, control-c control-d), you may now quit entirely out of ACL2 and lisp (see [good-bye]) in some cases where you formerly would not have, for example when sitting at the ACL2 prompt (which formerly, in Allegro Common Lisp for example, would merely take you into raw Lisp rather than quitting everything). We have eliminated structural flaws in the HTML documentation pages that could make them unreadable in some browsers. Thanks to Bill Young for bringing this issue to our attention and to Joe Hendrix for diagnosing the problem. The [proof-checker] could run very slowly after many instructions in a given session. This has been fixed; thanks to Art Flatau for bringing this problem to our attention. (Implementation detail: We now keep tag-trees duplicate-free when we accumulate them into state. This change could have minor speed advantages for some top-level proofs too, not just in the proof-checker.) The printing of accesses to stobjs using nth or update-nth has been done using symbolic constants since ACL2 Version_2.6. However, there was a bug that prevented this feature from working for [update-nth] except at a top-level call. This has been fixed. Thanks to Julien Schmaltz for bringing this problem to our attention. For example, consider these events: (defstobj st field0 field1) (thm (equal (nth 1 (update-nth 0 17 st)) (car (cons xxx yyy))) :hints ((\"Goal\" :in-theory (disable nth update-nth)))) Before the fix, the proof attempt of the above silly thm printed the following. (NTH 1 (UPDATE-NTH *FIELD0* 17 ST)) After the fix, we instead see the following. (NTH *FIELD1* (UPDATE-NTH *FIELD0* 17 ST)) It is now possible to certify and subsequently include [books] that require guard-checking to be off. For example, the book can contain the form (defconst *silly* (car 3)) even though 3 fails to satisfy the guard of [car]. Formerly, it was necessary to execute :[set-guard-checking] nil before a [certify-book] or [include-book] in order for such a form to be handled without error. Thanks to Hanbing Liu for bringing this problem to our attention. Fixed a [proof-checker] bug that could cause probably cause strange error, ``Attempt to access the plist field''. Thanks to Bill Young for bringing this problem to our attention. Fixed a [proof-checker] bug that was failing to record applications of rewrite rules using the proof-checker's :rewrite command, causing the proof summary to omit mention of that rule (for example, when using the proof-checker's :exit command to generate an :instructions hint). Thanks to Bill Young for pointing out this bug. Modernized some of the proof-tree emacs and infix printing stuff, thanks to suggestions made by Camm Maguire.") (NOTE-2-8-GUARDS (NOTE-2-8) "ACL2 Version 2.8 Notes on Guard-related Changes All the guard-related changes may be found elsewhere; in particular, see [note-2-8-bug-fixes].") (NOTE-2-8-NEW-FUNCTIONALITY (NOTE-2-8) "ACL2 Version 2.8 Notes on New Functionality WARNING: You may find that control-d (in emacs, control-c control-d) can throw you completely out of Lisp where it had not formerly done so. (CLISP and Allegro CL only) ACL2 now starts up inside the ACL2 loop --- that is, ([lp]) is executed automatically --- when built on CLISP or Allegro CL. This was already the case for GCL and CMUCL, and it still is not true for LispWorks. Thanks to Joe Corneli for bringing the CLISP command-line option \"-i\" to our attention, which led to this CLISP change and inspired reconsideration of how to do this for Allegro CL. Pete Manolios and Daron Vroon have changed the representation of ordinals in ACL2, defined algorithms for ordinal arithmetic, and created a library of theorems to reason about ordinal arithmetic. We thank them for these nice contributions. See [note-2-8-ordinals] for details, in particular, for how to preserve existing proofs that depend on the previous ordinal representation. Sometimes users create rules of class :[rewrite] that cause an infinite loop in the ACL2 rewriter. This has lead to Lisp stack overflows and even segmentation faults. Now, the depth of calls of functions in the ACL2 rewriter is limited, and under user control. See [rewrite-stack-limit]. Macros [mbe] (``must be equal'') and [mbt] (``must be true'') have been introduced, which allow the user to attach fast executable definitions to (presumably slower) :[logic] mode functions. Thanks to Vernon Austel for a key idea. Also provided is a macro [defexec], which employs [mbe] but enforces the requirement that the executable definition also terminates. Thanks to Jose Luis Ruiz Reina for collaborating in the design and development of [defexec], and for useful comments from a number of others as well in the development of mbe including Joe Hendrix and Rob Sumners. Definitions have been added for functions [rassoc-eq] and [rassoc-equal], which are like [rassoc] but use different tests and have different guards. (Compare [assoc-eq] and [assoc-equal], which are in similar relation to [assoc].) The user can now control multiple matching for free variables in hypotheses for :[forward-chaining] rules, as has already been supported for :[rewrite] and :[linear] rules. For :forward-chaining rules, ``free variables'' are those in the hypotheses not bound by a given trigger term. As for :rewrite and :linear rules, free-variable matching may be limited to the first successful attempt by specifying :match-free :once with :forward-chaining in the :[rule-classes], and [add-match-free-override] may be used to modify the behavior of an existing rule. Thanks to Erik Reeber for most of the implementation of these new capabilities, as well as significant assistance with a corresponding new documentation topic (see [free-variables-examples-forward-chaining]). It is no longer necessary to specify (set-match-free-error nil) in order to avoid errors when a rule with free variables in its hypotheses is missing the :match-free field. (This was already true during book certification, but now it is the case in interactive sessions as well.) The form (break-on-error) causes, at least for most Lisps, entry into the Lisp debugger whenever ACL2 causes an error. See [break-on-error]. Thanks to John Erickson for providing encouragement to provide this feature. A new [table] has been provided so that advanced users can override the built-in untranslate functionality. See [user-defined-functions-table]. The [pstack] mechanism (formerly denoted checkpoints) has been improved. The ``process [prover] stack,'' or pstack, is automatically printed when proofs abort. Evaluation of function calls on explicit arguments during proofs is now tracked. Actual parameters are shown with (pstack t) rather than formals. Thanks to Bill Legato for suggesting the first two of these improvements and, in general, encouraging changes that make ACL2 easier to use. The [defstobj] event is now allowed to take an :inline argument, which can speed up execution. Thanks to Rob Sumners for suggesting and implementing this new feature. Macro [assert$] has been added in order to make it easy to write assertions in one's code. Semantically, (assert$ test form) is the same as form, but it causes a hard error (using [illegal]) if test evaluates to nil. Macro [cw-gstack] no longer takes arguments for the gstack or [state]. However, it now takes a keyword argument (which is optional), :evisc-tuple, that can be used to control how it prints terms. In particular, cw-gstack abbreviates large terms by default, but (cw-gstack :evisc-tuple nil) causes terms to be printed in full. Thanks to Robert Krug and Eric Smith for requesting this improvement. The advanced user now has more control over the evisceration of terms. See [ld-evisc-tuple], in particular the new paragraph on ``The printing of error messages and warnings.'' The [include-book] event now has an additional (optional) keyword, :dir. The value of :dir should be a keyword that is associated with an absolute directory pathname to be used in place of the current book directory (see [cbd]) for resolving the first argument of include-book to an absolute pathname. At start-up, the only such keyword is :system, so that for example (include-book \"arithmetic/top\" :dir :system) will include the book \"arithmetic/top\" under the \"books/\" directory of your ACL2 installation. But you can associate ``projects'' with keywords using [add-include-book-dir], e.g., (add-include-book-dir :my-project \"/u/smith/project0/\"). See [add-include-book-dir] and also see [delete-include-book-dir] and see [include-book]. Note: You will probably not find :dir :system to be useful if the distributed books are not placed in the path of their original location, pointed to by :dir :system, which will often happen if the executable image is obtained from another site. Also see [include-book], in particular its ``soundness warning''. The printing of results in raw mode (see [set-raw-mode]) may now be partially controlled by the user: see [add-raw-arity]. Also, newlines are printed when necessary before the value is printed. For those using Unix/Linux `make': A cert.acl2 file can contain forms to be evaluated before an appropriate [certify-book] command is invoked automatically (not included in cert.acl2). Jared Davis has contributed a new set of books for ordered finite set theory to the standard distribution, books/finite-set-theory/osets-0.81/. See the README file in that directory. Thanks, Jared. Robert Krug has contributed two related changes (thanks, Robert!) in support of stronger arithmetic reasoning. First, one can now enable and disable nonlinear arithmetic with a :nonlinearp hint, which will override the default provided by [set-non-linearp] (initially, nil). See [hints]. Second, [computed-hints] can now have access to the HISTORY, PSPV, and CTX variables of the waterfall, which (for example) allows the writing of a hint which will enable nonlinear arithmetic on precisely those goals that are stable-under-simplificationp. See [computed-hints]. Robert Krug has contributed a new set of arithmetic books to the standard distribution, books/arithmetic-3/. See the README file in that directory. Thanks, Robert.") (NOTE-2-8-ORDINALS (NOTE-2-8) "ACL2 Version 2.8 Notes on Changes to the Ordinals Please see [ordinals].") (NOTE-2-8-OTHER (NOTE-2-8) "ACL2 Version 2.8 Notes on Miscellaneous Changes Execution of [table] events has been sped up in many cases by avoiding excessive consing. ACL2 now warns if :[rewrite] (or :[definition]) rules contain free variables on the right-hand side. Thanks to Dave Greve for raising this issue. Emacs file emacs/emacs-acl2.el has been updated to better comprehend the notion of the ``ACL2 shell'', which is the buffer to which ACL2 forms are written by commands defined in the above file. Thus, command control-t e has been modified always to write to the ACL2 shell (which is \"*shell*\" by default), and the following new commands have been defined. o control-t c Set the ACL2 shell to the current buffer. o control-t b Change to the ACL2 shell. The commands :[pl] and :[pr] may now be given a macro name that corresponds via the macro-aliases-table to a function name, so that for example :pl append is treated the same as :pl binary-append. A more interesting improvement, for :pl only, is that :pl may now take any term. When :pl is given a term other than a symbol, it will print all rewrite rules that match that term. Thanks to David Russinoff, Robert Krug, and Bill Legato for getting this going. A new function, [pkg-witness], returns a symbol in the given package. The installation instructions have been updated, for example to give more guidance on obtaining Lisp implementations and to mention the acl2-help mailing list. Jared Davis has suggested some symbols to be added to *acl2-exports*, and we have done so. Thanks, Jared. o MFC (used in [syntaxp] and [extended-metafunctions]; thanks also to Robert Krug for this one) o ID, CLAUSE, WORLD, and STABLE-UNDER-SIMPLIFICATIONP (used in [computed-hints]) o [set-default-hints] The command :[pe] has been improved so that when the event is inside an included book, the path of included books (from the top-level book down to the one containing the event) is shown. Thanks to Eric Smith (perhaps among others) for pointing out the utility of this improvement. A new release of the rtl library has been included: books/rtl/rel4/. See the README file in that directory.") (NOTE-2-8-PROOF-CHECKER (NOTE-2-8) "ACL2 Version 2.8 Notes on Proof-checker Changes Added new [proof-checker] commands wrap1, wrap, and wrap-induct. Wrap replaces multiple goals by their conjunction: (wrap instr1 instr2 ...) employs wrap1 so that the indicated instructions create only at most one new goal. Wrap-induct is a simple example of the use of wrap, so that induction creates only one goal (the conjunction of the base and induction steps). Wrap1 can be used immediately after a prover call (bash, prove, reduce, bdd, or induct) to collapse the new goals into one. See [proof-checker-commands]. The [proof-checker] command = failed to work as expected when a governing IF-test of the current term is T. This has been fixed (by fixing source function conjuncts-of). Thanks to Yoann Padioleau for bringing this problem to our attention. The type-alist command now takes optional arguments that control whether or not the governors and/or conclusion are used in computing the context that is printed (see [proof-checker-commands], specifically subtopic type-alist). Thanks to Rob Sumners for suggesting this improvement. The macro [toggle-pc-macro] has always taken an optional second argument of atomic-macro or macro. However, this was not clearly documented, and those two symbols had to be in the ACL2 package. Both of these problems have been remedied. Thanks to John Erickson for bringing the lack of documentation of the second argument to our attention.") (NOTE-2-8-PROOFS (NOTE-2-8) "ACL2 Version 2.8 Notes on Changes in Proof Engine ACL2 now prevents certain rewriting loops; see [rewrite-stack-limit]. During the computation of [constraint]s for functional instantiation, (prog2$ term1 term2) and (the type term2) are now treated as term2. A change has been made in heuristics for controlling rewriting during proofs by induction. Formerly, during induction proofs, ACL2 suppressed rewriting of certain ``induction hypothesis'' terms, and forced expansion of certain ``induction conclusion'' terms, until rewriting had stabilized. This meddling with the rewriter is still turned off when rewriting has stabilized, but it is now turned off earlier once an ancestor has been through the rewriter and the current goal is free of ``induction conclusion'' terms. Thanks to Dave Greve and Matt Wilding for providing an example and associated analysis that led us to look for a heuristic modification. A change has been made in the heuristics for handling certain ``weak'' [compound-recognizer] rules when building contexts. Those who want to dig deeply into this change are welcome to look at the code following the call of most-recent-enabled-recog-tuple in the code for function assume-true-false in the ACL2 sources. The handling of free variables in a hypothesis of a [rewrite] rule (see [free-variables]) has been improved in the case that the hypothesis is of the form (equiv x y), where equiv is a known equivalence relation (see [equivalence]). Previously, if the rewriter was attempting to rewrite the hypothesis (equiv x y) of a rewrite rule, in a context where x' is an instance of x, then the rewriter could fail to notice a term (equiv x' y') true in the current context where y' is an instance of y, in the case that x' precedes y' in the [term-order]. This has been remedied. This improvement applies regardless of whether x, y, or (we believe) both are already fully instantiated in the present context. Thanks to Joe Hendrix for bringing up an example and to Vernon Austel for providing another, simple example. A very minor change has been made to the rewriter in the case that an equality appears on the left-hand side of a :[rewrite] rule. Formerly, when such an equality (equal x y) was commuted to (equal y x) in order for the rule to match the current term, then all equalities on the instantiated right-hand side of the rule were commuted, except for those occurring inside another equality. The instantiated right-hand side is no longer modified. It seems very unlikely that this change will cause proofs to fail, though we cannot completely rule out that possibility. We have modified how the ACL2 simplifier handles the application of a defined function symbol to constant arguments in certain cases, which we now describe. As before, ACL2 attempts to simplify such a function application by evaluation, provided the :[executable-counterpart] of the function is enabled. And as before, if that evaluation fails due to a subroutine call of a constrained function (introduced by [encapsulate]), ACL2 may wrap a call of hide around this function application. (See [hide].) But now, ACL2 attempts to apply definitions and rewrite rules in the case that this evaluation fails, and only if the resulting term is unchanged does ACL2 wrap [hide] around this function application. Thanks to Matt Wilding for bringing up the idea of this modification. The generation of \"Goal\" for recursive (and mutually-recursive) definitions now uses the subsumption/replacement limitation (default 500). See [case-split-limitations]. Default hints now apply to hints given in definitions, not just theorems. See [default-hints]. Thanks to Robert Krug for implementing the following two improvements involving linear arithmetic reasoning: linear arithmetic now uses the conclusions of [forward-chaining] rules, and [type-set] now uses a small amount of linear reasoning when deciding inequalities.") (NOTE-2-8-RULES (NOTE-2-8) "ACL2 Version 2.8 Notes on Changes in Rules, Definitions, and Constants The [theory] [minimal-theory] has been changed by adding the [definition] [rune] for [mv-nth] to the theory. A corresponding change has been made to the theory warning mechanism, which was failing to warn if the definition of mv-nth is disabled, even though calls of mv-nth can be expanded by special-purpose code in the rewriter. Thanks to Serita Van Groningen for pointing out this problem with the theory warning mechanism. The [defevaluator] event has been modified so that in the body of the evaluator function, to add a new case (ATOM X) (returning nil) has been inserted immediately after the case (EQ (CAR X) 'QUOTE). This is a no-op semantically but may speed up proofs. Thanks to Warren Hunt for suggesting this change. A new form of :[compound-recognizer] rule is now allowed: (if (fn x) concl1 concl2) This is equivalent to an existing form: (and (implies (fn x) concl1) (implies (not (fn x)) concl2)) Thanks to Josh Purinton for bringing this to our attention. Rewrite rules realpart-+ and imagpart-+ have been added in order to simplify the [realpart] and [imagpart] (respectively) of a sum. They follow from a theorem add-def-complex that equates a sum with the complex number formed by adding real and imaginary parts. All three of these theorems may be found in source file axioms.lisp. Thanks to Eric Smith for raising a question leading to these additions, as well as to Joe Hendrix and Vernon Austel for helpful suggestions.") (NOTE-2-8-SYSTEM (NOTE-2-8) "ACL2 Version 2.8 Notes on System-level Changes ACL2 now runs on OpenMCL, ``an opensourced Common Lisp implementation, derived from Digitool's Macintosh Common Lisp product.'' Thanks to Greg Wright and Robert Krug for doing most of the work for this port. When ([lp]) is first executed, the underlying raw Lisp package will change to \"ACL2\" (if that is not already the current package in raw Lisp). This is a minor change that will probably not be noticed, since up to now it has probably been the case that the ACL2 executable starts up with \"ACL2\" as the underlying raw Lisp package. But this change was made because we have been informed that ACL2 executables based on OpenMCL need not start up with \"ACL2\" as the underlying raw Lisp package. ACL2 now runs on MCL 5.0. Thanks to Pascal Costanza for updates to the instructions in file mcl-acl2-startup.lisp and for an update to the ACL2 sources (parameter *compiled-file-extension*).") (NOTE-2-8{R} (RELEASE-NOTES) "ACL2 Version 2.8(r) (March, 2003) Notes The Makefile has been modified by adding a new target, clean-links. This can be used in order to remove all soft links, which is useful if the directory is copied or moved to a new location or if there are file system changes that cause problems with link pathnames. Please also see [note-2-8] for changes to Version_2.8 of ACL2.") (NOTE-2-9 (RELEASE-NOTES) "ACL2 Version 2.9 (October, 2004) Notes Table of Contents * BUG FIXES * NEW FUNCTIONALITY * CHANGES IN PROOF ENGINE * GUARD-RELATED CHANGES * PROOF-CHECKER CHANGES * SYSTEM-LEVEL CHANGES * BOOK CHANGES * MISCELLANEOUS CHANGES BUG FIXES. We fixed a soundness bug due to a conflict between user-supplied package names and internal package names (obtained by prepending a Lisp constant, *1*-package-prefix*) and user-supplied package names. For example, the form (defpkg \"ACL2_*1*_MYPKG\" ()) is no longer legal. Thanks to Robert Krug for asking a question that led directly to the discovery of this bug. We fixed a soundness bug that allows :[logic] mode functions to call :[program] mode functions. The fix furthermore prevents functions with [guard]s verified from calling functions with guards not verified. We had thought we already prevented all this, but there was a problem with the interaction of [local] definitions and redundancy checking (see [redundant-events]). We fixed a soundness bug that could occur when built-in functions were called during macroexpansion (a hole in so-called ``safe-mode''). Fixed a minor bug in system functions genvar1 and genvar, where [eq] had been used in place of [eql]. This bug was discovered during the plugging of a hole in safe-mode, mentioned just above. We fixed handling of the :inline keyword for [defstobj], which previously could cause raw Lisp errors in OpenMCL and CMU Common Lisp. Thanks to John Matthews for bringing this issue to our attention. Calls of [include-book] could result in a state for which some function definitions were not compiled that should have been. The result could be performance degradation or even stack overflows. This situation could arise in the following two ways. o Inclusion of a book with an absolute pathname that differs from the absolute pathname at certification time, presumably because of the use of soft links. Thanks to Bob Boyer and Warren Hunt for bringing a stack overflow to our attention that led us to this fix. o Large [mutual-recursion] nests (more than 20 functions) are executed in a superior book. We fixed some performance bugs that can increase the speed of [include-book] calls by a factor of close to 2. Thanks to Eric Smith for asking if we could speed up [include-book] processing; we have done so in the past, but primarily focusing on large [mutual-recursion] nests (which have nothing in particular to do with the current improvements). Also, thanks to Rob Sumners for a very useful remark early in the process that kept us from drawing an incorrect conclusion at that point. We fixed :[pl] so that it can be run on a form that returns multiple values, which it could not do previouslly. Thanks to Eric Smith for pointing out this problem. Fixed a bug in the Allegro ACL2 trace utility (see [trace$]) that was causing ``10>'' to be printed as ``9>'', ``11>'' to be printed as ``10 >'', ``12>'' to be printed as ``11 >'', and so on. Fixed a [proof-checker] bug that was preventing the use of the DV command (or a numerical command) on [let] expressions. Thanks to Bill Young for pointing out this problem. Fixed a bug in a comment on how to set ACL2_BOOKS_DIR in the makefile. Thanks to Dave Greve for pointing out this problem. Fixed a potential soundness bug in the linear arithmetic routines. Thanks to Jared Davis for noticing this problem and to Robert Krug for implementing the fix. (Technical details: We had been assuming that polynomials were being normalized -- see the definition of good-polyp in linear-a.lisp -- but this assumption was false.) When the macro [open-trace-file] is opened twice in succession, it now automatically closes the first trace output channel before opening another. It is now possible to use `make' to build ACL2 on Windows systems that support `make'. Thanks to Pete Manolios and Mike Thomas for pointing out the problem, to Jared Davis and Mike for helping us to analyze the problem, and to Jared for testing the fix. Fixed a bug in the [guard] of [with-output] that was causing a needless guard violation. NEW FUNCTIONALITY. The new events [add-default-hints] and [remove-default-hints] allow one to append to or subtract from the current list of default hints. The event [set-default-hints] continues to set the list of default hints, discarding the previous value of the [default-hints]. Note that [set-default-hints] is still [local] to the [encapsulate] or book in which it occurs, and [add-default-hints] has the same property, although neither is implemented any longer using the [ACL2-defaults-table]. New events [add-default-hints!], [remove-default-hints!], and [set-default-hints!] are the same as [add-default-hints], [remove-default-hints], and [set-default-hints], respectively, except that the former three events are not [local] to their enclosing [encapsulate] or book. Thanks to Jared Davis for suggesting these enhancements. OpenMCL's tracing routines have been modified in a similar manner as those of Allegro CL. Thanks to Robert Krug for providing this enhancement. Guard-checking can now be caused to happen on recursive calls. See ``GUARD-RELATED CHANGES'' below for details. Advanced users can now inhibit compilation of so-called ``*1* functions'' with the :comp command; see [comp]. Thanks to Rob Sumners for suggesting this enhancement. Added new legal argument hard? for the [er] macro, which is now documented. See [er]. Thanks to Rob Sumners for a discussion leading to this change. Also, the three legal first arguments to [er] --- hard, hard?, and soft --- may now be in any package (thanks to Jared Davis for bringing this issue to our attention). We have removed the requirement that for a rule's hypothesis (bind-free term var-list), at least one variable must occur free in term. For example, the expression (bind-free (bind-divisor a b) (x)) was legal because a and b occur free in (bind-divisor a b); but (bind-free (foo (bar)) (x)) was not legal. The latter is no longer disallowed. (Technical note: this allows [bind-free] to be used to create explicit substitutions in metafunction hypotheses.) The following two enhancements have been implemented for rules of class :[meta]. Thanks to Eric Smith for requesting more control of reasoning with :[meta] rules, which led to these enhancements, and to him and Robert Krug for helpful discussions. o It is now possible to control backchaining in rules of class :[meta] by providing a :backchain-limit-lst argument, as was already allowed for rules of class :[rewrite] and :[linear]. See [rule-classes]. However, unlike those other two rule classes, the value for :backchain-limit-lst is prohibited from being a non-empty list; it must be either nil or a non-negative integer. o (For advanced users.) It is now legal for hypothesis metafunctions to generate, in essense, calls of [syntaxp] and [bind-free], handled essentially as they are handled in hypotheses of :[rewrite] and :[linear] rules. We say ``essentially'' primarily because both [syntaxp] and [bind-free] are actually macros, but hypothesis metafunctions must generate translated terms (see [term]). The enterprising advanced user can call :[trans] to see examples of translated terms corresponding to calls of [syntaxp] and [bind-free]. A new command :[trans!] has been added, which is like :[trans] except that :[trans!] ignored issues of single-threadedness. See [trans!]. Thanks to Eric Smith for suggesting this addition. The :[pf] command now works when the argument is the name of a macro associated with a function by [macro-aliases-table]. CHANGES IN PROOF ENGINE. The simplifier has been changed slightly in order to avoid using [forward-chaining] facts derived from a literal (essentially, a top-level hypothesis or conclusion) that has been rewritten. As a practical matter, this may mean that the user should not expect forward-chaining to take place on a term that can be rewritten for any reason (generally function expansion or application of rewrite rules). Formerly, the restriction was less severe: forward-chaining facts from a hypothesis could be used as long as the hypothesis was not rewritten to t. Thanks to Art Flatau for providing an example that led us to make this change; see the comments in source function rewrite-clause for details. The rewriter has been modified to work slightly harder in relieving hypotheses. Thanks to Eric Smith for providing an example that inspired the following, which illustrates the issue. Suppose we introduce functions foo and bar with the (non-[local]) properties shown below. (encapsulate (((foo *) => *) ((bar *) => *)) (local (defun foo (x) (declare (ignore x)) t)) (local (defun bar (x) (declare (ignore x)) t)) (defthm foo-holds (implies x (equal (foo x) t))) (defthm bar-holds-propositionally (iff (bar x) t))) Consider what happens when ACL2's rewriter is used to prove the following theorem. (thm (foo (bar y))) With ACL2's inside-out rewriting, (bar y) is first considered, but rewrite rule bar-holds-propositionally does not apply because the context requires preserving equality, not mere Boolean (iff) equivalence. Then the rewriter moves its attention outward and sees the term (foo (bar y)). It attempts to apply the rule foo-holds, in a context created by binding its variable x to the term (bar y). It then attempts to relieve the hypothesis x of rule foo-holds in that context. Before this change, ACL2 basically assumed that since rewriting was inside out, then (bar y) had already been rewritten as much as possible, so the rewrite of x in the aforementioned context (binding x to (bar y)) simply returned (bar y), and the attempt to relieve the hypothesis of foo-holds failed. The change is essentially for ACL2's rewriter to make a second pass through the rewriter when the attempt fails to rewrite a variable to t, this time using the fact that we are in a Boolean context. (We mention that source function rewrite-solidify-plus implements this idea, for those who want to dig deeply into this issue.) In our example, that means that the rewriter considers (bar y) in a Boolean context, where it may apply the rule bar-holds-propositionally to relieve the hypothesis successfully. When ([set-non-linearp] t) has been executed, [non-linear-arithmetic] can now be applied in some cases for which it previously was not. Thanks to Robert Krug for supplying this modification and to Julien Schmaltz for providing a motivating example. We modified the rewriter to avoid certain infinite loops caused by an interaction of the opening of recursive functions with equality reasoning. (This change is documented in detail in the source code, in particular functions rewrite-fncall and fnstack-term-member.) Thanks to Fares Fraij for sending us an example that led us to make this change. The :[executable-counterpart] of function [hide] is now disabled when ACL2 starts up. This removes an anomoly, for example that (thm (not (equal 1 (* (hide 0) a)))) succeeded while (thm (equal (foo (equal 1 (* (hide 0) a))) (foo nil))) failed. Now both fail. The theory *s-prop-theory* is no longer used by the proof-checker; it has been replaced by (theory '[minimal-theory]. We have left the constant *s-prop-theory* defined in the source code in support of existing books, however. This change eliminates annoying theory warnings printed upon invocation of [proof-checker] commands s-prop, sl, and split. Terms are now kept in an internal form that avoids calls of primitive functions (built-ins without explicit definitions; see code for cons-term for details), in favor of the constants that result from evlaluating those calls. So for example, the internal form for (cons 1 2) is (quote (1 . 2)). This change was made at around the same time as changes in support of [bind-free]; see above. One consequence is that the splitting of goals into cases (technically, source function clausify and even more technically, source function call-stack) has been modified, which can cause subgoal numbers to change. GUARD-RELATED CHANGES. Guard-checking can now be caused to happen on recursive calls, where this was formerly not the case for :[program] mode functions and, perhaps more important, for :[logic] mode functions whose [guard]s have not been verified. Moreover, a warning is printed when ACL2 does not rule out the exclusion of guard-checking on recursive calls. See [set-guard-checking]. Thanks to David Rager for bringing this issue to our attention, and to Rob Sumners and the Univ. of Texas ACL2 seminar in general for their feedback. Guard violations are reported with less of the offending term hidden. Thanks to Jared Davis for suggesting that we look at this issue. PROOF-CHECKER CHANGES. We fixed the [proof-checker] so that diving works as you might expect for a macro call (op a b c) representing (binary-op a (binary-op b c)). In the past, if the current term was of the form (append t1 t2 t3), then (DV 3) (and 3) would dive to t3 even though the corresponding function call is (binary-append t1 (binary-append t2 t3)). This is still the case, but now this behavior holds for any macro associated with a function in binop-table (see [add-binop]). Moreover, users can now write customized diving functions; see [dive-into-macros-table], and also see books/misc/rtl-untranslate.lisp for example calls to [add-dive-into-macro]. Of course, the old behavior can still be obtained using the [proof-checker]'s DIVE command; see [proof-checker-commands]. The runes command in the [proof-checker] now shows only the [rune]s used by the most recent primitive or macro command (as shown by :comm), unless it is given a non-nil argument. Also, [proof-checker] command lemmas-used has been added as, in essence, an alias for runes. (The following two items are also mentioned above under ``BUG FIXES.'') Fixed a [proof-checker] bug that was preventing the use of the DV command (or a numerical command) on [let] expressions. Thanks to Bill Young for pointing out this problem. The theory *s-prop-theory* is no longer used by the proof-checker; it has been replaced by (theory '[minimal-theory]. We have left the constant *s-prop-theory* defined in the source code in support of existing books, however. This change eliminates annoying theory warnings printed upon invocation of [proof-checker] commands s-prop, sl, and split. SYSTEM-LEVEL CHANGES. Fixed a problem with building ACL2 on CMUCL in some systems (source function save-acl2-in-cmulisp). Thanks to Bill Pase for bringing this to our attention. The installation instructions have been extended to include instructions for building on GCL in Mac OS X. Thanks to Jun Sawada and Camm Maguire. Initial pre-allocation of space has been updated for GCL to reflect more current GCL executables (we considered GCL 2.6.1-38). This can help avoid running out of memory for large ACL2 sessions. The main Makefile has been replaced by GNUmakefile, in order to enforce the use of GNU `make'. If you use another `make' program, you'll get an error message that may help you proceed. (GCL only) SGC is no longer turned on for GCL 2.6 sub-versions through 2.6.3 if si::*optimize-maximum-pages* is bound to T, due to an apparent issue with their interaction in those sub-versions. Also, we have eliminated preallocation for all versions after 2.6.1 because GCL doesn't need it (comments are in source function save-acl2-in-akcl). Thanks to Camm Maguire for excellent GCL help and guidance, and to Camm and Bob Boyer for useful discussions. We have removed support for so-called ``small'' images. Thus, :[doc], :[pe] and :[pc], [verify-termination], and other commands are fully supported in ACL2 saved images. Because of this and other changes in the generation of the so-called ``*1*'' logical functions, related to guards (as described above in -GUARD-RELATED CHANGES'', and related to the discussion of safe-mode in ``BUG FIXES'' above), image sizes have increased substantially. We no longer time or run ``nice'' the certification of individual books. The file books/Makefile-generic had done these by default, and some individual distributed and workshop book directories had Makefiles that did so as well. Thanks to Mike Thomas, who pointed out the lack of nice on some Windows systems (and we decided on this simple solution). Overall targets in books/Makefile still time their runs by default, and the partiular time program is now controlled by a Makefile variable. Failures during make certify-books or make regression now show up in the log as ``**CERTIFICATION FAILED**'', regardless of the operating system (as long as it supports `make'). Formerly, one searched for ``**'' but this did not appear in openMCL runs. We have eliminated ``Undefined function'' warnings that could occur in OpenMCL. BOOK CHANGES. Reconciled the definitions of firstn in book/misc/csort.lisp, books/bdd/bdd-primitives.lisp, books/ordinals/ordinal-definitions.lisp, and books/data-structures/list-defuns.lisp. Thanks to Ray Richards for bringing this issue to our attention. Distributed book books/misc/defpun now can handle [stobj]s where it did not previously. Thanks to John Matthews for bringing this issue to our attention. The \"make\" variable COMPILE_FLG in file books/Makefile-generic formerly only had an effect if there was a cert.acl2 file present. That oversight has been remedied. File \"books/arithmetic/certify.lsp\" was missing a [certify-book] command for \"natp-posp\". Thanks to John Cowles for noticing this deficiency and supplying a fix. (This file is of use to those who want to certify the \"books/arithmetic/\" books without using \"make\".) A few small changes have been made to \"books/rtl/rel4\". Small changes were made to books misc/symbol-btree and misc/rtl-untranslate. In particular, the definition of symbol-btreep was strengthened. We made a minor fix to books/ordinals/e0-ordinal.lisp, adding (verify-guards ob+) and hence (verify-guards ocmp) as well. This was necessitated by the fix prohibiting functions with guards verified from calling functions with guards not verified (see also the related discussion under ``BUG FIXES'' above). MISCELLANEOUS CHANGES. Further sped up processing of large [mutual-recursion] nests (extending what was done for Version_2.7), perhaps by a factor of two in some cases. As promised in Version_2.5 (see [note-2-5]), structured pathnames are no longer supported. So for example, the argument to [include-book] must now be a string constant. Some documentation has been improved, for [stobj]s thanks to suggestions by John Matthews and much of the rest thanks to feedback from Eric Smith. The function [current-package] is now available to users (it has been taken off the list of so-called ``untouchables''). Thanks to Jared Davis for bringing this issue to our attention. The documentation for topic [using-computed-hints-7] has been improved. Thanks to Doug Harper and Eric Smith for inspiring this improvement. We added several symbols to *acl2-exports*: [cw], [er], [intern$], [set-case-split-limitations], and [set-difference-eq]. Thanks to Jared Davis for suggesting most of these. Now, a [table] event that sets the value for a key, (table tbl key val :put), is redundant (see [redundant-events]) when it does not change the value associated with an existing key of the table. In particular, [define-pc-macro] is now fully redundant when it does not change an existing [proof-checker] macro-command definition. Thanks to Bill Young for bringing the latter issue to our attention. The definitions of unused system functions ev-w and ev-w-lst have been deleted. ACL2 now prints a warning if a [defpkg] event introduces a package name with lower-case letters, since there is opportunity for later confusion in that case. Thanks to Frederic Peschanski for bringing this problem to our attention and Sandip Ray for encouragement. ACL2 now works in Version 19 of CMU Common Lisp. The function [sys-call] has been modified so that for ACL2 built on Allegro Common Lisp in Unix or Linux, the existing environment is used. Thanks to Erik Reeber for bringing this issue to our attention. The function [disabledp] can now be given a macro name that has a corresponding function; see [macro-aliases-table]. Also, [disabledp] now has a [guard] of t but causes a hard error on an inappropriate argument.") (NOTE-2-9-1 (RELEASE-NOTES) "ACL2 Version 2.9.1 (December, 2004) Notes (GCL only) A bug in [symbol-package-name] has been fixed that could be exploited to prove nil, and hence is a soundness bug. Thanks to Dave Greve for sending us an example of a problem with [defcong] (see below) that led us to this discovery. ACL2 now warns when [defcong] specifies [equal] as the first equivalence relation, e.g., (defcong equal iff (member x y) 2). The warning says that the rule has no effect because [equal] already refines all other equivalence relations. Formerly, this caused an error unless :event-name was supplied (see [defcong]), and in fact the error was a nasty raw Lisp error on GCL platforms due to some mishandling of packages by ACL2 that has been fixed (see the paragraph about [symbol-package-name] above). Thanks to Dave Greve for sending a helpful example in his report of this problem. (GCL only) The build process was broken for GCL 2.6.0 (and perhaps some earlier versions), and has been fixed. Thanks to Jose Luis Ruiz-Reyna for bringing this problem to our attention. (GCL only) We have increased the hole size to at least 20% of max-pages, which may eliminate some garbage collection at the expense of larger virtual memory (not larger resident memory or larger image). Thanks to Camm Maguire for helpful explanations on this topic. We have clarified the [guard] warning message that is printed during evaluation of recursively-defined functions whose [guard]s have not been verified, for example: ACL2 Warning [Guards] in TOP-LEVEL: Guard-checking may be inhibited on some recursive calls of executable counterparts (i.e., in the ACL2 logic), including perhaps EVENLP. To check guards on all recursive calls: (set-guard-checking :all) To leave behavior unchanged except for inhibiting this message: (set-guard-checking :nowarn) And, ACL2 no longer prints that message when the [guard] was unspecified for the function or was specified as T. Thanks to Serita Nelesen for bringing the latter issue to our attention. Finally, ACL2 now prints such a warning at most once during the evaluation of any top-level form; thanks to Bill Young for pointing out this issue. The function [verbose-pstack] has been enhanced to allow specified prover functions not to be traced. See [verbose-pstack]. Added [lp], wet, and [set-non-linearp] to *acl2-exports*, and hence to the \"[ACL2-user]\" package. The distributed book books/arithmetic-3/bind-free/integerp.lisp has been modified in order to prevent potential looping; specifically, the definition of function reduce-integerp-+-fn-1. Thanks to Robert Krug for providing this change. A small improvement was made in the wet failure message when the error occurs during translation to internal form. Thanks to Jared Davis for pointing out the obscurity of some wet error messages. We have improved ACL2's evaluation mechanism for the function bad-atom<=, which now is specified to return nil if neither argument is a so-called ``bad atom'' (as recognized by function bad-atom). The following events had caused a hard error, for example. (We're sorry that bad-atom and bad-atom<= are not documented, but we also consider it unlikely that anyone needs such documentation; otherwise, please contact the implementors.) (defun foo (x y) (declare (xargs :guard t)) (bad-atom<= x y)) (defun bar (x y) (declare (xargs :guard t)) (foo x y)) (thm (equal (bar 3 4) 7)) We have also changed the guard on [alphorder] to require both arguments to be atoms. For forms (local x) that are skipped during [include-book], or during the second pass of [certify-book] or [encapsulate], ACL2 had nevertheless checked that x is a legal event form. This is no longer the case. The [proof-checker] now does non-linear arithmetic when appropriate. It had formerly ignored [set-non-linearp] executed in the ACL2 command loop. Incremental releases are now supported. See [version] and {obsolete after Version 4.3} set-tainted-okp. Thanks to Hanbing Liu for discovering a flaw in our original design. The pattern-matching algorithm for :[rewrite] rules has been made slightly more restrictive, thanks to a suggestion and examples from Robert Krug. For example, previously one could get an infinite loop as follows. (defstub foo (x) t) (defaxiom foo-axiom (equal (foo (+ 1 x)) (foo x))) (thm (foo 0)) ; or replace 0 by any integer! That is because the term (foo 0) was considered to match against the pattern (foo (+ 1 x)), with x bound to -1. While such matching is sound, it leads to an infinite loop since it allows foo-axiom to rewrite (foo 0) to (foo -1), and then (foo -1) to (foo -2), and so on. The fix is to insist that the new value, in this case -1, is no larger in size according to [ACL2-count] than the old value, in this case 0. Since that test fails, the match is considered to fail and the loop no longer occurs. An analogous fix has been made for multiplication, where now we only match when the new term is still a non-zero integer. That change avoids a loop here. (defstub foo (x) t) (defaxiom foo-axiom (equal (foo (* 2 x)) (foo x))) (thm (foo 0)) ; or try (thm (foo 4)) Added macro find-lemmas in books/misc/find-lemmas.lisp (see brief documentation there) for finding all lemmas that mention all function symbols in a given list. :Restrict [hints] now work for :[definition] rules, though they continue to be ignored by the preprocessor and hence you may want to use :do-not '(preprocess) with any restrict hints. Thanks to John Matthews for pointing out the lack of support for :definition rules in :restrict hints. Some books have been updated. In particular, there is a new directory books/workshops/2004/ in workshops distribution, for the 2004 ACL2 workshop. There is also a new version of Jared Davis's ordered sets library, formerly in books/finite-set-theory/osets-0.81/ but now in books/finite-set-theory/osets/. Fixed a bug in the (under-the-hood) raw Lisp definition of [defchoose], which had been causing a warning in CMU Common Lisp. [Technical improvements related to the use of ``make dependencies'' for certifying distributed books:] File books/Makefile-generic now does a better job with ``make dependencies,'' specifically with respect to handling *.acl2 files and handling [include-book] commands with :dir :system. Regarding the latter, suppose for example that book basic.lisp contains the line: (include-book \"arithmetic/top-with-meta\" :dir :system) Then make dependencies would generate the following line: basic.cert: $(ACL2_SRC_BOOKS)/arithmetic/top-with-meta.cert Thus, if :dir :system is used with [include-book], the corresponding Makefile should define the variable ACL2_SRC_BOOKS. A standard Makefile header for a books directory could thus be as follows. # The following variable should represent the ACL2 source directory. It is the # only variable in this Makefile that may need to be edited. ACL2_SRC = ../../../../../.. ACL2_SRC_BOOKS = $(ACL2_SRC)/books include $(ACL2_SRC_BOOKS)/Makefile-generic ACL2 = $(ACL2_SRC)/saved_acl2h Finally, the ``-s'' flag may now be omitted when running ``make dependencies.''") (NOTE-2-9-2 (RELEASE-NOTES) "ACL2 Version 2.9.2 (April, 2005) Notes Also see [note-2-9-1] for other changes since the last non-incremental release (Version_2.9). There was a bug in non-linear arithmetic (see [non-linear-arithmetic]) that caused the following error: ACL2 !>(include-book \"rtl/rel4/lib/top\" :dir :system) .... ACL2 !>(set-non-linearp t) T ACL2 !>(thm (implies (and (bvecp a 77) (bvecp b 50)) (bvecp (fl (/ (* a b) (expt 2 23))) 104)) :hints ((\"Goal\" :in-theory (enable bvecp)))) [Note: A hint was supplied for our processing of the goal above. Thanks!] By the simple :definition BVECP, the :executable-counterparts of EXPT and UNARY-/ and the simple :rewrite rule ASSOCIATIVITY-OF-* we reduce the conjecture to Goal' (IMPLIES (AND (INTEGERP A) (<= 0 A) (< A 151115727451828646838272) (INTEGERP B) (<= 0 B) (< B 1125899906842624)) (BVECP (FL (* A B 1/8388608)) 104)). HARD ACL2 ERROR in VARIFY: This should not have happened. The supposed variable, '1/8388608, is instead a constant. ACL2 !> Thanks to Robert Krug for providing a fix for the above error. Guard-checking was being inhibited (since v2-9) for calls of built-in primitives on explicit values, e.g., (car 3). This has been fixed. Guard-related warnings could be printed during proofs (this bug was introduced in Version_2.9.1). These warnings have been eliminated. Compound-recognizer rules natp-compound-recognizer and posp-compound-recognizer are now built into ACL2 for predicates [natp] and [posp], and hence have been deleted from book natp-posp.lisp (where they were called natp-cr and posp-cr, respectively). The function file-clock-p, which recognizes a component of the ACL2 [state], is now defined using [natp] instead of [integerp]. Thanks to Jared Davis for suggesting this change. (Technical explanation about functions in ACL2 source file axioms.lisp: With a file-clock of -1, the call of make-input-channel in open-input-channel will create a channel that can't be closed; see the guard of close-input-channel.) (Allegro CL users only) Support is now provided for building an Allegro CL application, provided you have an Allegro CL dynamic runtime license. (Our belief is that with such a license, many users can use the same application, rather than each user needing a separate license.) See new GNUmakefile target allegro-app and file build-allegro-exe.cl for more information. The new home page now contains a link to a new page other-releases.html, which contains information about other ACL2 releases. (This is in one's local home page, but may not show up on the central ACL2 home page until the next non-incremental release.) Thanks to Warren Hunt for suggesting this addition. We thank Erik Reeber for suggesting a solution to output redirection using [sys-call], which we have described at the end of its documentation. A new documentation topic fixes the flawed argument for conservativity of the [defchoose] event that appears in Appendix B of Kaufmann and Moore's paper, ``Structured Theory Development for a Mechanized Logic'' (Journal of Automated Reasoning 26, no. 2 (2001), pp. 161-203). See [conservativity-of-defchoose]. Thanks to John Cowles and Ruben Gamboa for helpful feedback on drafts of this note. The solution to exercise 6.15 in books/textbook/chap6/solutions.txt has been fixed. Thanks to Aaron Smith for pointing out the problem. A new documentation topic [defun-sk-example] gives a little more help in using [defun-sk] effectively. Thanks to Julien Schmaltz for presenting this example as a challenge. (GCL only) There is now a way to speed up GCL builds of ACL2, at the cost of perhaps a percent or so in performance of the resulting image. Using `make' one supplies the following. LISP='gcl -eval \"(defparameter user::*fast-acl2-gcl-build* t)\" Various makefiles have been improved in several ways. (1) Parallel book certification, using GNU make's -j option, can be used. (2) Book certifications now stops at the first failure if books/Makefile or books/Makefile-generic is used, and returns non-zero exit status. However, the various make targets in the ACL2 source directory (regression, certify-books, etc.) still continue past failures unless you provide ACL2_IGNORE=' ' on the `make' command line. (3) The build process has been modified (file GNUmakefile) so that it stops upon a failed compile or a failed initialization. (4) The automatic dependency generation (from ``make dependencies'' has been improved so that commands of the form (ld \"my-book.lisp\") in .acl2 files cause the appropriate depedencies to be generated. Thanks to comments from several users that led to the above Makefile improvements: Ray Richards, Doug Harper, and the Rockwell ACL2 users for (1) and (2) (and inspiring (4)), and David Rager for (2) and (3). In particular, Doug Harper sent a replacement for the .date mechanism, which was interfering with make -n; so, these files are no longer written. A mechanism has been added for saving output. In particular, you can now call [ld] on a file with output turned off, for efficiency, and yet when a proof fails you can then display the proof attempt for the failed (last) event. See [set-saved-output]. Another new command --- see [set-print-clause-ids] --- causes subgoal numbers to be printed during proof attempts when output is inhibited. Documentation has been added for using ACL2's makefile support to automate the certification of collections of books. See [books-certification-classic]. Fixed a bug in [sys-call-status] that was causing hard Lisp errors. Improved [cw-gstack] to allow a :frames argument to specify a range of one or more frames to be printed. see [cw-gstack]. Fixed a bug in [proof-checker] command forwardchain. Thanks to Ming-Hsiu Wang for bringing this bug to our attention. We have provided a mechanism for saving an executable image. See [saving-and-restoring] and see [save-exec]. We have eliminated obsolete functions note-lib and make-lib. Modified the [ground-zero] [theory] so that it contains all of the built-in rules (in ACL2 source file axioms.lisp). It had formerly failed to include rules from some definitions and theorems near the end of axioms.lisp. A new event, [set-enforce-redundancy], allows the enforcement of [defthm], [defun], and most other events during book development. See [set-enforce-redundancy]. A bug has been fixed that had allowed [deftheory] [events] to cause a hard Lisp error when calling [union-theories] on ill-formed theories after, for example: :set-guard-checking nil (in-theory (union-theories '((:rewrite no-such-rule)) (current-theory 'ground-zero))) The handling of [guard] checking has been modified somewhat in a way that should only very rarely affect users. (An ``Essay on Guard Checking'' in the ACL2 source code explains this point to anyone interested in implementation details.) (GCL ONLY) Removed the -dir setting in the ACL2 wrapper script for GCL. This should generally have no effect for most users, but it eliminates a potential source of error down the road. Several interesting new definitions and lemmas have been added to the rtl library developed at AMD, and incorporated into books/rtl/rel4/lib/. Other book changes include a change to lemma truncate-rem-elim in books/ihs/quotient-remainder-lemmas.lisp, as suggested by Jared Davis. The macro [real/rationalp] may now be referred to in [in-theory] [events] and [hints], thanks to a new [add-macro-alias] event. Thanks to Jared Davis for this suggestion. ACL2 terms of the form (if p 'nil 't) are now printed as (not p), where in some setting they had been printed as (and (not p) t). Thanks to Robert Krug for this improvement. (GCL ONLY) Added profiling support, based heavily on code supplied by Camm Maguire. See file save-gprof.lsp for instructions. Thanks to Camm, and also to David Hardin for inspiring this addition. Added support for preprocessing before printing (untranslating) a term. See [user-defined-functions-table], in particular the discussion of untranslate-preprocess. Thanks to Jared Davis for inspiring this addition, and for providing a book that takes advantage of it (books/misc/untranslate-patterns.lisp). The documentation has been improved for explaining how [rune]s are assigned; see [rune]. Thanks to Robert Krug for pointing out inaccuracies in the existing documentation.") (NOTE-2-9-3 (RELEASE-NOTES) "ACL2 Version 2.9.3 (August, 2005) Notes Also see [note-2-9-1] and see [note-2-9-2] for other changes since the last non-incremental release (Version_2.9). We fixed a soundness bug that exploited the ability to define :[program] mode functions that are improperly guarded, and then to use those functions in [defconst] forms. The fix is to evaluate [defconst] forms using the same ``safe-mode'' that is used in macroexpansion (see [guards-and-evaluation]). Here is a proof of nil that succeeded in Allegro Common Lisp (but not, for example, GCL). See also a long comment in source function defconst-fn for an example that does not require the use of :set-guard-checking. :set-guard-checking nil ; execute before certifying the book below (in-package \"ACL2\") (encapsulate () (local (defun f1 () (declare (xargs :mode :program)) (char-upcase (code-char 224)))) (local (defconst *b* (f1))) (defun f1 () (char-upcase (code-char 224))) (defconst *b* (f1)) (defthm bad (not (equal *b* (code-char 224))) :rule-classes nil)) (defthm ouch nil :hints ((\"Goal\" :use bad)) :rule-classes nil) We fixed a soundness hole due to the fact that the \"LISP\" package does not exist in OpenMCL. We now explicitly disallow this package name as an argument to [defpkg]. Thanks to Bob Boyer and Warren Hunt for bringing an issue to our attention that led to this fix. ACL2 now requires all package names to consist of standard characters (see [standard-char-p], none of which is lower case. The reason is that we have seen at least one lisp implementation that does not handle lower case package names correctly. Consider for example the following raw lisp log (some newlines omitted). >(make-package \"foo\") #<\"foo\" package> >(package-name (symbol-package 'FOO::A)) \"foo\" >(package-name (symbol-package '|FOO|::A)) \"foo\" > Distributed book books/textbook/chap10/compiler, as well as workshop books in directory books/workshops/2004/cowles-gamboa/support/, were modified to accommodate the above change. Added newline, [add-to-set-eql], the-fixnum, and the-fixnum! to *acl2-exports*. Thanks to Jared Davis for bringing these to our attention. Added a line to acl2.lisp to support CMUCL running on Mac OSX, thanks to a suggestion from Fabricio Chalub Barbosa do Rosario. The executable scripts for saved ACL2 images now include $*, so that command-line arguments will be passed along. (For GCL profiling only) Fixed a colon (:) that should have been a semicolon (;) in file save-gprof.lsp. Thanks to David Hardin for pointing out this bug. The documentation for :[elim] rules has been expanded and improved, thanks to useful feedback from Hanbing Liu. Fixed a bug in the guard for function include-book-dir. For those who want to experiment with an alternate implementation of [mv] and [mv-let], there is now support for under-the-hood implementation of these in terms of raw Lisp functions values and multiple-value-bind, respectively. The regression suite has seen about a 10% speed-up in Allegro CL and about an 8% slowdown in GCL for builds with this change. See the makefile (GNUmakefile) for examples of how to build ACL2 by including the feature, :acl2-mv-as-values. Source file init.lsp has been renamed to init.lisp in support of this change (technical detail: otherwise GCL loads the init file too soon, before its -eval argument is evaluated). Thanks to David Rager for inspiring this change, by pointing out the problematic use of globals by the existing [mv] implementation from the standpoint of supporting parallel evaluation. This capability is experimental: there is likely to be some remaining work to be done on it. A change related to the one just above is that we now limit the maximum number of arguments to any call of [mv] to 32. Thanks to Bob Boyer for raising a question that lead to this change. Eliminated some compiler warnings in OpenMCL. In the rtl library (books/rtl/rel4/), functions bits and setbits have had their [guard]s improved (as they had been too restrictive, especially for setbits). A new function [time$] permits timing of forms, by using (under the hood) the host Common Lisp's time utility. We fixed an infinite loop that could occur during destructor elimination (see [elim]). Thanks to Sol Swords to bringing this to our attention and sending a nice example, and to Doug Harper for sending a second example that we also found useful. The method of speeding up GCL-based builds (see [note-2-9-2]) has changed slightly from Version_2.9.2. Now, in the `make' command: LISP='gcl -eval \"(defparameter user::*fast-acl2-gcl-build* t)\" We improved the pretty-printer's handling of keywords. For example, before this change one might see the following printed by ACL2. (MODIFY TH S :KEY1 VAL1 :KEY2 (IF (IF X Y Z) AAAAAAAAAA BBBBBBB)) Now, the above might print as follows. Notice that we have avoided breaking after a keyword (see [keywordp]) that is preceded by other forms on the same line. (MODIFY TH S :KEY1 VAL1 :KEY2 (IF (IF X Y Z) AAAAAAAAAA BBBBBBB)) See [note-2-9-3-ppr-change] for a detailed discussion of this change. (GCL ONLY) Evaluation in a break is no longer inhibited by ACL2 when built on top of GCL, so GCL now matches other Common Lisps in this respect. For ACL2 built on most host Common Lisps, you will see the string [RAW LISP] in the prompt, at least at a break, to emphasize that one is inside a break and hence should probably quit from the break. See [breaks]. Jared Davis suggested improvements to lemmas len-update-nth (in source file axioms.lisp) and append-true-listp-type-prescription (in books/meta/term-defuns.lisp), which have been incorporated. The former required a change in books/workshops book 2004/ruiz-et-al/support/q-dag-unification.cert, which has been made. The [proof-checker] command rewrite allows further binding of free variables in hypotheses, with new optional argument instantiate-free. Proof-checker command show-rewrites (sr) gives corresponding additional information. Documentation for these commands has been improved; see [proof-checker-commands]. Thanks to John Matthews and Bill Young for suggestions and feedback leading to these improvements. Fixed downcase printing so that the package name of a symbol is also downcased. For example, after execution of (defpkg \"FOO\" nil) and (set-acl2-print-case :downcase), 'foo::ab will print back as the same, rather than as 'FOO::ab. It is now possible to control the output so that numbers are printed in binary, octal, or hex, though the default is still radix 10. See [set-print-base]. Note that in support of this change, built-in functions [explode-nonnegative-integer] and explode-atom now take an extra print-base argument. Different support for radix conversion may be found in a book newly contributed by Jun Sawada, books/misc/radix.lisp. Built-in axiom car-cdr-elim is now only an :[elim] rule. It was formerly both an :elim rule and a :[rewrite] rule. A new rule, cons-car-cdr, takes the place of the old :rewrite rule, but is instead a hypothesis-free rule that can cause a case split (see source file axioms.lisp). Thanks to Jared Davis for suggesting this change. Lemmas about [alphorder] (alphorder-reflexive, alphorder-transitive, alphorder-anti-symmetric, and alphorder-total) are now available. (They had been [local] in source file axioms.lisp.) Thanks to Serita Nelesen for bringing this issue to our attention. ACL2 has, for some time, printed a space in the event summary after the open parenthesis for a [defthm] event, in order to ease backward searching for the original form, for example (defthm bar ...): Form: ( DEFTHM BAR ...) The intention was that this extra space should be printed for every event form; but it was missing in some cases, for example, for [verify-guards]. This has been fixed. In analogy to [include-book], now [ld] takes the (optional) keyword argument :dir. Thanks to Jared Davis for providing an implementation of this feature and to Eric Smith and Jeff Marshall for requesting this feature. We fixed a bug in [include-book] that could cause an error when redefinition is on, for example: (set-ld-redefinition-action '(:warn! . :overwrite) state) (include-book \"/u/acl2/books/arithmetic/top\") The behavior of [include-book] now matches the documentation: handling of compiled files for uncertified [books] will follow the same rules as for certified books. In particular, if you create an object file in raw Lisp for some book, then including that book will load that object file. Thanks to Jared Davis for bringing this issue to our attention. New documentation explains the interaction of redefinition and redundancy. See [redundant-events] --- the ``Note About Unfortunate Redundancies'' is new. Thanks to Grant Passmore for providing examples that led us to write this additional documentation. Solutions to exercises in { How To Prove Theorems Formally | http://www.cs.utexas.edu/users/moore/publications/how-to-prove-thms} are now available in distributed book books/misc/how-to-prove-thms.lisp. Also in that directory may be found a new book hanoi.lisp that contains a solution to the Towers of Hanoi problem. Subtopics [Note-2-9-3-ppr-change] Change in pretty-printing for ACL2 Version_2.9.3") (NOTE-2-9-3-PPR-CHANGE (NOTE-2-9-3) "Change in pretty-printing for ACL2 Version_2.9.3 We have improved pretty-printing in ACL2 Version_2.9.3 to handle keywords a little differently. To see a discussion of the basics of this change, see [note-2-9-3]. In this note we describe it in considerable detail. Those who wish to understand the ACL2 pretty-printer's implementation can now find considerably more comments on it in the source code. In this note, we do not focus on the implementation. Rather, we motivate the change and show how the improved prettyprinter performs. Why do we want better keyword handling? Imagine a macro that builds a new state from an old state by changing the values in the affected fields, leaving everything else unchanged. One could write (modify th s :key1 val1 :key2 val2 :key3 val3) where the three keys identify fields in the state. To make it easier to read new concrete states, we may have a function that prints them ``relative'' to a given base state, expressing the new state as a modification of the given base state. So we may find ourselves prettyprinting modify forms like that above. The previous prettyprinter will sometimes print the form above as follows. (modify th s :key1 val1 :key2 val2 :key3 val3) This can be unpleasant to read, because of the way :key1 and val1 are separated. Here is an example of the old prettyprinter and the new one, both printing an expression from the ACL2 source code in a width of 40: Old: (ADD-TO-TAG-TREE 'ASSUMPTION (MAKE ASSUMPTION :TYPE-ALIST TYPE-ALIST :TERM TERM :REWRITTENP REWRITTENP :IMMEDIATEP IMMEDIATEP :ASSUMNOTES (LIST (MAKE ASSUMNOTE :CL-ID NIL :RUNE RUNE :TARGET TARGET))) TTREE) New: (ADD-TO-TAG-TREE 'ASSUMPTION (MAKE ASSUMPTION :TYPE-ALIST TYPE-ALIST :TERM TERM :REWRITTENP REWRITTENP :IMMEDIATEP IMMEDIATEP :ASSUMNOTES (LIST (MAKE ASSUMNOTE :CL-ID NIL :RUNE RUNE :TARGET TARGET))) TTREE) Basically the change we made forces the prettyprinter to print each :key on a new line unless they all fit on a single line. So we would now get either (modify th s :key1 val1 :key2 :val2 :key3 val3) or (modify th s :key1 val1 :key2 val2 :key3 val3) Furthermore, we fixed it so that if val1 (say) is a big s-expression we may still print it on the same line as its key. The old prettyprinter enforced the rule that if you wanted to print (foo a b) and b gets broken up into several lines, then it has to start on a new line. Thus, we'd never print (foo a (bbb (mum x))) but would print instead (foo a (bbb (mum x))) Now, if a is a keyword, we can print the first way. So here are some nice examples of prettyprinted keyword forms. All of these are printed for a page of width 40. <-- 40 chars -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (MODIFY TH S :KEY1 V1 :KEY2 V2) (MODIFY TH S :KEY1 V1 :KEY2 V2 :KEY3 V3) (MODIFY TH S1 ; Because of the extra char :KEY1 V1 ; in S1 the flat size exceeds :KEY2 V2 ; 40 and we break it. :KEY3 V3) The old ppr would have printed this as: (MODIFY TH S1 :KEY1 V1 :KEY2 V2 :KEY3 V3) Returning to new examples: <-- 40 chars -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (MODIFY TH S :KEY1 (IF (IF X Y Z) AAAA BBBB) :KEY2 VAL2 :KEY3 VAL3) Now we extend AAAA and BBBB by one char each, so it would overflow the right margin if printed as above, and we get: <-- 40 chars -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (MODIFY TH S :KEY1 (IF (IF X Y Z) AAAAX BBBBX) :KEY2 VAL2 :KEY3 VAL3) If we make these names even longer we force the value off the line containing :key1: (MODIFY TH S :KEY1 (IF (IF X Y Z) AAAAXXXXX BBBBXXXXX) :KEY2 VAL2 :KEY3 VAL3) Here are some examples from the ACL2 source code, printed in 40 characters: (DEFTHM ALPHORDER-ANTI-SYMMETRIC (IMPLIES (AND (NOT (CONSP X)) (NOT (CONSP Y)) (ALPHORDER X Y) (ALPHORDER Y X)) (EQUAL X Y)) :HINTS ((\"Goal\" :IN-THEORY (UNION-THEORIES '(STRING< SYMBOL-<) (DISABLE CODE-CHAR-CHAR-CODE-IS-IDENTITY)) :USE ((:INSTANCE SYMBOL-EQUALITY (S1 X) (S2 Y)) (:INSTANCE BAD-ATOM<=-ANTISYMMETRIC) (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C Y)) (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C X))))) :RULE-CLASSES ((:FORWARD-CHAINING :COROLLARY (IMPLIES (AND (ALPHORDER X Y) (NOT (CONSP X)) (NOT (CONSP Y))) (IFF (ALPHORDER Y X) (EQUAL X Y))) :HINTS ((\"Goal\" :IN-THEORY (DISABLE ALPHORDER)))))) Here is that same one, printed in a width of 60. (DEFTHM ALPHORDER-ANTI-SYMMETRIC (IMPLIES (AND (NOT (CONSP X)) (NOT (CONSP Y)) (ALPHORDER X Y) (ALPHORDER Y X)) (EQUAL X Y)) :HINTS ((\"Goal\" :IN-THEORY (UNION-THEORIES '(STRING< SYMBOL-<) (DISABLE CODE-CHAR-CHAR-CODE-IS-IDENTITY)) :USE ((:INSTANCE SYMBOL-EQUALITY (S1 X) (S2 Y)) (:INSTANCE BAD-ATOM<=-ANTISYMMETRIC) (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C Y)) (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C X))))) :RULE-CLASSES ((:FORWARD-CHAINING :COROLLARY (IMPLIES (AND (ALPHORDER X Y) (NOT (CONSP X)) (NOT (CONSP Y))) (IFF (ALPHORDER Y X) (EQUAL X Y))) :HINTS ((\"Goal\" :IN-THEORY (DISABLE ALPHORDER)))))) Just for comparison, here is the above printed in 60 columns by the old prettyprinter. (DEFTHM ALPHORDER-ANTI-SYMMETRIC (IMPLIES (AND (NOT (CONSP X)) (NOT (CONSP Y)) (ALPHORDER X Y) (ALPHORDER Y X)) (EQUAL X Y)) :HINTS ((\"Goal\" :IN-THEORY (UNION-THEORIES '(STRING< SYMBOL-<) (DISABLE CODE-CHAR-CHAR-CODE-IS-IDENTITY)) :USE ((:INSTANCE SYMBOL-EQUALITY (S1 X) (S2 Y)) (:INSTANCE BAD-ATOM<=-ANTISYMMETRIC) (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C Y)) (:INSTANCE CODE-CHAR-CHAR-CODE-IS-IDENTITY (C X))))) :RULE-CLASSES ((:FORWARD-CHAINING :COROLLARY (IMPLIES (AND (ALPHORDER X Y) (NOT (CONSP X)) (NOT (CONSP Y))) (IFF (ALPHORDER Y X) (EQUAL X Y))) :HINTS ((\"Goal\" :IN-THEORY (DISABLE ALPHORDER)))))) Of course, given that you cannot tell for sure whether the keywords you're seeing are part of a keyword/value parameter list or part of some constant containing random keywords, the prettyprinter can't solve the problem perfectly. We just tried to make it work nicely on well-formed keyword/value parameter lists. For example, here is a form printed by the each prettyprinter. Old: (MEMBER X '(:MONDAY :MON :TUESDAY :TUES :WEDNESDAY :WED :THURSDAY :THURS :FRIDAY :FRI :SATURDAY :SAT :SUNDAY :SUN)) New: (MEMBER X '(:MONDAY :MON :TUESDAY :TUES :WEDNESDAY :WED :THURSDAY :THURS :FRIDAY :FRI :SATURDAY :SAT :SUNDAY :SUN)) The new way is not how one would print it by hand! But then, neither is the old way.") (NOTE-2-9-4 (RELEASE-NOTES) "ACL2 Version 2.9.4 (February, 2006) Notes Also see [note-2-9-1], see [note-2-9-2], and see [note-2-9-3] for other changes since the last non-incremental release (Version_2.9). A soundness bug has been fixed that was due to inadequate checking of :[meta] rules in the presence of [local] [events]. Specifically, a local [defevaluator] event is insufficient for supporting a :meta rule (an example is shown in source function chk-acceptable-rules). Thanks to Dave Greve and Jared Davis for bringing this bug to our attention, by sending a proof of nil that exploited this bug. The fix is to check legality of :meta rules even when skipping proofs during an [include-book] event or the second pass of an [encapsulate] event. Fixed problem with parallel make for workshop books by adding a dependency line to books/workshops/2003/Makefile. Default hints (see [set-default-hints]) no longer prevent the use of :INSTRUCTIONS (see [proof-checker]). Thanks to Jared Davis for pointing out this problem. New functions [remove-eq] and [remove-equal] have been defined, in analogy to [remove]. These two symbols have also been added to *acl2-exports*. Thanks to David Rager for pointing out that remove-equal was missing. Moreover, the definitions of delete1-eq and delete1-equal have been eliminated. Function remove1-eq, now in :[logic] mode in source file axioms.lisp, serves in place of delete1-eq, with corresponding new function definitions for [remove1] and [remove1-equal]. The symbol [assert$] has been added to *acl2-exports*. Thanks to Jared Davis for the suggestion. Added SBCL support. Thanks to Juho Snellman for significant assistance with the port. Thanks to Bob Boyer for suggesting the use of feature :acl2-mv-as-values with SBCL, which can allow thread-level parallelism in the underlying lisp; we have done so when feature :sb-thread is present. We have continued to incorporate suggestions for wording improvements in documentation and error messages. Thanks to all who send these suggestions, especially to Eric Smith, who has suggested the vast majority of them. Made a small improvement to errors and warnings caused on behalf of [set-enforce-redundancy], to indicate when an event of the same name already exists. Fixed a bug in books/misc/rtl-untranslate.lisp that was causing a guard violation when adding a new entry for an existing key. Fixed a bug in translation to internal form that caused [defun-sk] and [defchoose] to have difficulties handling ignored variables in [let] forms. Thanks to Sandip Ray to bringing this issue to our attention with a helpful example. The form (push :acl2-mv-as-values *features*) has been added in source file acl2-init.lisp for SBCL and OpenMCL only, in order to support parallel execution (looking to the future...). Default-hints (see [set-default-hints]) were being ignored inside the [proof-checker], but no longer. Thanks to John Erickson for bringing this problem to our attention and providing a simple example of it. Modified the TAGS \"make\" target (specifically, function make-tags) so that it is gracefully skipped if the etags program is not found. Thanks to David Rager for pointing out this issue. Sandip Ray has re-worked the supporting materials for his ACL2 Workshop 2003 talk (originally with John Matthews and Mark Tuttle), to run in a few minutes. The result is in workshops/2003/ray-matthews-tuttle/support/ and is included in the full ACL2 regression suite. Thanks, Sandip. Debian releases of ACL2 had created superfluous .cert.final files when certifying books. This has been fixed; thanks to Jared Davis for noticing this problem. Jared Davis has pointed out that ``If you add a :backchain-limit-lst 0 to a rewrite rule whose hypotheses are all forced, then ACL2 `really assumes them' without trying to relieve them right there through rewriting.'' Relevant documentation has been added for :backchain-limit-lst; see [rule-classes]. A new version of the rtl library has been included in books/rtl/rel5/. Thanks to David Russinoff for contributing hand proofs for the new lemmas, and to Matt Kaufmann for carrying out their mechanization. Fixed a bug in [save-exec] that was failing to set the initial cbd according to the current directory when starting up ACL2. Thanks to Camm Maguire for bringing our attention to this problem. Variables introduced during let* abstraction are now in the current package. Thanks to Jared Davis for suggesting such a change. See [set-let*-abstractionp]. It is now allowed for two definitions to be considered the same from the standpoint of redundancy (see [redundant-events]) when one specifies a :[guard] of t and the other has no explicit :guard (hence, the guard is implicitly t). Thanks to Jared Davis for bringing this issue to our attention. (For users of emacs/emacs-acl2.el) There have been a few enhancements to distributed file emacs/emacs-acl2. el (skip this paragraph if you don't use that file): o Control-t q continues to compare windows ignoring whitespace, but now, a prefix argument can be given to control case is also ignored (ignore case if positive, else use case). o Control-t Control-l has been defined to be similar to Control-t l, except that proofs are skipped and output is suppressed. o Control-t u has been defined to print, to the shell buffer, a :[ubt!] form for the command containing the cursor. o Control-t Control-f buries the current buffer. o Meta-x new-shell now puts the new shell buffer in shell-mode (thanks to David Rager for noticing this issue). Linear arithmetic has been modified so that we do not generate the equality (equal term1 term2) from the pair of inequalities (<= term1 term2) and (<= term2 term1) in the case that we would have to [force] both term1 and term2 to be [ACL2-numberp]s. Thanks to Dave Greve for providing a motivating example and to Robert Krug for providing a fix. The event [delete-include-book-dir] had not been allowed inside [books] and [encapsulate] forms. This was an oversight, and has been fixed. Sandip Ray has contributed a new library of books to support proofs of partial and total correctness of sequential programs based on assertional reasoning, in books/symbolic/. This work is based on the paper J. Matthews, J S. Moore, S. Ray, and D. Vroon, ``A Symbolic Simulation Approach to Assertional Program Verification,'' currently in draft form. In particular, the books include the macro defsimulate, which automatically transforms inductive assertion proofs of correctness of sequential programs to the corresponding interpreter proofs. See the README in that directory. We have changed the implementation of :dir :system for [ld] and [include-book]. This change will not affect you if you build an ACL2 executable in the normal manner, leaving in place the books/ subdirectory of the source directory; nor will it affect you if you download a GCL Debian binary distribution. The change is that if environment variable ACL2_SYSTEM_BOOKS is set, then it specifies the distributed books directory, i.e., the directory determined by :dir :system. You may find it convenient to set this variable in your ACL2 script file (typically, saved_acl2). If it is set when you build ACL2, the generated script for running ACL2 will begin by setting ACL2_SYSTEM_BOOKS to that value. Thanks to various people who have discussed this issue, in particular Jared Davis who sent an email suggesting consideration of the use of an environment variable, and to Eric Smith who helped construct this paragraph. (Note that this use of ACL2_SYSTEM_BOOKS replaces the use of ACL2_SRC_BOOKS described previously; see [note-2-9-1].) ACL2 now automatically deletes files TMP*.lisp created during the build process and created by :[comp]. If you want these to be saved, evaluate (assign keep-tmp-files t) in the ACL2 loop or in raw Lisp. The clean target for the standard `make' process for certifying books (see [books-certification-classic]) will however delete all files TMP*.*. The TMP files discussed just above now generally include the current process ID in their names, e.g., TMP@16388@1.lisp instead of TMP1.lisp. Thanks to Bob Boyer for suggesting this measure, which will reduce the possibility that two different processes will attempt to access the same temporary file. Now, :[pe] will print the information formerly printed by :pe!, slightly enhanced to work for logical names that are strings, not just symbols. Thanks to Warren Hunt for leading us to this change by suggesting that :pe nth print the definition of [nth]. We eliminated spurious warnings that could occur in raw mode in OpenMCL or CMUCL when [stobj]s are present. We thank Juho Snellman for pointing out the relevant bug and appropriate fix. Mfc-rw now takes a third argument that can specify an arbitrary known equivalence relation; see [extended-metafunctions]. Thanks to Dave Greve for discussions suggesting this improvement. A small modification to a symbol-reading function allows documentation string processing on Windows systems that use CR/LF for line breaks. Thanks to William Cook for bringing this issue to our attention. The documentation has been improved on how to control the printing of ACL2 terms. See [user-defined-functions-table]. Thanks to Sandip Ray for asking a question that led to the example presented there. We fixed an inefficiency that could cause an [ld] command to seem to hang at its conclusion. Thanks to Sandip Ray for pointing out this problem. We checked that ACL2 runs under LispWorks 4.4.5, and have inhibited redefinition warnings. Two changes have been made on behalf of congruence-based reasoning. Thanks to Dave Greve for examples and discussions that have led to these changes, and to Eric Smith and Vernon Austel, who also sent relevant examples. o When a call of the new unary function [double-rewrite] is encountered by the rewriter, its argument will be rewritten twice. This solves certain problems encountered in congruence-based rewriting. Warnings for :[rewrite] and :[linear] rules will suggest when calls of [double-rewrite] on variables in hypotheses are likely to be a good idea. See [double-rewrite]. o Hypotheses of the form (equiv var (double-rewrite term)), where equiv is a known [equivalence] relation and var is a free variable (see [free-variables]), will bind var to the result of rewriting term twice. Previously, hypotheses of the form (equal var term) would bind a free variable var, but the call had to be of equal rather than of an arbitrary known equivalence relation. The following improvements were made in support of ACL2 on top of OpenMCL. o New versions of OpenMCL that do not have :mcl in Lisp variable *features* will now work with ACL2. Thanks to David Rager for bringing this issue to our attention. o Added support for OpenMCL 1.0 for 64-bit DarwinPPC/MacOS X, thanks to Robert Krug. o Fixed tracing in OpenMCL so that the level is reset to 1 even if there has been an abort. o Added support in OpenMCL for WET. o Incorporated suggestions from Gary Byers for printing the ``Welcome to OpenMCL'' prompt before initially entering the ACL2 loop and, and for setting useful environment variable CCL_DEFAULT_DIRECTORY in the ACL2 script. Fixed a long-standing bug in forward-chaining, where variable-free hypotheses were being evaluated even if the [executable-counterpart]s of their function symbols had been disabled. Thanks to Eric Smith for bringing this bug to our attention by sending a simple example that exhibited the problem. Improved reporting by the [break-rewrite] utility upon failure to relieve hypotheses in the presence of free variables, so that information is shown about the attempting bindings. See [free-variables-examples-rewrite]. Thanks to Eric Smith for requesting this improvement. Also improved the [break-rewrite] loop so that terms, in particular from unifying substitutions, are printed without hiding subterms by default. The user can control such hiding (``evisceration''); see :DOC set-brr-term-evisc-tuple. A new directory books/defexec/ contains books that illustrate the use of [mbe] and [defexec]. Thanks to the contributors of those books (see the README file in that directory). The directories books/rtl/rel2 and books/rtl/rel3 are no longer distributed. They are still available by email request. (Subdirectory rel1/ supports some of the optional workshop/ books, so it is still distributed.) Added book books/misc/sticky-disable.lisp to manage [theories] that might otherwise be modified adversely by [include-book]. Thanks to Ray Richards for a query that led to our development of this tool. The commands (exit) and (quit) may now be used to quit ACL2 and Lisp completely; in fact they macroexpand to calls of the same function as does [good-bye] (which is now a macro). Thanks to Jared Davis for suggesting the new aliases. (OpenMCL-only comment:) These all work for OpenMCL even inside the ACL2 loop. The macro wet now hides structure by default on large expressions. However, a new optional argument controls this behavior, for example avoiding such hiding if that argument is nil. Thanks to Hanbing Liu for pointing out that wet was not helpful for very large terms. We have fixed a bug in the forward-chaining mechanism that, very rarely, could cause a proof to be aborted needlessly with an obscure error message. Thanks to Jared Davis for sending us an example that evoked this bug. Fixed a bug that was causing proof output on behalf of :functional-instance to be confusing, because it failed to mention that the number of constraints may be different from the number of subgoals generated. Thanks to Robert Krug for pointing out this confusing output. The fix also causes the reporting of rules used when silently simplifying the constraints to create the subgoals. Fixed a bug in handling of leading ./ in pathnames, as in: (include-book \"./foo\"). Thanks to Jared Davis for bringing this bug to our attention. Made a small fix for handling of free variables of :[forward-chaining] rules, which had erroneously acted as though a hypothesis (equal var term) can bind the variable var. A small change has been made for :[type-prescription] rules for hypotheses of the form (equal var term), where var is a free variable and no variable of term is free (see [free-variables]). As with :[rewrite] and :[linear] rules, we now bind var to term even if (equal u term) happens to be known in the current context for some term u. Also as with :rewrite and :linear rules, similar handling is given to hypotheses (equiv var (double-rewrite term)) where equiv is a known [equivalence] relation. We changed the handling of free variables in hypotheses of :[rewrite] rules being handled by the [proof-checker]'s rewrite (r) command, in complete analogy to the change described just above for :[type-prescription] rules. The installation instructions have been updated for obtaining GCL on a Macintosh. Thanks to Robert Krug for supplying this information and to Camm Maguire for simplifying the process by eliminating the gettext dependency. The macro [comp] is now an event, so it may be placed in [books]. Previously, a [save-exec] call could fail because of file permission issues, yet ACL2 (and the underlying Lisp) would quit anyhow. This has been fixed. Thanks to Peter Dillinger for bringing this problem to our attention. Jared Davis, with assistance from David Rager, has updated his ordered sets library, books/finite-set-theory/osets/. See file CHANGES.html in that directory. A new function, [reset-kill-ring], has been provided for the rare user who encounters memory limitations. See [reset-kill-ring].") (NOTE-2-9-5 (RELEASE-NOTES) "Changes in Version 3.0 since Version 2.9.4 Fixed a bug in [cw-gstack] that was causing a hard error when attempting to report on a forced assumption. Thanks to Jared Davis for pointing this out and sending an example that helped us to determine a fix. Added [set-backchain-limit] to the set of legal [events] that can be placed in [encapsulate] forms and [books]. Thanks to John Cowles for bringing this issue to our attention. Fixed a bug that broke wet. Thanks to David Rager for bringing this bug to our attention. Guard verification now evaluates ground subexpressions (those with no free variables) when computing the guard conjecture for the body of a function. Thanks to Jared Davis for useful conversations leading to this change. See [verify-guards], in particular its ``Note on computation of guard conjectures and evaluation'' near the end of that topic, for more details. Added a warning when a [theory-invariant] is redefined. Thanks to Jared Davis for suggesting a warning in this case and providing an informative example. Also, [theory-invariant]s are now maintained more completely, as they are checked at the end of every event except for events executed on behalf of an [include-book] or the second pass of an [encapsulate]. Fixed the handling of runic designators to match their specification (see [theories]), so that disabling the name of a [defthm] event [disable]s all rules generated for that event. (For those who do numerous builds using feature :acl2-mv-as-values, currently only OpenMCL and multi-threaded SBCL by default:) You can speed up builds by adding the following parameter to `make', under conditions described in GNUmakefile: USE_ACL2_PROCLAIMS=:REUSE. Arranged that traced functions (see [trace$]) are automatically untraced when events are undone (for example see [ubt]), at least for most underlying Common Lisp implementations. The macro [defun-sk] now creates non-executable functions, which allows [stobj]s to be used where they had previously been prohibited. More generally, the user now has control over [declare] forms to be used by the underlying [defun]'d function; see [defun-sk]. Thanks to Sandip Ray for pointing out the need for such a modification. :[Definition] rules are now treated, at least by default, as truly first-class definitions. In particular, :expand [hints] use the latest :[definition] rule by default. You may specify :install-body nil to get the previous behavior of :definition rules; See [definition], and you may choose a previously-installed :definition rule to provide the current body; see [set-body]. Also see [rule-classes] for details of the :install-body field, and see [hints] to see a new :with directive for controlling expansion. The :with directive for :expand hints can even direct the use of a :[rewrite] rule for expansion! Thanks to various people, including Sandip Ray and Rob Sumners, for discussions on the issue of the applicability of :definition rules for :expand [hints]. [Constraint]s for functional instantiation now use the original definition rather than a simplified (``normalized'') version of it. Fixed a bug that caused the prompt to stay the same when guard-checking is off (see [set-guard-checking]) and raw-mode is changed (see [set-raw-mode]). Lemma names in directory books/ordinals have been changed by replacing /\\ with & and replacing \\/ with V. We made this change because backslash is an escape character and hence disappears unless it is itself escaped. Fixed [proof-tree] output so that failed non-proof events do not cause the proof-tree to be re-printed. Thus for example, if you have already advanced the checkpoint marker, it will not be reset by subequent failed non-proof events. Thanks to Pete Manolios and Peter Dillinger for bringing this bug to our attention. Fixed a bug that was preventing the printing of [stobj] fields as constants instead of numbers in certain cases. (Note that this bug only affected printing, not soundness.) Thanks to Eric Smith for bringing this problem to our attention and providing the following example (which now works fine). (defstobj st fld1 fld2) (in-theory (disable update-nth)) (defund run (st) (declare (xargs :stobjs (st))) ;adding this didn't seem to help.. st) ;works great; *fld1* prints as *fld1* (thm (equal (update-nth *fld1* 'abc st) (car (cons x y)))) ;*fld1* gets printed as 0, presumably because the call to run intervenes. (thm (equal (update-nth *fld1* 'abc (run st)) (car (cons x y)))) The macro [progn] now allows the use of macros defined within its bodies even when at the event level, as illustrated by the following example. (progn (defmacro my-defun (&rest args) `(defun ,@args)) (my-defun g (x) x)) Thanks to Anna Slobodova for bringing this issue to our attention. A related change is that all arguments of [progn] must now be embedded event forms (see [embedded-event-form]), so use [er-progn] instead if this is not the case. The change to [progn] mentioned above also fixes a bug in handling [local] events inside a [progn] that is inside an [encapsulate] or in a book. For example, the following form formerly caused an error. (encapsulate () (defun foo (x) x) (progn (local (defun bar (x) x)) (defun abc (x) x))) We fixed two bugs in :[puff] and :[puff*]. The first, brought to our attention by Eric Smith (who we thank), caused a cryptic error message when puffing a command with no subsidiary stored events; try, for example, (encapsulate () (value-triple 3)). The second was due to a failure to restore the [ACL2-defaults-table]. Suppose for example that we have certified the book foo.lisp, which contains ([program]) followed by some definitions and/or theorems. Now suppose we start ACL2 and execute the following. (include-book \"foo\") (defthm test-thm (equal x x) :rule-classes nil) If we now execute :[puff] 1, ACL2 will roll back the world to before the [include-book]; then ``puff'' the include-book, which will leave us in :[program] mode; and finally skip re-execution of the [defthm] because such [events] are skipped in :[program] mode. The fix is to re-install the [ACL2-defaults-table] immediately after the [include-book] to its pre-[include-book] value. A new event, [make-event], provides something like macros that take state. For example, one can use it to put tests into certified books, do proof search, and generate new function names. Many examples appear in directory books/make-event/. See [make-event]. Thanks to Bob Boyer and Jared Davis for useful feedback and to Warren Hunt, David Rager, and Sandip Ray for helpful discussions leading to some of the examples in directory books/make-event/. In support of [make-event], which is described in the preceding paragraph, certify-book has a new keyword argument, :save-expansion, that controls whether the result of expanding [make-event] forms is written out to a file. See [certify-book]; and for a discussion of book expansion files, see [make-event]. We fixed a soundness bug that did not correctly detect [local] events. For example, the following event was admitted. (encapsulate () (local (encapsulate () (local (progn (program))) ; or, (local (with-output :off summary (program))) (set-irrelevant-formals-ok t) (defun foo (x) (declare (xargs :measure (acl2-count x))) (1+ (foo x))))) (defthm inconsistent nil :hints ((\"Goal\" :use foo)) :rule-classes nil)) A new value for [guard] checking, :none, is now allowed. If you execute :[set-guard-checking] :none, then no guard checking will take place (but raw Lisp code will not be executed in this case). As a result, you should never see a guard violation, even for calls of :program mode functions. We thank Pete Manolios, who has long wanted this feature, and also Peter Dillinger, for asking for it. New documentation explains the interaction between the [defun-mode] and the value supplied to :[set-guard-checking]. See [guard-evaluation-table], see [guard-evaluation-examples-script], and see [guard-evaluation-examples-log]. In the course of adding the [guard]-checking value :none described in the paragraph above, we eliminated an optimization that eliminated guard checking for some recursive calls of :[logic] mode mutually-recursive functions that have not had their guards verified. But we doubt that this change will be noticed by any users!) The ACL2 hyper-card has been enhanced, thanks to David Rager, with a listing of ``Useful EMACS Commands'' to match comments in emacs/emacs-acl2.el. Users contributed books following the Readme.lsp methodology: data-structures/memories and unicode (Jared Davis), proofstyles (Sandip Ray and J Moore). Made some improvements to books/Makefile-generic (a file discussed elsewhere; see [books-certification-classic]). In particular, improved handling of .acl2 files for dependencies target. (Only OpenMCL and, with feature :acl2-mv-as-values, GCL) Fixed a bug that was causing proclaiming to fail when definitions are submitted interactively. The default stack size has been increased for several lisps. (Very technical) A restriction has been weakened on the use of [local] [stobj]s under a call of an ACL2 evaluator (trans-eval or simple-translate-and-eval). Now, the error can only take place for [stobj] names that occur in the term being evaluated. Thanks to Erik Reeber for bringing this issue to our attention. The notion of ``ancestor'' has been changed slightly. This notion is used by extended metafunctions and [break-rewrite] (see [extended-metafunctions] and see [brr@]), and also with backchain limits (see [backchain-limit] and see [set-backchain-limit]). Basically, each time a hypothesis is encountered during application of a [rewrite] rule, that hypothesis is pushed (after instantiating and negating) onto the current list of ancestors before it is rewritten. However, hypotheses of the form (equal var term), where var is free (see [free-variables]), had not been included in the ancestors (similarly for (equiv var (double-rewrite term)) where equiv is a known [equivalence] relation). Now such ``binding hypotheses'' are included in a special way in ancestors data structures. In particular, (null (mfc-ancestors mfc)) will now be true if and only if the term being rewritten is part of the current goal as opposed to a hypothesis from a rule encountered during backchaining, even if that hypothesis is a binding hypothesis. Thanks to Dave Greve for bringing this issue to our attention. Termination and induction analysis now continue through both arguments of [prog2$], not just the second. (Normally, the gathering up of [if] tests stops at function calls; but it continued through the second argument of [prog2$], and now it will continue through both arguments.) Thanks to Sol Swords for discussion leading to this change. The ACL2 distribution is now kept on the http server rather than the ftp server (but the home page has not been moved). Thanks to Robert Krug for letting us know that some ACL2 users have found it inconvenient to fetch ACL2 using ftp. The file books/README.html has been renamed to books/Readme.html, since some browsers don't show the former in the directory listing.") (NOTE-2-9{R} (RELEASE-NOTES) "ACL2 Version 2.9(r) (October, 2004) Notes No changes have been made for support of non-standard analysis, other than a minor modification or two in books/nonstd/ books. Please also see [note-2-9] for changes to Version_2.9 of ACL2.") (NOTE-3-0 (RELEASE-NOTES) "ACL2 Version 3.0 (June, 2006) Notes Please see [note-2-9-5] for a description of changes since Version 2.9.4. These include the new [make-event] feature, a soundness bug fix, an improvement for :expand [hints], evaluation in the logic by way of :[set-guard-checking] :none, and many other improvements. More generally, there have been several incremental releases since Version 2.9: see [note-2-9-1], see [note-2-9-2], see [note-2-9-3], see [note-2-9-4], and see [note-2-9-5]. A very few users have contributed books following the instructions on the web. We expect that when more contributions come in, we will give more attention to the question of how to organize the distributed and workshop books. For now, we have simply added the new contributions according to the old-style distribution methodology.") (NOTE-3-0-1 (RELEASE-NOTES) "ACL2 Version 3.0.1 (August, 2006) Notes NOTE! New users can ignore these release notes, because the documentation has been updated to reflect all changes that are recorded here. Fixed a soundness bug, introduced in the previous release, due to a failure to disallow [table] [events] that set the [ACL2-defaults-table] in a [local] context. Here is a proof of nil that exploits the bug. (encapsulate () (local (program)) (defun foo () (declare (xargs :measure 17)) (+ 1 (foo)))) (thm nil :hints ((\"Goal\" :in-theory (disable foo (foo)) :use foo))) Fixed a bug in the alternatives to [good-bye], which are the [exit] and [quit] commands. Thanks to Jared Davis and Peter Dillinger for pointing this out right away. The definition of [len] has been highly optimized in raw Lisp. Thanks to Bob Boyer and Warren Hunt for suggesting such an improvement and providing a lot of help in coming up with the current implementation. The clause subsumption algorithms have been improved, both to improve efficiency during warnings for :[rewrite] rules and to punt when the subsumption computation for induction appears to be blowing up. Thanks to Robert Krug for bringing this issue to our attention and supplying a useful example. A bug has been fixed that prevented [time$] from working properly in OpenMCL and multi-threaded SBCL (actually, in any ACL2 image where feature :acl2-mv-as-values is present). Thanks to Sol Swords for bringing this problem to our attention. A [type-spec] of the form (satisfies pred) carries the requirement that pred be a unary function symbol in the current ACL2 [world]; otherwise, it is illegal. Thanks to Dave Greve for pointing out that Common Lisp has this requirement. Installed a fix provided by Gary Byers (for ACL2 source function install-new-raw-prompt), for OpenMCL, that fixes an issue exposed in some versions of OpenMCL when compiler optimization is off. Fixed a bug in contributed book misc/untranslate-patterns.lisp that was causing calls of add-untranslate-pattern to be rejected in [books]. Thanks to Ray Richards for pointing out this bug and to Jared Davis for assisting in the fix. Fixed a bug in [defstobj] when keywords :initially and :resizable are both supplied. In this case, the definition of the resizing function mistakenly failed to quote the :initially value, even though this value is not to be evaluated. One could even get an error in this case, as in the following example supplied by Erik Reeber, whom we thank for bringing this bug to our attention: (defstobj $test (test-x :type (array t (5)) :initially (0) :resizable t)) A new feature, [with-prover-time-limit], allows the setting of time limits during proofs. This is not a general-purpose time-limit utility, nor is it guaranteed to implement a strict bound; it only attempts to limit time approximately during proofs. Thanks to Pete Manolios and Daron Vroon, who made the most recent request for such a feature, and to Robert Krug for a helpful discussion. (GCL only) Fixed a bug in the procedure for building a profiling image. Thanks to Sol Swords for bringing this bug to our attention and to Eric Smith for bringing a subsequent problem to our attention. Handling of [theories] can now use significantly less time and space. A regression suite run took about 25% longer before this change than it did after making this change (and also the ones in the next two paragraphs). Thanks to Vernon Austel for bringing this issue to our attention and for supplying code, quite some time ago, that provided detailed, useful implementation suggestions. Also thanks to the folks at Rockwell Collins, Inc. for pushing the limits of the existing implementation, thus encouraging this improvement. Fixed a performance bug in obtaining executable counterpart symbols. We now avoid certain computations made on behalf of warnings, when such warnings are disabled. We have relaxed the checks made when including an uncertified book, to match the checks made when including a certified book. Thanks to Eric Smith for suggesting this change. Fixed a bug in :[pso] (see [set-saved-output]) that caused an error when printing the time summary. Made fixes to avoid potential hard Lisp errors caused by the use of :[program] mode functions. The fix was to use a ``safe mode,'' already in use to prevent such errors during macroexpansion; see [guards-and-evaluation]. However, such errors were possible during evaluation of macro [guard]s, for example as follows: (defun foo (x) (declare (xargs :mode :program)) (car x)) (defmacro mac (x) (declare (xargs :guard (foo 3))) x) (defun g (x) (mac x)) A similar issue existed for calls of [defpkg], [in-theory], [table], [make-event], and value-triple, but has been fixed for all but in-theory and make-event, where technical issues have caused us to defer this change. Fixed a bug in wet that caused problems in OpenMCL, and perhaps other Lisp implementations, when the argument to wet calls, or depends on, certain built-ins including [prog2$], [time$], [mbe], and [must-be-equal]. Thanks to David Rager for bringing this problem to our attention. The file books/Makefile-generic has been improved so that when book certification fails with `make', the failure message contains the book filename. Documentation has been written to explain how to avoid an expensive immediate rewrite of the result of applying a :[rewrite] or :[meta] rule. See [meta]. Thanks to Robert Krug for supplying this trick, and to Eric Smith and Dave Greve for useful discussions. (OpenMCL only) OpenMCL-based ACL2 image names formerly had extension \".dppccl\", which was correct only for some platforms (including 32-bit Darwin PPC). That has been fixed, thanks to a suggestion from Gary Byers. It is now legal to attach both a :use and a :cases hint at the same goal. Thanks to Eric Smith for (most recently) requesting this feature. It is now permissible to include the same symbol more than once in the imports list of a [defpkg] form (i.e., its second argument). Also, the evaluation of [defpkg] forms with long import lists now uses a reasonably efficient sorting routine to check for two different symbols with the same name (see also books/misc/sort-symbols.lisp). If you currently call a function like remove-duplicates-eql for your imports list, as had been suggested by a [defpkg] error message, then you may experience some speed-up by removing that call. Thanks to Eric Smith for helping to discover this issue through profiling. Made miscellaneous efficiency improvements not listed above (for example, following a suggestion of Eric Smith to avoid checking for so-called ``bad Lisp objects'' during [include-book], which saved almost 3% in time on one large example). Modified the notion of ``untouchable'' to separate the notion of untouchable functions and macros from the notion of untouchable state global variables. See [push-untouchable]. Thanks to Bob Boyer for sending an example, (put-global 'ld-evisc-tuple t state), that suggested to us the need for more restrictive handling of untouchables. In particular, many ld specials (see [ld]) are now untouchable. You may be able to work around this restriction by calling [ld]; see for example the change to books/misc/expander.lisp. But please contact the ACL2 implementors if this sort of workaround does not appear to be sufficient for your purposes. Fixed a bug in function set-standard-oi (see [standard-oi]). Fixed a bug in the use of [ld-evisc-tuple]. The bad behavior was an improper use of the print-level and print-length components of the tuple (specifically, taking its [caddr] and [cadddr] instead of taking its [cadr] and [caddr]). Thanks to Bob Boyer for bringing this bug to our attention. A new argument to the compile-flg argument of [certify-book], :all, causes creation of a file to be compiled in place of the given book, where that file contains not only a copy of the book (with [make-event] forms expanded) but also contains definitions of the so-called ``executable counterparts'' of the functions defined in the book. Then, functions defined in the book will be run compiled when including the book, even for functions whose [guard]s have not been verified, or are in :program mode and running in so-called ``safe mode'' (for example, during expansion of macros). The default behavior, value t of compile-flg, is unchanged. Moreover, a new :comp! argument of [include-book] now compiles the executable counterparts when creating the book's compiled file, and unlike :comp, always deletes the old compiled file first so that one always gets a fresh compile. Now, [certify-book] gives a \"Guards\" warning only for :[logic] mode functions that are defined in the given book but have not had their guards verified. Previously, it also warned about such functions that were defined in the certification world or in sub-books. A new command, [redo-flat], facilitates the debugging of failed [encapsulate] and [progn] forms by evaluating preliminary forms in order to leave one at the point of failure. See [redo-flat]. Thanks to Ray Richards and others for asking for such a utility, and to Sandip Ray for useful discussions. We have changed the automatic declaration of of function types (still done in GCL and OpenMCL only, for now). Our motivation was to avoid the assumption that Common Lisp functions return one value when ACL2 says that they do; thanks to Bob Boyer for bringing this issue to our attention with the example of defining (foo x y) to be (floor x y). ACL2 was saying that foo returns a single value, but because floor returns two values in raw Lisp, so does foo. Other changes to automatic declaration include comprehending [defund], not just [defun]. A new function, [mod-expt], computes (mod (expt base exp) m), and does so efficiently in some implementations (currently only in GCL 2.7.0, which is not yet released). Thanks to Warren Hunt for suggesting such an addition. New functions [getenv$] and [setenv$] have been made available for reading and writing environment variables. Thanks to Jun Sawada for requesting these utilities. The query utility :[pl] has been improved in several ways. As before, :[meta] rules are only printed if the argument is a symbol; but the information printed for them is now more appropriate. The following are changes for the case that the argument is not a symbol, but rather, a term. (1) Rules are displayed that have [equivalence] relations other than [equal]. (2) All matching :[definition] rules are displayed, where previously :definition rules were only shown if they were ``simple'' rules (sometimes known as ``abbreviations''); see [simple]. (3) The ``Equiv'' field is printed for terms, not just symbols. (4) The substitution is shown that, when applied to the left-hand side of the rule, will yield the specified term. Thanks to Eric Smith for suggesting these changes. The [proof-checker] command ;show-rewrites has been improved to match the changes described above for :[pl]. In particular, :[definition] rules that are not ``[simple]'' are now displayed by the [proof-checker]'s show-rewrites (and sr) command, and the [proof-checker]'s rewrite command has been correspondingly modified to accept these :definition rules. Fixed `make' targets copy-distribution, copy-workshops, and copy-nonstd so that they should also work for non-developers. Fixed a bug that was causing :[pr] to display [syntaxp] hypotheses oddly in some cases, in particular (syntaxp (let ...)). (The problem was in the ``untranslate'' display of the internal form of syntaxp calls.) Thanks to Robert Krug for bringing this problem to our attention. We also removed the restriction on [bind-free] that its argument could not be a variable, a constant, or (more interestingly) a [lambda] application (i.e., a [let] or [mv-let] expression).") (NOTE-3-0-1{R} (RELEASE-NOTES) "ACL2 Version 3.0.1(r) (August, 2006) Notes No significant changes have been made since Version 3.0 for support of non-standard analysis in particular. Please also see [note-3-0-1] for changes to Version 3.0.1 of ACL2.") (NOTE-3-0-2 (RELEASE-NOTES) "ACL2 Version 3.0.2 (December, 2006) Notes NOTE! New users can ignore these release notes, because the documentation has been updated to reflect all changes that are recorded here. Fixed soundness bugs in the handling of primitive function [pkg-witness], and improved its documentation. (The executable counterpart returned an incorrect default value, and the axiom symbol-package-name-pkg-witness-name needed pkg-name to be other than \"\" in order to avoid the default value of \"ACL2\".) As fallout, a new built-in :[forward-chaining] rule, symbol-package-name-of-symbol-is-not-empty-string, now asserts that the [symbol-package-name] of a symbol is never \"\". Thanks to Mike Gordon for bringing these soundness bugs to our attention by attempting to prove translations of ACL2 axioms in HOL4. Fixed a soundness bug in linear arithmetic, due to incomplete tracking of forced assumptions while deriving inequalities. Thanks to Robert Krug for providing a fix and a proof of nil before the fix. Fixed a soundness bug in the redundancy criterion for [defun] events, which has been modified; see [redundant-events]. This bug is illustrated below. Thanks to Peter Dillinger and Jared Davis for contributions to an email thread that led us to discover this bug. The solution is that for a definition to be redundant with an earlier definition, ACL2 no longer ignores :[measure] [xargs] except when skipping proofs (e.g., during [include-book]). However, a new ``measure'', (:? v1 ... vk), is supported, for specifying a measured subset of the set of formals, i.e., a set of formals that serves as the set of parameters for some valid measure. (encapsulate () (local (defun foo (x y) (declare (xargs :measure (acl2-count y))) (if (and (consp x) (consp y)) (foo (cons x x) (cdr y)) y))) ; So the following is redundant -- but it guesses a measure ; of (acl2-count x), which isn't right! (defun foo (x y) (if (and (consp x) (consp y)) (foo (cons x x) (cdr y)) y))) ; end of encapsulate ; Now we prove a non-theorem by exploiting the bug above, ; erroneously replacing formal y by a constant in the induction ; scheme hinted below. (This should not be allowed, as y should be ; labeled as a measured formal.) (defthm bad (atom x) :rule-classes nil :hints ((\"Goal\" :induct (foo x '(3))))) ; It's easy to get a contradiction by instantiating the ; non-theorem just above. (defthm contradiction nil :rule-classes nil :hints ((\"Goal\" :use ((:instance bad (x '(7))))))) Fixed a bug in :[pl] and the [proof-checker]'s show-rewrites (sr) command that was causing a Lisp break. For :[pl], also improved the display of unifying substitutions, modified output to take binding hypotheses (equal var term) into account properly, and arranged for inclusion of [meta] rules that modify the given term. Thanks to Eric Smith for bringing these issues to our attention. Introduced new utilities for undoing [command]s, :[ubu] and :[ubu!], which are analogous to :[ubt] and :[ubt!] (respectively) except that they only undo back up to, but not including, the indicated command. Fixed a performance bug, pointed out by Eric Smith, that was negating efforts made for the preceding release to avoid computation for disabled warnings. Added [time$] and value-triple to *acl2-exports*. Thanks to Bob Boyer and Erik Reeber (respectively) for bringing these issues to our attention. Improved the automatic proclaiming of function types for GCL and OpenMCL, specifically to use an output format consistent with the Common Lisp spec. Thanks to Bob Boyer for bringing this issue to our attention. Added books/misc/transfinite.lisp, which deals with transfinite induction in ACL2. Thanks to Eric Smith for contributing this book. Added books/misc/process-book-readme.lisp to the distribution. Thanks to Sandip Ray for pointing out its omission. Added contributions books/concurrent-programs/bakery/ and books/concurrent-programs/german-protocol/. These contributions can be used as tutorials, especially by new ACL2 users, for learning how to model concurrent protocols in ACL2 and the steps involved in reasoning about their correctness. Thanks to Sandip Ray for these contributions. See the Readme.lsp files in these directories. Theory invariants may now involve the variable ENS instead of the variable THEORY. The practical effect of this change is that any expression of the form (MEMBER-EQUAL rune THEORY) occurring in a [theory-invariant] expression should be replaced by (ACTIVE-RUNEP rune). See [theory-invariant]. Thanks to Eric Smith and Dave Greve for pointing out an inefficiency in the handling of theory invariants that led to this change, which can speed up their handling by orders of magnitude on large examples, and to Eric for testing this change and pointing out problems with an early implementation of it. Theory invariants (see [theory-invariant]) are no longer checked on theories defined by [deftheory] [events]. After all, one can define a theory with deftheory that is not intended to be used as the current theory, but rather is intended to be combined with other [theories] (see [theory-functions]). Thanks to Eric Smith for bringing this issue to our attention. [Theory-invariant] errors had been reported with very little detail when warnings were inhibited. This problem has been fixed; thanks to Eric Smith for bringing it to our attention and providing an example. We have also improved the handling of redundancy for [theory-invariant] [events]. The macro [defun-sk] now has a new optional keyword, rewrite, that can be used to change the form of the :[rewrite] rule generated when the quantifier is [forall]. Thanks to Eric Smith and Sandip Ray for useful discussions on this topic. We have also slightly modified the [hints] for the [defthm] event underneath a defun-sk in order to make the proof more reliably efficient. A new event, [reset-prehistory], allows setting of a barrier before which undoing is illegal. An argument to this macro allows the barrier to be made permanent; otherwise, it can be removed with :[ubt-prehistory]. Thanks to Peter Dillinger for useful conversations leading to the addition of [reset-prehistory]. A new query, ([wormhole-p] [state]), allows users to determine whether or not they are in a [wormhole]. Thanks to Peter Dillinger for providing this utility. Value-triple no longer evaluates its form during [include-book], and in raw Lisp its calls trivially macroexpand to nil, without any consideration of its argument. This change avoids errors and warnings when [stobj] names occur in the argument. We fixed what could be considered a soundness hole that could occur by exploiting redefinition in a particular way. Thanks to Peter Dillinger for raising a question that led to discovery of this hole. A bug has been fixed in handling of illegal [theory] expressions. Thanks to Eric Smith, who reported this problem and provided the example (in-theory '((:definition natp) (:rewrite doesntexist))) to show how a hard error could occur. Improved error reporting by [certify-book] when the certification [world] contains inadmissible forms. Modified [defchoose] to add two new keyword arguments. There is now a :doc keyword argument; previously, an optional documentation string (see doc-string) was to be placed just before the body, without a keyword. There is also a :strengthen argument that strengthens the axiom added, which allows for the definition of ``fixing'' functions for equivalence relations that choose canonical representatives of equivalence classes. See [defchoose]. Thanks for Dave Greve for useful discussions that led us to this :strengthen enhancement. Added books/misc/bash.lisp, which provides utilities for simplifying a goal into a list of subgoals (as documented at the top of that file). Thanks to Dave Greve for requesting this utility and suggesting refinements to its functionality, which have been incorporated. (For Emacs users only) The command meta-x new-shell provided by file emacs/emacs-acl2.el now puts you in shell-mode, which for example supports directory tracking. Thanks to Jared Davis for suggesting this change. Fixed some mishandling of [stobj]s by [make-event] expansion. Introduced a new event, [defttag], that introduces a ``trust tag'' (``ttag'') allowing for extensions of ACL2 and for the use of generally unsafe ACL2 constructs. Thanks to Peter Dillinger, Sandip Ray, and Erik Reeber for useful discussions on defttag and the following related items. A new event, [remove-untouchable], can be used to give users access to system functions and data structures. We also fixed a bug in [push-untouchable]; and, it no longer is a no-op in :[program] mode. Thanks to Peter Dillinger for proposing [remove-untouchable] and suggesting that it and [push-untouchable] be functional in :[program] mode. Raw-mode (see [set-raw-mode]) no longer disables [certify-book]. However, [set-raw-mode] is now disallowed unless there is an active ttag (see [defttag]). If you want to execute ([set-raw-mode] t) and there is no active ttag, consider executing ([set-raw-mode-on!]) instead. Redefinition of system functions is disallowed unless there is an active ttag. However, [redef!] now introduces (defttag :redef!) in order to allow redefinition of system functions. A new event, [progn!], is a legal embedded event form that can go in [books] and both [encapsulate] and [progn] forms (see [embedded-event-form]), and is similar to [progn] except that it allows arbitrary forms. Thus, a [progn!] form is potentially dangerous and can only be evaluated if there is an active ttag. See [ttags-seen] for information about how to find the ttags known in the current ACL2 [world], and for related caveats. A new book created with Peter Dillinger, books/misc/hacker.lisp (added after Version_3.3: now books/hacking/hacker.lisp), uses [progn!] to define utiliities with-raw-mode and with-redef-allowed, which respectively allow raw Lisp evaluation and redefinition to take place within a certifiable book (!). Macro [with-output] is no longer allowed in function bodies because it does not have (and has never had) any effect in raw Lisp. See [with-output] for a workaround. Fixed a bug in redundancy of [defstobj] in raw Lisp, which caused an error when certifying a book with a redundant [defstobj] event whose [stobj] had already been modified. Here is an example: (defstobj st fld) (update-fld 3 st) (certify-book \"foo\" 1) ; where foo.lisp contains (defstobj st fld) New books illustrating [make-event] have been contributed in directory books/make-event/: dotimes.lisp (David Rager), stobj-test.lisp, and logical-tangent.lisp (Peter Dillinger). Modified print-object$ (see [io]) so that it no longer prints an extra space at the end. Replaced the ``draconian restriction to avoid capture'' that had prevented some :functional-instance [hints] from being legal. The corresponding check now only requires that no variable free in the functional substitution is captured by a [let] or [mv-let] (or [lambda]) binding. See [lemma-instance]. Added new extended metafunction, mfc-rw+, which is equivalent to mfc-rw except that it takes an alist argument, which may be useful for efficiency. See [extended-metafunctions]. Thanks to Robert Krug for suggesting this more efficient variant of mfc-rw. Added support for the ignorable [declare] form. We now cause an error on a call of open-input-channel (see [io]) with an argument string whose first character is the | character. Thanks to Bob Boyer for providing an example (several months ago) showing the danger of such calls, namely that the following command would log you out and kill all of your processes when running on top of GCL in Linux: (open-input-channel \"|kill -9 -1\" :object state) Restricted the use of [make-event] to contexts in which it can be tracked properly, under legal [events] (see [embedded-event-form]). Thanks to Peter Dillinger for bringing an example to our attention that led to this fix. Fixed a bug that was avoiding [guard]-checking for the functions [compress1] and [compress2]. Thanks to David Rager for bringing this bug to our attention. Added an error message when a [defun] or [mutual-recursion] event fails, to clarify whether failure is for the [measure] conjecture or for the [guard] conjecture. Thanks to David Rager for requesting clarification for such failures. Fixed a bug in reporting of [guard] violations (hard Lisp error) when certain macros (for example, [cond]) are used in the [guard]. Thanks to Jared Davis for bringing this problem to our attention and providing assistance with the solution, in particular by providing a helpful example. Grant Passmore has contributed a resolution/paramodulation prover written in ACL2, in directory books/deduction/passmore/. Thanks, Grant. Improved the error message when illegal theories are encountered. Improved the suppression of output for inhibit-output arguments of routines in the book books/misc/expander.lisp. Thanks to Qiang Zhang for pointing out the possibility for improvement here. Added a new directory books/arithmetic-3/extra/ that extends books/arithmetic-3 with additional rules, contributed by Alex Spiridonov with guidance from Robert Krug. WARNING: This directory is under development. It may undergo large changes in future releases, so please consider it experimental and subject to change. Feedback is welcomed. As part of the work mentioned just above, Robert Krug and Alex Spiridonov contributed improvements to books/arithmetic-3/: o A new rule |(* (/ x) (/ (expt x n)))| in bind-free/collect.lisp, which is important for reducing collect-* expressions though it slowed down one proof (see comment above this rule in bind-free/collect.lisp). o Slight improvements of rules integerp-mod and rationalp-mod in floor-mod/floor-mod.lisp. o To avoid conflict with books/rtl/rel6/arithmetic/, renamed rule mod-minus to mod-neg in floor-mod/floor-mod.lisp, and renamed integerp-+-reduce-leading-constant to integerp-+-reduce-leading-rational-constant in bind-free/integerp.lisp. (GCL on Windows only) Made a low-level change to avoid multiplying stacks for GCL on Windows, since GCL 2.6.6 broke while doing this. Fixed bugs in linear arithmetic (rarely evidenced, it seems) involving using < to compare complex rational constants. Thanks to Robert Krug for helping with the fixes. Added a new event, [assert-event], for checking that forms evaluate to non-nil values. Thanks to Peter Dillinger for suggesting and collaborating on this addition.") (NOTE-3-0{R} (RELEASE-NOTES) "ACL2 Version 3.0(r) (June, 2006) Notes No significant changes have been made since Version 2.9 for support of non-standard analysis in particular. Please also see [note-3-0] for changes to Version 3.0 of ACL2.") (NOTE-3-1 (RELEASE-NOTES) "ACL2 Version 3.1 (December, 2006) Notes NOTE! New users can ignore these release notes, because the documentation has been updated to reflect all changes that are recorded here. Please see [note-3-0-2] for a description of changes since Version 3.0.1, and also see [note-3-0-1] for additional changes since Version 3.0.") (NOTE-3-1{R} (RELEASE-NOTES) "ACL2 Version 3.1(r) (December, 2006) Notes No significant changes have been made since Version 3.0 for support of non-standard analysis in particular. Please also see [note-3-1] for changes to Version 3.1 of ACL2.") (NOTE-3-2 (RELEASE-NOTES) "ACL2 Version 3.2 (April, 2007) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Before this release, a raw Lisp error could put the ACL2 user into the debugger of the host Common Lisp. Now, such cases will generally put the user back at the top-level loop after an informative message. For details, see [set-debugger-enable]; also see [break$]. Fixed a soundness bug that was allowing unknown packages to sneak into a book and wreak havoc. Thanks to Peter Dillinger for sending an interesting example that led us to an exploration resulting in finding this bug. (A comment in the source code for note-3-2 shows such an example.) That example led us to fix a couple of other bugs related to packages. See [hidden-death-package] if you are generally interested in such issues, and for associated examples, see comments in note-3-2 in the ACL2 source code. Fixed subtle soundness bugs related to :[meta] rules by restricting evaluators (see [defevaluator]), as discussed in a new documentation topic: see [evaluator-restrictions]. Fixed a soundness bug that was allowing redefinition from :[logic] to :[program] mode. This prohibition had been in ACL2 for awhile but was accidentally removed in the preceding version. Fixed a soundness bug related to [trace$]. Thanks to Peter Dillinger for bringing it to our attention and for useful discussions, and providing a proof of nil, the essence of which is illustrated as follows: (value-triple (trace$ (bar :entry (defun foo () 17)))) Thus, [trace$] could be used to cause destructive raw Lisp behavior. Now, trace$ fails unless it is either given a list of symbols or else there is an active trust tag (see [defttag]); otherwise, consider using trace! instead. Closed a loophole that could be viewed as compromising soundness. It was possible to write files during book certification by exploiting [make-event] expansion, but that is no longer the case by default. A new function [open-output-channel!] is identical as a function to open-output-channel, except that the new function may be called even during [make-event] expansion and [clause-processor] [hints], but requires that there is an active trust tag (see [defttag]). Thanks to Peter Dillinger for producing a convincing example (forging a [certificate] during book certification; see [open-output-channel!]) and to him, Sandip Ray, and Jared Davis for useful discussions on the topic. Added book books/defexec/reflexive/reflexive.lisp to illustrate reflexive functions. ACL2 now generate scripts that invoke the saved image with exec. (Previously this was only done for GCL and CLISP.) The benefit of this change can be to avoid the lingering of ACL2 processes after enclosing processes have exited. Thanks to Peter Dillinger for pointing out this issue. ACL2 has a better implementation of ([good-bye]) (hence of synonyms ([quit]) and ([exit])). As a result, you should now be able to exit ACL2 and Lisp from within the ACL2 read-eval-print loop with any of the above; formerly, this was not supported for some Lisp implementations, and was slow in OpenMCL. Thanks to SBCL developer Harald Hanche-Olsen for useful advice. Fixed a bug in raw-mode (see [set-raw-mode]) that was causing hard errors when evaluating calls of [er-progn], or of macros expanding to such calls. Fixed a few Makefile dependencies, necessary only for parallel `make'. A new book, misc/defpun-exec-domain-example.lisp, provides an example showing how partial functions which return a unique value for arguments in a specified domain can be efficiently executed with ACL2. Execution is achieved using the [mbe] construct. Thanks to Sandip Ray for providing this example. Existing function [mod-expt] computes (mod (expt base exp) mod) with great efficiency in GCL, but not in other Lisps. Now, the book arithmetic-3/floor-mod/mod-expt-fast.lisp defines a function mod-expt-fast that should provide significantly improved performance for such expressions in other Lisps as well, though still probably not as fast as when using mod-expt in GCL. Thanks to Warren Hunt, with contributions from Robert Krug, for providing this book, Modified macro [break-on-error] to print of an error message before entering a break, and to cause a hard error if the underlying Lisp cannot handle it (formerly, a raw Lisp break would occur). Thanks to Bob Boyer for bringing these issues to our attention. The book books/misc/defpun.lisp, as well as other books related to the defpun macro, has been modified to avoid namespace collisions by prefixing function symbol names with \"DEFPUN-\"; for example base has been replaced by defpun-base. Thanks to Dave Greve for providing a first version of this update to defpun.lisp. A theory, base, in books/arithmetic-3/bind-free/top.lisp, has been renamed arithmetic-3-bind-free-base, to avoid potential name conflicts. Fixed books/arithmetic-3/bind-free/banner.lisp to print (as before) a message about how to turn on non-linear arithmetic, by modifying the call of value-triple to use :on-skip-proofs t. Thanks to Robert Krug for bringing this issue to our attention. Modified books/Makefile-subdirs and books/Makefile-psubdirs so that they can be used with books/Makefile-generic. Thus, one can set things up so that `make' can be used to certify books both in the current directory and subdirectories, for example as follows. ACL2 = ../../saved_acl2 arith-top: top all all: top DIRS = pass1 bind-free floor-mod include ../Makefile-subdirs include ../Makefile-generic top.cert: top.lisp top.cert: bind-free/top.cert top.cert: floor-mod/floor-mod.cert top.cert: floor-mod/mod-expt-fast.cert An experimental extension of ACL2 is under development by Bob Boyer and Warren Hunt to support function memoization, hash conses, and an applicative version of hash tables. The default build of ACL2 does not include this extension, other than simple logic definitions of functions in new source file hons.lisp. Future versions of ACL2 may fully incorporate this experimental extension. The [defevaluator] event macro has been modified primarily by adding a new constraint as follows, where evl is the evaluator. The idea is that for the evaluation of a function call, one may replace each argument by the quotation of its evaluation and then also replace the alist environment with nil. (DEFTHMD UNHIDE-evl-CONSTRAINT-0 (IMPLIES (AND (CONSP X) (SYNTAXP (NOT (EQUAL A ''NIL))) (NOT (EQUAL (CAR X) 'QUOTE))) (EQUAL (evl X A) (evl (CONS (CAR X) (KWOTE-LST (UNHIDE-evl-LIST (CDR X) A))) NIL)))) In order to support this change, there is another change: an evaluator maps nil to nil (note (AND X (CDR (ASSOC-EQ X A))) in place of (CDR (ASSOC-EQ X A)) below). (DEFTHM UNHIDE-evl-CONSTRAINT-1 (IMPLIES (SYMBOLP X) (EQUAL (UNHIDE-evl X A) (AND X (CDR (ASSOC-EQ X A)))))) With the new [defevaluator], Dave Greve has been able to do a proof about beta reduction that seemed impossible before (see books/misc/beta-reduce.lisp). Thanks to Dave for suggesting an initial version of this change. Explicit compilation is now avoided for OpenMCL, resulting in fewer files to manage (no more files resulting from compilation) and, according to some tests, slightly faster run times. See [compilation]. Thanks to Bob Boyer and Warren Hunt for suggesting this possibility. Now, the term-evisc-tuple (see [ld-evisc-tuple]) is overridden by state global user-term-evisc-tuple in all cases. Formerly, this was only the case when term-evisc-tuple was called with non-nil first argument. Symbols with the dot (.) character are generally no longer printed with vertical bars. For example, before this change: ACL2 !>'ab.c |AB.C| ACL2 !> After this change: ACL2 !>'ab.c AB.C ACL2 !> Thanks to Jared Davis for suggesting this improvement. Fixed bugs in guard verification for theorems. The following examples illustrate these bugs. If either theorem's body is executed in raw Lisp there is likely to be a hard Lisp error, even though [verify-guards] was supposed to ensure against that behavior. ; Example: Verify-guards failed to check that all functions in the theorem ; had already been guard-verified. (defun my-car (x) (car x)) (defthm my-car-compute-example (equal (my-car 3) (my-car 3))) (verify-guards my-car-compute-example) ; Example: Verify guards of a theorem whose body uses state improperly. (defthm bad-state-handler (if (state-p state) (equal (car state) (car state)) t) :rule-classes nil) (verify-guards bad-state-handler) See [gcl] for an example, developed with Warren Hunt and Serita Nelesen, that shows how to get fast fixnum (small integer) arithmetic operations in GCL. Fixnum declarations are now realized as (signed-byte 30) and (unsigned-byte 29) instead of what was generally (signed-byte 29) and (unsigned-byte 28). MCL users may thus find better performance if they switch to OpenMCL. Note that some definitions have changed correspondingly; for example, [zpf] now [declare]s its argument to be of type (unsigned-byte 29) instead of (unsigned-byte 28). A few [books] may thus need to be adjusted; for example, changes were made to books in books/data-structures/memories/. ACL2's rewriter now avoids removing certain true hypotheses and false conclusions. When a hypothesis rewrites to true or a conclusion rewrites to false, ACL2 formerly removed that hypothesis or conclusion. Now, it only does such removal when the hypothesis or conclusion is either a call of [equal] or an equivalence relation (see [equivalence]), or else is sufficiently trivial (roughly, either redundant with another hypothesis or conclusion or else trivially true without considering the rest of the goal). A specific example may be found in source file simplify.lisp; search for ``; But we need to do even more work''. Thanks to Robert Krug for providing the idea for this improvement and its initial implementation. As is common with heuristic changes, you may find it necessary on occasion to rename some subgoals in your [hints]. And in this case, you might also find it necessary on rare occasions to add :do-not '(generalize) [hints]. A new function, mfc-relieve-hyp, allows (for example) for more powerful [bind-free] hypotheses, by providing an interface to the rewriter's routine for relieving hypotheses. See [extended-metafunctions]. Thanks to Robert Krug for providing the idea for this feature and its initial implementation. Two improvements have been made to non-linear arithmetic (see [non-linear-arithmetic]). One allows for deducing strict inequality (<) for the result of certain polynomial multiplications, where previously only non-strict inequality (<=) was deduced. A second allows the use of the product of two polynomials when at least one of them is known to be rational. We had previously restricted the use of the product to the case where both were known to be rational. Thanks to Robert Krug for these improvements. (OpenMCL and Allegro CL only) Fixed ACL2's redefinitions of raw Lisp trace and untrace in OpenMCL and Allegro CL so that when given no arguments, they return the list of traced functions. For trace, this is an ANSI spec requirement. Note that [trace$] and [untrace$] continue to return nil in the ACL2 loop. Fixed a bug that was allowing the symbol &whole to appear in other than the first argument position for a [defmacro] event, in violation of the Common Lisp spec (and leading to potentially surprising behavior). Thanks to Peter Dillinger for bringing this bug to our attention. It had been illegal to use [make-event] under some calls of [ld]. This has been fixed. Thanks to Jared Davis for bringing this issue to our attention with a simple example, in essence: (ld '((defmacro my-defun (&rest args) `(make-event '(defun ,@args))) (my-defun f (x) x))) ACL2 no longer prohibits certain [make-event] forms when including uncertified [books]. Thanks to Peter Dillinger for first bringing this issue to our attention. Hard errors arose when using [break-rewrite] stack display commands, in particular :path and :frame, from inside the [proof-checker]. This has been fixed. Fixed a bug that could cause functions that call system built-ins f-put-global, f-get-global, or f-boundp-global to cause a raw Lisp error even when proving theorems. Thanks to Peter Dillinger, for reporting such a failure for the form (thm (w '(1 2 3))). Renamed the formal parameters of function set-equal in distributed book books/arithmetic-3/bind-free/normalize.lisp so that more distributed books can be included together in the same session. In particular books books/data-structures/set-theory and books/arithmetic-3/extra/top-ext can now be included together. Thanks to Carl Eastlund for bringing this problem to our attention and to Robert Krug for suggesting the formals renaming as a fix. Metafunctions must now be executable. See [meta]. New utilities allow for user-defined simplifiers at the goal level, both verified and unverified (``trusted''), where the latter can even be defined by programs outside ACL2. See [clause-processor], which points to a new directory books/clause-processors/ that contains examples of these new utilities, including for example a system (``SULFA'') contributed by Erik Reeber that implements a decision procedure (thanks, Erik). Also see [proof-checker-commands] for the new [proof-checker] command clause-processor (or for short, cl-proc). The rewriter has been tweaked to run faster in some cases involving very large terms. Thanks to Eric Smith and Jared Davis for providing a helpful example that helped us locate the source of this inefficiency. Added books/make-event/defspec.lisp. This book shows how one can mimic certain limited forms of higher-order statements in ACL2 by use of macros, [make-event], and [table] events. Thanks to Sandip Ray for his contribution. A new release of the RTL library, books/rtl/rel7/, replaces the previous version, books/rtl/rel6/. Thanks to Hanbing Liu and David Russinoff for providing this new version. We thank David Russinoff for providing a proof of the law of quadratic reciprocity. See books/quadratic-reciprocity/Readme.lsp. Eliminated a slow array warning (see [slow-array-warning]) that could occur when exiting a [wormhole] after executing an [in-theory] event in that wormhole. Thanks to Dave Greve for bringing this problem to our attention. A new accessor, (mfc-rdepth mfc), provides a new field, the remaining rewrite stack depth, which has been added to metafunction context structures; see [extended-metafunctions]. Thanks to Eric Smith for suggesting this addition. The algorithms were modified for collecting up rule names and other information used in proofs, into so-called ``tag-trees''. Tag-trees are now free of duplicate objects, and this change can dramatically speed up some proofs that involve many different rules. Thanks to Eric Smith for doing some profiling that brought this issue to our attention, and for reporting that this change reduced proof time on an example by about 47% (from 3681.46 reported seconds down to 1954.69). All legal xargs keywords may now be used in [verify-termination] [events]. In particular, this is the case for :normalize. (SBCL and CMUCL only) Fixed a problem with stobj array resizing functions that was causing a hard error in ACL2 images built on SBCL or CMUCL. A new [table], [evisc-table], allows you to introduce print abbreviations, for example for large constants. Moreover, a new reader macro --- #, --- makes it convenient to reference constants even inside a quote. See [evisc-table]. Thanks to Bob Boyer and Warren Hunt for useful discussions leading to this feature. The macros in books/misc/expander.lisp now have a new keyword argument, :simplify-hyps-p. The default behavior is as before, but now case splitting from hypothesis simplification can be avoided. For details, evaluate (include-book \"misc/expander\" :dir :system) and then :doc! defthm? and :doc! symsym. Thanks to Daron Vroon for sending a question that prompted this additional functionality. ACL2 failed to apply :[restrict] hints to rules of class :[definition], except for the simplest sorts (see [simple]). This has been fixed. Thanks to Jared Davis for pointing out this bug by sending a small example. Added a new :msg argument to assert-event; see [assert-event]. The implementation of value-triple has been modified to support this change. Fixed a bug in macro io? that now allows the commentp argument to be t. This provides a way other than cw to print without modifying state, for example as follows. (Warning: Certain errors may leave you in a [wormhole], in which case use :a! to abort.) ACL2 !>(prog2$ (io? event t state () (fms \"Howdy~%\" nil *standard-co* state nil)) (+ 3 4)) Howdy 7 ACL2 !>:set-inhibit-output-lst (proof-tree event) (PROOF-TREE EVENT) ACL2 !>(prog2$ (io? event t state () (fms \"Howdy~%\" nil *standard-co* state nil)) (+ 3 4)) 7 ACL2 !> ACL2 now disallows calls of [progn!] inside function bodies, just as it already disallowed such calls of [progn], since in both cases the Common Lisp meaning differs from the ACL2 meaning. Redefinition of system functions now always requires an active trust tag (see [defttag]). This restriction was intended before, but there was a hole that allowed a second redefinition without an active trust tag. Thanks to Peter Dillinger for pointing out this bug. [Verify-termination] has been disabled for a few more built-in functions that are in :[program] mode. (If you are curious about which ones they are, evaluate (f-get-global 'built-in-program-mode-fns state).) [Note added for Version_3.4: This state global has been changed to 'program-fns-with-raw-code.] Moreover, such functions now will execute only their raw Lisp code, so for example they cannot be called during macroexpansion. Thanks to Peter Dillinger and Sandip Ray for useful discussions on details of the implementation of this restriction. New untouchable state global variables, temp-touchable-vars and temp-touchable-fns, can control the enforcement of untouchability. See [remove-untouchable]. Thanks to Peter Dillinger for suggesting these features. The ``TTAG NOTE'' string was being printed by [encapsulate] events whenever an active trust tag was already in effect (see [defttag]), even if the encapsulate event contained no [defttag] event. This has been fixed. Thanks to Peter Dillinger for a query leading to this fix. Fixed a bug in [progn!] that could leave the user in raw-mode (see [set-raw-mode]). This could occur when certifying a book with a compile-flg value of t (see [certify-book]), when that book contained a [progn!] event setting raw-mode to t without setting raw-mode back to nil: (progn! (set-raw-mode t) ...)") (NOTE-3-2-1 (RELEASE-NOTES) "ACL2 Version 3.2.1 (June, 2007) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. (OpenMCL and multi-threaded SBCL only) Fixed a soundness bug in the evaluation of [mbe] forms in the presence of Lisp feature :acl2-mv-as-values. Thanks to Sol Swords for reporting this problem and sending a simple proof of nil (which can be found in a comment in the ACL2 sources, in (deflabel note-3-2-1 ...)). Added a new utility, [dmr] (Dynamicaly Monitor Rewrites), for watching the activity of the rewriter and some other proof processes. See [dmr]. We thank Robert Krug for useful contributions. Fixed a bug in evaluation of calls of [with-prover-time-limit]. Fixed the writing of executable scripts when building ACL2, so that the build-time value of environment variable ACL2_SYSTEM_BOOKS is no longer written there. Thanks to Dave Greve for discussing this change. Fixed bugs in :[pl] (which are similarly present in the [proof-checker]'s sr (show-rewrites) command. The first bug was evident from the following forms sent by Robert Krug, which caused an error. (include-book \"arithmetic-3/floor-mod/floor-mod\" :dir :system) :pl (mod (+ 1 x) n) The second bug was due to a failure to take note of which rules are disabled, and could be seen by executing the following (very slow!). (defstub modulus () t) (include-book \"arithmetic-3/floor-mod/floor-mod\" :dir :system) :pl (mod (+ x y) (modulus)) Modified [certify-book] so that by default, all executable-counterpart functions (sometimes called ``*1* functions'') are compiled. This is the behavior that was already supported with a compile-flg argument of :all; the change is that argument t now has this behavior as well (and :all is supported only for legacy purposes). A new value for compile-flg, :raw, gives the behavior formerly produced by value t, namely where executable-counterpart functions are not compiled. The above changes are irrelevant if compilation is suppressed; see [compilation]. Finally, if environment variable ACL2_COMPILE_FLG is set, then after converting to upper-case this environment variable's value of \"T\", \"NIL\", or \":RAW\" will determine the value of the optional compile-flg argument to be t, nil, or :raw, respectively, when this argument is not explicitly supplied. Modified [include-book] so that :comp argument now acts like :comp!, i.e., compiling a file that includes the file together with all executable counterpart (so-called ``*1*'') functions. A new argument, :comp-raw, has the behavior that :comp had formerly, i.e., compiling the actual book only. The function [nonnegative-integer-quotient] is now computed in raw Lisp by calling [floor] on its arguments. This change was suggested by Peter Dillinger, in order to avoid stack overflows such as reported by Daron Vroon. A new book, books/misc/misc2/misc.lisp, contains a proof of equivalence of [nonnegative-integer-quotient] and [floor], and serves as a repository for other miscellaeous proofs, including those justifying ACL2 modifications such as this one. Enhanced [accumulated-persistence] to break down results by useful vs. useless rule applications. In particular, this provides information about which rules were ever applied successfully, as requested by Bill Young. Added coverage of :[meta] rules to the [accumulated-persistence] statistics. Fixed a bug that was causing a :[clause-processor] hint to fire on a subgoal of the goal to which it was attached, when the original application didn't change the clause. Thanks to Dave Greve for pointing out this bug and providing a useful example. Fixed a bug in handling of computed [hints] related to the stable-under-simplificationp parameter (see [computed-hints]). There were actually two bugs. A minor but confusing bug was that the same goal was printed twice upon application of such a hint. The major bug was that :use [hints] (as well as other ``top'' hints: :by, :cases, and :clause-processor) were not being applied properly. Thanks to Jared Davis for sending an example some time ago that showed the duplicate printing, and to Dave Greve for sending an example showing mis-application of :[clause-processor] [hints]. Note that you may find that existing computed hints using the stable-under-simplificationp parameter no longer have the same behavior; see a comment about computed hints in note-3-2-1, ACL2 source file ld.lisp, for an example of how you might want to fix such computed hints. David Russinoff has contributed an updated version of books/quadratic-reciprocity/ including minor modifications of the treatment of prime numbers and a proof that there exist infinitely many primes. Thanks to David for contributing this work, and to Jose Luis Ruiz-Reina for posing the challenge. Reduced the sizes of some [certificate] (.cert) files by relaxing the test that allows original [defpkg] [events] to be placed there, rather than evaluating the import list term into an explicit list of symbols. Improved execution efficiency slightly for function rcdp in file books/misc/records.lisp, by using [mbe] to introduce a tail-recursive body. The executable script generated by [save-exec] (and by the normal build process) now includes a time stamp as a comment. Thanks to Jared Davis for suggesting this change in order to support his use of omake. In the process, we also arranged that the startup banner for an executable created by [save-exec] shows all of the build (save) times, not just the one for the original image. Sped up most redundant [defpkg] [events] by avoiding evaluation and sorting of the imports list in the case of identical event forms. And, for [defpkg] events that are not redundant, sped up their processing in Allegro CL (and perhaps other Lisps, but apparently not GCL) by using our own import function. Modified [add-include-book-dir] so that it refuses to associate a keyword with a different directory string than one it is already bound to. See [delete-include-book-dir] for how to remove the existing binding first. Thanks to Robert Krug for pointing out that without this change, one can find it difficult to debug a failure due to rebinding a keyword with [add-include-book-dir]. Added a new value for the :do-not-induct hint (see [hints]), :otf-flg-override, which causes ACL2 to ignore the :[otf-flg] when considering whether to abort the proof because of a :do-not-induct hint. Thanks to Daron Vroon for suggesting such an addition. Modified the printing of messages for entering and exiting raw mode (see [set-raw-mode]), so that in particular they are inhibited during [include-book] or whenever observations are inhibited (see [set-inhibit-output-lst]). Thanks to Peter Dillinger for suggesting such a change. (For system hackers only.) The handling of [events] of the form (progn! (state-global-let* ...)) had a bug that was causing bindings to be evaluated twice. Moreover, the use of system function [state-global-let*] is suspect in raw Lisp. We have eliminated special treatment of state-global-let* by progn! in favor of a new keyword argument, state-global-bindings, that provides the intended functionality. See [progn!]. Moreover, special handling that allowed [make-event] forms under state-global-let* has been removed; the desired effect can be obtained using (progn! :state-global-bindings ...). Thanks to Peter Dillinger for pointing out the above bug and collaborating on these changes. Incorporated backward-compatible enhancements to books/misc/expander.lisp from Daron Vroon (documented near the top of that file). The specification of :backchain-limit-lst had required that only a single (:[rewrite], :[linear], or :[meta]) rule be generated. We have weakened this restriction to allow more than one rule provided that each rule has the same list of hypotheses. For example, the rule class (:rewrite :backchain-limit-lst 1) is now legal for the corollary formula (implies (f x) (and (g x) (h x))), where this was not formerly the case. Thanks to Dave Greve for bringing this issue to our attention.") (NOTE-3-2-1{R} (RELEASE-NOTES) "ACL2 Version 3.2.1(r) (June, 2007) Notes Please also see [note-3-2-1] for changes to Version 3.2.1 of ACL2.") (NOTE-3-2{R} (RELEASE-NOTES) "ACL2 Version 3.2(r) (April, 2007) Notes Changed the default distributed [books] directory for ACL2(r) from books/ to books/nonstd/. See [include-book], in particular the discussion of ``Distributed Books Directory''. Added directory books/arithmetic-3/ and its subdirectories to books/nonstd/. (But a chunk of theorems from arithmetic-3/extra/ext.lisp are ``commented out'' using #-:non-standard-analysis because they depend on books/rtl/rel7/, which is not yet in books/nonstd/; feel free to volunteer to remedy this!) Incorporated changes from Ruben Gamboa to some (linear and non-linear) arithmetic routines in the theorem prover, to comprehend the reals rather than only the rationals. Please also see [note-3-2] for changes to Version 3.2 of ACL2.") (NOTE-3-3 (RELEASE-NOTES) "ACL2 Version 3.3 (November, 2007) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Below we roughly organize the changes since Version 3.2.1 into new features, bug fixes, prover algorithm enhancements, and miscellaneous. Also see [note-3-2-1] for other changes since Version 3.2. NEW FEATURES A new ``gag-mode'' provides less verbose, more helpful feedback from the theorem prover, in support of The Method (see [the-method]). See [set-gag-mode]. We recommend the use of gag-mode, which may become the default in future ACL2 releases, and we welcome suggestions for improvement. We thank Robert Krug and Sandip Ray for helpful feedback in the design of [gag-mode]. Note that when proofs fail, then even without gag-mode and even if proof output is inhibited, the summary will contain a useful listing of so-called ``key checkpoints'' (see [set-gag-mode]). Added support for a leading `~' in filenames. Thanks to Bob Boyer for suggesting this enhancement. Note that since `~/' depends on the user, it is disallowed in [books] to be certified (see [certify-book]), since otherwise an [include-book] form in a book, b, could have a different meaning at certification time than at the time [include-book] is later executed on book b. Made a change to allow (time$ FORM) and (with-prover-time-limit TIME FORM) when FORM includes [make-event] calls that change the ACL2 [world]. Thanks to Jared Davis for requesting such support for [time$]. Computed [hints] (see [computed-hints]) may now produce a so-called ``error triple'', i.e., a result of the form (mv erp val state), where a non-nil erp causes an error, and otherwise val is the value of the hint. It remains legal for a computed hint to return a single ordinary value; indeed, the symbol form of a computed hint must still be a function that returns an ordinary single value. New hints provide additional control of the theorem prover, as follows. See [hints] for more details, and see new distributed book directory books/hints/ for examples, in particular file basic-tests.lisp in that directory for simple examples. o The hint :OR (hints-1 ... hints-k) causes an attempt to prove the specified goal using each hints-i in turn, until the first of these succeeds. If none succeeds, then the prover proceeds after heuristically choosing the ``best'' result, taking into account the goals pushed in each case for proof by induction. o A custom hint is a keyword that the user associates with a corresponding hint-generating function by invoking [add-custom-keyword-hint]. Thus, a custom hint may be viewed as a convenient sort of computed hint. o A custom hint, :MERGE, is implemented in distributed book books/hints/merge.lisp. It is useful for combining hints. o A sophisticated yet useful custom hint is the :CONSIDER hint implemented in distributed book books/hints/consider-hint.lisp. With this hint, you can for example give the equivalent of a :USE hint without the need to supply an instantiation. Include that book in order to see documentation online with :doc consideration, and see the book books/hints/consider-hint-tests.lisp for examples. A new hint, :[reorder], allows the specification of which subgoals are to be considered first. Thanks to Sandip Ray for putting forward this idea. Enhanced [set-saved-output] by supporting a second argument of :same, which avoids changing which output is inhibited. Added macros thm? and not-thm? to distributed book books/make-event/eval.lisp, so that it's easy to test within a certified book that a proof attempt succeeds or that it fails. Added printing function [cw!], which is analogous to [cw] just as [fmt!] is to [fmt], i.e., printing so that the result can be read back in. Thanks to Jared Davis for suggesting this enhancement (after doing his own implementation). The ACL2 customization file can now be specified using environment variable ACL2-CUSTOMIZATION [note: starting with Version_4.0, ACL2_CUSTOMIZATION]. See [ACL2-customization]. Thanks to Peter Dillinger for requesting this feature. Added new emacs capabilities for proof trees (all documented in emacs): o New function start-proof-tree-noninteractive, for example (start-proof-tree-noninteractive \"*shell*\") o C-z o Switch to another frame o C-z b Switch to prooftree buffer o C-z B Switch to prooftree buffer in \"prooftree-frame\" frame Added Common Lisp function, search, as a macro in [logic] mode, with limited support for keyword arguments. Thanks to Warren Hunt for requesting this addition. Sandip Ray has contributed a book, books/make-event/defrefine.lisp, that provides a collection of macros to aid in reasoning about ACL2 functions via refinement. Wrote and incorporated new utility for listing all the theorems in an included book. See books/misc/book-thms.lisp. Thanks to Jared Davis for requesting this functionality. The new distributed book misc/defp.lisp generalizes the [defpun] macro to allow more general forms of tail recursion. (Low-level printing improvement) A new function, set-ppr-flat-right-margin, allows the right margin for certain kinds of ``flat'' printing to exceed column 40. Thanks to Jared Davis for pointing out that state global variables 'fmt-hard-right-margin and 'fmt-soft-right-margin are not alone sufficient to extend the right margin in all cases. The event [add-include-book-dir] can now take a relative pathname as an argument. Formerly, it required an absolute pathname. A new book, books/misc/defopener.lisp, provides a utility creating a theorem that equates a term with its simplification. ACL2 now provides limited support for the Common Lisp primitive FLET, which supports local function bindings. See [flet]. Thanks to Warren Hunt for requesting this feature. Added a definition of [boole$], a close analogue of Common Lisp function boole. Thanks to Bob Boyer for providing an initial implementation. BUG FIXES Fixed [defstobj] to inhibit a potentially useless theory warning. Fixed a bug in the application of [certify-book] to relative pathnames for files in other than the current directory. Thanks to Amr Helmy for bringing this bug to our attention. Fixed a bug in :[pl] and :[pr] for displaying rules of class :[meta]. Thanks to Jared Davis for finding this bug and providing a fix. Formerly, [set-default-backchain-limit] was not a legal event form for [encapsulate] forms and [books]. This has been fixed. Thanks to Robert Krug and Sandip Ray for bringing this bug to our attention. Fixed the handling of [hints] in [proof-checker] commands for the prover, such as bash --- see [proof-checker-commands] --- so that the user can override the default settings of hints, in particular of :do-not and :do-not-induct hints attached to \"Goal\". This fix also applies to the distributed book misc/bash.lisp, where Robert Krug noticed that he got an error with :hints ((\"Goal\" :do-not '(preprocess))); we thank Robert for pointing out this problem. Fixed a bug in handling of [stobj]s occurring in guards of functions whose [guard]s have been verified. In such cases, a raw Lisp error was possible when proving theorems about non-''live'' [stobj]s. We thank Daron Vroon for sending us an example that highlighted this bug. The following (simpler) example causes such an error in previous versions of ACL2. (defstobj st fld) (defun foo (st) (declare (xargs :stobjs st :guard (fld st))) st) (thm (equal (foo '(3)) '(3))) The [dmr] feature for dynamic monitoring of rewrites had a bug, where the file used for communicating with emacs was the same for all users, based on who built the ACL2 executable image. This has been fixed. Thanks to Robert Krug for bringing this bug to our attention. Fixed a bug in some warnings, in particular the warning for including an uncertified book, that was giving an incorrect warning summary string. Inclusion of uncertified books erroneously re-used [make-event] expansions that were stored in stale [certificate]s. This is no longer the case. Thanks to Jared Davis for bringing this bug to our attention. Fixed a bug that was disallowing calls of [with-output] in [events] that were executing before calling [certify-book]. Modified the functionality of binop-table so other than binary function symbols are properly supported (hence with no action based on right-associated arguments). See [add-binop]. Fixed small [proof-checker] issues related to packages. Emacs commands ctrl-t d and ctrl-t ctrl-d now work properly with colon (`:') and certain other punctuation characters. The p-top command now prints ``***'' regardless of the current package. Fixed a bug that allowed [certify-book] to succeed without specifying value t for keyword argument :skip-proofs-okp, even with [include-book] [events] in the certification [world] depending on events executed under [skip-proofs]. Improved [show-accumulated-persistence] in the following two ways. Thanks to Robert Krug and Bill Young for requesting these improvements and for providing useful feedback. o It can provide more complete information when aborting a proof. o The :frames reported for a rule are categorized as ``useful'' and ``useless'' according to whether they support ``useful'' or ``useless'' :tries of that rule, respectively. See [accumulated-persistence] for further explanation. Modified [make-event] so that the reported time and warnings include those from the expansion phase. In analogy with [encapsulate] and [progn], the rules reported still do not include those from subsidiary events (including the expansion phase). A related change to [ld] avoids resetting summary information (time, warnings) with each top-level form evaluation; [events] already handle this information themselves. Fixed [set-inhibit-output-lst] so that all warnings are inhibited when warning! but not warning is included in the list. Formerly, only soundness-related warnings were inhibited in this case. Thanks to Eric Smith for bringing this bug to our attention. Distributed directory doc/HTML/ now again includes installation instructions (which was missing in Version_3.2.1), in doc/HTML/installation/installation.html. Some fixes have been made for [proof-tree] support. o [Proof-tree] output is no longer inhibited automatically during [certify-book], though it continues to be inhibited by default (i.e., ACL2 continues to start up as though [set-inhibit-output-lst] has been called with argument '(proof-tree)). o Fixed a bug in Xemacs support for [proof-tree] help keys C-z h and C-z ?. o Fixed a bug in [proof-tree]s that was failing to deal with the case that a goal pushed for proof by induction is subsumed by such a goal to be proved later. Now, the proof-tree display regards such subsumed goals as proved, as is reported in the theorem prover's output. Fixed a bug that was disallowing [value-triple] forms inside [encapsulate] forms in a certification [world] (see [portcullis]). If the :load-compiled-file argument of a call of [include-book] is :comp, then an existing compiled file will be loaded, provided it is more recent than the corresponding book (i.e., .lisp file). A bug was causing the compiled file to be deleted and then reconstructed in the case of :comp, where this behavior was intended only for :comp!. Fixed a bug that was avoiding compilation of some executable counterparts (sometimes called ``*1* functions'') during [certify-book], and also during [include-book] with :load-compiled-file value of :comp or :comp!). Thanks to Eric Smith for sending a small example to bring this bug to our attention. Incorporated a fix from Eric Smith for a typo (source function ancestors-check1) that could cause hard Lisp errors. Thanks, Eric! Fixed the following issues with packages and book [certificate]s. See [hidden-death-package] if you are generally interested in such issues, and for associated examples, see comments on ``Fixed the following issues with packages'' in note-3-3 in the ACL2 source code. o Reduced the size of .cert files by eliminating some unnecessary [defpkg] events generated for the [portcullis]. o Fixed a bug that has caused errors when reading symbols from a [portcullis] that are in undefined packages defined in locally included books. o Fixed a bug that could lead to failure of [include-book] caused by a subtle interaction between [set-ignore-ok] and [defpkg] events generated for the [portcullis] of a [certificate]. PROVER ALGORITHM ENHANCEMENTS Non-linear arithmetic (see [non-linear-arithmetic]) has been improved to be more efficient or more powerful in some cases. Thanks to Robert Krug for contributing these improvements. Improved certain (so-called ``[type-set]'') reasoning about whether or not expressions denote integers. Thanks to Robert Krug for contributing code to implement this change, along with examples illustrating its power that are now distributed in the book books/misc/integer-type-set-test.lisp. Improved ACL2's heuristics for relieving hypotheses, primarily to use linear reasoning on conjuncts and disjuncts of the test of an [if] expression. For example, given a hypothesis of the form (if (or term1 term2) ...), ACL2 will now use linear reasoning to attempt to prove both term1 and term2, not merely for term2. Thanks to Robert Krug for supplying examples illustrating the desirability of such an improvement and for useful discussions about the fix. Made a slight heuristic change, so that when a hypothesis with [let] or [mv-let] subterms (i.e. [lambda] subterms) rewrites to t, then that hypothesis is necessarily eliminated. Thanks to Jared Davis for sending an example that led us to develop this change, and thanks to Robert Krug for a helpful discussion. MISCELLANEOUS Added documentation on how to use [make-event] to avoid duplicating expensive computations, thanks to Jared Davis. See [using-tables-efficiently]. Modified the error message for calls of undefined functions to show the arguments. Thanks to Bob Boyer for requesting this enhancement. Modified utilies :[pr], :[pr!], :[pl], and :[show-bodies] to incorporate code contributed by Jared Davis. That code defines low-level source functions info-for-xxx that collect information about rules, which is thus available to advanced users. Dynamic monitoring of rewrites (see [dmr]) has been improved in the following ways, as suggested by Robert Krug. o Some stale entries from the rewrite stack are no longer printed, in particular above ADD-POLYNOMIAL-INEQUALITIES. o An additional rewrite stack entry is made when entering non-linear arithmetic (see [non-linear-arithmetic]). o An ADD-POLYNOMIAL-INEQUALITIES entry is printed with a counter, to show how often this process is called. Modified [save-exec] so that the newly-saved image will have the same raw Lisp package as the existing saved image. This is a very technical change that will likely not impact most users; for example, the package in the ACL2 read-eval-print loop (see [lp]) had already persisted from the original to newly-saved image. Thanks to Jared Davis for suggesting this change. Changed [make-event] expansion so that changes to [set-saved-output], [set-print-clause-ids], set-fmt-soft-right-margin, and set-fmt-hard-right-margin will persist after being evaluated during make-event expansion. (Specifically, *protected-system-state-globals* has been modified; see [make-event-details].) Thanks to Jared Davis for bringing this issue to our attention. Output from the [proof-checker] is now always enabled when invoking [verify], even if it is globally inhibited (see [set-inhibit-output-lst]). Improved the message printed when an :induct hint fails, to give more information in some cases. Thanks to Rex Page for suggesting where an improvement could be made and providing useful feedback on an initial improvement. Added a warning for [congruence] rules (see [defcong]) that specify [iff] as the second equivalence relation when [equal] can be used instead. Those who heed these warnings can eliminate certain subsequent [double-rewrite] warnings for [rewrite] rules with conclusions of the form (iff term1 term2), and hence implicitly for Boolean conclusions term1 that are interpreted as (iff term1 t). Thanks to Sarah Weissman for sending us an example that highlighted the need for such a warning. Modified macro :[redef!] (which is for system implementors) so that it eliminates untouchables. Several improvements have been made to the experimental hons/memoization version of ACL2. See [hons-and-memoization]. The distributed books directory, (@ distributed-books-dir), is now printed in the start-up message.") (NOTE-3-3{R} (RELEASE-NOTES) "ACL2 Version 3.3(r) (November, 2007) Notes Please also see [note-3-3] for changes to Version 3.3 of ACL2.") (NOTE-3-4 (RELEASE-NOTES) "ACL2 Version 3.4 (August, 2008) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Below we roughly organize the changes since Version 3.3 into changes to existing features, new features, bug fixes, new and updated books, and Emacs support. Each change is described just once, though of course many changes could be placed in more than one category. CHANGES TO EXISTING FEATURES Fixed a long-standing potential infinite loop in the rewriter. Thanks to Sol Swords for sending a concise example illustrating the looping behavior. (Those interested in details are welcome to look at the comment about loop behavior in source function rewrite-equal.) Incorporated a slight strengthening of non-linear arithmetic contributed by Robert Krug (thanks, Robert). With non-linear arithmetic enabled, the problem was essentially that ACL2 made the following ``optimization'': given inequalities (< a u) and (< b v), for positive rational constants a and b terms u and v of which at least one is known to be rational, infer (< (* a b) (* u v)). Without this optimization, however, ACL2 now infers the stronger inequality obtained by direct multiplication of the two given inequalities. To see the effect of this change, submit the event (set-non-linearp t) followed by: (thm (implies (and (rationalp x) (< 3 x) (rationalp y) (< 4 y)) (< 0 (+ 12 (* -4 x) (* -3 y) (* x y))))) The utility [set-checkpoint-summary-limit] has been modified in several ways: it now takes a single argument (no longer takes [state] as an argument); a natural number n abbreviates the pair (n . n); the argument is no longer evaluated, but it still optionally may be quoted; and a new value, t, suppresses all printing of the checkpoint summary. Thanks to Jared Davis for suggesting most of these improvements. There was formerly a restriction on [mbe] that the :exec argument may not contain a call of [mbe]. This restriction has been removed, thanks to a request from Jared Davis and Sol Swords. Thanks also to Sandip Ray, who pointed out that this restriction may have been in place in order that [defexec] can guarantee termination using the :exec code; its [documentation] has therefore been updated to clarify this situation. Rules of class :[rewrite] are now stored by performing certain logical simplifications on the left side of the conclusion: (prog2$ X Y) is replaced by Y, (mbe :logic X :exec Y) is replaced by X (more precisely, the analogous change is made to the generated call of [must-be-equal]); and (the TYPE X) is replaced by X (again, the change is actually made on the macroexpanded form). Thanks to Jared Davis and Sol Swords for requesting this change. An analogous change has also been made for rules of class :[forward-chaining]. The [trace$] utility has been reimplemented to work independently of the underlying Lisp trace. It thus works the same for every host Lisp, except as provided by an interface to the underlying host Lisp trace (the :native option). Note that the host Lisp trace continues to be modified for GCL, Allegro CL, and CCL (OpenMCL); see [trace]. See [trace$] for updated detailed documentation on tracing options, many of which are new, for example an :evisc-tuple option that can be set to :no-print if you want the function traced without the usual entry and exit printing. The previous [trace$] had some issues, including the following, which have all been fixed. Thanks to Peter Dillinger for assistance in determining desired functionality of the new [trace$] and for helping to test it. Recursive calls were not always shown in the trace for two reasons. (1) Compiler inlining could prevent recursive calls from being shown in the trace, in particular in CCL (OpenMCL). Thanks to Jared Davis and Warren Hunt for pointing out this issue and requesting a fix, and to Bob Boyer and Gary Byers for relevant helpful discussions. (2) ACL2's algorithm for producing executable counterparts prevented tracing of recursive calls even after (set-guard-checking :none). Thanks to Peter Dillinger for requesting a fix. It was possible to exploit a bug in the interaction of multiple values and trace to prove a contradiction. An example is in a comment in (deflabel note-3-4 ...) in the ACL2 source code. Certain large structures could cause expensive computations for printing even when a :cond condition was specified and evaluated to nil. [Trace!] now suppresses printing of the event summary, and returns the value that would be returned (if there is an active trust tag) by the corresponding call of [trace$]. Some bugs have been fixed in the underlying native trace installed by ACL2 for GCL, Allegro CL, and CCL (OpenMCL), including the following. In GCL it had been impossible to use the variable ARGLIST in a :cond expression. In Allegro CL and CCL, a [trace$] bug mishandled tracing non-ACL2 functions when directives such as :entry and :exit were supplied. GCL trace now hides the world even when tracing non-ACL2 functions. Tracing in CCL no longer causes a Lisp error when untracing a traced function defined outside the ACL2 loop; for example (trace$ len1) followed by (untrace$ len1) no longer causes an error. The macro wet has been changed, for the better we think. see [wet]. The generation of goals for [forcing-round]s has been changed to avoid dropping assumptions formerly deemed ``irrelevant''. (A simple example may be found in a comment in source function unencumber-assumption, source file prove.lisp.) Thanks to Jared Davis for sending us an example that led us to make this change. Modified the implementation of [make-event] so that in the [certificate] of a book, [local] events arising from [make-event] forms are elided. For example, if (make-event
) expands to (local ), then where the latter had been stored in the certificate, now instead (local (value-triple :ELIDED)) will be stored. Thanks to Eric Smith for requesting this improvement. He has reported that a preliminary version of this improvement shrunk a couple of his .cert files from perhaps 40MB each to about 140K each. Now, a [table] event that sets the entire table, (table tbl nil alist :clear), is redundant (see [redundant-events]) when the supplied alist is equal to the current value of the table. Thanks to Peter Dillinger for requesting this change. The event constructor [progn!] now returns the value that is returned by evaluation of its final form if no error occurs, except that it still returns nil if the that final evaluation leaves ACL2 in raw-mode. :[Pso] and :[psog] have been improved so that they show the key checkpoint summary at the end of a failed proof. (For a discussion of key checkpoints, see [set-gag-mode].) As a result, a call of [set-checkpoint-summary-limit] now affects subsequent evaluation of :[pso] and :[psog]. In particular, you no longer need to reconstruct a proof (by calling [thm] or [defthm]) in order to see key checkpoints that were omitted due to the limit; just call [set-checkpoint-summary-limit] and then run :pso or :psog. The [proof-checker] behaves a little differently under [gag-mode]. Now, proof-checker commands that call the theorem prover to create new proof-checker goals, such as bash and induct (see [proof-checker-commands]), will show key checkpoints when in [gag-mode]. As before, proof-checker commands pso and pso! (and now, also psog) --- see [pso], see [psog], and see [pso!] --- can then show the unedited proof log. However, unlike proof attempts done in the ACL2 loop, such proof attempts will not show a summary of key checkpoints at the end, because from a prover perspective, all such goals were considered to be temporarily ``proved'' by giving them ``byes'', to be dispatched by later proof-checker commands. A little-known feature had been that a [measure] of 0 was treated as though no measure was given. This has been changed so that now, a [measure] of nil is treated as though no measure was given. Expanded *acl2-exports* to include every documented symbol whose name starts with \"SET-\". Thanks to Jared Davis for remarking that [set-debugger-enable] was omitted from *acl2-exports*, which led to this change. The [trace] mechanism has been improved so that the :native and :multiplicity options can be used together for Lisps that support the trace :exit keyword. These Lisps include GCL and Allegro CL, whose native trace utilities have been modified for ACL2. For SBCL and CCL (OpenMCL), which use the built-in Lisp mechanism for returning multiple values in ACL2 (see [mv]), the use of :multiplicity with :native remains unnecessary and will be ignored. In support of this change, the modification of native Allegro CL tracing for ACL2 was fixed to handle :exit forms correctly that involve [mv]. NEW FEATURES The command :[redef!] is just like :[redef], but prints a warning rather than doing a query. The old version of :redef! was for system hackers and has been renamed to :[redef+]. Introduced a new utility for evaluating a function call using the so-called executable counterpart --- that is, executing the call in the logic rather than in raw Lisp. See [ec-call]. Thanks to Sol Swords for requesting this utility and participating in its high-level design. See [print-gv] for a new utility that assists with debugging guard violations. Thanks to Jared Davis for requesting more tool assistance for debugging guard violations. Improved the guard violation error message to show the positions of the formals, following to a suggestion of Peter Dillinger. Added new [guard-debug] capability to assist in debugging failed attempts at [guard] verification. See [guard-debug]. Thanks to Jared Davis for requesting a tool to assist in such debugging and to him, Robert Krug, and Sandip Ray for useful discussions. New utilities provide the formula to be proved by [verify-guards]. See [verify-guards-formula] and see [guard-obligation], Thanks to Mark Reitblatt for making a request leading to these utilities. These utilities can be applied to a term, not just an event name; thanks to Peter Dillinger for correspondence that led to this extension. A new utility causes runes to be printed as lists in proof output from simplification, as is done already in proof summaries. See [set-raw-proof-format]. Thanks to Jared Davis for requesting this utility. An experimental capability allows for parallel evaluation. See [parallelism]. Thanks to David Rager for providing an initial implementation of this capability. Defined [xor] in analogy to [iff]. Thanks to Bob Boyer, Warren Hunt, and Sol Swords for providing this definition. Improved distributed file doc/write-acl2-html.lisp so that it can now be used to build HTML documentation files for [documentation] strings in user [books]. See the comment in the definition of macro acl2::write-html-file at the end of that file. Thanks to Dave Greve and John Powell for requesting this improvement. It is now possible to specify :[hints] for non-recursive function definitions (which can be useful when definitions are automatically generated). See [set-bogus-defun-hints-ok]. Thanks to Sol Swords for requesting such a capability. Keyword argument :dir is now supported for [rebuild] just as it has been for [ld]. We relaxed the criteria for functional substitutions, so that a function symbol can be bound to a macro symbol that corresponds to a function symbol in the sense of [macro-aliases-table]. So for example, a functional substitution can now contain the doublet (f +), where previously it would have been required instead to contain (f binary-+). We now allow arbitrary packages in raw mode (see [set-raw-mode]) --- thanks to Jared Davis for requesting this enhancement --- and more than that, we allow arbitrary Common Lisp in raw mode. Note however that for arbitrary packages, you need to be in raw mode when the input is read, not just when the input form is evaluated. Two new keywords are supported by the [with-output] macro. A :gag-mode keyword argument suppresses some prover output as is done by [set-gag-mode]. Thanks to Jared Davis for asking for a convenient way to set [gag-mode] inside a book, in particular perhaps for a single theorem; this keyword provides that capability. A :stack keyword allows sub-[events] of [progn] or [encapsulate] to ``pop'' the effect of a superior [with-output] call. Thanks to Peter Dillinger for requesting such a feature. See [with-output]. The command [good-bye] and its aliases [exit] and [quit] now all take an optional status argument, which provides the Unix exit status for the underlying process. Thanks to Florian Haftmann for sending a query to the ACL2 email list that led to this enhancement. Keyword commands now work for macros whose argument lists have lambda list keywords. For a macro with a lambda list keyword in its argument list, the corresponding keyword command reads only the minimum number of required arguments. See [keyword-commands]. It is now legal to [declare] variables ignorable in [let*] forms, as in (let* ((x (+ a b)) ...) (declare (ignorable x)) ...). Thanks to Jared Davis for requesting this enhancement. Added a warning when more than one hint is supplied explicitly for the same goal. It continues to be the case that only the first hint applicable to a given goal will be applied, as specified in the user-supplied list of :hints followed by the [default-hints-table]. Thanks to Mark Reitblatt for sending a question that led both to adding this clarification to the [documentation] and to adding this warning. You may now use [set-non-linear], [set-let*-abstraction], set-tainted-ok, and [set-ld-skip-proofs] in place of their versions ending in ``p''. Thanks to Jared Davis for suggesting consideration of such a change. All ``set-'' utilites now have a version without the final ``p'' (and most do not have a version with the final ``p''). Added a \"Loop-Stopper\" warning when a :[rewrite] rule is specified with a :[loop-stopper] field that contains illegal entries that will be ignored. Thanks to Jared Davis for recommending such a warning. Added a substantial documentation topic that provides a beginner's guide to the use of quantification with [defun-sk] in ACL2. Thanks to Sandip Ray for contributing this guide, to which we have made only very small modifications. See [quantifier-tutorial]. [Defun-sk] now allows the keyword option :strengthen t, which will generate the extra constraint that that is generated for the corresponding defchoose event; see [defchoose]. Thanks to Dave Greve for suggesting this feature. BUG FIXES Fixed a soundness bug related to the use of [mbe] inside [encapsulate] events. An example proof of nil (before the fix) is in a comment in (deflabel note-3-4 ...) in the ACL2 source code. We therefore no longer allow calls of [mbe] inside [encapsulate] events that have non-empty [signature]s. Fixed a bug related to the definition of a function supporting the macro [value-triple]. Although this bug was very unlikely to affect any user, it could be carefully exploited to make ACL2 unsound: (defthm fact (equal (caadr (caddr (value-triple-fn '(foo 3) nil nil))) 'value) ; but it's state-global-let* in the logic :rule-classes nil) (defthm contradiction nil :hints ((\"Goal\" :use fact :in-theory (disable (value-triple-fn)))) :rule-classes nil) Non-[local] definitions of functions or macros are no longer considered redundant with built-ins when the built-ins have special raw Lisp code, because ACL2 was unsound without this restriction! A comment about redundant definitions in source function chk-acceptable-defuns shows how one could prove nil without this new restriction. Note that system utility :[redef+] removes this restriction. Although ACL2 already prohibited the use of certain built-in :[program] mode functions for [verify-termination] and during macroexpansion, we have computed a much more complete list of functions that need such restrictions, the value of constant *primitive-program-fns-with-raw-code*. Modified what is printed when a proof fails, to indicate more clearly which event failed. Fixed a problem with [dmr] in CCL (OpenMCL) that was causing a raw Lisp break after an interrupt in some cases. Thanks to Gary Byers for a suggestion leading to this fix. Fixed bugs in [proof-checker] code for dealing with free variables in hypotheses. Upon an abort, the printing of [pstack] and [gag-mode] summary information for other than GCL was avoided when inside a call of [ld]. This has been fixed. (Windows only) Fixed bugs for ACL2 built on SBCL on Windows, including one that prevented [include-book] parameters :dir :system from working, and one that prevented certain compilation. Thanks to Peter Dillinger for bringing these to our attention and supplying a fix for the second. Thanks also to Andrew Gacek for bringing [include-book] issues to our attention. Also, fixed writing of file saved_acl2 at build time so that for Windows, Unix-style pathnames are used. Fixed a hard Lisp error that could occur with keywords as [table] names, e.g., (table :a :a nil :put). Thanks to Dave Greve for bringing this problem to our attention and providing this example. Fixed handling of :OR [hints] so that proof attempts under an :OR hint do not abort (reverting to induction on the original input conjecture) prematurely. Thanks to Robert Krug for pointing out this problem and pointing to a possible initial fix. (SBCL and CLISP only) It is now possible to read symbols in the \"COMMON-LISP\" package inside the ACL2 command loop (see [lp]). This could cause a raw Lisp error in previous versions of ACL2 whose host Common Lisp was SBCL or CLISP. Thanks to Peter Dillinger for bringing this issue to our attention. Fixed a bug that was preventing certain [hints], such as :do-not hints, from being used after the application of an :or hint. Thanks to Robert Krug for bringing this bug to our attention. (Hons version only) Fixed a bug in the interaction of [memoize] ([hons] version only) with event processing, specifically in interaction with failures inside a call of [progn] or [encapsulate]. Thanks to Jared Davis for bringing this bug to our attention and sending an example. A simplified example may be found in a comment in source function table-cltl-cmd, source file history-management.lisp; search for ``Version_3.3'' there. Fixed [cw-gstack] so that its :evisc-tuple is applied to the top clause, instead of using (4 5 nil nil) in all cases. If no :evisc-tuple is supplied then (term-evisc-tuple t state) is used for the top clause, as it is already used for the rest of the stack. Fixed a bug in the interaction of [proof-tree]s with :induct hint value :otf-flg-override. Thanks to Peter Dillinger for reporting this bug and sending an example that evokes it. Fixed bugs in :[pr] and [find-rules-of-rune] for the case of rule class :[elim]. Thanks to Robert Krug and Jared Davis for bringing these related bugs to our attention. Improved failure messages so that the key checkpoints are printed only once when there is a proof failure. Formerly, a proof failure would cause the key checkpoints to be printed for every [encapsulate] or [certify-book] superior to the proof attempt. Fixed a bug in generation of [guard]s for calls of [pkg-witness]. Thanks to Mark Reitblatt for sending an example showing this bug. The bug can be in play when you see the message: ``HARD ACL2 ERROR in MAKE-LAMBDA-APPLICATION: Unexpected unbound vars (\"\")''. A distillation of Mark's example that causes this hard error is as follows. (defun foo (x) (declare (xargs :guard t)) (let ((y x)) (pkg-witness y))) The [cond] macro now accepts test/value pairs of the form (T val) in other than the last position, such as the first such pair in (cond (t 1) (nil 2) (t 3)). Thanks to Jared Davis for sending this example and pointing out that ACL2 was sometimes printing goals that have such a form, and hence cannot be submitted back to ACL2. A few macros corresponding to [cond] in some books under books/rtl and books/bdd were similarly modified. (A second change will probably not be noticeable, because it doesn't affect the final result: singleton [cond] clauses now generate a call of [or] in a single step of macroexpansion, not of [if]. For example, (cond (a) (b x) (t y)) now expands to (OR A (IF B X Y)) instead of (IF A A (IF B X Y)). See the source code for cond-macro for a comment about this change.) Fixed a bug in the interaction of [proof-checker] command DV, including numeric (``diving'') commands, with the [add-binop] event. Specifically, if you executed (add-binop mac fn) with fn having arity other than 2, a [proof-checker] command such as 3 or (dv 3) at a call of mac could have the wrong effect. We also fixed a bug in diving with DV into certain AND and OR calls. Thanks for Mark Reitblatt for bringing these problems to our attention with helpful examples. Fixed a couple of bugs that were causing an error, ``HARD ACL2 ERROR in RENEW-NAME/OVERWRITE''. Thanks to Sol Swords for bringing the first of these bugs to our attention. Fixed a bug that could cause [certify-book] to fail in certain cases where there are [local] [make-event] forms. Fixed a bug in [start-proof-tree] that could cause Lisp to hang or produce an error. Thanks to Carl Eastlund for sending an example to bring this bug to our attention. Fixed a bug in the proof output, which was failing to report cases where the current goal simplifies to itself or to a set including itself (see [specious-simplification]). Fixed a bug in [with-prover-time-limit] that was causing a raw Lisp error for a bad first argument. Thanks to Peter Dillinger for pointing out this bug. The following was claimed in :doc [note-3-3], but was not fixed until the present release: Distributed directory doc/HTML/ now again includes installation instructions, in doc/HTML/installation/installation.html. In certain Common Lisp implementations --- CCL (OpenMCL) and LispWorks, at least --- an interrupt could leave you in a break such that quitting the break would not show the usual summary of key checkpoints. This has been fixed. NEW AND UPDATED BOOKS Updated books/clause-processors/SULFA/ with a new version from Erik Reeber; thanks, Erik. Added new books directory tools/ from Sol Swords. See books/tools/Readme.lsp for a summary of what these books provide. The distributed book books/misc/file-io.lisp includes a new utility, write-list!, which is like write-list except that it calls [open-output-channel!] instead of [open-output-channel]. Thanks to Sandip Ray for requesting this utility and assisting with its implementation. Added record-update macro supplied by Sandip Ray to distributed book books/misc/records.lisp. Sandip Ray has contributed books that prove soundness and completeness of different proof strategies used in sequential program verification. Distributed directory books/proofstyles/ has three new directories comprising that contribution: soundness/, completeness/, and counterexamples/. The existing books/proofstyles/ directory has been moved to its subdirectory invclock/. Jared Davis has contributed a profiling utility for ACL2 built on CCL (OpenMCL). See books/misc/oprof.lisp. Thanks, Jared. ACL2 utilities [getprop] and [putprop] take advantage of under-the-hood Lisp (hashed) property lists. The new book books/misc/getprop.lisp contains an example showing how this works. Added the following new book directories: books/paco/, which includes a small ACL2-like prover; and books/models/jvm/m5, which contains the definition of one of the more elaborate JVM models, M5, along with other files including JVM program correctness proofs. See files Readme.lsp in these directories, and file README in the latter. Added books about sorting in books/sorting. See Readme.lsp in that directory for documentation. Added book books/misc/computed-hint-rewrite.lisp to provide an interface to the rewriter for use in computed hints. Thanks to Jared Davis for requesting this feature. Jared Davis has provided a pseudorandom number generator, in books/misc/random.lisp. Robert Krug has contributed a new library, books/arithmetic-4/, for reasoning about arithmetic. He characterizes it as being more powerful than its predecessor, books/arithmetic-3/, and without its predecessor's rewriting loops, but significantly slower than its predecessor on some theorems. Incorporated changes from Peter Dillinger to verify guards for functions in books/ordinals/lexicographic-ordering.lisp (and one in ordinal-definitions.lisp in that directory). A new directory, books/hacking/, contains a library for those who wish to use trust tags to modify or extend core ACL2 behavior. Thanks to Peter Dillinger for contributing this library. Obsolete version books/misc/hacker.lisp has been deleted. Workshop contribution books/workshops/2007/dillinger-et-al/code/ is still included with the workshops/ tar file, but should be considered deprecated. In books/make-event/assert.lisp, changed assert! and assert!-stobj to return (value-triple :success) upon success instead of (value-triple nil), following a suggestion from Jared Davis. EMACS SUPPORT Changed emacs/emacs-acl2.el so that the fill column default (for the right margin) is only set (still to 79) in lisp-mode. Modified Emacs support in file emacs/emacs-acl2.el so that names of events are highlighted just as [defun] has been highlighted when it is called. Search in the above file for font-lock-add-keywords for instructions on how to eliminate this change. The name of the temporary file used by some Emacs utilities defined in file emacs/emacs-acl2.el has been changed to have extension .lsp instead of .lisp; thus it is now temp-emacs-file.lsp. Also, `make' commands to `clean' books will delete such files (specifically, books/Makefile-generic has been changed to delete temp-emacs-file.lsp).") (NOTE-3-4{R} (RELEASE-NOTES) "ACL2 Version 3.4(r) (August, 2008) Notes Please also see [note-3-4] for changes to Version 3.4 of ACL2. Fixed makefiles, books/nonstd/Makefile and GNUmakefile. The old set-up seemed to work fine as long as all books certified, but it was really broken, for example only certifying some of the books in books/nonstd/nsa/, and then only when required by books in other directories. Also fixed the ``clean'' target to clean links rather than to make links.") (NOTE-3-5 (RELEASE-NOTES) "ACL2 Version 3.5 (May, 2009) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Below we roughly organize the changes since Version 3.4 into the following categories: changes to existing features, new features, heuristic improvements, bug fixes, new and updated books, Emacs support, and experimental [hons] version. Each change is described in just one category, though of course many changes could be placed in more than one category. CHANGES TO EXISTING FEATURES Many improvements have been made to ACL2's ``evisceration'' mechanism for hiding substructures of objects before they are printed, and to related documentation: o A new documentation topic explains evisc-tuples. See [evisc-tuple]. o A new interface, [set-evisc-tuple], has been provided for setting the four global evisc-tuples. See [set-evisc-tuple]. o A new mode, ``iprinting'', allows eviscerated output to be read back in. See [set-iprint]. o Function default-evisc-tuple has been deprecated and will probably be eliminated in future releases; use abbrev-evisc-tuple instead. Also eliminated is the brr-term-evisc-tuple (also the user-brr-term-evisc-tuple). The term-evisc-tuple controls printing formerly controlled by the brr-term-evisc-tuple or user-brr-term-evisc-tuple. o ACL2 output is done in a more consistent manner, respecting the intention of those four global evisc-tuples. In particular, more proof output is sensitive to the term-evisc-tuple. Again, see [set-evisc-tuple]. o A special value, :DEFAULT, may be provided to [set-evisc-tuple] in order to restore these [evisc-tuple]s to their original settings. o (Details for heavy users of the evisc-tuple mechanism) (1) There are no longer [state] globals named user-term-evisc-tuple or user-default-evisc-tuple. (2) Because of the above-mentioned :DEFAULT, if you have referenced state globals directly, you should use accessors instead, for example (abbrev-evisc-tuple state) instead of (@ abbrev-evisc-tuple). (3) For uniformity, [set-trace-evisc-tuple] now takes a second argument, state. Improved [break-on-error] in several ways. First, it breaks earlier in a more appropriate place. Thanks to Dave Greve for highlighting this problem with the existing implementation. Also, [break-on-error] now breaks on hard errors, not only soft errors (see [er], options hard and hard?). Thanks to Warren Hunt and Anna Slobodova for sending an example that showed a flaw in an initial improvement. Finally, new options cause printing of the call stack for some host Common Lisps. See [break-on-error]. Thanks to Bob Boyer for requesting this feature. [Trace!] may now be used in raw Lisp (though please note that all soundness claims are off any time you evaluate forms in raw Lisp!). Thanks to Bob Boyer for feedback that led to this enhancement. ACL2 now searches for file acl2-customization.lsp in addition to (and just before) its existing search for acl2-customization.lisp; See [ACL2-customization]. Thanks to Jared Davis for suggesting this change, which supports the methodology that files with a .lisp extension are certifiable books (thus avoiding the need to set the BOOKS variable in makefiles; see [books-certification-classic]). Improved the error message for illegal [declare] forms of the form (type (satisfies ...)). Thanks to Dave Greve for sending an example highlighting the issue. If trace output is going to a file (because [open-trace-file] has been executed), then a note will be printed to that effect at the time that a call of [trace$] or [trace!] is applied to one or more [trace] specs. The notion of redundancy (see [redundant-events]) has been made more restrictive for [mutual-recursion] events. Now, if either the old or new event is a [mutual-recursion] event, then redundancy requires that both are [mutual-recursion] events that define the same set of function symbols. Although we are not aware of any soundness bugs fixed by this modification, nevertheless we believe that it reduces the risk of soundness bugs in the future. The definition of trace* has been moved to a book, misc/trace1.lisp. A new version, used in ACL2s, is in book misc/trace-star.lisp. [Trace] utilities [trace$] and [trace!] are still built into ACL2. [Note: File misc/trace1.lisp was deleted after Version 4.2.] Certain [certificate] files will now be much smaller, by printing in a way that takes advantage of structure sharing. Certifying the following example produces a .cert file of over 3M before this change, but less than 1K after the change. (defun nest (i) ;; Makes an exponentially-sized nest of conses i deep. (if (zp i) nil (let ((next (nest (1- i)))) (cons next next)))) (make-event `(defconst *big* ',(nest 20))) Thanks to Sol Swords for providing the above example and to him as well as to Bob Boyer, Jared Davis, and Warren Hunt for encouraging development of this improvement. We have also applied this improvement to the printing of function definitions to files on behalf of [certify-book] and [comp]. Names of symbols are now printed with vertical bars according to the Common Lisp spec. Formerly, if the first character of a symbol name could be the first character of the print representation of a number, then the symbol was printed using vertical bars (|..|) around its name. Now, a much more restrictive test for ``potential numbers'' is used, which can result in fewer such vertical bars. Base 16 is now carefully considered as well; see [set-print-base]. Thanks to Bob Boyer for requesting this improvement. Note that macros set-acl2-print-base and set-acl2-print-case have been replaced by functions; see [set-print-base] and see [set-print-case]. The ACL2 reader now supports `#.' syntax in place of the `#, syntax formerly supported. Thanks to Bob Boyer for requesting this change. See [sharp-dot-reader]. NOTE that because of this change, `#.' no longer causes an abort; instead please use (a!) or optionally, if in the ACL2 loop, :a!; see [a!]. Some small changes have been made related to [gag-mode]: o [Gag-mode] now suppresses some messages that were being printed upon encountering disjunctive splits from :OR [hints]. Thanks to Sol Swords for suggesting this improvement. o ACL2 had printed ``Q.E.D.'' with all output suppressed and [gag-mode] enabled. Now, ``Q.E.D.'' will be suppressed when PROVE and SUMMARY output are suppressed, even if gag-mode is enabled. o The use of [set-gag-mode] had drastic effects on the inhibited output (see [set-inhibit-output-lst]), basically inhibiting nearly all output (even most warnings) when turning on gag-mode and enabling all output except proof-tree output when turning off gag-mode. Now, [set-gag-mode] only inhibits or enables proof (PROVE) output, according to whether gag-mode is being turned on or off (respectively). The related utility [set-saved-output] has also been modified, basically to eliminate :all as a first argument and to allow t and :all as second arguments, for inhibiting prover output or virtually all output, respectively (see [set-saved-output]). A [defstub] event [signature] specifying output of the form (mv ...) now introduces a :[type-prescription] rule asserting that the new function returns a [true-listp] result. Thanks to Bob Boyer for sending the following example, which motivated this change. (defstub census (*) => (mv * *)) (defn foo (x) (mv-let (a1 a2) (census x) (list a1 a2))) Improved the efficiency of [string-append] so that in raw Lisp, it calls [concatenate]. Thanks to Jared Davis for suggesting this change, including the use of [mbe]. A minor change was made to the definition of [concatenate] to support this change, and the lemma append-to-nil was added (see below). The checksum algorithm used for [certificate] files of [books] has been changed. Thanks to Jared Davis for contributing the new code. This change will likely not be noticed unless one is using the experimental [hons] version of ACL2, where it can greatly speed up book certification and inclusion because of function memoization (of source function fchecksum-obj). Fewer calls are made to the checksum algorithm on behalf of [certify-book] and a few other operations. Thanks to Jared Davis for providing data that helped lead us to these changes. Formatted printing directives ~p, ~q, ~P, and ~Q are deprecated, though still supported. See [fmt]. Instead, please use ~x, ~y, ~X, and ~Y (respectively). As a by-product, rule names in proof output are no longer hyphenated. A new keyword, :multiplicity, is available for tracing raw Lisp functions using the ACL2 [trace] utility. See [trace$]. Users may now control whether or not a slow array access results in a warning printed to the screen (which is the default, as before), and if so, whether or not the warning is followed by a break. See [slow-array-warning]. On linux-like systems (including Mac OS X and SunOS), :[comp] will now write its temporary files into the \"/tmp\" directory, which is the value of [state] global 'tmp-dir. You can change that directory with (assign tmp-dir \"\"). The messages printed for uncertified books have been enhanced. Thanks to Jared Davis for requesting such an improvement. A function definition that would be redundant if in :[logic] mode is now considered redundant even if it (the new definition) is in :[program] mode. That is, if a definition is ``downgraded'' from :logic to :program mode, the latter (:program mode) definition is considered redundant. Previously, such redundancy was disallowed, but we have relaxed that restriction because of a scenario brought to our attention by Jared Davis: include a book with the :logic mode definition, and then include a book with the :program mode definition followed by [verify-termination]. Thanks, Jared. The ACL2 reader no longer accepts characters other than those recognized by [standard-char-p] except for #\\Tab, #\\Page, and #\\Rubout (though it still accepts strings containing such characters). As a result, no [make-event] expansion is allowed to contain any such unacceptable character or string. Thanks to Sol Swords for sending an example that led us to make this restriction. A simple example is the following book: (in-package \"ACL2\") (defconst *my-null* (code-char 0)) (make-event `(defconst *new-null* ,*my-null*)) For this book, a call of [certify-book] formerly broke during the compilation phase, but if there was no compilation, then a call of [include-book] broke. Now, the error occurs upon evaluation of the [make-event] form. ACL2 now collects up [guard]s from [declare] forms more as a user might expect, without introducing an unexpected ordering of conjuncts. We thank Jared Davis for sending us the following illustrative example, explained below. (defun f (x n) (declare (xargs :guard (and (stringp x) (natp n) (= (length x) n))) (type string x) (ignore x n)) t) Formerly, a guard was generated for this example by unioning the conjuncts from the :guard onto a list containing the term (string x) generated from the type declaration, resulting in an effective guard of: (and (natp n) (= (length x) n) (stringp x)) The guard of this guard failed to be verified because (stringp x)) now comes after the call (length x). With the fix, contributions to the guards are collected up in the order in which they appear. So in the above example, the effective guard is the specified :guard; the contribution (stringp x) comes later, and is thus dropped since it is redundant. NOTE by the way that if :guard and :stobjs are specified in the same [xargs] form, then for purposes of collecting up the effective guard as described above, :stobjs will be treated as through it comes before the :guard. Modified [close-output-channel] to try to do a better job flushing buffers. Thanks to Bob Boyer for helpful correspondence. The notion of ``subversive recursion'' has been modified so that some functions are no longer marked as subversive. See [subversive-recursions], in particular the discussion elaborating on the notion of ``involved in the termination argument'' at the end of that [documentation] topic. Formerly, :[type-prescription] rules for new definitions inside [encapsulate] forms were sometimes added as [constraint]s. This is no longer the case. See also discussion of the ``soundness bug in the forming of constraints'', which is related. NEW FEATURES It is now possible to affect ACL2's termination analysis (and resulting induction analysis). Thanks to Peter Dillinger for requesting this feature. The default behavior is essentially unchanged. But for example, the following definition is accepted by ACL2 because of the use of the new :ruler-extenders features; See [ruler-extenders]. (defun f (x) (declare (xargs :ruler-extenders :all)) (cons 3 (if (consp x) (f (cdr x)) nil))) The following lemma was added in support of the improvement to [string-append] described above: (defthm append-to-nil (implies (true-listp x) (equal (append x nil) x))) A mechanism has been provided for users to contribute documentation. See [managing-ACL2-packages] for an example, which contains a link to an external web page on effective use of ACL2 packages, kindly provided by Jared Davis. ACL2 [documentation] strings may now link to external web pages using the new symbol, ~url; see markup. Of course, those links appear in the web version of the documentation, but you made need to take a bit of action in order for these to appear as links in the Emacs Info version; see [documentation]. Added [intersectp] (similar to [intersectp-eq] and [intersectp-equal]). The user now has more control over how ACL2 prints forms; See [print-control]. Thanks to Bob Boyer for useful discussions leading to this enhancement. Some Common Lisp implementations only allow the syntax pkg-name::expression when expression is a symbol. The ACL2 reader has been modified to support a package prefix for arbitrary expressions; see [sharp-bang-reader]. Thanks to Hanbing Liu for a query that led to this feature and to Pascal J. Bourguignon for suggesting an implmentation. Ill-formed [documentation] strings need not cause an error. See set-ignore-doc-string-error. Thanks to Bob Boyer for requesting this feature. Type declarations are now permitted in let* forms; see [let*], see [declare], and see [type-spec]. (For Lisp programmers) Macro with-live-state has been provided for programmers who refer to free variable STATE, for example with macros that generate uses of STATE, and want to avoid compiler warnings when evaluating in raw Lisp. For example, the following form can be submitted either inside or outside the ACL2 loop to get the desired effect (see doc-string): (with-live-state (f-put-global 'doc-prefix \" \" state)). For another example use of this macro, see the definition of trace$ (ACL2 source file other-events.lisp). (System hackers only) Added :[redef-] to undo the effect of :[redef+]. See [redef-]. Function [random$] is a built-in random number generator. See [random$]. Thanks to Sol Swords for requesting this feature and providing an initial implementation. HEURISTIC IMPROVEMENTS Sped up [guard] generation for some functions with large if-then-else structures in their bodies. Thanks to Sol Swords for sending an illustrative example. Sped up [guard] generation in some cases by evaluating ground (variable-free) subexpressions. Thanks to Bob Boyer for sending a motivating example: (defn foo (x) (case x ((1 2) 1) ((3 4) 3) ... ((999 1000) 999))). Modified slightly a heuristic association of ``size'' with constants, which can result in significant speed-ups in proofs involving constants that are very large cons trees. Added a restriction in the linear arithmetic procedure for deleting polynomial inequalities from the linear database. Formerly, an inequality could be deleted if it was implied by another inequality. Now, such deletion requires that certain heuristic ``parent tree'' information is at least as restrictive for the weaker inequality as for the stronger. Thanks to Dave Greve for bringing a relevant example to our attention and working with us to figure out some surprising behavior, and to Robert Krug for making a key observation leading to the fix. (GCL especially) Improved compiled code slightly by communicating to raw Lisp the output type when a function body is of the form (the character ...). This tiny improvement will probably only be observed in GCL, if at all. Applied a correction suggested by Robert Krug to the variant of [term-order] used in parts of ACL2's arithmetic reasoning. BUG FIXES Fixed bugs in the handling of [flet] expressions, one of which had the capability of rendering ACL2 unsound. Thanks to Sol Swords for pointing out two issues and sending examples. One example illustrated how ACL2 was in essence throwing away outer [flet] bindings when processing an inner flet. We have exploited that example to prove a contradiction, as follows: this book was certifiable before this fix. (in-package \"ACL2\") (defun a (x) (list 'c x)) ; Example from Sol Swords, which failed to be admitted (claiming that ; function A is undefined) without the above definition of A. (defun foo1 (x y) (flet ((a (x) (list 'a x))) (flet ((b (y) (list 'b y))) (b (a (list x y)))))) (defthm not-true (equal (foo1 3 4) '(b (c (3 4)))) :hints ((\"Goal\" :in-theory (disable (:executable-counterpart foo1)))) :rule-classes nil) (defthm contradiction nil :hints ((\"Goal\" :use not-true)) :rule-classes nil) Sol's second example, below, pointed to a second bug related to computing output signatures in the presence of nested flet expressions, which we have also fixed: this form failed before the fix. :trans (flet ((foo (a) (list (flet ((bar (b) b)) a)))) x) Fixed a subtle soundness bug in the forming of constraints from deduced type prescriptions. As a result, when ACL2 prints a warning message labeling encapsulated functions as ``subversive'', ACL2 will no longer deduce :[type-prescription] rules for those functions. Examples that exploit the bug in ACL2 Version_3.4 may be found in comments in ACL2 source function convert-type-set-to-term (file other-processes.lisp) and especially in function putprop-type-prescription-lst (file defuns.lisp). For more on the general issue of ``subversive recursions,'' see [subversive-recursions].) Fixed a soundness bug in the handling of inequalities by the [type-set] mechanism, which was using the inequality database inside the body of a [lambda]. Fixed a long-standing soundness bug in [compress1] and [compress2], whose raw Lisp code gave the logically incorrect result in the case of a single entry other than the [header], where that entry mapped an index to the [default] value. Also fixed soundness bugs in [compress1], in the case of :order >, where the raw Lisp code could drop the [header] from the result or, when the input alist had entries in ascending order, fail to return an alist in descending order. For example, the following book certified successfully. (in-package \"ACL2\") (defthm true-formula-1 (equal (compress1 'a '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5 :DEFAULT 1 :NAME A :ORDER <) (1 . 1))) '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5 :DEFAULT 1 :NAME A :ORDER <))) :hints ((\"Goal\" :in-theory (disable (compress1)))) :rule-classes nil) (defthm ouch-1 nil :hints ((\"Goal\" :use true-formula-1)) :rule-classes nil) (defthm true-formula-2 (equal (compress1 'a '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5 :DEFAULT NIL :NAME A :ORDER >) (1 . 1) (2 . 2))) '((:HEADER :DIMENSIONS (4) :MAXIMUM-LENGTH 5 :DEFAULT NIL :NAME A :ORDER >) (2 . 2) (1 . 1))) :hints ((\"Goal\" :in-theory (disable (compress1)))) :rule-classes nil) (defthm ouch-2 nil :hints ((\"Goal\" :use true-formula-2)) :rule-classes nil) (defthm true-formula-3 (equal (compress1 'a '((:HEADER :DIMENSIONS (3) :MAXIMUM-LENGTH 4 :NAME A :ORDER >) (1 . B) (0 . A))) '((:HEADER :DIMENSIONS (3) :MAXIMUM-LENGTH 4 :NAME A :ORDER >) (1 . B) (0 . A))) :hints ((\"Goal\" :in-theory (disable (compress1)))) :rule-classes nil) (defthm ouch-3 nil :hints ((\"Goal\" :use true-formula-3)) :rule-classes nil) Fixed a soundness bug involving measured subsets and [verify-termination], by changing [verify-termination] so that it uses [make-event]. See [verify-termination], in particular the discussion about [make-event] near the end of that [documentation] topic. Peter Dillinger first raised the idea to us of making such a change; when we found this soundness bug, we were certainly happy to do so! Fixed a bug that could cause a hard Lisp error but not, apparently, unsoundness. The bug was in the lack of attention to the order of guard and type declarations when checking for redundancy. In the following example, the second definition was redundant during the first pass of the [encapsulate] form. The second definition, however, was stored on the second pass with a guard of (and (consp (car x)) (consp x)), which caused a hard Lisp error when evaluating (foo 3) due to a misguided attempt to evaluate (car 3) in raw Lisp. The fix is to restrict redundancy of definitions so that the guard and type declarations must be in the same order for the two definitions. (encapsulate () (local (defun foo (x) (declare (xargs :guard (consp x))) (declare (xargs :guard (consp (car x)))) x)) (defun foo (x) (declare (xargs :guard (consp (car x)))) (declare (xargs :guard (consp x))) x)) ; Now we get a hard Lisp error from evaluation of the guard of foo: (foo 3) Fixed a bug in the guard violation report for function [intern-in-package-of-symbol]. Thanks to Dave Greve for bringing this bug to our attention. Made a change to allow certain [hints], in particular certain :[clause-processor] hints, that had previously caused errors during termination proofs by viewing the function being defined as not yet existing. Thanks to Sol Swords for bringing this issue to our attention with a nice example. ACL2 now properly handles interrupts (via control-c) issued during printing of the checkpoint summary. Previously it was possible on some platforms to make ACL2 hang when interrupting both during a proof and during the ensuing printing of the checkpoint summary. Thanks to Jared Davis and Sol Swords for bringing this problem to our attention. Fixed a bug that was preventing, inside some book \"b\", the use of a :dir argument to [include-book] that refers to a directory defined using [add-include-book-dir] earlier in the book \"b\". (We found this ourselves, but we thank John Cowles for observing it independently and sending us a nice example.) (GCL and CCL only) Fixed a bug in certain under-the-hood type inferencing. Thanks to Sol Swords for sending an example using [stobj]s defined with the :inline keyword, along with a helpful backtrace in CCL, and to Gary Byers for his debugging help. Fixed a bug in [print-gv], which was mishandling calls of functions with more than one argument. Fixed a bug in the handling of [and] and [or] terms by the [proof-checker] command DV, including numeric (``diving'') commands. Thanks for Mark Reitblatt for bringing this problems to our attention with a helpful example. Fixed printing of goal names resulting from the application of :OR [hints] so that they aren't ugly when working in other than the \"ACL2\" package. Thanks to Sol Swords for bringing this issue to our attention. Fixed [proof-tree] printing so that interrupts will not cause problems with hiding ordinary output because of incomplete proof-tree output. Thanks to Peter Dillinger for pointing out this issue. Fixed a hard error that could be caused by mishandling a [force]d hypothesis during [forward-chaining]. Thanks to Peter Dillinger for bringing this bug to our attention by sending a useful example. Fixed a bug that could cause simplifications to fail because of alleged ``specious simplification.'' This bug could appear when deriving an equality from the linear arithmetic database, and then attempting to add this equality to the current goal's hypotheses when it was already present. Thanks to Eric Smith for sending a helpful example (in July 2005!) that helped us debug this issue. Fixed a bug in processing of :[type-set-inverter] rules. Fixed a bug that was causing an error, at least for an underlying Lisp of CCL (OpenMCL), when [ec-call] was applied to a term returning multiple values. Thanks to Sol Swords for sending an example that brought this bug to our attention. Fixed handling of array orders to treat keyword value :order :none correctly from an array's [header]. Previously, there were two problems. One problem was that :order :none was treated like the default for :order, <, while :order nil was treated in the manner specified by :order :none (see [arrays]). Now, both :order :none and :order nil are treated as :order nil had been treated, i.e., so that there is no reordering of the alist by [compress1]. The other problem with this case of :order was that the :maximum-length field of the [header] was not being respected: the length could grow without bound. Now, as previously explained (but not previously implemented) --- see [arrays] --- a [compress1] call made on behalf of aset1 causes a hard error if the header of the supplied array specifies an :order of :none or nil. An ignorable [declare] form had caused an error in some contexts when it should have been allowed. In particular, this problem could arise when using an ignorable declaration at the top level in a [defabbrev] form. It could also arise upon calling [verify-termination] when the corresponding [defun] form contained an ignorable declaration at the top level. These bugs have been fixed. Contrary to existing documentation (see [make-event-details]), the value of ``[ld] special variable'' [ld-skip-proofsp] was always set to nil during [make-event] expansion, not merely when the make-event form has a non-nil value for keyword parameter :check-expansion. This has been fixed. Thanks to Sol Swords for bringing this issue to our attention. We have disallowed the certification of a book when not at the top-level, either directly in the top-level loop or at the top level of [ld]. Before this restriction, the following would certify a book with a definition such as (defun foo (x) (h x)) that calls function h before defining it, if the certification was by way of the form such as: (er-progn (defun h (x) x) (certify-book \"my-book\")) But a subsequent [include-book] of \"my-book\" would then fail, because h is not defined at the top level. Printing with [fmt] directive ~c now works properly even when the print-base is other than 10. Thanks to Sol Swords for reporting this bug and providing a fix for it. (SBCL, CMUCL, and CCL only) Fixed a bug in [sys-call-status] in the case that the underlying Common Lisp is SBCL, CMUCL, or CCL (OpenMCL). Thanks to Jun Sawada for bringing this bug to our attention and providing a fix. Fixed a bug that was preventing [local] [defstobj] events in [encapsulate] events. Thanks to Jared Davis for bringing this bug to our attention. Fixed a bug evidenced by error message ``Unexpected form in certification world'', which could result from attempting to certify a book after evaluating an [encapsulate] form with a local [defmacro]. Thanks to Jared Davis for pointing out this bug and sending the example: (encapsulate () (local (defmacro foo (x) `(table foo 'bar ,x))) (local (foo 3))) Formerly, evaluating a [trace$] form inside a [wormhole] such as the [break-rewrite] loop could leave the user in a bad state after returning to the top level, in which that function could not be untraced. This has been fixed. Note however that when you proceed from a break in the [break-rewrite] loop, the tracing state will be the same as it was when you entered that break: all effects of calling [trace$] and [untrace$] are erased when you proceed from the break. A :[guard] of (and) is no longer ignored. Thanks to Sol Swords for bringing this bug to our attention. A bug has been fixed that could result in needlessly weak induction schemes in the case that a recursive call is made in the first argument of [prog2$]. This has been fixed by including [prog2$] as a default ruler-extender in the new ruler-extenders feature (see above, and see [ruler-extenders]). For details on this bug see Example 11 in distributed book books/misc/misc2/ruler-extenders-tests.lisp. (For CCL/OpenMCL on Windows) ACL2 should now build on CCL (OpenMCL) on Windows. Thanks to David Rager for bringing this issue to our attention and helping with a fix that worked for CCL 1.2, and to the CCL team for improving handling of Windows-style filenames in CCL 1.3. NEW AND UPDATED BOOKS See {ReleaseVersionNumbers | https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers} for a list of books in Version 3.5 of ACL2 but not Version 3.4. Run the shell command svn log -r 94:HEAD to see all changes to books/ since the release of Version 3.4. Here are just a few highlights. Thanks largely to Jared Davis, many Makefiles have been improved to do automatic dependency analysis. See [books-certification-classic] for how to get your own Makefiles to do this by adding a line: -include Makefile-deps. Libraries books/arithmetic-4/ and books/rtl/rel7/ have been eliminated from the default book certification (make regression), in favor of new libraries books/arithmetic-5/ and books/rtl/rel8/ contributed by Robert Krug and Hanbing Liu, respectively. They and Jun Sawada have arranged the compatibility of these libraries; i.e., it is possible to evaluate both of the following in the same session: (include-book \"arithmetic-5/top\" :dir :system) (include-book \"rtl/rel8/lib/top\" :dir :system) Library books/rtl/rel1/ is no longer certified by default (though it is still distributed in support of ACL2(r); see [real]). EMACS SUPPORT Slightly modified Control-t e (defined in emacs/emacs-acl2.el) to comprehend the notion of an ``ACL2 scope'', and added Control-t o to insert a superior [encapsulate] defining such a scope. See the Emacs documentation for Control-t e (generally obtained after typing Control-h k). Modified distributed file emacs/emacs-acl2.el so that if you put the following two forms in your ~/.emacs file above the form that loads emacs/emacs-acl2.el, then Emacs will not start up a shell. Thanks to Terry Parks for leading us to this modification. (defvar acl2-skip-shell nil) (setq acl2-skip-shell t) EXPERIMENTAL HONS VERSION Bob Boyer and others have contributed numerous changes for the experimental ``hons'' version of ACL2 (see [hons-and-memoization]). The ACL2 [state] can now be queried with (@ hons-enabled) so that a result of t says that one is in the experimental hons version, while nil says the opposite.") (NOTE-3-5{R} (RELEASE-NOTES) "ACL2 Version 3.5(r) (May, 2009) Notes Please also see [note-3-5] for changes in Version 3.5 of ACL2. This release incorporates improvements from Ruben Gamboa in support for non-standard analysis in ACL2(r), in the following ways: ACL2(r) now supports non-classical objects that are not also numeric, e.g., non-classical cons pairs. Consequently, the built-in standard-numberp has been replaced with [standardp]. If f is a classical function, the value (f x1 ... xn) is guaranteed to be standard when the xi are standard. ACL2(r) can now recognize this fact automatically, using defun-std. For example, the following can be used to assert that the square root of 2 is a standard value. (defthm-std sqrt-2-rational (standardp (acl2-sqrt 2))) More generally, the expression (f x1 ... xn) can contain free variables, but the result is guaranteed to be standard when the variables take on standard variables, as in the following: (defthm-std sqrt-x-rational (implies (standardp x) (standardp (acl2-sqrt x)))) A potential soundness bug in [encapsulate] was fixed. Specifically, when a classical, constrained function is instantiated with a lambda expression containing free variables, it may produce non-standard values depending on the values of the free variables. This means that the functional instantiation cannot be used to justify a non-classical theorem. For example, consider the following sequence: (encapsulate ((f (x) t)) (local (defun f (x) x))) (defthm-std f-x-standard (implies (standardp x) (standardp (f x)))) (defthm plus-x-standard (implies (standardp x) (standardp (+ x y))) :hints ((\"Goal\" :use ((:functional-instance f-x-standard (f (lambda (x) (+ x y)))))))) (defthm plus-x-eps-not-standard (implies (standardp x) (not (standardp (+ x (/ (i-large-integer))))))) (defthm nil-iff-t nil :hints ((\"Goal\" :use ((:instance plus-x-standard (y (/ (i-large-integer)))) (:instance plus-x-eps-not-standard))))) ACL2(r) also supports the introduction of non-classical functions with [defchoose]. These behave just as normal functions introduced with [defchoose], but they have a non-classical choice property. Finally, ACL2(r) now comes with a revamped library supporting non-standard analysis, still distributed separately as books/nonstd/. The new library uses [defchoose] to state more natural and useful versions of the IVT, MVT, etc. It also supports the introduction of inverse functions, e.g., logarithms. Finally, the library has much more extensive support for differentiation.") (NOTE-3-6 (RELEASE-NOTES) "ACL2 Version 3.6 (August, 2009) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Below we roughly organize the changes since Version 3.5 into the following categories of changes: existing features, new features, heuristic improvements, bug fixes, distributed books, Emacs support, and experimental [hons-and-memoization] version. Each change is described in just one category, though of course many changes could be placed in more than one category. Note that (starting with ACL2 Version 3.5) LispWorks is no longer supported as a platform for ACL2, as the LispWorks compiler could not handle the ACL2 sources; see comments in the ACL2 sources about ``function size'' being ``too large''. CHANGES TO EXISTING FEATURES In the [xargs] [declare] form, the function symbol (or symbols, plural, in the case of [mutual-recursion]) being defined may now be used in the specified :measure and :[guard] terms. Note that, the definition(s) of the new symbol(s) are still not used in the termination proof. Thanks to Daron Vroon for discussions leading to this addition for the measure and to Dave Greve for requesting such an enhancement for the guard. Processing of the :guard-hints in an [xargs] [declare] form is now delayed until the start of [guard] verification. As a result, the function symbol(s) being defined may now be used as one might expect in such hints, for example in an :in-theory form. Thanks to Jared Davis for suggesting that we make such an improvement and providing an example. Made a low-level change to [make-event] in support of the ACL2s utility ``dynamic-make-event''. Thanks to Peter Dillinger for explaining the issue leading to this change. Modified the failure message printed when a measure conjecture fails to be proved, to indicate whether or not the hint :ruler-extenders :all would create a different measure conjecture. Thanks to Peter Dillinger for suggesting such a modification. A call of [add-default-hints] had added hints to the end of the current list of default hints. Now, it adds them to the beginning of that list, so that they are tried first. However, [add-default-hints] now takes a keyword argument, :at-end. If that argument is supplied and evaluates to other than nil, then the previous behavior occurs. When [save-exec] is used to save ACL2 images, the build dates are now printed on separate lines at startup and in the executable script. Thanks To Bob Boyer for requesting some newlines. [Forward-chaining] rules are now generated so that every [let] (also [let*] and [lambda]) expression is expanded away, as is every call of a so-called ``guard holder'' ([must-be-equal], [prog2$], [ec-call], [the]). These were formerly only expanded away in the conclusion. Thanks to Konrad Slind for a helpful email leading to this change. [Current-theory] now causes a hard error when applied to a name not found in the current ACL2 logical [world], rather than simply returning nil. When the underlying Common Lisp is GCL, ACL2 no longer uses the #n= reader macro when writing out certain files, including [certificate] files. In all other Lisps, it now uses the #n= ``print-circle'' feature not only for [certificate] files and ``expansion.lsp'' files written for example in support of [make-event], but also for files written in support of :[comp]. This is all managed with new [state] global variable print-circle-files; see [print-control]. Thanks to Dave Greve for pointing out that GCL is limited by default to 1024 indices for #n=. NEW FEATURES A documentation topic explains in some detail how [hints] work with the ACL2 proof ``waterfall'': see [hints-and-the-waterfall]. This topic may be useful to those who write computed hints (see [computed-hints]) or other advanced hints. Added a new hint keyword, :no-thanks, that avoids printing the usual ``Thanks'' message for [hints]. Thanks to Peter Dillinger for requesting this feature. Added a new hint keyword, :backtrack, that checks the goals produced by processing a goal, and can cause the goal to be re-processed using a new hint. See [hints]. Thanks to Pete Manolios for a conversation that led to the idea of this hint. Added a new class of hints, [override-hints], that is similar to [default-hints], except that override-hints are always applied, even if the user has supplied a hint explicitly for the goal. See [override-hints]. Thanks to Pete Manolios and Harsh Raju Chamarthi for useful discussions on this topic, including its application to testing. When a goal ready to be pushed for proof by induction is given the new hint ``:do-not-induct :otf'', it is indeed pushed for proof by induction, rather than causing immediate failure as in the case of the hint ``:do-not-induct t''. Instead, the proof fails when the goal is later picked to be proved by induction. Thanks to Peter Dillinger for discussions leading to this feature. Related to computed hints only: Each history entry in the list stored in variable HIST (see [computed-hints]) now has a :CLAUSE field, which provide's access to a goal's parent, parent's parent, and so on (within the same induction and forcing round only). It is now possible to inhibit warnings produced by [in-theory] [events] and [hints] that occur when certain built-in definitions and executable-counterparts are disabled: just evaluate (assign verbose-theory-warning nil). Thanks to Jared Davis (and probably others in the past) for requesting such a mechanism. HEURISTIC IMPROVEMENTS A source function (linearize-lst) was replaced by tail-recursive code, which can avoid a stack overflow. Thanks to Dave Greve for sending a helpful example. The heuristics for limiting [forward-chaining] have been slightly relaxed, to allow derivations based on the occurrence of all arguments of the forward-chaining rule's conclusion in the goal (after stripping leading calls of NOT). Thanks to Dave Greve for contributing this improvement and providing a motivating example. We simplified induction schemes by eliminating each hypothesis of the form (not (equal term (quote const))) for which some other hypothesis in the same case equates term with some (presumably other) quoted constant. Thanks to Dave Greve for requesting an improvement of this sort. BUG FIXES Fixed a soundness bug related to redundancy of [encapsulate] events (see [redundant-events]) and [ruler-extenders]. A proof of nil in ACL2 Version 3.5 appears in a comment in (deflabel note-3-6 ...) in the ACL2 source code. The fix is to insist that in order for one [encapsulate] event to be redundant with another, they must be evaluated with the same [default-ruler-extenders]. Analogous to this issue of [default-ruler-extenders] for [encapsulate]s is an issue of the [default-verify-guards-eagerness], which has similarly been fixed. Fixed soundness bugs related to the handling of [subversive-recursions] for [constraint]s. Proofs of nil in ACL2 Version 3.5 appear in a comment in (deflabel note-3-6 ...) in the ACL2 source code. Fixed a bug that could cause the following error during calls of [certify-book] in the presence of calls of [skip-proofs] in the book: ACL2 Warning [Skip-proofs] in HARD ACL2 ERROR in FMT0: Illegal Fmt Syntax. The tilde-@ directive at position 0 of the string below is illegal because its variable evaluated to 0, which is neither a string nor a list. \"~@0\" Thanks to Dave Greve for reporting this bug and making available a very helpful test case. The :corollary of a rule (see [rule-classes]) failed to use the [default-hints] of the logical [world]. This has been fixed. (CCL only) We removed a call, for CCL 1.3 (and beyond) only, of foreign function sync in the closing of output channels. Thanks to Daron Vroon for reporting issues with such a call on a non-Intel platform. Fixed a bug in reporting failures when monitoring rewrite rules with free variables in the hypotheses, that could cause a hard Lisp error (from which ACL2 continues, however). Thanks to Eric Smith for sending a very helpful example with his bug report. Fixed the handling of :induct [hints], which had thrown away hint information from parent goals. For example, the [thm] form below failed to prove even though the second hint is in some sense superfluous; induction occurs automatically at \"Goal'\" even without the hint on that. The failure was due to discarding the hint information on \"Goal\". (in-theory (disable append)) (thm (equal (cdr (cons a (append (append x y) z))) (append x y z)) :hints ((\"Goal\" :in-theory (enable append)) (\"Goal'\" :induct t) ; failed unless this line is commented out )) Fixed a bug in the [args] command that was failing to show the formals of primitives (built-in functions like consp that do not come with explicit definitions). Thanks to John Cowles for pointing out this bug. (At a lower level, the bug was that primitives failed to have 'stobjs-in or 'stobjs-out properties.) Fixed bugs in the utility supporting moving directories of certified books, sometimes used in Debian builds (as described in source function make-certificate-file). Thanks to Alan Dunn for pointing out such a bug, in paths associated with [defpkg] events in [portcullis] commands in [certificate]s (which are used for error reporting). There were also bugs, now fixed, that prevented renaming some book paths. Please note that this mechanism is not guaranteed to be sound; in particular, it can probably misbehave when macros are used to generate portcullis events. However, it seems likely that such issues will be very rare. Eliminated warnings that could arise when tracing a function with [trace$]. Now, when [trace$] is applied to a function without option :native, that function's declarations and documentation are discarded. Fixed a bug that could cause a failure when building an executable image using SBCL as the underlying Common Lisp. Thanks to Jun Sawada for reporting this failure. We made a similar fix for CMUCL. Fixed a bug in [save-exec] in the case that an absolute pathnanme is supplied. Thanks to Jared Davis for bringing this bug to our attention. Fixed a bug in the use of [trace$] with the :native and :multiplicity options that caused hard errors for some underlying Lisps. Fixed a bug in the interaction of [trace$] and :[comp], which caused error as [comp] tried to re-trace functions that it temporarily untraced. NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE See {ReleaseVersionNumbers | https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers} for a list of books in Version 3.6 of ACL2 but not Version 3.5. For changes to existing books rather than additions, see the {log entries | http://code.google.com/p/acl2-books/source/list} starting with revision r286 up through revision r329. It is no longer required to specify a value for environment (or `make') variable ACL2_SYSTEM_BOOKS when running `make' in the distributed book directory, even when that directory is not under the directory containing the ACL2 executable. Thanks to Peter Dillinger for providing this improvement, by modifying books/Makefile-generic and, as needed, distributed book Makefiles. Thanks to Peter Dillinger, some books in support of the ACL2 Sedan (ACL2s) are more easily available for ACL2 users who do not use ACL2s. See [ACL2-sedan]. EMACS SUPPORT If the following form is evaluated before the load of emacs/emacs-acl2.el, then variables are now set to reflect the directory containing that file. (if (boundp '*acl2-sources-dir*) (makunbound '*acl2-sources-dir*)) Fixed info-dir-entry line in generated info file (by patching doc/write-acl2-texinfo.lisp). Thanks to Alan Dunn for providing this patch. EXPERIMENTAL HONS VERSION Bob Boyer and others have contributed numerous changes for the experimental ``hons'' version of ACL2 (see [hons-and-memoization]). A number of these have been crafted to work specifically with CCL (Clozure Common Lisp, formerly OpenMCL), which is now required as the underlying Lisp for the ``hons'' version of ACL2. A heuristic (source function too-many-ifs has been made more scalable (for the non-HONS version as well, in fact), but with no functional change. Thanks to Jared Davis for noticing performance issues and suggesting fixes. Other changes including the following, quoting Bob Boyer: The CCL CASE macro now does better than a dumb linear search in some CASEes. SH and CSH are functions to talk to the underlying Gnu-Linux from CCL. Good for repeated calling when you simply cannot afford the copying cost of a FORK because you are using, say, a dozen gigabytes. Added CCL compiler-macros for IF and OR, to support some 'coverage' analysis, cf. IF-REPORT, extending the profiling. Introduced the type 'mfixnum' so that things like counting honses and counting calls to memoized or profiled functions can run fast in CCL 64 bits and yet still run at all under 32 bits. Moved all HONSes to CCL's newish static space, which permits the address of a cons to be used as a hash key, as in most Lisps. (CCL moves most conses and most everything when it does a compacting-gc.) Quite a few changes in the memoize-fn reporting. Added a timer facility, cf. call-with-timeout. Good for running under throttle some gross thoughts like 'Is it true that you can't fit 12 pigeons into 11 holes' on some propositional calculus systems/functions. Added rwx-size, pid-owner-cmdlines, rss, and proc-stat to help see what is really going on virtually in Gnu-Linux. Fixed at least one bug in compact-print-file and helped make its integration into ACL2's read-object$ a little more sound. Still worried some about *print-readably* vs. readtable-case. Does anyone else stay awake late at night worrying about readtable-case? Revised how the *watch-dog-process* interrupts the main process for the thousandth time, cf. watch. Haven't changed it in weeks, which means that (a) it is getting tolerable or (b) I've run out of gas.") (NOTE-3-6-1 (RELEASE-NOTES) "ACL2 Version 3.6.1 (September, 2009) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. The essential changes to ACL2 since Version 3.6 are the two bug fixes described below. There was also some functionality-neutral code refactoring, as requested by Daron Vroon in support of the ACL2 Sedan (see [ACL2-sedan]). Also see {ReleaseVersionNumbers | https://code.google.com/p/acl2-books/wiki/ReleaseVersionNumbers} for a list of books in Version 3.6.1 of ACL2 but not Version 3.6. For changes to existing books rather than additions, see the {log entries | http://code.google.com/p/acl2-books/source/list} starting with revision r329 up through revision 350. Fixed a soundness bug in the handling of [ruler-extenders], specifically in the handling of [let]-expressions. Thanks to Pete Manolios, who sent us a proof of nil, essentially as follows. In the termination proof for foo below, the binding of x to (cons t x) was not substituted into the recursive call of foo for purposes of the termination proof. (defun foo (x) (declare (xargs :ruler-extenders :all)) (let ((x (cons t x))) (if (endp (cdr x)) x (cons t (foo (cdr x)))))) (defthm foo-bad nil :hints ((\"Goal\" :use ((:instance foo (x '(3)))) :in-theory (disable foo (foo)))) :rule-classes nil) Fixed a typo in code supporting [ruler-extenders] (specifically, swapped arguments in a recursive call of ACL2 source function get-ruler-extenders2, which could cause problems for functions defined using [mutual-recursion]). Thanks to Daron Vroon for bringing this bug to our attention, pointing out the swapped arguments.") (NOTE-3-6{R} (RELEASE-NOTES) "ACL2 Version 3.6(r) (August, 2009) Notes Please also see [note-3-6] for changes in Version 3.6 of ACL2.") (NOTE-4-0 (RELEASE-NOTES) "ACL2 Version 4.0 (July, 2010) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Below we roughly organize the changes since Version 3.6.1 into the following categories of changes: existing features, new features, heuristic improvements, bug fixes, distributed books, Emacs support, and experimental versions. Each change is described in just one category, though of course many changes could be placed in more than one category. Also see [note-3-6-1] for other changes since Version 3.6. CHANGES TO EXISTING FEATURES There have been extensive changes to the handling of compiled files for books, which may generally be invisible to most users. The basic idea is that when compiled files are loaded on behalf of [include-book], they are now loaded before events in the book are processed, not afterwards. This can speed up calls of include-book, especially if the underlying Lisp compiles all definitions on the fly (as is the case for CCL and SBCL). One functional change is that for keyword argument :load-compiled-file of [include-book], the values :comp-raw, :try, and :comp! are no longer legal. (Note that the handling of :comp-raw was actually broken, so it seems that this value wasn't actually used by anyone; also, the handling of :comp! formerly could cause an error in some Lisp platforms, including SBCL.) Another change is that if [include-book] is called with :load-compiled-file t, then each sub-book must have a compiled file or a so-called ``expansion file''; see [book-compiled-file]. In the unlikely event that this presents a problem, the makefile provides a way to build with compilation disabled; see [compilation]. Users of raw mode (see [set-raw-mode]) will be happy to know that [include-book] now works if there an up-to-date compiled file for the book, since [portcullis] commands are now incorporated into that compiled file. The mechanism for saving expansion files has changed, and the :save-expansion argument of [certify-book] has been eliminated; see [certify-book]. More discussion of ACL2's new handling of book compilation is described in a new documentation topic; see [book-compiled-file]. It was possible to get a hard Lisp error when certifying a book with a redundant [defconst] form whose term is not identical to the existing [defconst] form for the same name. The following example illustrates the problem, which has been fixed (as part of the change in handling of compiled files for books, described above). Imagine that after the initial (in-package \"ACL2\") form, file foo.lisp has just the form (defconst *a* (append nil nil)). Then before the fix, we could have: ACL2 !>(defconst *a* nil) [[output omitted]] ACL2 !>(certify-book \"foo\" 1) [[initial output omitted] * Step 5: Compile the functions defined in \"/v/joe/foo.lisp\". Compiling /v/joe/foo.lisp. End of Pass 1. End of Pass 2. OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, Speed=3 Finished compiling /vjoe/foo.lisp. Loading /v/joe/foo.lisp Error: Illegal attempt to redeclare the constant *A*. The [wormhole] facility has been changed to repair a bug that allowed guard violations to go undetected. The major change has to do with the treatment of what used to be called the ``pseudo-flag'' argument which has been replaced by a quoted lambda expression. See [note-4-0-wormhole-changes] for help in converting calls of [wormhole]. Also see see [wormhole] and see [wormhole-eval]. The function assign-wormhole-output has been eliminated but its functionality can be provided by [wormhole-eval]. The ACL2 tutorial has been greatly expanded, for example to include a self-contained discussion of rewriting. See [ACL2-tutorial]. Formerly, the [mbe] macro and [must-be-equal] function were disallowed in any definition within an encapsulate having a non-empty signature. Now, these are allowed provided the definition has been declared to be non-executable (see [defun-nx]). As a result, [defevaluator] [events] may now include [must-be-equal] among the function symbols known by the evaluator; this had not previously been allowed. Thanks to Sol Swords for discussions leading to this relaxation for [defevaluator]. [Princ$] now prints strings more efficiently. Thanks to Jared Davis for suggesting the improvements to princ$. The use of [xargs] declaration :non-executable t no longer requires the absence of [state] or declared [stobj]s among the formal parameters of a function definition. As before, the use of :non-executable t turns off single-threadedness checking for the body, and also as before, attempts to execute the function will fail. Thanks to Sol Swords for requesting this relaxation (for automatic generation of so-called ``flag functions'' for definitions using [mutual-recursion]). The [documentation] has been improved for explaining to advanced users the details of the ACL2 hint mechanism; see [hints-and-the-waterfall], and see the example about nonlinearp-default-hint in distributed book books/hints/basic-tests.lisp. Thanks to Robert Krug for useful discussions, in particular suggesting the above example as one to be explained with the documentation. The time$ macro has been enhanced to allow user control of the timing message that is printed, and of when it is printed. See [time$]. Thanks to Jared Davis for providing the essential design, helpful documentation (largely incorporated), and an initial implementation for raw Lisp. The :ttags argument to [include-book] had been required when including a certified book that uses trust tags. This is no longer the case: essentially, :ttags defaults to :all except that warnings will be printed. Thanks to Jared Davis for requesting such a relaxation, and to him and Sandip Ray for useful discussions. The definition of [mv-let] has been modified so that the single-step macroexpansion (see [trans1]) of its calls can be evaluated. Thanks to Pete Manolios for bringing this evaluation issue to our attention and ensuing discussions. All calls of so-called ``guard-holders'' --- [prog2$], [must-be-equal] (from calls of see [mbe]), [ec-call], and [mv-list] --- are now removed before storing hypotheses of rules of class :[rewrite] or :[linear]. Thanks to Sol Swords for requesting this enhancement and sending the following example in the case of [rewrite] rules. (defthm foo (prog2$ (cw \"asdf\") (and (equal (car (cons x y)) x) (equal (cdr (cons x y)) y)))) The handling of [fmt] directive ~s has been modified so that if the argument is a symbol that would normally be printed using vertical bars (|), then that symbol is printed as with ~f. Thanks to Jared Davis for providing the following example showing that treatment of ~s was a bit unexpected: (cw \"~s0.~%\" '|fo\\|o|). Error messages have been improved for ill-formed terms (in ACL2's so-called ``translation'' routines). Thanks to Jared Davis for requesting such an enhancement. Modified [defun-sk] so that it executes in :[logic] mode. Previously, evaluation of a [defun-sk] event in :[program] mode caused a somewhat inscrutable error, but now, :[program] mode is treated the same as :[logic] mode for purposes of [defun-sk]. The ``system hacker'' commands ([redef+]) and ([redef-]) are now embedded event forms (see [embedded-event-form]), hence may be used in [books] as well as in [progn] and [encapsulate] [events]. Also, these two commands are now no-ops in raw Lisp. The function symbol worldp (in the \"ACL2\" package) has been renamed to plist-worldp. The function gc$-fn (resulting from macroexpansion of [gc$]) is now in :[logic] mode. Thanks to Jared Davis for requesting this change. The user now has control over whether compilation is used, for example whether or not [certify-book] compiles by default, using function set-compiler-enabled. See [compilation]. Modified the conversion of relative to absolute pathnames in [portcullis] [command]s for book certification. Now, more pathnames remain as relative pathnames. The \"Ttags\" warning that can be printed by [include-book] is now given even if [set-inhibit-output-lst] has specified `warning'. To suppress it, specify warning! instead, for example, (set-inhibit-output-lst '(acl2::warning! acl2::proof-tree)). On occasion, ACL2 prints the message ``Flushing current installed world'' as it cleans up when certain actions (installing a [world]) are interrupted. This operation has been sped up considerably. If your session includes many [events], you can probably speed up any such operation further by invoking [reset-prehistory]. Thanks to Jared Davis for sending a query that led us to make this improvement. Calls of the form (ec-call (must-be-equal logic exec)) are no longer allowed, since we do not have confidence that they would be handled correctly. The underlying function for [good-bye] (and hence for [exit] and [quit]) is now in :[logic] mode. Thanks to Jared Davis for requesting this enhancement. We now require that every function symbol in the [signature] of an [encapsulate] event have a :[logic] mode definition at the end of the first pass, not merely a :[program] mode definition (which formerly was sufficient). You can still define such a function in :program mode, provided it is followed by a :logic mode definition (where of course both definitions are [local], since we are discussing functions is introduced in the [signature]). Thanks to Carl Eastlund for bringing this issue to our attention. (Note: An analogous modification has been made for :[bdd] [hints] as well.) The following functions now have raw Lisp implementations that may run faster than their ACL2 definitions: [assoc-eq], [assoc-equal], [member-eq], [member-equal], subsetp-eq, [subsetp-equal], [remove-eq], [remove-equal], [position-eq], and [position-equal]. Thanks to Jared Davis for suggesting that we consider such an improvement. We now avoid infinite loops caused when tracing functions that implement [trace$]. Thanks to Rob Sumners and Eric Smith for useful discussions. The implementation of [trace!] has been modified slightly, to accommodate the fix for ``some holes in the handling of trust tags'' described later, below. This item applies unless the host Lisp is GCL. An interrupt (control-c) will now cause a proof to exit normally in most cases, by simulating a timeout, as though [with-prover-time-limit] had been called with a time-limit of 0. If the first interrupt doesn't terminate the proof, a second one should do so (because a different, more ``severe'' mechanism is used after the first attempt). As a result, [redo-flat] should work as one might expect even if a proof is interrupted. Thanks to Dave Greve for requesting this enhancement to [redo-flat]. Technical note: for reasons related to this change, time-limits are no longer checked in evaluator functions (ev-fncall, ev, ev-lst, ev-fncall-w, ev-w, and ev-w-lst). It is now legal for [proof-checker] [macro-command]s to appear in :[instructions] that are used in place of :[hints]. Thanks to Sandip Ray for (most recently) requesting this feature. The value of :command-conventions for [ld] special variable ld-post-eval-print is now treated as though it were t if the value [ld] special variable ld-error-triples is nil. The following example illustrates this change. ACL2 !>(ld-post-eval-print state) ; default :COMMAND-CONVENTIONS ACL2 !>(ld-error-triples state) ; default T ACL2 !>(set-ld-error-triples nil state) *** Then, before the change: ACL2 !>(mv t 3 state) 3 *** Instead, after the change: ACL2 !>(mv t 3 state) (T 3 ) The default behavior of [ld] has been changed. Formerly when an error occurred that halted a subsidiary call of ld, then the parent ld would continue. That is no longer the case. Consider the following example. (ld '((ld '((defun f (x) x) (defun bad (x)) ; ERROR -- missing the body )) (defun g (x) x))) Formerly, g would be defined in the resulting logical [world]. Now, the error halts not only the inner ld but also the outer ld. See [ld], and for details of the new default value for :ld-error-action, :RETURN!, see [ld-error-action]. Also see the paragraph below about a new utility, :[p!]. Thanks to Robert Krug and Sandip Ray for helpful discussions. Environment variable ACL2-CUSTOMIZATION has been replaced by ACL2_CUSTOMIZATION --- that is, the hyphen has been replaced by an underscore --- so that it can be set conveniently in the bash shell. See [ACL2-customization]. The ``Warnings:'' summary is now omitted when there are no warnings, where formerly ``Warnings: None'' was printed. Thanks to Jared Davis for suggesting this change. We have modified the generation of constraints for [encapsulate] [events] in two primary ways, neither of them likely to affect many users. One change is that the virtual movement of definitions and theorems to in front of an [encapsulate] event, or of definitions to behind that event, is no longer inhibited in the case of nested encapsulates with non-empty [signature]s. The following example illustrates the other change, as discussed below. (encapsulate ((f (x) t)) (local (defun f (x) x)) (defun g (x) (cons x (f x))) (defun h (x) (g x)) (defthm h-is-f (equal (car (h x)) x))) Previously, the [constraint] on f and h was essentially the conjunction of the definition of h and the theorem h-is-f. Now, the definition of g is conjoined as well; moreover, g receives the same [constraint] as do f and h, where previously g was only constrained by its definition. While we are not aware of a soundness bug caused by the previous approach, the new approach follows more precisely the intended notion of [constraint]. The use of [trace$] (or [trace!]) option :multiplicity had been required when option :native was supplied. This is no longer the case. Also, a bug has been fixed that had prevented :multiplicity from working properly in GCL and Allegro CL. Several errors have been eliminated that formerly occurred when the constraints for a function symbol were unknown because it was constrained using a dependent clause-processor (see [define-trusted-clause-processor]. Now, it is assumed that the supporters argument in a [define-trusted-clause-processor] event is such that every ancestor of any function symbol constrained by the ``promised encapsulate'' of that event among, or ancestral in, those supporters. Thanks to Sol Swords, Sandip Ray, and Jared Davis for helpful discussions. The notion of [constraint] for functions introduced by [defun] has been modified slightly. No longer do we remove from the body of the definition calls of so-called ``guard-holders'': [prog2$], [must-be-equal], [ec-call], and [mv-list], and uses of the-error generated by [the]. Also, we now expand calls of the-error with the same aggressive heuristics applied to a number of other functions (technically, adding it to the list *expandable-boot-strap-non-rec-fns*). NEW FEATURES A new event, [defattach], allows evaluation of calls of constrained ([encapsulate]d) functions. In particular, users can now, in principle, soundly modify ACL2 source code; please feel free to contact the ACL2 implementors if you are interested in doing so. See [defattach]. Eric Smith has noticed that if you exit the [break-rewrite] loop using :[a!] during an [ld] of a file, then all changes to the logical [world] are discarded that were made during that call of [ld]. A new utility, :[p!], pops just one level instead, and avoids discarding that work. (This change is related to an item above, ``The default behavior of [ld] has been changed.'') Thanks to Eric for pointing out this issue. New function [mv-list] is the identity function logically, but converts multiple values to lists. The first argument is the number of values, so an example form is as follows, where foo returns three values: (mv-list 3 (foo x y)). Thanks to Sol Swords for requesting this feature and for reporting a soundness bug in one of our preliminary implementations. A new [state] global variable, host-lisp, has as its value a keyword whose value depends on the underlying Common Lisp implementation. Use (@ host-lisp) to see its value. It is now possible to write [documentation] for HTML without error when there are links to nonexistent documentation topics. See the comments in macro acl2::write-html-file at the end of file doc/write-acl2-html.lisp. When there are such errors, they should be easier to understand than previously. Thanks to Alan Dunn for providing the initial modifications. It is now possible to inhibit specified parts of the Summary printed at the conclusion of an event. See [set-inhibited-summary-types]. Also see [with-output], in particular the discussion of the new :summary keyword. Thanks to Sol Swords for requesting more control over the Summary. A new :[hints] keyword, :case-split-limitations, can override the default case-split-limitations settings (see [set-case-split-limitations]) in the simplifier. Thanks to Ian Johnson for requesting this addition and providing an initial implementation. It is now possible to defer and avoid some ttag-related output; see [set-deferred-ttag-notes]. Thanks to Jared Davis for requesting less verbosity from ttag-related output. A new [command], :[pl2], allows you to restrict the rewrite rules printed that apply to a given term. See [pl2]. Thanks to Robert Krug for requesting such a capability. ACL2 now provides a utility for canonicalizing filenames, so that soft links are resolved; see [canonical-pathname]. Moreover, ACL2 uses this utility in its own sources, which can eliminate some issues. In particular, [include-book] with argument :ttags :all no longer breaks when given a book name differing from the book name that was used at certification time; thanks to Sol Swords for reporting that problem. Also, certain errors have been eliminated involving the combination of packages in the certification world and trust tags; thanks to Jared Davis for sending an example of that problem. You can now suppress or enable guard-checking for an individual form; see [with-guard-checking]. Thanks to Sol Swords for requesting this feature. The [walkabout] utility has been documented (thanks to Rob Sumners for suggesting this documentation). This utility can make it easy to explore a large cons tree. New interactive commands (pp n) and (pp print-level print-length) have been added to restrict how much of the current object is displayed. See [walkabout]. Rules of class :[type-prescription] may now be provided a :backchain-limit-lst keyword. The default behavior is unchanged, but now [type-set] is sensitive not only to the new :backchain-limit-lst of a :[type-prescription] rule (if supplied) but to the [default-backchain-limit] of the current logical [world]. Setting of backchain-limits can now specify either the new (type-set) limit or the old limit (for rewriting); see [set-default-backchain-limit] and see [set-backchain-limit]. Moreover, the functions [default-backchain-limit] and [backchain-limit] now take a second argument of :ts or :rewrite to specify which backchain-limit is desired. HEURISTIC IMPROVEMENTS The so-called ``too-many-ifs'' heuristic has been modified. Such a heuristic has been employed in ACL2 (and previous Boyer-Moore provers) for many years, in order to limit the introduction of calls of [if] by non-recursive functions. Most users need not be concerned with this change, but two proofs in the regression suite (out of thousands) needed trivial adjustment, so user proofs could need tweaking. In one application, this modification sped up proofs by 15%; but the change in runtime for the regression suite is negligible, so such speedups may vary. Thanks to Sol Swords for providing a test from ACL2 runs at Centaur Technology, which was useful in re-tuning this heuristic. Guard proof obligations could have size quadratic in the number of clauses in a [case] statement. This inefficiency has been removed with a change that eliminates a hypothesis of the form (not (eql term constant)) when there is already a stronger hypothesis, equating the same term with a different constant. Thanks to Sol Swords for bringing this problem to our attention and suggesting an alternate approach to solving it, which we may consider in the future if related efficiency problems persist. We adjusted the heuristics for determining induction schemes in the presence of [ruler-extenders], when handling calls of a function symbol that is a ruler-extender, in either of two cases: either the function takes only one argument; or the function is [prog2$] or [ec-call], and the first argument contains no recursive call. These cases are treated more directly as though the ruler-extender call is replaced by the unique (in the case of [prog2$] and [ec-call], the second) argument. A new :[type-prescription] rule, true-listp-append, has been added: (implies (true-listp b) (true-listp (append a b))) If you are interested in the motivation for adding this rule, see comments in true-listp-append in ACL2 source file axioms.lisp. The use of :forward-chaining lemmas has been improved slightly. In previous versions, a conclusion derived by forward chaining was discarded if it was derivable by type-set reasoning, since it was ``already provable.'' But this heuristic prevented the conclusion from triggering further forward chaining. This has been fixed. Thanks to Dave Greve for pointing out this problem. The fundamental utility that turns an IF expression into a set of clauses has been optimized to better handle tests of the form (equal x 'constant) and their negations. This eliminates an exponential explosion in large case analyses. But it comes at the inconveience of sometimes reordering the clauses produced. The latter aspect of this change may require you to change some Subgoal numbers in proof hints. We apologize for the inconvenience. Certification can now run faster (specifically, the compilation phase) for books with very large structures generated by [make-event], when there is significant sharing of substructure, because of a custom optimization of the Lisp reader. Thanks to Sol Swords for bringing this efficiency issue to our attention. Jared Davis reported inefficiency in certain [make-event] evaluation due to a potentially expensive ``bad lisp object'' check on the expansion produced by the make-event. This check has been eliminated except in the case that the expansion introduces packages (for example, by including a book during the expansion phase that introduces packages). Thanks to Jared for providing a helpful example. The application of rules of class :[induction] had the potential to loop (as commented in ACL2 source function apply-induction-rule). This has been fixed. Thanks to Daron Vroon and Pete Manolios for sending nice examples causing the loop. Heuristics have been tweaked so that false goals may be simplified to nil that had formerly been left unchanged by simplification, perhaps resulting in useless and distracting proofs by induction. Thanks to Pete Manolios for pointing out this issue by sending the following example: (thm (<= (+ 1 (acl2-count x)) 0)). (Technical explanation: When every literal in a clause simplifies to nil, even though we might not normally delete one or more such literals, we will replace the entire clause by the false clause.) Improved the efficiency of the built-in function, [take]. Thanks to Bob Boyer for suggesting this improvement. ACL2 can now use evaluation to relieve hypotheses when applying :[type-prescription] rules. Thanks to Peter Dillinger and Dave Greve for requesting this enhancement, and to Robert Krug for a relevant discussion long ago. Evaluation has been sped up during theorems for calls of [mv-let], by avoiding repeated evaluation of the expression to which its variables are bound. Thanks to Sol Swords for requesting this improvement and sending an illustrative example. Modified a heuristic to avoid the opening up non-recursive function calls on calls of [hide] involving [if]-expressions. For example, the [thm] form below is now admitted (defun bar (x) (cons x x)) (thm (equal (bar (hide (if a b c))) (cons (hide (if a b c)) (hide (if a b c))))) BUG FIXES Fixed a soundness bug in destructor elimination, which was preventing some cases from being generated. Thanks to Eric Smith for reporting this bug and sending a helpful example. (Technical detail: the fixes were in ACL2 source functions apply-instantiated-elim-rule and eliminate-destructors-clause1, and comments in the former contain Eric's example.) Fixed a bug that supported a proof of nil by exploiting the fact that [portcullis] [command]s were not included in check-sum computations in a book's [certificate]. For such a proof of nil, see the relevant comment in the ACL2 source file ld.lisp under (deflabel note-4-0 ...). Changed the implementation of [add-include-book-dir]. The previous implementation could allow relative pathnames to be stored in the [portcullis] [command]s of [certificate]s of [books], which perhaps could lead to unsoundness (though we did not try to exploit this to prove nil). Thanks to Jared Davis for reporting a bug in our first new implementation. An additional change to both [add-include-book-dir] and [delete-include-book-dir] is that these now work in raw-mode (see [set-raw-mode]). (Thanks to Dave Greve for suggesting a reduction in the warnings we produced related to raw-mode.) Note that it is no longer permitted to make a direct call of the form (table acl2-defaults-table :include-book-dir-alist ...); use [add-include-book-dir] instead. Fixed a soundness bug related to [xargs] keyword :non-executable. New macros, defun-nx and defund-nx, have been provided for declaring functions to be non-executable; see [defun-nx]. While we expect this bug to occur only rarely if at all in practice, the following example shows how it could be evoked. ;;;;;;;;;;;;;;;;;;;; ;;; Book sub.lisp ;;;;;;;;;;;;;;;;;;;; (in-package \"ACL2\") (defun f () (declare (xargs :guard t :non-executable t)) (mv-let (a b c) (mv 3 4) (declare (ignore a b)) c)) (defun g () (declare (xargs :guard t)) (prog2$ (mv-let (x y z) (mv 2 3 4) (declare (ignore x y z)) nil) (f))) (defthm g-nil (equal (g) nil) :hints ((\"Goal\" :in-theory (disable (f)))) :rule-classes nil) ;;;;;;;;;;;;;;;;;;;; ;;; Book top.lisp ;;;;;;;;;;;;;;;;;;;; (in-package \"ACL2\") (include-book \"sub\") (defthm contradiction nil :hints ((\"Goal\" :use g-nil)) :rule-classes nil) The modification described above pertaining to [defun-nx] also prevents execution of non-executable functions that have been [trace]d. The following example illustrates the problem; now, the following [defun] of g is illegal, and the problem disappears if [defun-nx] is used instead. (defun g (x) ; Use defun-nx to avoid an error after Version_3.6.1. (declare (xargs :guard t :non-executable t)) x) (g 3) ; causes error, as expected (trace$ g) (g 3) ; returned 3 before the bug fix; after fix, causes error as expected A hard error was possible when attempting to include an uncertified book containing [events] of the form (make-event '(local ...)). This has been fixed. Thanks to Sol Swords for bringing this issue to our attention. Fixed a bug in the heuristic improvement described for Version_3.6 (see [note-3-6]) as ``We simplified induction schemes....'' The bug had prevented, in unusual cases such as the following (notice the impossible case), a proof by induction. (defun foo (a x) (and (consp x) (case a (0 (foo (car x) (cdr x))) (1 (foo (cdr x) (car x))) (0 (foo a (cons x x)))))) (in-theory (disable (:type-prescription foo))) (thm (atom (foo a x))) Macro [cw-gstack] did not work with an :evisc-tuple argument. This has been fixed by changing cw-gstack so that it now evaluates its arguments. Thanks to Sol Swords for bringing this bug to our attention. Fixed a bug in :[pso] during the printing of failure messages for termination proofs. Fixed a bug in the handling of #. (see [sharp-dot-reader]). Thanks to Bob Boyer for bringing this bug to our attention. Replaced a hard Lisp error with a clean error, in certain cases that a :[hints] value is erroneously supplied as a non-nil atom. Example: (thm (equal x x) :hints 3). Fixed a bug in the interaction of function tracing with conversion of a function from :[program] to :[logic] mode. The following example illustrates what had been wrong. (defun f (x) (declare (xargs :mode :program)) (car x)) (f 3) ; raw Lisp hard error (trace$ f) (f 3) ; raw Lisp hard error (still) (defun f (x) (car x)) ; upgrade f to :logic mode (f 3) ; clean guard violation; f is no longer traced (trace$) ; uh oh - f is shown as traced (untrace$ f) (f 3) ; OUCH: hard Lisp error because old :program mode definition of ; the executable counterpart (sometimes called *1*f) was restored! Made a fix so that when building ACL2 with `make' option ACL2_SAFETY=3, there will no longer be any safety-0 compiled code generated. Thanks to Gary Byers for bringing this bug to our attention. Fixed a bug in the handling of [override-hints] that generate custom keyword hints (see [custom-keyword-hints]) involving the variable stable-under-simplificationp. Thanks to Ian Johnson for bringing this bug to our attention with explanation that included a helpful example, included as comment in the ACL2 source code for function apply-override-hint. The saved_acl2 script in CLISP could contain unexpected characters where simple newlines were expected. Dave Greve found this in a Cygwin environment on Windows. Thanks to Dave for reporting this bug and experimenting with a fix, and thanks to the CLISP folks for providing helpful information. Fixed a bug that could make :[oops] cause an error. Also, the [oops] command can no longer take you back before a [reset-prehistory] event. (GCL only) Fixed a bug that could occur when calling trace in raw Lisp in GCL. Proof summaries have been improved, so that they account for [rune]s used in rewriting that takes place when generating goals to be proved in a forcing round. Thanks to Jared Davis for sending us an example illustrating this issue. Fixed a bug that (at least in CCL) could put extra backslashes (`\\') in a pathname that ACL2 writes out to the executable script created by a build. Thanks to Gary Byers for explaining that the CCL behavior is legal (for our previous use of Common Lisp function merge-pathnames). We closed some holes in the handling of trust tags (also known as ``ttags''; see [defttag]) by [include-book]. The following example illustrates this rather subtle situation. Consider the following book. (in-package \"ACL2\") (make-event (er-progn (encapsulate () (defttag :foo) (value-triple \"Imagine something bad here!\")) (value '(value-triple :some-value))) :check-expansion t) Formerly, the following commands succeeded. (certify-book \"test3\" 0 t :ttags :all) :u (include-book \"test3\" :ttags nil) But because of [make-event] keyword argument :check-expansion t, we know that the event (defttag :foo) is evaluated by the above [include-book] form, and hence the :ttags argument of include-book, above, should have specified :foo. The problem was that [defttag] forms evaluated during [make-event] expansion did not contribute to the trust tag information stored in the book's [certificate]. Note: Because of this change, one should avoid using [make-event] with :check-expansion t when the expansion would introduce a [defttag] event during [include-book] but not [certify-book] time. For an example illustrating this issue, see [make-event-details], specifically the new version of the section labeled ``A note on ttags'' at the end of that [documentation] topic. Closed a small loophole that had the potential, in rare circumstances, to violate atomicity of under-the-hood updates for ACL2 [arrays]. The following example was formerly allowed, but resulted in a guard-verified function (here, g) whose guard proof obligation is not a theorem outside the [encapsulate] event. We now disallow [guard] verification for functions introduced non-[local]ly inside an [encapsulate] event unless we determine that the proof obligations hold outside the [encapsulate] event as well. (encapsulate ((f (x) t)) (local (defun f (x) (declare (xargs :guard t)) (consp x))) ;; ERROR! (defun g (x) (declare (xargs :guard (f x))) (car x))) The use of :[comp] on [stobj] functions had potentially caused a hard Lisp error; for example, this could occur when (defstobj foo fld) was followed by :comp foop. This has been fixed. Fixed a bug that could cause a raw Lisp error when the first argument of [with-local-stobj] is not a symbol. It had been possible to use the reserved keyword :computed-hints-replacement as the name of a custom keyword hint (see [custom-keyword-hints]). This has been fixed. Thanks to Dave Greve, who pointed out a confusing hint error message (which has also been fixed) that led us to this issue. Fixed a bug that could cause a hard Lisp error, instead of a graceful ACL2 error, if keyword :backchain-limit-lst in a rule class is given a cons that is not a true list, such as (1 . 1). Eliminated an error that could occur when redefining a function as a macro and then compiling, as in the example below. (defun foo (x) x) :redef! (defmacro foo (x) x) :comp t Thanks to Eric Smith for sending the above example in his bug report. Fixed a bug that could result in an assertion when a [clause-processor] causes an error. NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE See the {log entries | http://code.google.com/p/acl2-books/source/list} for a record of books changed or added since the preceding release, with log entries. We note in particular the new system/ directory, which begins to specify ACL2 system code in anticipation of opening the architecture of ACL2 (see [defattach] for a relevant tool). Some system functions were changed slightly (but with the expectation of not generally affecting ACL2 behavior) in support of the development of this directory. Those interested in contributing to further such efforts are invited to contact the ACL2 implementors. New utilities have been provided for certifying most of the distributed books with more `make'-level parallelism. For example, we have obtained close to a 12x reduction in time by using `make -j 24 regression-fast' on a 24-processor machine. For more information see books/make-targets, or to include the books/workshops in the regression run, see books/regression-targets. Thanks to Sol Swords for providing these nice utilities. The top-level makefile, GNUmakefile, has been fixed so that the build processes (which are inherently sequential) will ignore the -j option of `make'. Note that regressions can still, however, be done in parallel, as the -j option will be passed automatically to the appropriate `make' command. EMACS SUPPORT EXPERIMENTAL VERSIONS The HONS version, supported primarily by Bob Boyer and Warren Hunt (see [hons-and-memoization]), has undergone numerous improvements. For example, keyword argument :FORGET is now supported when calling [memoize] from within the ACL2 loop, and system function worse-than is [memoize]d with the :condition that both terms are function applications (clearing the memo-table after each prover invocation). Thanks to Jared Davis and Sol Swords for investigating the memoization of worse-than, and with suitable condition. Thanks also to Jared Davis for contributing structural modifications to the implementation of [hons]. David Rager contributed modifications to the parallel version (see [parallelism]), which include taking advantage of atomic increments available at least since Version 1.0.21 of SBCL and Version 1.3 of CCL. Subtopics [Note-4-0-wormhole-changes] How to convert calls of wormhole for Version 4.0") (NOTE-4-0-WORMHOLE-CHANGES (NOTE-4-0) "How to convert calls of wormhole for Version 4.0 Here we describe how to convert an ``old-style'' call of [wormhole] --- that is, a call suitable for ACL2 versions preceding 4.0 --- in which the pseudo-flag was t. In order to convert such a call (wormhole t 'name input form ...) to a new-style call, the following steps must be carried out. Note that the wormhole name must always be quoted now. First, eliminate the first argument, t, and add a new second argument that is the quoted lambda expression '(lambda (whs) (set-wormhole-entry-code whs :ENTER)) Setting the entry code to :ENTER is not necessary if you maintain the invariant (after initialization) that it is always :ENTER. In that case, the simpler quoted lambda will suffice: '(lambda (whs) whs) Second, change the form argument so that instead of talking about the state-global variable wormhole-output it talks about the state-global variable wormhole-status. Look for (@ wormhole-output), (assign wormhole-output ...), (f-get-global 'wormhole-output ...) and (f-put-global 'wormhole-output ...) in form and replace them with expressions involving wormhole-status. However, remember that the old data stored in wormhole-output is now in the wormhole-data component of the wormhole-status. Thus, for example, an old use of (@ wormhole-output) will typically be replaced by (wormhole-data (@ wormhole-status)) and an old use of (assign wormhole-output ...) will typically be replaced by (assign wormhole-status (set-wormhole-data (@ wormhole-status) ...)) In summary, an old-style call like (wormhole t 'name input '(...1 (@ wormhole-output) ...2 ...3 (assign wormhole-output ...4) ...5) ...6) can become (wormhole 'name '(lambda (whs) (set-wormhole-entry-code whs :ENTER)) input '(...1 (wormhole-data (@ wormhole-status)) ...2 ...3 (assign wormhole-status (set-wormhole-data (@ wormhole-status) ...4) ...5) ...6) In any case, and especially if your wormhole call had a pseudo-flag other than t, we recommend that you see [wormhole].") (NOTE-4-0{R} (RELEASE-NOTES) "ACL2 Version 4.0(r) (July, 2010) Notes Please see [note-4-0] for changes in Version 4.0 of ACL2.") (NOTE-4-1 (RELEASE-NOTES) "ACL2 Version 4.1 (September, 2010) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Below we roughly organize the changes since Version 4.1 into the following categories of changes: existing features, new features, heuristic improvements, bug fixes, distributed books, Emacs support, and experimental versions. Each change is described in just one category, though of course many changes could be placed in more than one category. CHANGES TO EXISTING FEATURES The [guard] associated with calls of the macro, [search], has been weakened so that now, given strings are no longer restricted to contain only standard characters unless the :test argument is [char-equal]. Modified the writing of ``hidden [defpkg]'' forms into [certificate] files (see [hidden-defpkg]), to support moving certificate files for distributed books, as is done by ACL2s (see [ACL2-sedan]) and Debian releases of ACL2. Thanks to Camm Maguire for reporting a problem with Debian releases of ACL2 that led to this change. Expanded the constant *acl2-exports* by adding intersection-equal to the list. Thanks to Jared Davis for requesting this change. The :[comp] utility now compiles functions that have code conditionalized for raw Lisp only (presumably because a trust tag was active when they were defined). Previously, this was not the case when :comp was applied to more than a single function symbol. NEW FEATURES A new macro, [top-level], allows evaluation directly in the top level loop for forms that normally need to be evaluated inside function bodies, such as [with-local-stobj]. See [top-level]. Thanks to Jared Davis for requesting such a utility. Added [count], a Common Lisp function, to ACL2. In support of that addition, also added rewrite rule eqlablep-nth. HEURISTIC IMPROVEMENTS [None this time.] BUG FIXES We fixed a soundness bug that could occur when a function that returns multiple values that is called in its own guard. Thanks to Sol Swords for reporting this bug and sending a small self-contained example, which is included in a comment in the function chk-acceptable-defuns1 in ACL2 source file defuns.lisp. It was possible to cause an error when giving theory hints during redefinition of functions. This has been fixed. Thanks to Ian Johnson for sending an example that nicely illustrated this problem. Fixed system function io? for the case that formal parameter commentp is t and vars is non-empty. Thanks to David Rager for bringing to our attention the fact that io? was broken for such a combination of parameters. Not exactly a bug fix, but: [defun-sk] was breaking when a :[guard] is specified, so we have improved the documentation (see [defun-sk]) to explain how to provide verified guards for a function introduced by [defun-sk]. Thanks to Jared Davis for bringing this issue to our attention. Made a fix to the handling of interrupts, which in rare cases might have left one in a state where all subsequent proof attempts were labeled as ``Aborting due to an interrupt''. Fixed :[pso] and related utilities, so that when proof output is redirected to a file, all summary output goes to that file rather than to the terminal. (GCL on Windows only) Removed an inappropriate check, resulting in an error about ``pathname-device,'' that could prevent Windows GCL builds of ACL2. Thanks to Camm Maguire for reporting this problem and a helpful discussion. (Windows only) Modified the computation of canonical pathnames to avoid issues of case-insensitivity, in particular for the drive (e.g., \"C:\" vs. \"c:\"). Thanks to Harsh Raju Chamarthi for reporting this issue and helping with its debugging. (Windows only) The value of (@ distributed-books-dir) no longer will be missing the Windows drive prefix, for example, \"C:\". Thanks to Harsh Raju Chamarthi for reporting this issue and helping with its debugging. NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE See the {log entries | http://code.google.com/p/acl2-books/source/list} for a record of books changed or added since the preceding release, with log entries. Modified books/Makefile-generic by adding a new BOOKS_SKIP_COMP variable, which is used in Makefiles in some subdirectories of books/, in order to avoid errors when compiling certified books for multiple Lisps. EMACS SUPPORT Distributed file emacs/emacs-acl2.el has been modified so that the forms control-t e and control-t control-e now pick up package markers (see [sharp-bang-reader]), in the following sense: if the top-level form is preceded by a line starting with #!, then that line is included in the inserted string. Thanks to Jared Davis for suggesting this enhancement and providing a preliminary implementation. EXPERIMENTAL VERSIONS For the HONS version there have been some changes to [memoize]: [Memoize] accepts a new keyword, :recursive, that is a synonym for the existing keyword :inline. Thanks to Sol Swords for requesting this addition. Moreover, it is now enforced that these keywords have Boolean values. [Memoize] may now be called on :[program] mode functions. Thanks to Sol Swords for requesting this enhancement. A bug has been fixed. Now, if [memoize] is called with a :condition-fn (with value other than nil or t), then the [guard] of the memoized function and the :condition-fn must be the same. Previously, one could exploit the lack of such a check to get a hard Lisp error, for example as follows. (defun f (x) (declare (xargs :guard t)) x) (defun cf (x) (declare (xargs :guard (consp x))) (car x)) (memoize 'f :condition-fn 'cf) (f 3) Memoization is now illegal for built-in functions that use underlying raw Lisp in their implementations. To see why, consider the form (gc$), which is a macro call expanding to (gc$-fn nil). Previously, after evaluation of (memoize 'gc$-fn), a call of gc$ would no longer call the garbage collector, which had been invoked by raw Lisp code. Now, evaluation of (memoize 'gc$-fn) causes an error.") (NOTE-4-1{R} (RELEASE-NOTES) "ACL2 Version 4.1(r) (September, 2010) Notes Please see [note-4-1] for changes in Version 4.1 of ACL2.") (NOTE-4-2 (RELEASE-NOTES) "ACL2 Version 4.2 (January, 2011) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Below we roughly organize the changes since Version 4.2 into the following categories of changes: existing features, new features, heuristic improvements, bug fixes, distributed books, Emacs support, and experimental versions. Each change is described in just one category, though of course many changes could be placed in more than one category. CHANGES TO EXISTING FEATURES The [accumulated-persistence] utility can now do finer-grained tracking, providing data for individual hypotheses and the conclusion of a rule. See [accumulated-persistence]. To try this out, evaluate the form (accumulated-persistence :all); then see [accumulated-persistence] for a discussion of display options using show-accumulated-persistence. Thanks to Dave Greve for suggesting this new capability and collaborating on its design and implementation. The [defattach] utility now permits the use of :[program] mode functions, though this requires the use of a trust tag (see [defttag]). See [defattach] and for discussion of the new capability, see [defproxy], which explains how part of this change involves allowing :[program] mode functions to be declared [non-executable]. Redefinition (see [ld-redefinition-action]) is no longer permitted for functions that have attachments (see [defattach]). In such cases, the attachment must be removed first, e.g. with (defattach foo nil). Made small changes to [mv-nth] and [defun-sk] in order to permit guard verification of functions introduced with more than one quantified variable in a [defun-sk] form. The change to [mv-nth] is to weaken the [guard] by eliminating the requirement that the second argument satisfy [true-listp], and replacing the call of [endp] in the definition body by a corresponding call of [atom]. The new definition of [mv-nth] is thus logically equivalent to the old definition, but with a weaker guard. Thanks to Sol Swords for sending the following example, for which the final [verify-guards] form had failed but now succeeds. (defstub foo (a b c) nil) (defun-sk forall-a-b-foo (c) (forall (a b) (foo a b c)) :witness-dcls ((declare (Xargs :guard t :verify-guards nil)))) (verify-guards forall-a-b-foo) The implementations of [prog2$], [time$], [with-prover-time-limit], [with-guard-checking], [mbe] (and [must-be-equal]), and [ec-call] have changed. See the discussion below of the new utility, [return-last]. A consequence is that [trace$] is explicitly disallowed for these and related symbols, which formerly could cause hard Lisp errors, because they are now macros. Tracing of return-last is also disallowed. Another consequence is that time$ now prints a more abbreviated message by default, but a version of the old behavior can be obtained with :mintime nil. The following utilities no longer print an observation about raw-mode transitions: set-raw-mode-on, [set-raw-mode-on!], [set-raw-mode], and set-raw-mode-off. Thanks to Jared Davis for suggestion this change in the case of [include-book] (which proved awkward to restrict to that case). The system function translate-and-test now permits its LAMBDA form to refer to the variable WORLD, which is bound to the current ACL2 logical [world]. Modified abort handling to avoid talking about an interrupt when the error was caused by a Lisp error rather than an interrupt. The value of the constant *acl2-exports*, which is still a list, has been extended significantly, though only with the addition of symbols that one might reasonably have expected all along to belong to this list. A new distributed book, books/misc/check-acl2-exports.lisp, checks (at certification time) that no documented constant, macro, or function symbol in the \"ACL2\" package has been accidentally omitted from *acl2-exports*. Thanks to Dave Greve for helpful discussions related to this change. Improved the built-in `untranslate' functions to produce let* expressions when appropriate (more to help with tools that call untranslate and the like, than to help with proof output). The utility [redo-flat] now works for [certify-book] failures, just as it continues to work for failures of [encapsulate] and [progn]. The following only affects users who use trust tags to add to list values of either of the [state] global variables program-fns-with-raw-code or logic-fns-with-raw-code. For functions that belong to either of the above two lists, trace$ will supply a default value of :fncall to keyword :notinline, to avoid discarding raw-Lisp code for the function. The [guard] of the macro [intern] has been strengthened so that its second argument may no longer be either the symbol *main-lisp-package-name* or the string \"COMMON-LISP\". That change supports another change, namely that the following symbols in the \"COMMON-LISP\" package are no longer allowed into ACL2: symbols in that package that are not members of the list constant *common-lisp-symbols-from-main-lisp-package* yet are imported into the \"COMMON-LISP\" package from another package. See [pkg-imports] and see [symbol-package-name]. To see why we made that change, consider for example the following theorem, which ACL2 was able to prove when the host Lisp is GCL. (let ((x \"ALLOCATE\") (y 'car)) (implies (and (stringp x) (symbolp y) (equal (symbol-package-name y) \"COMMON-LISP\")) (equal (symbol-package-name (intern-in-package-of-symbol x y)) \"SYSTEM\"))) Now suppose that one includes a book with this theorem (with :[rule-classes] nil), using an ACL2 built on top of a different host Lisp, say CCL, that does not import the symbol SYSTEM::ALLOCATE into the \"COMMON-LISP\" package. Then then one can prove nil by giving this theorem as a :use hint. The axioms introduced by [defpkg] have changed. See the discussion of [pkg-imports] under ``NEW FEATURES'' below. The error message for free variables (e.g., in definition bodies and guards) now supplies additional information when there are governing IF conditions. Thanks to Jared Davis for requesting this enhancement and collaborating in its design. The command :[redef-] now turns off redefinition. Improved proof output in the case of a :[clause-processor] hint that proves the goal, so that the clause-processor function name is printed. The [proof-checker] command `then' now stops at the first failure (if any). It is no longer permitted to submit definitions in :logic mode for merely part of an existing [mutual-recursion] event. Such an action left the user in an odd state and seemed a potential soundness hole. The function [break$] is now in :[logic] mode. Thanks to Jared Davis for requesting this enhancement. The macro [verify-termination] now provides clearer output in the case that it is redundant. More important perhaps, as a courtesy it now causes an error when applied to a constrained function, since presumably such an application was unintended (as the constrained function could never have been in :[program] mode). Note that if one desires different behavior, one can create one's own version of [verify-termination] (but with a different name). Improved the [guard]s for the following functions, often weakening them, to reflect more precisely the requirements for calling [eq]: alist-difference-eq, intersection-eq, intersection1-eq, [intersectp-eq], not-in-domain-eq, set-difference-assoc-eq, set-equalp-eq, and [union-eq]. Thanks to Jared Davis for pointing out this issue for [intersectp-eq]. (CCL only) Made a change that can reduce the size of a compiled file produced by [certify-book] when the host Lisp is CCL, by discarding source information (for example, discarding [local] events). NEW FEATURES See the discussion above about new statistics that can be gathered by the [accumulated-persistence] utility. A new hint, :[instructions], allows use of the [proof-checker] at the level of [hints] to the prover. Thanks to Pete Manolios for requesting this feature (in 2001!). See [instructions]. (For system hackers) There are new versions of system functions translate1 and translate, namely translate1-cmp and translate-cmp respectively, that do not take or return [state]. See the Essay on Context-message Pairs for relevant information. Thanks to David Rager for collaborating on this enhancement. A new utility, [return-last], is now the unique ACL2 function that can pass back a multiple value result from one of its arguments. Thus, now the following are macros whose calls ultimately expand to calls of [return-last]: [prog2$], [time$], [with-prover-time-limit], [with-guard-checking], [mbe] (and [must-be-equal]), and [ec-call]. With an active trust tag, an advanced user can now write code that has side effects in raw Lisp; see [return-last]. Thanks to Jared Davis for requesting this feature. A new function, [pkg-imports], specifies the list of symbols imported into a given package. The axioms for [defpkg] have been strengthened, taking advantage of this function. Now one can prove theorems using ACL2 that we believe could not previously be proved using ACL2, for example the following. (equal (symbol-package-name (intern-in-package-of-symbol str t)) (symbol-package-name (intern-in-package-of-symbol str nil))) Thanks to Sol Swords for a helpful report, which included the example above. See [pkg-imports] and see [defpkg]. Added function [no-duplicatesp-eq]. Added a new hint keyword, :[backchain-limit-rw], to control the level of backchaining for [rewrite], [meta], and [linear] rules. This overrides, for the current goal and (as with :[in-theory] hints) descendent goals, the default [backchain-limit] (see [set-backchain-limit]). Thanks to Jared Davis for requesting this feature. Support is now provided for creating and certifying books that do not depend on trust tags, in the case that the only use of trust tags is during [make-event] expansion. See [set-write-ACL2x]. Thanks to Sol Swords for reporting a couple of bugs in a preliminary implementation. Function (file-write-date$ filename state) has been added, giving the write date of the given file. See [forward-chaining-reports] for how to get new reports on the forward chaining activity occurring in your proof attempts. Thanks to Dave Greve for inspiring the addition of this utility. It is now possible to use ACL2's printing utilities to return strings, by opening output channels to the keyword :STRING rather than to filenames. See [io]. Thanks to Jared Davis for a helpful conversation that led us to add this feature. HEURISTIC IMPROVEMENTS We have slightly improved the handling of :[forward-chaining] rules that contain free variables. Formerly, such rules might fire only once, when the first match for a free variable is discovered, and would not fire again even if subsequent forward chaining made available another match. This made it difficult to predict whether a rule with free variables would fire or not, depending as it did on the order in which newly derived conclusions were added. The new handling is a little slower but more predictable. Thanks to Dave Greve for sending a helpful example that led us to consider making such an improvement. We have slightly improved the so-called ``[type-set]'' heuristics to work a bit harder on terms of the form (rec term), where rec is a so-called ``compound-recognizer'' function, that is, a function with a corresponding enabled :[compound-recognizer] rule. Thanks to Jared Davis for sending a helpful example (found, in essence, in the modified function type-set-rec, source file type-set-b.lisp). We made three heuristic improvements in the way contexts (so-called ``type-alists'') are computed from goals (``clauses''). Although these changes did not noticeably affect timing results for the ACL2 regression suite, they can be very helpful for goals with many hypotheses. Thanks to Dave Greve for sending a useful example (one where we found a goal with 233 hypotheses!). The algorithm for substituting alists into terms was modified. This change is unlikely to affect many users, but in one example it resulted in a speed-up of about 21%. Thanks to Dave Greve for supplying that example. Sped up [include-book] a bit by memoizing checksums of symbols. (This change pertains to ``normal'' ACL2 only, not the [hons] version (see [hons-and-memoization], where such memoization already occurred.) We found about a 23% speed-up on an example from Dave Greve. Made a small change to the algorithm used to prove hypotheses of :[type-prescription] rules (ACL2 source function type-set-relieve-hyps). One change avoids a linear walk through the context (the ``type-alist'' structure), while the other could avoid storing unnecessary [force]d assumptions (into the so-called ``tag-tree''). BUG FIXES Fixed a long-standing soundness bug caused by the interaction of [force]d hypotheses with destructor [elim]ination. The fix was to avoid using forcing when building the context (so-called ``type-alist'') when the goal is considered for destructor elimination; those who are interested can see a discussion in source function eliminate-destructors-clause1, which includes a proof of nil that no longer succeeds. A similar fix was made for generalization, though we have not exploited the previous code to prove nil in that case. Fixed a bug that allowed book certification to ignore skip-proofs around [encapsulate] [events]. Thus, a book could contain an event of the form (skip-proofs (encapsulate ...)), and a call of [certify-book] on that book could succeed even without supplying keyword :skip-proofs-okp t. This bug was introduced in Version 3.5 (May, 2009). Fixed a bug that could occur when including a book that attempts to redefine a function as a macro, or vice-versa. (For details of the issue, see the comment in the definition of variable *hcomp-fn-macro-restore-ht* in source file other-events.lisp.) (Windows only) Fixed handling of the Windows drive so that an executable image saved on one machine can be used on another, even with a different drive. Thanks to Harsh Raju Chamarthi for reporting this issue and doing a lot of testing and collaboration to help us get this right. Made a change to avoid possible low-level errors, such as bus errors, when quitting ACL2 by calling [good-bye] or its synonyms. This was occurring in CCL, and we are grateful to Gary Byers for helping us find the source of those errors (which basically was that ACL2 was attempting to quit while already in the process of quitting). Fixed a bug in [with-guard-checking], which was being ignored in function bodies. Fixed a bug in [top-level], which was not reverting the logical [world] when an error resulted from evaluation of the given form. Thanks to Jared Davis for bringing this bug to our attention. Fixed a long-standing bug (back through Version 2.7) that was discarding changes to the connected book directory (see [cbd]) when exiting and then re-entering the top-level ACL2 loop (with [lp]). In some host Lisps, it has been possible to be in a situation where it is impossible to interrupt checkpoint printing during the summary. We had thought this solved when the host Lisp was CCL, but Sol Swords sent us an example (for which we are grateful) illustrating that this behavior could occur. This has been fixed. Fixed a bug in a proof obligation generated for :[meta] and :[clause-processor] rules, that the [guard] on the metafunction or clause-processor function, fn, holds under suitable assumptions. Those assumptions include not only that the first argument of fn satisfies [pseudo-termp], but also that all [stobj] inputs satisfy the corresponding stobj recognizer predicates. We had erroneously considered stobj outputs of fn instead of stobj inputs. Thanks to Sol Swords for bringing this bug to our attention with a simple example, and correctly pointing us to the bug in our code. Fixed the following bugs in [defattach]. We hadn't always been applying the full functional substitution when generating guard proof obligations. We had been able to hit an assertion when reattaching to more than one function. Attachment was permitted in the case of an untouchable function (see [remove-untouchable]). Finally, the guard proof obligation could fail in the case that the two functions have different formal parameter lists, as in the following example. (encapsulate ((foo (x) x :guard (symbolp x))) (local (defun foo (x) x))) (defun bar (x2) (declare (xargs :guard (symbolp x2))) x2) (defattach foo bar) Fixed a raw Lisp error that could be caused by including a book using [make-event] to define a function symbol in a locally-introduced package. An example appears in a comment in ACL2 source function write-expansion-file. Made a change that can prevent an error near the end of book certification when the underlying Host Lisp is Allegro Common Lisp, in the case that environment variable ACL2_SYSTEM_BOOKS has been set to the name of a directory with a parent that is a soft link. Thanks to Dave Greve for supplying an example to led us to this fix, which involves avoiding Allegro CL's implementation of the Common Lisp function, truename. Fixed a bug that was failing to substitute fully using bindings of free variables in [force]d hypotheses. A related change is that instead of binding such a free variable to a new variable of the form ???-Y, the new variable is now of the form UNBOUND-FREE-Y. Fixed a bug that could inhibit the printing of certain theory warnings (and probably, in the other direction, cause inappropriate such printing). We eliminated excessive \"Raw-mode\" warnings about [add-include-book-dir] that could be generated by the use of raw-mode during [include-book]. Thanks to Dave Greve for bringing this issue to our attention. Fixed the printing of results from forms within an [encapsulate], so that they are abbreviated according to the [ld-evisc-tuple]. It is now possible to evaluate [stobj]-related forms after evaluating :[set-guard-checking] :none or :[set-guard-checking] nil, even in cases where such evaluation formerly caused a guard violation due to a bug in ACL2. Here is an example of an error that no longer occurs. ACL2 !>(defstobj st fld) Summary Form: ( DEFSTOBJ ST ...) Rules: NIL Time: 0.00 seconds (prove: 0.00, print: 0.00, other: 0.00) ST ACL2 !>(set-guard-checking :none) Turning off guard checking entirely. To allow execution in raw Lisp for functions with guards other than T, while continuing to mask guard violations, :SET-GUARD-CHECKING NIL. See :DOC set-guard-checking. ACL2 >(fld st) ACL2 Error in TOP-LEVEL: The guard for the function call (FLD ST), which is (STP ST), is violated by the arguments in the call (FLD ST). [... etc. ...] You can understand how things now work by imagining that when a function introduced by [defstobj] is called, [guard]-checking values of :none or nil are temporarily converted to t. Thanks to Pete Manolios, Ian Johnson, and Harsh Raju Chamarthi for requesting this improvement. Fixed a bug in which the wrong attachment could be made when the same function has an attachment in a book and another in the certification world of that book (possibly even built into ACL2), if the load of a compiled file is aborted because a sub-book's compiled file is missing. The bug has been present since the time that [defattach] was added (Version_4.0). An example may be found in a comment in the [deflabel] for note-4-2 (ACL2 source file ld.lisp). The :[doc] and related utilities now cause a clean error when provided other than a symbol. Thanks to Jared Davis for pointing out the raw Lisp error that had occurred in such cases. It had been the case that in raw-mode (see [set-raw-mode]), it was possible to confuse [include-book] when including a book in a directory different from the current directory. This has been fixed. Thanks to Hanbing Liu for bringing this problem to our attention with a small example. NEW AND UPDATED BOOKS AND RELATED INFRASTRUCTURE Many changes have been made to the distributed books, thanks to an active ACL2 community. You can contribute books and obtain updates between ACL2 releases by visiting the {ACL2 Books | http://acl2-books.googlecode.com/} web page. There is new Makefile support for certifying just some of the distributed books. See [books-certification-classic], in particular discussion of the variable ACL2_BOOK_DIRS. Thanks to Sandip Ray for requesting this enhancement. The [documentation] for [make-event] now points to a new book, books/make-event/defrule.lisp, that shows how make-event can be used to do macroexpansion before generating [events]. Thanks to Carl Eastlund for useful interaction on the acl2-help mailing list that led us to add this example. EMACS SUPPORT Incorporated a version of changes from Jared Davis to the control-t f emacs utility (distributed file emacs/emacs-acl2.el), so that one can fill a format string from anywhere within the string. EXPERIMENTAL VERSIONS We refrain from listing changes here to experimental versions, other than an enhancement to the [hons] version that can reduce sizes of [certificate] files, by applying [hons-copy] to introduce structure sharing (ACL2 source function make-certificate-file1).") (NOTE-4-2{R} (RELEASE-NOTES) "ACL2 Version 4.2(r) (January, 2011) Notes Please see [note-4-2] for changes in Version 4.2 of ACL2.") (NOTE-4-3 (RELEASE-NOTES) "ACL2 Version 4.3 (July, 2011) Notes NOTE! New users can ignore these release notes, because the [documentation] has been updated to reflect all changes that are recorded here. Below we roughly organize the changes since Version 4.2 into the following categories of changes: existing features, new features, heuristic improvements, bug fixes, changes at the system level and to distributed books, Emacs support, and experimental versions. Each change is described in just one category, though of course many changes could be placed in more than one category. CHANGES TO EXISTING FEATURES Significant changes have been made for list-processing primitives such as [member] and [assoc]; see [equality-variants]. In summary: instead of separate functions based on [eq], [eql], and [equal], there is essentially just one function, which is based on [equal]; the [eq] and [eql] variants are logically just the [equal] variant. For example, [member-eq] and [member] are macros that generate corresponding calls of [member-equal] in the logic, although in raw Lisp they will execute using tests [eq] and [eql], respectively. References to any of these in logical contexts such as [theories] are now references to the function based on [equal]; for example, the hint :in-theory (disable member) is completely equivalent to the hint :in-theory (disable member-equal). Distributed books have been modified as necessary to accommodate this change. While the need for such changes was relatively infrequent, changes were for example needed in contexts where terms are manipulated directly; for example, [defevaluator] needs to mention [member-equal] rather than [member], just as it was already the case to mention, say, [binary-append] rather than [append]. Again, see [equality-variants] for more information about equality variants. A few improvements were made in support of the modified treatment of equality variants discussed above. The changes include the following. o We now allow the use of macro aliases (see [macro-aliases-table] in :trigger-fns of rules (see [rule-classes]). o We now remove so-called ``guard holders'' (including calls of [return-last], hence of [mbe]) in :trigger-terms of rules. o We also remove guard holders in formulas of :[congruence] and [type-prescription] rules. o Macros union-eq and intersection-eq can now take any positive number of arguments, and [union-eq] can take zero arguments. (Thanks to Jared Davis for requesting this enhancement.) The same can be said for new macros [union$] and [intersection$], respectively. o A few changes were made to built-in theorems from source file axioms.lisp, in particular disabling :[type-prescription] rule consp-assoc-equal (formerly two enabled rules, consp-assoc-eq and consp-assoc) but adding this theorem as a :forward-chaining rule, and similarly for true-list-listp-forward-to-true-listp-assoc-equal (and eliminating rule true-list-listp-forward-to-true-listp-assoc-eq; and disabling rule true-listp-cadr-assoc-eq-for-open-channels-p. Also, theorem all-boundp-preserves-assoc has been renamed to all-boundp-preserves-assoc-equal and also strengthened. o Some [guard]s were slightly improved (logically weaker or the same). Improved get-output-stream-string$ to allow for a context and to do genuine error printing instead of using [cw]. See [io]. Added the symbols [flet] and [with-local-stobj] to *acl2-exports*. A small change was made to the processing of more than one :[guard] declaration for the same function. In particular, a guard of t is essentially ignored. Attachments are now allowed during evaluation of the first argument of [prog2$] even in contexts (such as proofs) during which the use of attachments is normally prohibited. More generally, the second of the three arguments of [return-last] has this property, except in the case of [mbe] (or related macros like [mbe1]), where the exec argument may provide the value. Thanks to Sol Swords for useful discussions leading us to implement this enhancement. The restriction has been removed that prohibited the use of [mbe] inside [encapsulate] [events] with a non-empty [signature]. This restriction was introduced in Version 3.4, but has not been necessary since Version 4.0, when we first started disallowing [guard] verification for functions introduced non-[local]ly inside such [encapsulate] events. We weakened the checks involving common ancestors for evaluator and [meta] (and [clause-processor]) functions (see [evaluator-restrictions]) so that except in the [mbe] case, the next-to-last argument of [return-last] is not considered. Thanks to Sol Swords for bringing this issue to our attention. The macro [append] no longer requires at least two arguments. Thanks to Dave Greve for requesting this enhancement. (Mostly for system hackers) Now, [break-on-error] breaks at a more appropriate (earlier) time for certain system functions that do not return state, such as translate11. Thanks to David Rager for requesting this improvement. [Show-accumulated-persistence] may take a new argument, :runes, which simply causes an alphabetical list of [rune]s to be printed out. Improved [trace$] so that :entry, :exit, and :cond forms may reference state even if the function being traced does not include state as a formal. The system function acl2x-expansion-alist now takes a second argument, namely [state]. This change allows for more flexibility in the sorts of attachments that can be made to this function (see [defattach]). Thanks to Jared Davis and Sol Swords for requesting this enhancement and providing a preliminary implementation. An obscure [proof-checker] change, unlikely to affect users, replaces the state global variables erp, val, print-macroexpansion-flg, and print-prompt-and-instr-flg by pc-erp, pc-val, pc-print-macroexpansion-flg, and pc-print-prompt-and-instr-flg, respectively. [State] globals fmt-hard-right-margin and fmt-soft-right-margin are now untouchable (see [set-fmt-hard-right-margin] and see [push-untouchable]). If you bind these state globals with [state-global-let*], then you will need to do so with appropriate setters to restore their values, for example as follows. (state-global-let* ((fmt-hard-right-margin 500 set-fmt-hard-right-margin) (fmt-soft-right-margin 480 set-fmt-soft-right-margin)) ...) The error message has been improved for the case of evaluating an undefined function that has an attachment (see [defattach]). Thanks to Jared Davis for sending the following example, which illustrates the additional part of the message. ACL2 !>(defstub foo (x) t) [[... output omitted ...]] ACL2 !>(defattach foo identity) [[... output omitted ...]] ACL2 !>(defconst *x* (foo 3)) ACL2 Error in ( DEFCONST *X* ...): ACL2 cannot ev the call of undefined function FOO on argument list: (3) Note that because of logical considerations, attachments (including IDENTITY) must not be called in this context. [[... additional output omitted ...]] The directory string supplied to [add-include-book-dir] no longer must terminate with the `/' character, as had been required in some Lisp implementations. Thanks to Sol Swords for bringing this issue to our attention. We no longer print induction schemes with [gag-mode]; use :[pso] if you want to see them. Thanks to Dave Greve for this suggestion. It is now legal to supply a constant for a [stobj] array dimension. See [defstobj]. Thanks to Warren Hunt for requesting this enhancement. We cleaned up a few issues with [defpkg]. o It is no longer illegal to submit a [defpkg] form in raw-mode (see [set-raw-mode]). Thanks to Jun Sawada for reporting an example in which an [include-book] form submitted in raw-mode caused an error because of a `hidden' [defpkg] form (see [hidden-defpkg]). There will no longer be an error in such cases. o It had been the case that [local]ly including a book could make it possible to use a package defined by that book. Consider for example the following book, foo.lisp. (in-package \"ACL2\") (local (include-book \"arithmetic/top\" :dir :system)) After certifying this book, it had been possible to admit the following events in a new session. (include-book \"foo\") (defconst acl2-asg::*foo* 3) (defconst *c* 'acl2-asg::xyz) In Version_4.3, neither of these [defconst] events is admitted. o A hard Lisp error is now avoided that had been possible in rare cases when including books with hidden packages (see [hidden-defpkg]). An example may be found in a comment in the [deflabel] for note-4-3 (in ACL2 source file ld.lisp). The undocumented (but sometimes useful) functions packn1 and packn are now [guard]-verified :[logic] mode functions. Thanks to Sandip Ray for requesting this enhancement. It had been the case that when including a book, functions defined in the book's certification [world] (that is, in its [portcullis] [command]s) were typically not given compiled code. That has been fixed. The commands :[pl] and :[pl2] have been improved, primarily by printing information for more rule classes. See [pl] and see [pl2]. See also the item below about the new [proof-checker] command, show-type-prescriptions. NEW FEATURES New macros [mv?-let] and [mv?] extend the funtionality of [mv-let] and [mv] (respectively) to the case of a single value. Macro [with-local-state] is available for system programmers who wish bind [state] locally, essentially using [with-local-stobj]. But this should only be done with extreme care, and it requires an active trust tag; see [with-local-state]. Formatted printing functions now have analogues that print to strings and do not take an output channel or [state] as arguments. See [printing-to-strings]. The system function ancestors-check is now available for verified modification by users, i.e., attachment using (defattach ancestors-check ). Thanks to Robert Krug for providing the necessary proof support, which we modified only in small ways. New macros, observation-cw and warning$-cw, provide formatted printing of [observation]s and warnings (respectively) without [state]. Thanks to Harsh Raju Chamarthi and David Rager for requests leading to these utilities. Observation-cw is now used in some of the distributed books (thanks to Robert Krug for useful interaction for that). The [proof-checker] command type-alist (see [proof-checker-commands]) now takes an optional third argument that causes the production of forward-chaining reports (see [forward-chaining-reports]). Thanks to Dave Greve for requesting such an enhancement. The reports generated by forward-chaining, [forward-chaining-reports], have been changed to indicate when a conclusion reached by forward chaining is REDUNDANT with respect to the type information already known. Thanks to Dave Greve for suggesting this enhancement. The utility [with-prover-time-limit] is now legal for [events] (see [embedded-event-form]). For example, the following is now legal. (encapsulate () (with-prover-time-limit 2 (defthm append-assoc (equal (append (append x y) z) (append x (append y z)))))) The new utility [with-prover-step-limit] is analogous to the utility [with-prover-time-limit], but counts ``prover steps'' rather than checking for time elapsed. See [with-prover-step-limit]. Also see [set-prover-step-limit] to provide a default step-limit. Note that just as [with-prover-time-limit] may now be used to create [events], as discussed just above, [with-prover-step-limit] may also be used to create [events]. Thanks to Carl Eastlund for requesting support for step-limits. The macro [progn$] is analogous to [prog2$], but allows an arbitrary number of arguments. For example: ACL2 !>:trans1 (progn$ (f1 x) (f2 x) (f3 x)) (PROG2$ (F1 X) (PROG2$ (F2 X) (F3 X))) ACL2 !> Thanks to David Rager for contributing this macro. The macro [defattach] may now be supplied the argument :skip-checks :cycles. In this case, as with argument :skip-checks t, a trust tag is reuired (see [defttag]), and no logical claims are made. The effect is to avoid the usual check that the extended ancestor relation has no cycles (see [defattach]). Thanks to Dave Greve for requesting this feature. You can now limit the printing of subgoal names when using :[set-gag-mode] :goals. See [set-print-clause-ids]. Thanks to Karl Hoech for a suggestion leading to this enhancement. A new [proof-checker] command, show-type-prescriptions, or st for short, provides information about :[type-prescription] rules that match a given term. Thanks to Dave Greve for requesting this enhancement. See also the item above about related improvements to commands :[pl] and :[pl2]. HEURISTIC IMPROVEMENTS ACL2 now avoids some repeated attempts to rewrite hypotheses of rewrite rules. See [set-rw-cache-state] for a discussion of this behavior and how to avoid it. The default behavior has been observed to reduce by 11% the overall time required to complete a regression. Here are the directories that had the top three time decreases and top three time increases, shown in seconds. -368 coi/gacc (1064 down to 696: decrease of 35%) -220 workshops/1999/ste (664 down to 444: decrease of 33%) -148 unicode (331 down to 183: decrease of 45%) .... +7 workshops/2002/cowles-flat/support (229 up to 236: increase of 3%) +8 workshops/1999/ivy/ivy-v2/ivy-sources (508 up to 516: increase of 2%) +12 workshops/2009/hardin/deque-stobj (78 up to 91: increase of 17%) The so-called ``ancestors check,'' which is used to limit backchaining, has been strengthened so that two calls of [equal] are considered the same even if their arguments appear in the opposite order. Thanks to Robert Krug for providing an implementation and a useful discussion. The check for [irrelevant-formals] in processing of [defun]s has been made more efficient. Thanks to Eric Smith for reporting this issue in 2001 (!) and thanks to Warren Hunt for recently sending an example. For that example, we have seen the time for the [irrelevant-formals] check reduced from about 10 seconds to about 0.04 seconds. (GCL only) The macro [mv] has been modified so that certain fixnum boxing can be avoided. (Allegro CL only) We have set to nil four Allegro CL variables that otherwise enable storing of certain source information (for details, see the discussion of ``cross-referencing'' in ACL2 source file acl2-init.lisp). As a result of this change we have about a 6% speedup on the regression suite, but a 27% time reduction on an example that includes a lot of books. Exhaustive matching for the case of [free-variables] has been extended to [type-prescription] rules, in analogy to the default setting :match-free :all already in place for [rewrite], [linear], and [forward-chaining] rules. See [free-variables-type-prescription]. Thanks to Dave Greve for requesting this enhancement. BUG FIXES A soundness bug was fixed in some raw-Lisp code implementing the function, [take]. Thanks to Sol Swords for pointing out this bug with (essentially) the following proof of nil. (defthmd take-1-nil-logic (equal (take 1 nil) '(nil)) :hints((\"Goal\" :in-theory (disable (take))))) (thm nil :hints ((\"Goal\" :use take-1-nil-logic))) Calls of [mbe] in ``safe-mode'' situations --- i.e., during evaluation of [defconst], [value-triple], and [defpkg] forms, and during macroexpansion --- are now guard-checked. Thus, in these situations both the :logic and :exec forms will be evaluated, with an error if the results are not equal. Formerly, only the :logic form was evaluated, which was a soundness bug that could be exploited to prove nil. For a such a proof and a bit of further explanation, see the example at the top of the comments for (deflabel note-4-3 ..) in ACL2 source file ld.lisp. It had been possible to prove nil by proving the following theorem using ACL2 built on CCL and then proving its negation using ACL2 built on a different host Lisp. (defthm host-lisp-is-ccl (equal (cdr (assoc 'host-lisp *initial-global-table*)) :ccl) :rule-classes nil) This hole has been plugged by moving the setting of 'host-lisp out of the constant *initial-global-table*. Fixed [trace$] for arguments that are [stobj] accessors or updaters. It also gives an informative error in this case when the accessor or updater is a macro (because the introducing [defstobj] event specified :inline t). Avoided a potential error that could occur when no user home directory is located. Our previous solution for Windows simply avoided looking for ACL2 customization files (see [ACL2-customization]) and acl2-init.lsp files in a user's home directory. With this change, we handle such files the same for Windows as for non-Windows systems: we always look for ACL2 customization files (see [ACL2-customization]) and acl2-init.lsp files in a user's home directory, but only if such a directory exists. Thanks to Hanbing Liu for reporting this issue. (GCL only) Fixed a bug that prevented the use of [get-output-stream-string$] when the host Lisp is GCL. Fixed [with-live-state] to work properly for executable counterparts (so-called ``*1*'' functions). Fixed a bug in the error message caused by violating the [guard] of a macro call. Fixed a bug in an error message that one could get when calling [defattach] with argument :skip-checks t to attach to a :[program] mode function symbol that was introduced with [defun]. (This is indeed an error, but the message was confusing.) Thanks to Robert Krug for bringing this bug to our attention. Fixed a bug in the loop-checking done on behalf of [defattach], which could miss a loop. For an example, see the comment about loop-checking in the comments for (deflabel note-4-3 ..) in ACL2 source file ld.lisp. Terms of the form (hide ) without free variables could be simplified, contrary to the purpose of [hide]. This is no longer the case, Thanks to Dave Greve for reporting this issue. An infinite loop could occur when an error was encountered in a call of [wormhole-eval], for example with the following form, and this has been fixed. (wormhole-eval 'demo '(lambda () (er hard 'my-top \"Got an error!\")) nil) Fixed a bug in detection of package redefinition. While we have no example demonstrating this as a soundness bug, we cannot rule it out. Fixed a bug in the message produced by an erroneous call of [flet]. Thanks to Jared Davis for reporting this bug and sending a helpful example. For a failed [defaxiom] or [defthm] event, we now avoid printing [rune]s that are used only in processing proposed rules to be stored, but not in the proof itself. Thanks to Dave Greve for sending us an example that led us to make this fix. ACL2 did not reliably enforce the restriction against non-[local] [include-book] [events] inside [encapsulate] events, as illustrated by the following examples. ; not permitted (as expected) (encapsulate () (include-book \"foo\")) ; permitted (as expected) (encapsulate () (local (include-book \"foo\"))) ; formerly permitted (surprisingly); now, not permitted (local (encapsulate () (include-book \"foo\"))) Moreover, the corresponding error message has been fixed. Thanks to Jared Davis and Sandip Ray for relevant discussions. When [include-book] is given a first argument that is not a string, a more graceful error now occurs, where previously an ugly raw Lisp error had occurred. Thanks to Eric Smith for bringing this bug to our attention. Fixed a bug in an error message that was printed when an unexpected expression has occurred where a [declare] form is expected. (Since all functions are compiled when the host Lisp is CCL or SBCL, the following bug fix did not occur for those host Lisps.) After evaluation of ([set-compile-fns] t), all defined functions are expected to run with compiled code; but this was not the case for functions exported from an [encapsulate] event. This has been fixed. It had been the case that the :[puff] command was broken for [include-book] form whose book had been certified in a world with an [add-include-book-dir] event. This has been fixed. Evaluation of [stobj] updaters (see [defstobj]) may no longer use attachments (see [defattach]). This is a subtle point that will likely not affect many users. Thanks to Jared Davis for bringing this issue to our attention; a slight variant of his example appears in a comment in ACL2 source function oneify-cltl-code. It had been the case that even when a [stobj] creator function was declared to be untouchable (see [push-untouchable]), a [with-local-stobj] form based on that same stobj was permitted. Now, such forms are not admitted. Thanks to Jared Davis for a query leading to this fix. Fixed a buggy message upon [guard] violations, which was suggesting the use of (set-guard-checking :none) in some cases when guard-checking was already set to :none. It had been possible to get a hard Lisp error when computing with [ec-call] in [books]. The following is an example of such a book, whose certification no longer causes an error. (in-package \"ACL2\") (defun f (x) x) (defconst *c* (ec-call (f 3))) (defun g (x) (cons x x)) The command :[pl2], and also the [proof-checker] commands rewrite and show-rewrites (and hence their respective aliases r and sr), now take rule-id arguments that can be :[definition] [rune]s. These commands dealt with definition rules already, e.g. :pl2 (append x y) binary-append but they did not allow explicit specification of :definition runes, e.g.: :pl2 (append x y) (:definition binary-append) The following example illustrates a bug in the processing of (admittedly obscure) [hints] of the form :do-not-induct name, where name is not t, :otf-flg-override, :otf, or nil. In this example, ACL2 had essentially ignored the hint and reverted to prove the original goal by induction, rather than to skip the goal temporarily as is expected for such hints. Thanks to David Rager for a helpful discussion. (thm (and (equal (append (append x y) z) (append x y z)) (equal (append (append x2 y2) z2) (append x2 y2 z2))) :hints ((\"Subgoal 1\" :do-not-induct some-name))) Fixed a slight bug in the definitions of built-in [theories]. For example, in a fresh ACL2 session the value of the following form is nil, but formerly included several :[definition] [rune]s. (let ((world (w state))) (set-difference-theories (function-theory :here) (function-theory 'ground-zero))) CHANGES AT THE SYSTEM LEVEL AND TO DISTRIBUTED BOOKS Many changes have been made to the distributed books, as recorded in svn logs under the `Source' and 'Updates' links at the {ACL2 Books | http://acl2-books.googlecode.com/} web page. Here we list some of the more significant changes. o A large library has been graciously contributed by the formal verification group at Centaur Technology. See books/centaur/ and, in particular, file books/centaur/README, which explains how the library depends on the experimental HONS extension (see [hons-and-memoization]). o Among the new books is an illustration of [defattach], books/misc/defattach-example.lisp, as well as a variant of defattach that avoids the need for [guard] verification, books/misc/defattach-bang.lisp. o Distributed book books/misc/trace1.lisp has been deleted. It had provided slightly more friendly [trace] output for new users, but distributed book books/misc/trace-star.lisp may be better suited for that purpose. ACL2 can once again be built on LispWorks (i.e., as the host Lisp), at least with LispWorks 6.0. Thanks to David Rager for useful conversations. Several changes have been made from previous LispWorks-based ACL2 executables: o ACL2 now starts up in its read-eval-print loop. o You can save an image with [save-exec]. o Multiprocessing is not enabled. o The stack size is managed using a LispWorks variable that causes the stack to grow as needed. o When ACL2 is built a script file is written, as is done for other host Lisps. Thus, (assuming that no PREFIX is specified), saved_acl2 is just a small text file that invokes a binary executable, which for Lispworks is saved_acl2.lw. The HTML documentation no longer has extra newlines in
  environments.

  Statistics on ACL2 code size may be found in distributed file
  doc/acl2-code-size.txt. This file and other information can be
  found in a new [documentation] topic, [about-ACL2].

  Fixed the build process to pay attention to environment variable
  ACL2_SYSTEM_BOOKS (which may be supplied as a command-line argument
  to `make'). An ACL2 executable can thus now be built even when
  there is no books/ subdirectory if a suitable replacement directory
  is supplied.

  Some warnings from the host Lisp are now suppressed that could
  formerly appear. For example, the warnings shown below occurs in
  Version 4.2 using Allegro CL, but not in Version 4.3.

    ACL2 !>(progn (set-ignore-ok t)
                  (set-irrelevant-formals-ok t)
                  (defun bar (x y)
                    x))
    [[.. output omitted ..]]
     BAR
    ACL2 !>:comp bar
    ; While compiling BAR:
    Warning: Variable Y is never used.
    ; While compiling (LABELS ACL2_*1*_ACL2::BAR ACL2_*1*_ACL2::BAR):
    Warning: Variable Y is never used.
     BAR
    ACL2 !>

  EMACS SUPPORT

  The distributed Emacs file emacs/emacs-acl2.el now indents calls of
  er@par and warning$@par the same way that calls of defun are
  indented.

  EXPERIMENTAL VERSIONS

  The parallel version (see [parallelism]) now supports parallel
  evaluation of the ``waterfall'' part of the ACL2 prover; see
  [set-waterfall-parallelism]. Thanks to David Rager for doing the
  primary design and implementation work.

  A new macro, [spec-mv-let], supports speculative and parallel
  execution in the parallel version, courtesy of David Rager.

  Among the enhancements for the HONS version (see
  [hons-and-memoization]) are the following.

      [Memoize]d functions may now be traced (see [trace$]). Thanks to Sol
      Swords for requesting this enhancement.

      [Memoize-summary] and [clear-memoize-statistics] are now :[logic]
      mode functions that return nil. Thanks to Sol Swords for this
      enhancement.

      [Memoize] is now explicitly illegal for constrained functions.
      (Already such memoization was ineffective.)

      A new keyword argument, :AOKP, controls whether or not to allow
      memoization to take advantage of attachments; see [memoize] and
      for relevant background, see [defattach].

      [Memoize] is now illegal by default for :[logic] mode functions that
      have not had their guards verified. See [memoize] (keyword
      :ideal-okp) and see [ACL2-defaults-table] (key
      :memoize-ideal-okp) for and explanation of this restriction and
      how to avoid it.

      [History] commands such as :[pe] and :[pbt] now display ``M'' or
      ``m'' to indicate memoized functions. See [pc].")
 (NOTE-4-3{R}
  (RELEASE-NOTES)
  "ACL2 Version 4.3(r) (July, 2011) Notes

  Please see [note-4-3] for changes in Version 4.3 of ACL2.")
 (NOTE-5-0
  (RELEASE-NOTES)
  "ACL2 Version 5.0 (August, 2012) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes since Version 4.3 into the
  following categories of changes: existing features, new features,
  heuristic improvements, bug fixes, changes at the system level and
  to distributed books, Emacs support, and experimental versions.
  Each change is described in just one category, though of course
  many changes could be placed in more than one category.

  NOTE: ACL2 is now distributed under Version 2 of the GNU General
  Public License. [Added later: The license has changed since
  Version_5.0. See LICENSE.] Formerly, any later version had been
  acceptable. Moreover, books are no longer distributed from a
  University of Texas website, but rather, from Google Code at the
  {ACL2 Books Downloads |
  http://code.google.com/p/acl2-books/downloads/} page.

  CHANGES TO EXISTING FEATURES

  A fatal error now occurs if environment variable ACL2_CUSTOMIZATION
  has a value other than NONE or the empty string, but is not the
  name of an existing file. Thanks to Harsh Raju Chamarthi for
  requesting such a change.

  Functions read-acl2-oracle (and read-acl2-oracle@par), read-run-time,
  and main-timer are no longer untouchable (see
  [remove-untouchable]).

  We now avoid certain duplicate conjuncts in the [constraint] stored
  for [encapsulate] [events]. For example, the constraint stored for
  the following event formerly included (EQUAL (FOOP (CONS X Y))
  (FOOP Y)) and (BOOLEANP (FOOP X)) twice each, but no more.

    (encapsulate
     ((foop (x) t))
     (local (defun foop (x) (declare (ignore x)) t))
     (defthm foop-constraints
       (and (booleanp (foop x))
            (equal (foop (cons x y)) (foop y)))
       :rule-classes
       ((:type-prescription :corollary (booleanp (foop x)))
        (:rewrite :corollary (equal (foop (cons x y)) (foop y))))))

  The :[guard] for a constrained function (see [signature]) may now
  mention function symbols introduced in the same [encapsulate] event
  that introduces that function. Thanks to Nathan Wetzler for a
  helpful discussion leading to this improvement.

  The test for redundancy (see [redundant-events]) of [encapsulate]
  [events] has been improved in cases involving redefinition (see
  [ld-redefinition-action]). Thanks to Jared Davis for providing the
  following example, which illustrates the problem.

    (redef!)

    (encapsulate ()
      (defun g (x)
        (+ 3 x)))

    (g 0) ; 3, as expected

    (encapsulate ()
      (defun g (x)
        (+ 4 x)))

    (g 0) ; 4, as expected

    ; Unfortunately, the following was flagged as redundant because it agreed
    ; with the first encapsulate above.  That has been fixed; now, it is
    ; recognized as not being redundant.
    (encapsulate ()
      (defun g (x)
        (+ 3 x)))

  The test for redundancy of [defun] and [defconst] events has been
  improved in the case that redefinition is active. In that case,
  redundancy now additionally requires that the ``translated'' body
  is unchanged, i.e., even after expanding macro calls and replacing
  constants (defined by [defconst]) with their values. Thanks to Sol
  Swords for requesting this enhancement, and to Jared Davis for
  pointing out a bug in a preliminary change. See [redundant-events],
  in particular the ``Note About Unfortunate Redundancies''. Note
  that this additional requirement was already in force for
  redundancy of [defmacro] events.

  The macro [defmacro-last] and the [table] [return-last-table] have
  been modified so that when they give special treatment to a macro
  mac and its raw Lisp counterpart mac-raw, a call (return-last
  'mac-raw ...) can be made illegal when encountered directly in the
  top level loop, as opposed to inside a function body. See
  [return-last]. Thanks to Harsh Raju Chamarthi for showing us an
  example that led us to make this improvement.

  We removed a barrier to admitting function definitions, as we explain
  using the following example.

    (defun foo (m state)
      (declare (xargs :stobjs state))
      (if (consp m)
          (let ((state (f-put-global 'last-m m state)))
            (foo (cdr m) state))
        state))

  Previously, ACL2 complained that it could not determine the outputs
  of the [let] form, as is necessary in order to ensure that [state]
  is returned by it. ACL2 now works harder to solve this problem as
  well as the analogous problem for [mv-let] and, more generally for
  [mutual-recursion]. (The main idea is to reverse the order of
  processing the [if] branches if necessary.) We thank Sol Swords for
  contributing a version of the above example and requesting this
  improvement.

  It is no longer the case that [break-on-error] causes a Lisp break
  when encountering an error during translation of user input into
  internal (translated) form (see [term]). The reason is that an
  improvement to the translation process, specifically the one
  described in the preceding paragraph, allows certain backtracking
  from ``errors'', which are intended to be silent rather than
  causing breaks into raw Lisp. Thanks to Jared Davis for sending an
  example leading to this change.

  (CCL and SBCL only) When the host Lisp is CCL or SBCL, then since all
  functions are compiled, a [certify-book] command will no longer
  load the newly-compiled file (and similarly for [include-book] with
  argument :load-compiled-file :comp).

  [Set-write-acl2x] now returns an error triple and can take more
  values, some of which automatically allow including uncertified
  books when [certify-book] is called with argument :acl2x t.

  The environment variable COMPILE_FLG has been renamed
  ACL2_COMPILE_FLG; see [certify-book].

  The macros [defthmd] and [defund] no longer return an error triple
  with value :SKIPPED when proofs are being skipped. Rather, the
  value returned is the same as would be returned on success when
  proofs are not skipped.

  For those who use [set-write-ACL2x]: now, when [certify-book] is
  called without a :ttagsx argument supplied, then the value of
  :ttagsx defaults to the (explicit or default) value of the :ttags
  argument.

  The :[pl] and :[pl2] [command]s can now accept [term]s that had
  previously been rejected. For example, the command :pl (member a
  (append x y)) had caused an error, but now it works as one might
  reasonably expect, treating [member] as [member-equal] (see
  [equality-variants] for relevant background). Thanks to Jared Davis
  for reporting this problem by sending the above example.

  We have eliminated some hypotheses in built-in [rewrite] rules
  characterp-nth and ordered-symbol-alistp-delete-assoc-eq.

  Added the symbols [f-get-global], [f-put-global], and
  [state-global-let*] to *acl2-exports*.

  Added to the [guard]s of [push-untouchable] and [remove-untouchable]
  the requirement that the second argument must be a Boolean. Thanks
  to Jared Davis for sending an example that led to this change.

  The built-in function string-for-tilde-@-clause-id-phrase has been
  put into :[logic] mode and had its guards verified, as have some
  subsidiary functions. A few new rules have been added in support of
  this work; search for string-for-tilde-@-clause-id-phrase in ACL2
  source file boot-strap-pass-2.lisp if interested. Thanks to David
  Rager for contributing an initial version of this improvement.

  All trust tags are now in the [keyword] package. The [defttag] event
  may still take a symbol in an arbitrary package, but the trust tag
  created will be in the keyword package (with the same [symbol-name]
  as the symbol provided). Similarly, non-nil symbols occurring in
  the :ttags argument of an [include-book] or [certify-book] command
  will be converted to corresponding keywords. See [defttag].

  There have been several changes to [gag-mode]. It is now is initially
  set to :goals, suppressing most proof commentary other than key
  checkpoints; see [set-gag-mode]. (As before, see [pso] for how to
  recover the proof output.) Also, top-level induction schemes are
  once again printed when gag-mode is on, though these as well as
  printing of guard conjectures can be abbreviated (``eviscerated'')
  with a new [evisc-tuple]; see [set-evisc-tuple], in particular the
  discussion there of :GAG-MODE. Finally, the commentary printed
  within [gag-mode] that is related to [forcing-round]s is now less
  verbose. Thanks to Dave Greve and David Rager for discussions
  leading to the change in the printing of induction schemes under
  gag-mode; thanks to Warren Hunt for an email that led us to similar
  handling for printing of guard conjectures; and thanks to Robert
  Krug for a suggestion that led us to restore, in abbreviated form,
  important information about the sources of forcing round goals.

  An error now occurs if [ld] is called while loading a compiled book.
  See [calling-ld-in-bad-contexts]. Thanks to David Rager for
  reporting a low-level assertion failure that led us to make this
  change.

  The [proof-checker] interactive loop is more robust: most errors will
  leave you in that loop, rather than kicking you out of the
  proof-checker and thus back to the main ACL2 read-eval-print loop.
  Thanks to David Hardin for suggesting this improvement in the case
  of errors arising from extra right parentheses.

  The summary at the end of a proof now prints the following note when
  appropriate:

    [NOTE: A goal of NIL was generated.  See :DOC nil-goal.]

  See [nil-goal].

  Improved [dmr] to show the function being called in the case of
  explicit evaluation: ``(EV-FNCALL function-being-called)''.

  It is now permitted to bind any number of [stobjs] to themselves in
  the bindings of a [let] expression. But if any stobj is bound to
  other than itself in [let] bindings, then there still must be only
  one binding in that LET expression. The analogous relaxation holds
  for [lambda] expressions. Thanks to Sol Swords for requesting such
  a change, which was needed for some code generated by macro calls.

  The macro [top-level] now returns without error; See [top-level].
  Formerly, this macro always returned an error triple (mv t ..
  state), which meant that normal calls of [ld] would stop after
  encountering a call of top-level. Thanks to Jared Davis for
  bringing this issue to our attention.

  It is no longer the case that when you specify [xargs] keyword
  :non-executable t in a [defun] form rather than using [defun-nx],
  then the form of the body need match only the shape (prog2$
  (throw-nonexec-error ... ...) ...). We now require that the body of
  the definition of a function symbol, fn, with formals (x1 ... xk),
  be of the form (prog2$ (throw-nonexec-error 'fn (list x1 ... xk))
  ...). This fixes the following odd behavior, which could be
  considered a bug. Consider a book that contains the following two
  events.

    (defun foo (x)
      (declare (xargs :guard t :non-executable t :mode :logic))
      (prog2$ (throw-nonexec-error 'bar (list x))
              (cons 3 x)))
    (defn h (x)
      (foo x))

  After certifying this book and then including it in a new session,
  the behavior occurred that is displayed below; notice the mention
  of BAR. However, if the two forms were submitted directly in the
  loop, then the error message had mentioned FOO instead of BAR. This
  discrepancy has been eliminated, by rejecting the proposed
  definition of foo because the name in the first argument of
  throw-nonexec-error was 'bar where now it must be 'foo.

    ACL2 !>(h 3)

    ACL2 Error in TOP-LEVEL:  ACL2 cannot ev the call of undefined function
    BAR on argument list:

    (3)

    To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

    ACL2 !>

  A tautology checker used in the ACL2 sources (function if-tautologyp)
  has been limited somewhat in the effort it makes to recognize a
  tautology. While we expect it to be rare for the effect of this
  change to be noticeable, we thank Sol Swords for sending us an
  example that motivated this change: a [guard] verification that
  took about 5 seconds in Version_4.3 now takes, on the same machine,
  about 0.07 seconds.

  The behavior of backquote (`) has been changed slightly to be
  compatible with its behavior in raw Lisp. The change is to allow
  the use of comma-atsign (,@) at the end of a list, as in the
  following example.

    (let ((x 3) (y 2) (z 7)) `(,x ,y ,@z))

  Formerly, evaluation of this form had caused a guard violation in the
  ACL2 loop unless guard-checking was off (i.e., [set-guard-checking]
  was invoked with nil or :none), in which case it returned (3 2).
  But we observed evaluation of this form to return (3 2 . 7) in
  every host Lisp on which ACL2 runs (Allegro CL, CCL, CLISP, CMUCL,
  GCL, LispWorks, and SBCL). Now, ACL2 behaves like these Lisps.

  A call of the [theory] macro had previously returned nil when applied
  to other than the name of name of a previously executed [deftheory]
  event. Now, a hard error occurs.

  The [table] binop-table has been replaced by the table
  [untrans-table]. However, [add-binop] and [remove-binop] continue
  to have the same effect as before. See [add-macro-fn], which is a
  new feature discussed below.

  The function [booleanp] is now defined using [eq] instead of [equal],
  which may increase its efficiency. Thanks to Jared Davis for this
  change.

  For pairs (key . val) in the [macro-aliases-table], there had been a
  requirement that val is a known function symbol. Now, it only needs
  to be a symbol. (This change was made to support the new feature,
  [defun-inline], described elsewhere in these release notes.)

  NEW FEATURES

  A new ``tau system'' provides a kind of ``type checker.'' See
  [tau-system]. Thanks to Dave Greve for supplying a motivating
  example (on which this system can provide significant speedup), and
  to Sol Swords for sending a very helpful bug report on a
  preliminary implementation.

  Users may now arrange for additional summary information to be
  printed at the end of [events]. [Note added at Version_6.1:
  Formerly we pointed here to print-summary-user, but now, see
  [finalize-event-user]; also see [note-6-1]]. Thanks to Harsh Raju
  Chamarthi for requesting this feature and participating in a design
  discussion.

  A new, advanced [proof-checker] command, geneqv, shows the generated
  equivalence relation at the current subterm. Thanks to Dave Greve
  for an inquiry leading to this enhancement.

  A new reader macro, #u, permits the use of underscore characters in a
  number. See [sharp-u-reader]. Thanks to Jared Davis for requesting
  this capability.

  New [proof-checker] commands pl and pr provide interfaces to the ACL2
  commands :[pl] and :[pr], respectively. These can be useful if you
  want to see trivially-proved hypotheses, as now clarified in the
  [proof-checker] documentation for its show-rewrites command. See
  [proof-checker-commands]. Thanks to Pete Manolios for suggesting
  such clarification and capability.

  It is now legal to call [non-executable] functions without the usual
  [signature] restrictions imposed on executable code. For example,
  the third event below was not admissible, but now it is.

    (defstobj foo fld)
    (defun-nx id (x)
      x)
    (defun f (foo)
      (declare (xargs :stobjs foo :verify-guards nil))
      (cons 3 (id foo)))

  Thanks to Jared Davis for requesting this enhancement, in particular
  for calling non-executable functions in the :logic part of an [mbe]
  call. Here is Jared's example, which is admissible now but formerly
  was not.

    (defstobj foo (fld))
    (defun-nx my-identity (x) x)
    (defun my-fld (foo)
      (declare (xargs :stobjs foo))
      (mbe :logic (my-identity foo)
           :exec (let ((val (fld foo)))
                   (update-fld val foo))))

  A new macro, [non-exec], allows the use of non-executable code, for
  example inside ordinary function definitions. Thanks to Sol Swords
  for requesting this enhancement.

  A new ``provisional certification'' process is supported that can
  allow [books] to be certified before their included sub-books have
  been certified, thus allowing for potentially much greater
  `make'-level parallelism. See [provisional-certification]. Thanks
  to Jared Davis for requesting this feature and for helpful
  discussions, based in part on rudimentary provisional certification
  schemes that he developed first at Rockwell Collins and later for
  his `Milawa' project. Also, thanks to Jared and to Sol Swords for
  testing this feature and for providing a fix for a bug in a
  preliminary implementation, and thanks to Sol for providing
  performance feedback and a crucial suggestion that led to an
  improved implementation.

  Event summaries now show the names of events that were mentioned in
  [hints] of type :use, :by, or :clause-processor. See
  [set-inhibited-summary-types]. Thanks to Francisco J. Martin Mateos
  for requesting such an enhancement (actually thanks to the
  community, as his request is the most recent but this has come up
  from time to time before).

  ACL2 now stores a data structure representing the relation ``Event A
  is used in the proof of Event B.'' See [dead-events], which
  explains this data structure and mentions one application: to
  identify dead code and unused theorems. Thanks to Shilpi Goel for
  requesting such a feature and for helpful feedback.

  A new [documentation] topic provides a guide to programming with
  state; see [programming-with-state]. Thanks to Sarah Weissman for
  suggesting that such a guide might be useful, and to David Rager
  for helpful feedback on a preliminary version. There also has been
  some corresponding reorganization of the documentation as well as
  creation of additional documentation (e.g., see
  [state-global-let*]). Now, most built-in functions and macros
  commonly used in programs (as opposed to [events] like [defun], for
  example) are subtopics of a new topic --- see [ACL2-built-ins] ---
  which is a subtopic of [programming], a topic that in turn has
  considerably fewer direct subtopics than before.

  It is now possible to bind extra variables in a :USE hint, thus
  avoiding the error message: ``The formula you wish to instantiate,
  ..., mentions only the variable(s) ...''. See [lemma-instance], in
  particular the discussion of keyword :extra-bindings-ok. Thanks to
  Sol Swords for requesting such an enhancement.

  The function read-object-suppress is like read-object except that it
  avoids errors and discards the value read. See [io].

  A [stobj] may now be passed as an argument where another stobj is
  expected if the two are ``congruent''. See [defstobj], in
  particular, its discussion of the new :congruent-to keyword of
  defstobj. Thanks to Sol Swords for requesting this enhancement and
  for useful discussions contributing to its design.

  A new top-level utility has been provided that shows the assembly
  language for a defined function symbol; see [disassemble$]. Thanks
  to Jared Davis for requesting such a utility and to Shilpi Goel for
  pointing out an inconvenience with the initial implementation. Note
  that it uses the distributed book books/misc/disassemble.lisp,
  which users are welcome to modify (see [community-books]).

  The macro set-accumulated-persistence is an alias for
  [accumulated-persistence]. Thanks to Robert Krug for suggesting
  this addition.

  A new [documentation] topic lists lesser-known and advanced ACL2
  features, intended for those with prior ACL2 experience who wish to
  extend their knowledge of ACL2 capabilities. See
  [advanced-features]. Thanks to Warren Hunt and Anna Slobodova for
  requesting such information.

  A new macro, [deftheory-static], provides a variant of [deftheory]
  such that the resulting theory is the same at [include-book] time
  as it was at [certify-book] time. Thanks to Robert Krug for helpful
  discussions on this new feature and for updating his
  books/arithmetic-5/ distributed books to use this feature.

  A new event, [defabsstobj], provides a new way to introduce
  single-threaded objects (see [stobj] and see [defstobj]). These
  so-called ``abstract [stobj]s'' permit user-provided logical
  definitions for primitive operations on stobjs, for example using
  an alist-based representation instead of a list-based
  representation for array fields. Moreover, the proof obligations
  guarantee that the recognizer is preserved; hence the
  implementation avoids executing the recognizer, which may be an
  arbitrarily complex invariant that otherwise would be an expensive
  part of [guard] checks. Thanks to Warren Hunt for a request leading
  us to design and implement this new feature, and thanks to Rob
  Sumners for a request leading us to implement a related utility,
  [defabsstobj-missing-events]. See [defabsstobj]. Also thanks to Sol
  Swords for sending an example exhibiting a bug in the initial
  implementation, which has been fixed.

  A new command, :psof , is like :pso but directs proof
  replay output to the specified file. For large proofs, :[psof] may
  complete much more quickly than :[pso]. see [psof]. More generally,
  a new utility, [wof] (an acronym for ``With Output File''), directs
  standard output and proofs output to a file; see [wof].

  The new macro [defnd] defines a function with :[guard] t and
  [disable]s that function, in analogy to how [defund] defines with
  [defun] and then [disable]s. Thanks to Shilpi Goel for requesting
  this feature.

  The :[pl2] command now shows :[linear] rules; and a new
  [proof-checker] command, show-linears (equivalently, sls), is an
  analogue of the [proof-checker] show-rewrites (sr) command, but for
  [linear] rules. Thanks to Shilpi Goel for requesting this new
  proof-checker command. Finally, a corresponding new proof-checker
  command, apply-linear (al), is an analogue of the [proof-checker]
  rewrite (r) command, but for [linear] rules.

  The macros [add-macro-fn] and [remove-macro-fn] replace macros
  [add-binop] and [remove-binop], respectively, though the latter
  continue to work. The new macros allow you to decide whether or not
  to display calls of binary macros as flat calls for
  right-associated arguments, e.g., (append x y z) rather than
  (append x (append y z)). See [add-macro-fn].

  It is now possible to request that the host Lisp compiler inline
  calls of specified functions, or to direct that the host Lisp
  compiler not inline such calls. See [defun-inline] and see
  [defun-notinline]. We thank Jared Davis for several extensive,
  relevant conversations, and for finding a bug in a preliminary
  implementation. We also thank others who have engaged in
  discussions with us about inlining for ACL2; besides Jared Davis,
  we recall such conversations with Rob Sumners, Dave Greve, and
  Shilpi Goel.

  HEURISTIC IMPROVEMENTS

  Reading of ACL2 [arrays] (see [aref1], see [aref2]) has been made
  more efficient (as tested with CCL as the host Lisp) in the case of
  consecutive repeated reads of the same named array. Thanks to Jared
  Davis and Sol Swords for contributing this improvement.

  Slightly modified the induction schemes stored, so that calls of
  so-called ``guard-holders'' (such as [mbe] and [prog2$] --- indeed,
  any call of [return-last] --- and [the]) are expanded away. In
  particular, calls of equality variants such as [member] are treated
  as their corresponding function calls, e.g., [member-equal]; see
  [equality-variants]. Guard-holders are also now expanded away
  before storing [constraint]s for [encapsulate] [events], which can
  sometimes result in simpler constraints.

  Improved the performance of [dmr] (technical note: by modifying raw
  Lisp code for function dmr-flush, replacing finish-output by
  force-output).

  We now avoid certain rewriting loops. A long comment about this
  change, including an example of a loop that no longer occurs, may
  be found in source function expand-permission-result.

  Slightly strengthened [type-set] reasoning at the level of literals
  (i.e., top-level hypotheses and conclusions). See the comment in
  ACL2 source function rewrite-atm about the ``use of dwp = t'' for
  an example of a theorem provable only after this change.

  Strengthened the ability of [type-set] reasoning to make deductions
  about terms being integers or non-integer rationals. The following
  example illustrates the enhancement: before the change, no
  simplification was performed, but after the change, the conclusion
  simplifies to (foo t). Thanks to Robert Krug for conveying the
  problem to us and outlining a solution.

    (defstub foo (x) t)
    (thm ; should reduce conclusion to (foo t)
     (implies (and (rationalp x)
                   (rationalp y)
                   (integerp (+ x (* 1/3 y))))
              (foo (integerp (+ y (* 3 x))))))

  BUG FIXES

  Fixed a class of soundness bugs involving each of the following
  functions: [getenv$], [get-wormhole-status], [cpu-core-count],
  [wormhole-p], [random$], file-write-date$, and serialize-read-fn,
  and (for the HONS version of ACL2) [clear-memoize-table] and
  [clear-memoize-tables] as well as (possible soundness bug)
  serialize-write-fn. For example, we were able to admit the
  following events, but that is no longer the case (neither for
  getenv$ as shown, nor analogously for other functions listed
  above).

    (defthm not-true
      (stringp (cadr (getenv$ \"PWD\" (build-state))))
      :rule-classes nil)

    (defthm contradiction
      nil
      :hints ((\"Goal\"
               :in-theory (disable (getenv$))
               :use not-true))
      :rule-classes nil)

  Fixed a soundness bug involving with-live-state, which could cause an
  error in the use of [add-include-book-dir] or
  [delete-include-book-dir] in a book or its [portcullis] commands.
  See [with-live-state], as the documentation for this macro has been
  updated; in particular it is now untouchable (see
  [remove-untouchable]) and is intended only for system hackers.
  Thanks to Jared Davis for reporting a bug in the use of
  [add-include-book-dir] after our first attempt at a fix.

  Fixed a soundness bug based on the use of [skip-proofs] together with
  the little-used argument k=t for [certify-book]. An example proof
  of nil appears in a comment in the ACL2 sources, in (deflabel
  note-5-0 ...).

  Fixed a soundness bug that allowed users to define new
  [proof-checker] primitive commands. Before this fix, a book proving
  nil could be certified, as shown in a comment now in the
  introduction of the [table] pc-command-table in source file
  proof-checker-a.lisp.

  (Technical change, primarily related to [make-event]:) Plugged a
  security hole that allowed [books]' [certificate]s to be
  out-of-date with respect to [make-event] expansions, but not
  recognized as such. The change is to include the so-called
  expansion-alist in the certificate's checksum. An example appears
  in a comment in the ACL2 sources, in (deflabel note-5-0 ...).

  Fixed a bug in [guard] verification due to expanding calls of
  primitives when translating user-level terms to internal form, so
  called ``translated terms'' (see [term]). While we have not
  observed a soundness hole due to this bug, we have not ruled it
  out. Before the bug fix, the following event was admissible, as
  guard verification succeeded (but clearly should not have).

    (defun f ()
      (declare (xargs :guard t))
      (car (identity 3)))

  For those who want details about this bug, we analyze how ACL2
  generates [guard] proof obligations for this example. During that
  process, it evaluates ground subexpressions. Thus, (identity '3) is
  first simplified to '3; so a term must be built from the
  application of car to '3. Guard-checking is always turned on when
  generating guard proof obligations, so now, ACL2 refuses to
  simplify (car '3) to 'nil. However, before this bug fix, when ACL2
  was building a term by applying car to argument '3, it did so
  directly without checking guards; source code function cons-term is
  `smart' that way. After the fix, such term-building reduction is
  only performed when the primitive's guard is met.

  While calls of many event macros had been prohibited inside
  executable code, others should have been but were not. For example,
  the following was formerly allowed.

    (defun foo (state)
      (declare (xargs :mode :program :stobjs state))
      (add-custom-keyword-hint :my-hint (identity nil)))
    (foo state) ; Caused hard raw Lisp error!

  Thus, several event macros (including for example
  [add-custom-keyword-hint]) may no longer be called inside
  executable code.

  Fixed an assertion that could occur, for example, after reverting to
  prove the original goal by induction and generating a goal of NIL.
  Thanks to Jared Davis for sending us a helpful example to bring
  this bug to our attention.

  It was possible for [defstobj] to generate raw Lisp code with
  excessively restrictive type declarations. This has been fixed.
  Thanks to Warren Hunt for reporting this bug and sending an example
  that illustrates it. See [stobj-example-2] for examples of such raw
  Lisp code; now, one finds (and fixnum (integer 0 *)) where formerly
  the type was restricted to (integer 0 268435455).

  Fixed a bug in that was ignoring the use of
  :computed-hint-replacement in certain cases involving a combination
  of computed hints and custom keyword hints. Thanks to Robert Krug
  for reporting this bug and sending a very helpful example.

  Fixed a bug in the output from [defattach], which was failing to list
  previous [events] in the message about ``bypassing constraints that
  have been proved when processing the event(s)''.

  (GCL only) Fixed a bug in [set-debugger-enable] (which was only a bug
  in GCL, not an issue for other host Lisps).

  Fixed ACL2 trace output to indent properly for levels above 99 (up to
  9999). Thanks to Warren Hunt for bringing this bug to our
  attention.

  Fixed a bug in the reporting of times in event summaries --- probably
  one that has been very long-standing! The times reported had often
  been too small in the case of compound [events], notably
  [include-book]. Thanks to everyone who reported this problem (we
  have a record of emails from Eric Smith and Jared Davis on this
  issue).

  Fixed a bug in :expand [hints], where the use of :lambdas could
  prevent other parts of such a hint. For example, the following
  invocation of [thm] failed before this fix was made.

    (defund foo (x) (cons x x))
    (thm (equal (car (foo x)) x)
    :hints ((\"Goal\" :expand (:lambdas (foo x)))))

  Certain ``program-only'' function calls will now cause hard Lisp
  errors. (The rather obscure reason for this fix is to support
  logical modeling of the ACL2 evaluator. A relevant technical
  discussion may be found in source function oneify-cltl-code, at the
  binding of variable fail_program-only-safe.)

  There was an unnecessary restriction that [flet]-bound functions must
  return all [stobj]s among their inputs. For example, the following
  definition was rejected because state was not among the outputs of
  h. This restriction has been removed.

    (defun foo (state)
      (declare (xargs :stobjs state))
      (flet ((h (state) (f-boundp-global 'x state)))
        (h state)))

  We fixed a bug, introduced in the preceding release (Version 4.3), in
  the check for irrelevant formals (see [irrelevant-formals]). That
  check had been too lenient in its handling of lambda ([let])
  expressions, for example allowing the following definition to be
  admitted in spite of its first formal parameter obviously being
  irrelevant.

    (defun foo (x clk)
      (if (zp clk)
          :diverge
        (let ((clk (1- clk)))
          (foo x clk))))

  Fixed a bug in the mini-proveall target in GNUmakefile. The fix
  includes a slight change to the :mini-proveall [command] (an extra
  event at the end). Thanks to Camm Maguire for reporting this bug.

  Fixed a bug that occurred when [certify-book] was called after using
  [set-fmt-soft-right-margin] or [set-fmt-hard-right-margin] to set a
  small right margin.

  Fixed [set-inhibit-warnings] so that it takes effect for a subsequent
  [include-book] event. Thanks to Jared Davis and David Rager for
  queries that led to this fix.

  Hard Lisp errors are now avoided for certain :[rewrite] rules: those
  whose [equivalence] relation is other than equal when the rule is
  originally processed, but is no longer a known equivalence relation
  when the rule is to be stored. Thanks to Jared Davis for sending a
  useful example, a minor variant of which is included in a comment
  in source function interpret-term-as-rewrite-rule (file
  defthm.lisp).

  Fixed a bug in the ACL2 evaluator (source function raw-ev-fncall),
  which was unlikely to be exhibited in practice.

  Fixed a hard Lisp error that could occur for ill-formed :[meta]
  [rule-classes], e.g., (:meta :trigger-fns '(foo)).

  It is now an error to include a [stobj] name in the :renaming alist
  (see [defstobj]).

  Some bogus warnings about non-recursive function symbols have been
  eliminated for rules of class :[type-prescription].

  (Allegro CL host Lisp only) Fixed an obsolete setting of compiler
  variable comp:declared-fixnums-remain-fixnums-switch, which may
  have been responsible for intermittent (and infrequent) checksum
  errors encountered while including books during certification of
  the regression suite.

  Fixed a [proof-checker] bug that could result in duplicate goal names
  in the case of forced hypotheses. An example showing this bug,
  before the fix, appears in a comment in the ACL2 sources, in
  (deflabel note-5-0 ...).

  We fixed a bug in a prover routine involved in [type-set]
  computations involving linear arithmetic. This bug has been around
  since at least as far back as Version_3.3 (released November,
  2007). We are not aware of any resulting unsoundness, though it did
  have the potential to weaken the prover. For example, the following
  is proved now, but was not proved before the bug was fixed.

    (thm
     (implies (and (rationalp x)
                   (rationalp y)
                   (integerp (+ (* 1/3 y) x)))
              (integerp (+ y (* 3 x))))
     :hints ((\"Goal\" :in-theory (disable commutativity-of-+))))

  Although all bets are off when using redefinition (see
  [ld-redefinition-action]), we wish to minimize negative effects of
  its use, especially raw Lisp errors. The examples below had caused
  raw Lisp errors, but no longer.

    (defstobj st fld :inline t)
    (redef!)
    (defstobj st new0 fld)
    (u)
    (fld st) ; previously an error, which is now fixed

    ; Fresh ACL2 session:
    (redef!)
    (defun foo (x) x)
    (defmacro foo (x) `(quote ,x))
    (u)

    ; Fresh ACL2 session:
    (redef!)
    (defmacro foo (x) (cons 'list x))
    (defun foo (x) x)

  Fixed a bug that could cause hard Lisp errors in an [encapsulate]
  event. Thanks to Sol Swords for sending an example that exhibited
  this bug. Here is a simpler such example; the bug was in how it was
  checked whether the [guard] for a guard-verified function (here, g)
  depends on some function introduced in the [signature] of the
  [encapsulate] (here, the function f).

    (encapsulate
     ((f (x) t))
     (local (defun f (x) (declare (xargs :guard t)) x))
     (defun g (x)
       (declare (xargs :guard (if (integerp x) (f x) t)))
       x))

  Fixed a bug in mfc-relieve-hyp that we believe could prohibit its use
  on the last hypothesis. Thanks to Sol Swords for reporting this bug
  and providing a fix.

  The syntax #! (see [sharp-bang-reader]) was broken after a skipped
  readtime conditional. For example, the following input line caused
  an error.

    #+skip #!acl2(quote 3)

  This bug has been fixed.

  Fixed a bug in the [break-rewrite] utility, which was evidenced by
  error messages that could occur when dealing with free variables.
  An example of such an error message is the following; we thank
  Robert Krug for sending us an example that produced this error and
  enabled us to produce a fix.

    HARD ACL2 ERROR in TILDE-@-FAILURE-REASON-PHRASE1:  Unrecognized failure
    reason, ((MEM-ARRAY . X86) (ADDR QUOTE 9)).

  We fixed an obscure bug that we believe could interfere with
  [defproxy] because of an incorrect (declaim (notinline ))
  form.

  CHANGES AT THE SYSTEM LEVEL AND TO DISTRIBUTED BOOKS

  Improvements have been made related to the reading of characters. In
  particular, checks are now done for ASCII encoding and for the
  expected [char-code] values for Space, Tab, Newline, Page, and
  Rubout. Also, an error no longer occurs with certain uses of
  non-standard characters. For example, it had caused an error to
  certify a book after a single [portcullis] [command] of (make-event
  `(defconst *my-null* ,(code-char 0))); but this is no longer an
  issue. Thanks to Jared Davis for helpful correspondence that led us
  to make these improvements.

  The character encoding for reading from files has been fixed at
  iso-8859-1. See [character-encoding]. Thanks to Jared Davis for
  bringing this portability issue to our attention (as this change
  arose in order to deal with a change in the default character
  encoding for the host Lisp, CCL), and pointing us in the right
  direction for dealing with it. In many cases, the character
  encoding for reading from the terminal is also iso-8859-1; but this
  is not guaranteed. In particular, when the host Lisp is SBCL this
  may not be the case.

  Although the HTML documentation is distributed with ACL2, it had not
  been possible for users to build that documentation without
  omitting graphics, for example on the ACL2 home page. That has been
  fixed, as files graphics/*.gif are now distributed.

  Compiler warnings are suppressed more completely than they had been
  before. For example, the following had produced a compiler warning
  when the host Lisp is CCL, but no longer does so.

    (defun f () (car 3))
    (trace$ f)

  Removed support for ``tainted'' [certificate]s. One reason is that
  there are rarely incremental releases. A stronger reason is that
  for the compatibility of a new release is with the previous
  non-incremental release, it's not particularly relevant whether or
  not the new release is incremental.

  The `make' variable BOOKS can now be defined above the line that
  includes Makefile-generic. (For relevant background, see
  [books-certification-classic].)

  (SBCL only) ACL2 images built on SBCL now have an option,
  --dynamic-space-size 2000, that can avoid space problems that could
  previously have caused the session to die.

  The default value for variable LISP in file GNUmakefile is now ccl.
  Thus, if you use `make' in the standard way to build an ACL2
  executable, the default host Lisp is ccl rather than gcl.

  EMACS SUPPORT

  EXPERIMENTAL VERSIONS

  For the version supporting the reals, ACL2(r) (see [real]), the
  supporting function floor1 has been defined in raw Lisp. This
  avoids an error such as in the following case.

    (defun f () (declare (xargs :guard t)) (floor1 8/3))
    (f) ; had caused raw Lisp error, before the fix

  Among the enhancements for the parallel version, ACL2(p) (see
  [parallelism]), are the following. We thank David Rager for his
  work in developing ACL2(p) and these improvements in particular.

      The macro set-parallel-evaluation has been renamed
      [set-parallel-execution].

      Calls of the macro [set-waterfall-printing] are no longer [events],
      so may not be placed at the top level of [books]. However, it
      is easy to create events that have these effects; see
      [set-waterfall-printing]. Note that now, :[ubt] and similar
      commands do not change the settings for either
      waterfall-parallelism or waterfall-printing.

      The implementation of [deflock] has been improved. Now, the macro it
      defines can provide a lock when invoked inside a
      [guard]-verified or :[program] mode function. Previously, this
      was only the case if the function definition was loaded from
      raw Lisp, typically via a compiled file.

      The underlying implementation for waterfall parallelism (see
      [set-waterfall-parallelism]) has been improved. As a result,
      even the largest proofs in the regression suite can be run
      efficiently in :resource-based waterfall parallelism mode.
      Among these improvements is one that can prevent machines from
      rebooting because operating system limits have been exceeded;
      thanks to Robert Krug for bringing this issue to our attention.

      There is also a new flag for configuring the way waterfall
      parallelism behaves once underlying system resource limits are
      reached. This flag is most relevant to :full waterfall
      parallelism. see [set-total-parallelism-work-limit] for more
      information.

      The [dmr] utility has the same behavior in ACL2(p) as it has in ACL2
      unless waterfall-parallelism has been set to a non-nil value
      (see [set-waterfall-parallelism]), in which case statistics
      about parallel execution are printed instead of the usual
      information.

      The user can now build the regression suite using waterfall
      [parallelism]. See the distributed file
      acl2-customization-files/README for details, and see
      [unsupported-waterfall-parallelism-features] for a disclaimer
      related to building the regression suite using waterfall
      parallelism.

      When building ACL2 with both the hons and parallelism extensions
      (what is called ``ACL2(p)'' or, equivalently, ``ACL2(hp)''),
      the functions that are automatically memoized by the hons
      extension are now automatically unmemoized and memoized when
      the user toggles waterfall parallelism on and off,
      respectively.

      Calling [set-waterfall-parallelism] with a flag of t now results in
      the same settings as if it were called with a flag of
      :resource-based, which is now the recommended mode for
      waterfall parallelism. Thanks to Shilpi Goel for requesting
      this feature.

      The prover now aborts in a timely way in response to interrupts
      issued during a proof with waterfall parallelism enabled. (This
      had often not been the case.) Thanks to Shilpi Goel for
      requesting this improvement.

  Among the enhancements for the HONS extension (see
  [hons-and-memoization]) are the following.

      The compact-print code has been replaced by new serialization
      routines contributed by Jared Davis. This may improve
      performance when including books that contain [make-event]s
      that expand to very large constants. You can also now save
      objects to disk without going into raw lisp; see [serialize]
      for details.

      Printing of certain messages has been sped up (by using Lisp function
      force-output in place of finish-output). Thanks to Jared Davis
      for contributing this improvement.

      [Stobj] array writes are perhaps twice as fast.

      It is now permitted to [memoize] functions that take user-defined
      [stobj]s as inputs, provided that no [stobj]s are returned.
      Even if stobjs are returned, memoization is permitted provided
      the condition is nil, as when profiling (see [profile]). Thanks
      to Sol Swords for an observation that led to this improvement
      and for useful conversations, including follow-up leading us to
      improve our initial implementation.

      Fixes have been made for memoizing with a non-nil value of
      :ideal-okp. Errors had occurred when memoizing with a
      :condition other than t for a :[logic] mode function that had
      not been [guard]-verified, even with a non-nil value of
      :ideal-okp; and after successfully memoizing such a function
      (without such :condition), it had not been possible to
      [unmemoize] it. Thanks to Sol Swords for reporting issues with
      the :ideal-okp argument of [memoize].

      If a book defined a function that was subsequently [memoize]d in that
      book, the function would no longer behaves as memoized upon
      completion of book certification (unless that [certify-book]
      command was undone and replaced by evaluation of a
      corresponding [include-book] command). This has been fixed.
      Thanks to David Rager for pointing out the problem by sending
      an example.

      We now support ACL2(h) built not only on 64-bit CCL but also on all
      supported host Ansi Common Lisps (i.e., all supported host
      Lisps except GCL). Thanks to Jared Davis for doing much of the
      work to make this improvement. Note that performance will
      likely be best for 64-bit CCL; for some Lisps, performance may
      be much worse, probably depending in part on the underlying
      implementation of hash tables.")
 (NOTE-6-0
  (RELEASE-NOTES)
  "ACL2 Version 6.0 (December, 2012) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes since Version 5.0 into the
  following categories of changes: existing features, new features,
  heuristic improvements, bug fixes, changes at the system level,
  Emacs support, and experimental versions. Each change is described
  in just one category, though of course many changes could be placed
  in more than one category.

  NOTE. But we start with one major change that is outside the usual
  categories:

  LICENSE change

  The ACL2 license has been changed from GPL Version 2 to a 3-clause
  BSD license, found in the LICENSE file distributed with ACL2.

  CHANGES TO EXISTING FEATURES

  Function [fmt-to-string] and similar functions (see
  [printing-to-strings]) now use the default right margin settings;
  formerly the right margin had been set at 10,000. If you want the
  former behavior, you can use the :fmt-control-alist, as illustrated
  below.

    (fmt-to-string \"~x0\"
                   (list (cons #\\0 (make-list 30)))
                   :fmt-control-alist
                   `((fmt-soft-right-margin . 10000)
                     (fmt-hard-right-margin . 10000)))

  The use of attachments (see [defattach]) has been made more
  efficient, avoiding some low-level checks (Common Lisp `boundp'
  checks). Thanks to Shilpi Goel for constructing an example that we
  used to help direct us to remove inefficiency. The following
  results for that example --- a Fibonacci program run on a machine
  interpreter in raw-mode (see [set-raw-mode]) --- give a sense of
  the potential speedup, though we note that a full ACL2(h)
  regression showed no significant speedup.

    ; Time before the change:
    ; 0.89 seconds realtime, 0.90 seconds runtime

    ; Time after the change:
    ; 0.75 seconds realtime, 0.75 seconds runtime

    ; Time when cheating to avoid the cost of attachments, by redefining a
    ; function to BE its attachment (so, this gives a lower bound on possible
    ; execution time):
    ; 0.72 seconds realtime, 0.72 seconds runtime

  Functions read-acl2-oracle and read-acl2-oracle@par are no longer
  untouchable (see [remove-untouchable]). We reported this change for
  Version_5.0 but it was not made; thanks to Jared Davis for bringing
  this to our attention. Function get-timer also is no longer
  untouchable.

  The function [butlast] now behaves more reasonably on arguments
  violating its [guard]. For example, (butlast '(1 2 3) -1) is now
  provably equal to (1 2 3) instead of to (1 2 3 nil). Thanks to
  Jared Davis for suggesting a change to the definition of butlast.

  The utilities mfc-ts and mfc-ap (see [extended-metafunctions])
  formerly never used forcing (see [force]). Now, by default, forcing
  is allowed during execution of these functions if and only if it is
  permitted in the rewriting environment where they are called.
  Moreover, these and the mfc-xx utilities --- mfc-rw, mfc-rw+, and
  mfc-relieve-hyp --- are now macros that take (optional) keyword
  arguments :forcep and :ttreep. The :forcep argument is :same by
  default, providing the forcing behavior inherited from the
  environment (as described above); but it can be the symbol t or
  nil, indicating that forcing is to be enabled or disabled,
  respectively. The :ttree argument is nil by default, but when it is
  t, then a second value is returned, which is a tag-tree. See
  [extended-metafunctions].

  Many improvements have been made to the tau-system (see
  [tau-system]), including support for arithmetic intervals bounded
  by constants. Thus, for example, (and (<= 0 x) (<= x 15)) is a tau
  predicate. The [documentation] has also been improved (see
  [introduction-to-the-tau-system]). Also see [time-tracker-tau] for
  discussion of how the new [time-tracker] utility can help discover
  ways to detect slowdown related to the tau-system.

  The [defthm] [events] printed by [defabsstobj], namely those that
  remain to be proved, are now given with :rule-classes nil since
  there is probably no intention to use them as rules. Thanks to
  Robert Krug for suggesting that we consider this change.

  The formal parameters for a macro definition (see [defmacro]) may now
  include [state] and user-defined [stobj]s. (However, macro formals
  may not be declared as stobjs; see [xargs].) Thanks to Jose Luis
  Ruiz-Reina for raising this issue and to Rob Sumners for helpful
  conversations --- both of these nearly 10 years ago!

  The utilities [defun-inline], [defun-notinline], [defund-inline], and
  [defund-notinline] have been simplified, by taking advantage of the
  lifting of restrictions on formal parameters of macro definitions
  mentioned above (involving symbols that happen to be [stobj]
  names). Now, when any of the above four utilities is called with a
  given set of formal parameters, those formals will be used not only
  for the generated [defun] event but also for the generated
  [defmacro] event. (Previously, they had been renamed for the
  [defmacro] event in order to respect the stobj name restriction
  that no longer exists.) Thanks to Jared Davis for pointing out the
  value of making this change.

  The [events] [add-invisible-fns] and [remove-invisible-fns] now
  convert arguments as appropriate using the [macro-aliases-table].
  For example, the event (add-invisible-fns append car) is now legal
  (though probably not a good idea), because add-invisible-fns is now
  sensitive to the fact that [append] maps to [binary-append] in the
  [macro-aliases-table].

  When :pe is applied to a built-in function that does not have a
  defining event, such as [symbolp], :pe now gives more useful output
  that points to the documentation instead of printing a call of
  ENTER-BOOT-STRAP-MODE. Thanks to Anthony Knape for bringing this
  issue to our attention.

  The macros [memoize] and [unmemoize] now cause a warning rather than
  an error in ACL2 (and work as before in ACL2(h)).

  Terms are now parsed into :[type-prescription] rules in a manner that
  removes [let] bindings both at the top level and in the conclusion
  (but still not in the hypotheses of the rule). See
  [type-prescription]. Thanks to Jared Davis for requesting such an
  enhancement.

  Printing of numbers is now appropriately sensitive to the print
  radix; see [set-print-radix]. Thanks to Shilpi Goel for requesting
  this enhancement.

  The system function explode-atom no longer includes the radix
  indicator. The new function explode-atom+ may be used for that
  purpose.

  NEW FEATURES

  Among the new features for system hackers are analogues of system
  function simple-translate-and-eval that do not return [state].
  (Thanks to David Rager for requesting this feature and helpful
  conversations on its implementation.) This and other low-level
  changes are typically documented in comments in the corresponding
  release note event, which in this case is (deflabel note-6-0 ...).

  More built-in functions are now [guard]-verified (and in :[logic]
  mode). Furthermore, a mechanism exists for marking yet more
  built-in functions as guard-verified based on [books] contributed
  by users; see Part II of
  {http://www.cs.utexas.edu/users/moore/acl2/open-architecture/ |
  http://www.cs.utexas.edu/users/moore/acl2/open-architecture/}. The
  current state of that enterprise may be viewed by evaluating the
  constant *system-verify-guards-alist*, which associates a community
  book name with a list of functions. When ACL2 is built in the
  normal way, each of those functions is marked as guard-verified
  when ACL2 is started up; but a special developer build can be used
  to check that the indicated book, together with its sub-books,
  proves that those functions are guard-verified.

  Metatheorems (see [meta]) may now have additional hypotheses, called
  ``meta-extract hypotheses'', that allow metafunctions to depend on
  the validity of certain terms extracted from the context or the
  logical [world]. See [meta-extract]. Thanks to Sol Swords for
  providing an initial implementation, together with very helpful
  discussions as well as a community book,
  books/clause-processors/meta-extract-user.lisp, that extends the
  power of meta-extract hypotheses.

  New utilities [oracle-funcall], [oracle-apply], and
  [oracle-apply-raw] call a function argument on specified arguments.
  Thanks to Jared Davis for requesting this utility.

  A new utility makes it convenient to track time spent inside
  specified function calls or, more generally, during specified
  evaluation. See [time-tracker].

  New runic designators make it easy to refer to macro names when
  building theories. Thus, for example, the object (:i append) may be
  used in theory expressions to designate the [rune] (:induction
  binary-append). See [theories]. Thanks to Jared Davis for a useful
  discussion leading to this enhancement.

  [Defabsstobj] [events] now take an optional :congruent-to keyword
  argument, much like [defstobj]. Thanks to Sol Swords for requesting
  this feature and for suggesting a very nice optimization that
  avoids the need to prove additional lemmas.

  [Flet] may now include inline and notinline declarations. Thanks to
  Jared Davis for requesting this feature.

  The utility gc-verbose controls printing of messages by the garbage
  collector, for certain host Lisps. See [gc-verbose]. Thanks to
  Shilpi Goel for requesting this utility.

  Added definitions of functions [nat-listp] and [ACL2-number-listp].
  Thanks to Harsh Raju Chamarthi for requesting these additions. Many
  community books had varying definitions of these functions; these
  additions guarantee that all books must agree on how these two
  functions are defined. (Some community books have been changed in
  order that they remain certifiable, given these additions.) Note
  that a few built-in :[forward-chaining] rules were modified in
  order to accommodate these additions, and the definition of
  [integer-listp] was modified to call [eq] instead of [equal], like
  the other such definitions.

  See [get-command-sequence] for a new utility that returns a list of
  [command]s between two given command descriptors.

  HEURISTIC IMPROVEMENTS

  We obtained a substantial speedup --- 13% observed for the regression
  suite, and 8% observed for the ACL2(h) regression suite --- by
  tweaking the [break-rewrite] implementation to eliminate virtually
  all of its overhead when it is not in use (the default, which holds
  until :[brr] t is evaluated). Thanks to David Rager for a
  conversation involving ACL2(p) performance statistics that
  suggested looking at changing [break-rewrite] to boost performance.

  The heuristics for automatically expanding recursive function calls
  have been changed during proofs by induction. Now, during
  induction, more terms that suggested the induction scheme are
  automatically expanded. Thanks to David Rager for providing an
  example and having discussions with us that spurred us to develop
  this heuristic improvement.

  BUG FIXES

  Fixed a soundness bug in [defabsstobj] based on [guard]s that
  violated single-threadedness restrictions. Thanks to Sol Swords for
  bringing this bug to our attention and supplying a proof of nil,
  which we include as a comment in source file ld.lisp, in (deflabel
  note-6-0 ...). We also thank Sol for helpful discussions about
  [guard]s of functions introduced by defabsstobj, which has led us
  to enhance the [documentation]; see [defabsstobj].

  Fixed a soundness bug in [defabsstobj] based on interrupted updates
  of abstract stobjs. As part of the fix a new keyword, :PROTECT, has
  been introduced for defabsstobj exports, along with a new top-level
  defabsstobj keyword, :PROTECT-DEFAULT; see [defabsstobj]. We do
  some analysis that we expect will avoid the use of :PROTECT in many
  cases, which is fortunate since the use of :PROTECT t may cause a
  slight slowdown in (abstract) stobj updates. Thanks to Sol Swords
  for bringing this bug to our attention and supplying a proof of
  nil, which we include as a comment in source file
  other-events.lisp, in the definition of function
  set-absstobj-debug.

  Fixed a raw Lisp error that occurred when tracing a stobj resize
  function, thanks to an error report from Warren Hunt, Marijn Heule,
  and Nathan Wetzler.

  Fixed a raw Lisp error that occurred for certain ill-formed
  signatures, as in the following example.

    ACL2 !>(encapsulate
               (((f (*) => * :guard t)))
               (local (defun f (x) (consp x))))

    ***********************************************
    ************ ABORTING from raw Lisp ***********
    Error:  value (F (*) => * :GUARD T) is not of the expected type SYMBOL.
    ***********************************************

  The notion of ``error triple'' (see [error-triples]) had been
  implemented ambiguously, with the result that for a [stobj], st,
  the result of evaluating the following two forms was the same: (mv
  nil st state) and (mv t st state). Of course, these are just
  examples; in general, a result of (mv erp val state) was sometimes
  treated as an error triple even when val is a [stobj]. Now, (mv erp
  val state) is an error triple only when erp and val are ordinary
  (non-[stobj]) values. Thanks to Warren Hunt and Marijn Heule for
  bringing this problem to our attention.

  The ``with-error-trace'' utility, [wet], now works in the non-error
  case when given a form that returns multiple values. (Note however
  that [state] will be printed as REPLACED-STATE; and similarly, a
  user-defined [stobj], say ST, will be printed as REPLACED-ST.)

  Some possible error messages for [defabsstobj] have been fixed that
  had been ill-formed. Thanks to Sol Swords for bringing this bug to
  our attention.

  Fixed a bug that sometimes caused the times displayed in the summary
  for [certify-book] to be smaller than the actual times.

  Fixed a bug in the [guard]s to system functions fmt-char and fmt-var,
  which are no longer :[logic]-mode, guard-verified functions.

  (GCL only) Fixed a bug present in Gnu Common Lisp for #u (see
  [sharp-u-reader]).

  CHANGES AT THE SYSTEM LEVEL

  The [state] global variable 'distributed-books-dir has been renamed
  'system-books-dir. On a related note, the [documentation] now
  refers to ``community books'' rather than ``distributed books'',
  and there is a corresponding new documentation topic; see
  [community-books].

  Fixed a bug in the implementation of [wet] (which is actually in the
  community book books/misc/wet.lisp).

  A directory, interface/, is no longer part of the ACL2 distribution.
  Rather, it is a subdirectory of the ACL2 community books. Thus, if
  you fetch those books in the usual way (see the installation
  instructions on the ACL2 home page), you will find a directory
  books/interface/. Subdirectory emacs/ of that interface directory
  provides Emacs support for [proof-tree]s as well an acl2-mode. This
  change has been reflected in ACL2 file emacs/emacs-acl2.el, so
  users will probably not be impacted if they load that file into
  Emacs.

  The community books file books/Makefile-generic now causes, by
  default, a backtrace to be printed when there is a raw Lisp error.

  Some changes have been made to how regressions are run, i.e., to how
  the community books are certified. (1) The standard regression now
  includes community books directory books/centaur. To skip these
  (for example, a Windows system has encountered difficulty with them
  even after installing Perl), include ACL2_CENTAUR=skip with your
  `make' command. (2) A new `make' (or environment) variable,
  ACL2_JOBS, specifies the number of parallel jobs to run, serving as
  a replacement for the -j argument of `make' that works for all
  community books, including those under directory centaur; see
  [books-certification-classic]. (3) It is no longer necessary to do
  an ACL2(h) regression in order to build a copy of the documentation
  generated by Jared Davis's xdoc utility at
  books/xdoc-impl/manual/preview.html; a vanilla ACL2 regression will
  build this manual. (4) It is no longer necessary to set the ACL2
  environment variable for ACL2(h) regressions if you want to use the
  executable saved_acl2h in the ACL2 sources directory.

  The ACL2 home page now has a search utility for documentation and
  books. Thanks to Shilpi Goel and David Rager for feedback on a
  preliminary version of this utility.

  (only for SBCL with 64-bit ACL2(h)) The value of SBCL command line
  option --dynamic-space-size for ACL2(h) on 64-bit platforms has
  been increased from 2000 to 16000 (as explained in a comment in the
  ACL2 source definition of *sbcl-dynamic-space-size*).

  EMACS SUPPORT

  EXPERIMENTAL/ALTERNATE VERSIONS

  Among the enhancements for ACL2(r) (see [real]) are the following.

      Thanks to Ruben Gamboa for his helpful role in making the following
      improvements made with Ruben Gamboa in support for non-standard
      analysis in ACL2(r).

      Constrained functions can now be introduce as non-classical. See
      [signature].

      [Defun-sk] now takes a new keyword argument, :CLASSICALP, that
      determines whether or not the named function is classical. See
      [defun-sk].

      Incorporated a bug fix from Ruben Gamboa for [ceiling]. The default
      (for `bad' arguments) had been 1, but now we follow normal ACL2
      practice by returning 0 in that case.

  Among the enhancements for the HONS extension (see
  [hons-and-memoization]) are the following.

      Macros [with-fast-alist], [with-stolen-alist], and
      [fast-alist-free-on-exit] are now defined in ACL2(h), rather
      than being defined in the community book
      \"books/centaur/misc/hons-extra.lisp\". Thanks to Jared Davis and
      Sol Swords for donating this code, and thanks to Jared for
      helpful discussions leading to this change.

  Among the enhancements for ACL2(p) (see [parallelism]) are the
  following. We thank David Rager for his work in developing ACL2(p)
  and for his helpful role in these improvements.

      A bug has been fixed that could leave one in a [wormhole], awaiting
      input, after an error, such as an error in an :in-theory hint
      during a proof. Thanks to Shilpi Goel for bringing this bug to
      our attention.

      A key checkpoint for a given goal is now printed only once.
      Previously, if a key checkpoint led to more than one goal
      pushed for proof by induction, the key checkpoint would be
      printed once for each such goal during the proof, and also once
      for each such goal in the summary at the end.")
 (NOTE-6-1
  (RELEASE-NOTES)
  "ACL2 Version 6.1 (February, 2013) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes since Version 6.0 into the
  following categories of changes: existing features, new features,
  heuristic improvements, bug fixes, changes at the system level,
  Emacs support, and experimental versions. Each change is described
  in just one category, though of course many changes could be placed
  in more than one category.

  CHANGES TO EXISTING FEATURES

  More system functions are in :[logic] mode, [guard]-verified.
  Evaluate

    (strip-cars (cdr (assoc-equal \"system/top\" *system-verify-guards-alist*)))

  for the list of functions checked to be guard-verifiable in the
  community books. Thanks to those who have contributed to this
  effort, as shown in file headers in directory system/ of the
  community books.

  The macro [defund] now avoids an error when :mode :program has been
  specified in an [xargs] form of a [declare] form, for example:
  (defund f (x) (declare (xargs :mode :program)) x). It does this by
  avoiding the generation of [in-theory] [events] in such cases.
  Thanks to David Rager and Jared Davis for requesting such a change,
  and for ensuing helpful discussions.

  Added a field :UNIFY-SUBST to metafunction contexts (see
  [extended-metafunctions]), accessed with function mfc-unify-subst.
  Thanks to Sol Swords for requesting this enhancement.

  The functions [sys-call] and [sys-call-status] are now
  [guard]-verified :[logic]-mode functions.

  It had been the case that if any supporter of a dependent clause
  processor (see [define-trusted-clause-processor]) is among the
  ancestors of a given formula, then it was illegal to apply
  functional instantiation (see [lemma-instance]) to that formula.
  Now, this is illegal only if some such supporter is in the domain
  of the functional substitution.

  The tau system (see [tau-system], or if you are unfamiliar with the
  tau system, see [introduction-to-the-tau-system]) now allows the
  user to define and verify functions that compute bounds on
  arithmetic expressions. See [bounders].

  The utility print-summary-user has been replaced by
  [finalize-event-user], which is described below. If you previously
  attached a function to print-summary-user, say
  my-print-summary-user, then you can get the effect you had
  previously as follows.

    (defun my-finalize-event-user (state)
      (declare (xargs :mode :logic :stobjs state))
      (prog2$ (my-print-summary-user state)
              state))
    (defattach finalize-event-user my-finalize-event-user)

  It had been the case that when you [ld] a file, the connected book
  directory (see [cbd]) was set to the canonical pathname of that
  file's directory for the duration of the LD call. This could cause
  problems, however, if the file is actually a soft link: an
  [include-book] form in the book with a relative pathname for the
  book would be resolved with respect to the absolute pathname for
  that link, which is probably not what was intended. So soft links
  are no longer followed when computing the above connected book
  directory. The following example, which is how we discovered this
  problem, may clarify. We attempted to execute the form (ld
  \"top.lisp\") using ACL2(r) (see [real]) in community books directory
  nonstd/arithmetic/, where all of the .lisp files are soft links to
  files in arithmetic/. Thus, the form (include-book \"equalities\")
  attempted to include arithmetic/equalities instead of
  nonstd/arithmetic/equalities, which caused an error.

  We no longer document the use of value :START for
  [with-prover-step-limit]. This value has always been used by the
  ACL2 implementation and may have semantics that change with new
  ACL2 versions. If you have reason to use this value, please contact
  the ACL2 implementors.

  NEW FEATURES

  By default, the prover now gives information about case splits. See
  [splitter]. Thanks to many ACL2 users, most recently David Rager,
  for requesting such a capability. Also thanks to David Rager and
  Jared Davis for helpful discussions, and thanks to Robert Krug for
  feedback on the initial implementation and documentation that led
  us to make improvements.

  New utilities [initialize-event-user] and [finalize-event-user] allow
  the user to run [state]-modifying code at the start and end of
  [events]. Thanks to Harsh Raju Chamarthi for requesting these
  capabilities. Note that [finalize-event-user] replaces
  print-summary-user.

  HEURISTIC IMPROVEMENTS

  Several heuristic improvements have been made to the tau system, even
  if you do not explicitly use the new capability for computing
  bounds on arithmetic expressions, mentioned above. See
  [tau-system], or if you are unfamiliar with the tau system, see
  [introduction-to-the-tau-system].

  BUG FIXES

  A soundness bug has been fixed that exploited the use of expansion
  files (see [book-compiled-file]) together with [defstobj]. For an
  example illustrating this bug, see the comment about
  ``Expansion/Defstobj Bug'' in the form (deflabel note-6-1 ...) in
  ACL2 source file ld.lisp.

  We fixed a soundness bug involving system function
  [canonical-pathname] and (most likely) other functions in the
  former value of constant *unattachable-primitives*. Thanks to Jared
  Davis and Sol Swords for bringing this bug to our attention by way
  of an example. We include a very slight variant of that example in
  a comment within the form (deflabel note-6-1 ...) in ACL2 source
  file ld.lisp.

  There was a soundness bug that allowed attachments to prove nil in a
  consistent logical [world] involving [defaxiom] [events]. This has
  been fixed, by requiring that no function symbol ancestral in a
  [defaxiom] formula is allowed to get an attachment. See
  [defattach], in particular discussion of ``a restriction based on a
  notion of a function symbol syntactically supporting an event'',
  which concludes with a proof of nil that is no longer possible.

  (ACL2(h) only) We fixed a soundness bug in the interaction of
  memoization with congruent stobjs, in cases where the :congruent-to
  field of [defstobj] was not the canonical representative in the
  congruence class. For an example illustrating this bug, see the
  comment about ``memoize/congruent stobj bug'' in the form (deflabel
  note-6-1 ...) in ACL2 source file ld.lisp.

  Functions defined by [defstobj] had failed to be compiled when
  certifying books, except in host Lisps that compile on-the-fly
  (CCL, SBCL). This has been fixed for all host Lisps. A related
  change, probably less significant, was made for [defabsstobj].
  Thanks to Sol Swords for reporting bugs that turned out to be
  mistakes in a preliminary implementation of this change.

  Fixed an assertion error involving linear arithmetic. Thanks to Sol
  Swords for sending an example illustrating the bug (now appearing
  as a comment in ACL2 source function linearize1).

  Fixed a bug that was breaking the ACL2s build mechanism (see
  [ACL2-sedan]) by causing certain needless evaluation of ``hidden
  [defpkg]'' forms in [certificate] files when executing a call of
  [include-book]. The bug could also affect rare error messages
  arising from ill-formed [certificate] files. Thanks to Harsh Raju
  Chamarthi for bringing this bug to our attention by sending us an
  example script of the sort that was breaking during an ACL2s build.

  Fixed handling of pathnames by some low-level code (system function
  our-truename) that could cause errors, for example for host-Lisp
  GCL on some platforms when environment variable HOME points to a
  non-existent directory. Thanks to Camm Maguire for bringing this
  issue to our attention and helping with the debugging.

  Fixed a coding bug in generation of stobj resizing functions for a
  stobj named OLD. The following example illustrates the bug.

    (defstobj old
      (fld :type (array (unsigned-byte 31) (8))
            :initially 0 :resizable t))
    (resize-fld 10 old)
    ; The following returned 8 but should have returned 10:
    (fld-length old)

  Fixed a bug in [defabsstobj-missing-events] (which macroexpanded
  incorrectly). Thanks to Sol Swords for bringing this bug to our
  attention.

  Fixed two bugs in the handling of step-limits. Thanks to Hanbing Liu
  for bringing the main such bug to our attention, which was that
  ACL2 could report a step-limit violation during [certify-book] (in
  fact, during any compound event such as a call of [encapsulate] or
  [progn]), even without direct user involvement in managing
  step-limits (see [set-prover-step-limit] and see
  [with-prover-step-limit]). The other bug was that a bad argument to
  [set-prover-step-limit] could result in a raw Lisp error, for
  example: (progn (set-prover-step-limit '(a b))).

  CHANGES AT THE SYSTEM LEVEL

  The books/ directory no longer needs to exist in order to build an
  ACL2 executable. Thanks to Robert Krug for pointing out that the
  installation instructions had suggested that this was already the
  case.

  Many changes have been made to the [community-books]. For example,
  some community books now include std/lists/rev.lisp, which contains
  the rule revappend-removal, which may cause some proofs involving
  [revappend] to fail where they formerly succeeded, or vice-versa.
  When a proof fails that formerly succeeded, it may be useful for
  you to look over the [rune]s printed in the event summary.

  EMACS SUPPORT

  EXPERIMENTAL/ALTERNATE VERSIONS

  For ACL2(p), [wormhole-eval] is now locked by default; thanks to
  David Rager for suggesting this change. But there is a way to avoid
  the lock; see [wormhole-eval]. In particular, the lock is avoided
  in the implementations of [accumulated-persistence] and
  [forward-chaining-reports], which are not supported in ACL2(p) (see
  [unsupported-waterfall-parallelism-features]).")
 (NOTE-6-2
  (RELEASE-NOTES)
  "ACL2 Version 6.2 (June, 2013) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes since Version 6.1 into the
  following categories of changes: existing features, new features,
  heuristic improvements, bug fixes, changes at the system level,
  Emacs support, and experimental versions. Each change is described
  in just one category, though of course many changes could be placed
  in more than one category.

  CHANGES TO EXISTING FEATURES

  The macro [top-level] has been changed, so that evaluation of a form
  (top-level x) results in an error when evaluation of x results in
  an error. Thanks to Jared Davis for observing that when evaluating
  a file using [ld], an interrupt of a call of a [top-level] call in
  that file would not prevent evaluation of later forms in the file.

  The macro [the] no longer causes an error when [guard]-checking is
  :NONE. For example, it had been the case that evaluation of (the
  integer t) always caused an error; but now, there is no error after
  executing command :[set-guard-checking] :NONE. Thanks to Jared
  Davis for asking for a way to avoid such errors.

  The error printed when attempting to ``reincarnate'' a package ---
  that is, to define a package that is not part of the ACL2 logical
  [world] but exists in raw Lisp because it was once part of the
  world --- is now much more instructive. In particular, it shows
  pathnames for the previous and proposed [defpkg] events, and it
  shows the symbols that are imported by one but not the other.
  Thanks to Jared Davis for requesting this improvement.

  Functions [open-input-channel] and [open-output-channel] no longer
  cause an error when failing to open a channel because of a
  permissions problem, but instead return (mv nil state). Thanks to
  Jared Davis for requesting this change. (Note: this change does not
  apply if the host Lisp is non-ANSI, i.e., if the host Lisp is
  non-ANSI GCL.)

  The advanced [meta-extract] mechanisms, provided for using facts from
  the [world] or metafunction context, have been enhanced in the
  following ways, in collaboration with Sol Swords. See
  [meta-extract] for more details.

      It is now permissible to use calls of meta-extract-global-fact in
      hypotheses of [clause-processor] rules, much as they are used
      in hypotheses of [meta] rules. See [meta-extract]. Thanks to
      Sol Swords for requesting this feature.

      The utility meta-extract-global-fact is now a macro, which expands to
      a corresponding call of the new function,
      meta-extract-global-fact+. This new function takes an
      alternate, extra [state] as an argument; it is not to be
      executed, and it operates on the alternate state, whose logical
      [world] is intended to be the same as that of the ``live''
      (usual) state.

      A new sort of value for the obj argument is supported for
      meta-extract-global-fact (and meta-extract-global-fact+), which
      results in a term equating a function application to its
      result. See [meta-extract], in particular the discussion of
      :fncall.

  It is now possible for trace$ to avoid printing prefixes of the form
  \"n> \" and \"). Now, forcing will take place as expected; see
      [force]. Thanks to Robert Krug for bringing this issue to our
      attention and sending an example, which we include as a comment
      in the ACL2 source code (see (deflabel note-6-2 ...)).

      The heuristic is now delayed until after we check whether the
      hypothesis is already known, using [type-set] reasoning alone
      (in particular, not using rewriting), to be true or to be
      false. We believe that this is now the ``right'' order for
      those two operations. We saw a slight speed up in the
      regression tests (about a percent) with this change, but that
      might be in the noise.

      A technical change makes the heuristic slightly less aggressive in
      preventing backchaining. Roughly speaking, ordering checks
      based on function symbol counts could suffice to permit
      backchaining, where now variable counts also suffice. Thanks to
      Robert Krug for showing us an example where backchaining led to
      a term with no free variables that was nevertheless subject to
      the ancestors check, preventing it from being rewritten.

      (For those who use [defattach] to attach to ancestors-check) We have
      used defrec to introduce an `ancestor' data structure. A new
      function, strip-ancestor-literals, should be used to obtain the
      literals from a list of ancestors, although strip-cars will
      still work at this time.

  When we rewrite the current literal of the current clause we assume
  the falsity of the other literals and of the conclusions produced
  by forward chaining. We have changed the order in which those
  assumptions are made, which affects the type-alist used during
  rewriting. This has three effects: the new type-alist, which is
  sometimes stronger than the old one, may allow additional rules to
  fire, the choice of free vars may be different, and the order of
  the literals in forced subgoals may be different. Should ``legacy''
  proofs fail under the new type-alist, we recommend looking for
  rules that are fired in the new proof that were not fired (on that
  same subgoal) in the old one. Thanks to Dave Greve for sending us
  an example that led us to make this change.

  BUG FIXES

  We fixed a soundness bug that could be exploited by calling system
  functions acl2-magic-mfc or acl2-magic-canonical-pathname. Thanks
  to Sol Swords for bringing this bug to our attention.

  We fixed a soundness bug in the handling of [stobj]s, in which
  strings were recognized as stobjs in raw Lisp. Thanks to Jared
  Davis for sending us a proof of nil that exploited this bug. We now
  have a much simpler example of this bug, as follows.

    (defstobj st fld)
    (defthm bad (stp \"abc\") :rule-classes nil)
    (defthm contradiction
      nil
      :hints ((\"Goal\" :in-theory (disable (stp)) :use bad))
      :rule-classes nil)

  We fixed bugs in extended metafunctions (see
  [extended-metafunctions]). The macro mfc-ap no longer takes a
  :TTREEP keyword argument, because this argument could allow
  returning a tag tree that does not properly account for forcing.
  The remaining mfc-xx macros --- mfc-relieve-hyp, mfc-rw+, mfc-rw,
  and mfc-ts --- still take a :TTREEP keyword argument, but the
  corresponding functions when :TTREEP is t ---
  mfc-relieve-hyp-ttree, mfc-rw+-ttree, mfc-rw-ttree, and
  mfc-ts-ttree --- were introduced with incorrect output signatures.
  A complication is that mfc-relieve-hyp-ttree was improperly defined
  in raw Lisp in a way that actually matched the incorrect signature!
  All of these bugs have been fixed. Perhaps any of them could have
  made it possible to prove nil, though we have not tried to do so.

  (Windows only) On Windows, it had been possible for ACL2 not to
  consider two pathnames to name the same file when the only
  difference is the case of the drive, e.g., `C:' vs. `c:'. This has
  been fixed. Thanks to Sol Swords for reporting this issue.

  Fixed a bug in the storing of rules for the tau system; see
  [tau-system]. (The error message mentions
  PARTITION-SIGNATURE-HYPS-INTO-TAU-ALIST-AND-OTHERS.) Thanks to Sol
  Swords for reporting this bug and sending a simple example to
  illustrate it.

  It had been possible to admit the missing [defthm] events printed by
  [defabsstobj], and yet get an error when subsequently submitting
  the same defabsstobj event, stating: ``Note discrepancy with
  existing formula''. The problem could occur when an expression of
  the form (or X Y) occurred in one of those missing events, because
  ACL2 created it from the term (if X 't Y) but then translated (or X
  Y) to (if X X Y), resulting in a mismatch. This has been fixed.
  Thanks to Jared Davis for reporting this bug using a simple
  example.

  A hard Lisp error was possible for certain illegal functional
  substitutions (see [lemma-instance]). Thanks to Sol Swords for
  reporting this bug.

  We fixed a bug in the case that an exported function of a
  [defabsstobj] event had a [guard] of t. Thanks to Jared Davis for
  sending a simple example when reporting this bug.

  We now avoid an infinite loop that could occur when attempting to
  close the standard character output channel (see [standard-co]).
  Instead, an error message explains how to accomplish what was
  probably intended. Thanks to Shilpi Goel for bringing this issue to
  our attention.

  (Windows only) Fixed a bug that was causing a hard error on Windows
  when ACL2 encountered filenames starting with the tilde character
  (~), for example, (ld \"~/acl2-customization.lsp\"). Thanks to Sol
  Swords for bringing this bug to our attention. Also thanks to Harsh
  Raju Chamarthi for a useful conversation that led to a better fix
  than our first one.

  CHANGES AT THE SYSTEM LEVEL

  ACL2 may now be built on recent versions of a new host Lisp, ANSI Gnu
  Common Lisp (GCL). Traditional (non-ANSI) GCL was the original host
  Lisp underlying ACL2, and we are grateful for GCL support that we
  received from the late Bill Schelter and, more recently and
  particularly for ANSI GCL, from Camm Maguire.

  The `make' process suggested for book certification has changed
  substantially, thanks in large part to contributions from Jared
  Davis and Sol Swords. We have seen the new process provide better
  performance on machines with many cores, and we expect maintenance
  advantages such as eliminating the need for Makefiles in individual
  book directories. The ``classic'' process, which was based on
  community books file books/Makefile-generic, is still supported
  (see [books-certification-classic]) but may disappear in a future
  release of ACL2. See [books-certification]. Most changes should be
  invisible to the user, other than improved `make'-level
  parallelism, with the exception of the following.

      o Variable ACL2_JOBS is no longer supported, nor is it necessary;
      simply use `make' option `-j' instead.

      o Regressions now use `make' option -k by default, which causes the
      regression to keep going after errors, rather than -i, which
      ignores errors. If you encounter problems because of this
      change, use ACL2_IGNORE=-i with your `make' command.

      o The `regression' target works for the experimental extension,
      ACL2(h) (see [hons-and-memoization]); target `regression-hons'
      no longer exists.

  Please let us know if you run into problems with the new
  infrastructure, as we consider the legacy infrastructure to be
  deprecated and we will probably eliminate much of it in the future.
  In particular, circular dependencies were formerly prohibited at
  the directory level, but that is no longer the case, and we expect
  such cycles to occur in the future.

  Although ACL2 users don't typically modify raw Lisp variables, we
  have arranged to reset Lisp variable *default-pathname-defaults* if
  necessary at startup so that it will not interfere with ACL2, in
  particular by messing up the initial connected book directory (see
  [cbd]). Thanks to Jared Davis, Sol Swords, and Raymond Toy for
  helping us to identify this issue.

  EMACS SUPPORT

  EXPERIMENTAL/ALTERNATE VERSIONS

  In ACL2(h), [print-object$] no longer uses the serialize printer
  except in system applications as before (e.g., write out .cert
  files). Thanks to Dave Greve for bringing this issue to our
  attention.

  Jared Davis contributed changes related to the [memoize] utility of
  ACL2(h), including some low-level changes as well as the following.

  o [Never-memoize] specifies that a given function should never be
  memoized.

  o Removed memoize-let, which may never have ever been used.

  o Removed the :inline keyword option to memoize, which was just an
  alias for the :recursive option.

  For ACL2(p), some anomalous behavior may no longer occur because
  prover calls (more specifically, trips through the ACL2
  ``waterfall'') will return only after all sub-computations
  (threads) have finished. Thanks to David Rager for contributing
  this improvement.

  ACL2(pr), which includes [parallelism] (as for ACL2(p)) and
  non-standard analysis support for the [real]s (as for ACL2(r)), now
  builds and can certify the community nonstd/ books. Thanks to David
  Rager for his contribution to this capability.")
 (NOTE-6-3
  (RELEASE-NOTES)
  "ACL2 Version 6.3 (October, 2013) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes since Version 6.2 into the
  following categories of changes: existing features, new features,
  heuristic improvements, bug fixes, changes at the system level,
  Emacs support, and experimental versions. Each change is described
  in just one category, though of course many changes could be placed
  in more than one category.

  CHANGES TO EXISTING FEATURES

  The evaluation of a term from a [bind-free] hypothesis had been
  expected to produce an alist binding free variables to terms. While
  that is still legal, it is also legal for that evaluation to
  produce a list of such alists: then each is considered, until one
  of them permits all remaining hypotheses to be relieved. See
  [bind-free]. Thanks to Sol Swords for requesting this enhancement.

  ACL2 continues to provide a way to specify keyword command
  abbreviations for the top-level loop; see [ld-keyword-aliases].
  However, [ld-keyword-aliases] is now a [table] rather than a
  [state] global; it is thus no longer a so-called [ld] special. The
  functionality of set-ld-keyword-aliases has essentially been
  preserved, except that it is now an event (see [events]), hence it
  may appear in a book; it is [local] to a book (or [encapsulate]
  event); and the [state] argument is optional, and deprecated. A
  non-local version (set-ld-keyword-aliases!) has been added, along
  with corresponding utilities add-keyword-alias and
  add-keyword-alias! for adding a single keyword alias. See
  [ld-keyword-aliases]. Thanks to Jared Davis for correspondence that
  led us to make this change.

  The [proof-checker] command (exit t) now exits without a query (but
  still prints an event to show the :INSTRUCTIONS). Thanks to Warren
  Hunt for feedback leading us to make this change.

  We made the following minor changes to the behavior of dmr; see
  [dmr]. First, if dmr monitoring is enabled, then (dmr-start) will
  have no effect other than to print a corresponding observation, and
  if monitoring is disabled, then (dmr-stop) will have no effect
  other than to print a corresponding observation. Second, it had
  been the case that when (dmr-start) is invoked, the debugger was
  always automatically enabled with value t (see
  [set-debugger-enable]), and the debugger remained enabled when
  (dmr-stop) was invoked. Now, the debugger is only enabled by
  (dmr-start) if it is not already enabled and does not have setting
  :never. Moreover, if such automatic enabling takes place, then the
  old setting for the debugger is restored by (dmr-stop) unless
  [set-debugger-enable] has first been called after that automatic
  enabling. Finally, if the value of [state] global variable
  'debugger-enable is :bt, then the new value will be :break-bt, not
  t.

  When a call of [progn] is executed in the ACL2 loop, its constituent
  [events] and their results are printed, just as was already done
  for calls of [encapsulate]. Thanks to Jared Davis for a
  conversation causing us to consider this change.

  (CCL only) When [set-debugger-enable] is invoked with an argument
  that prints a backtrace and CCL is the host Lisp, the backtrace
  will be limited to 10,000 stack frames. (We have seen more than
  65,000 stack frames before this change.) This limit is the value of
  raw Lisp variable *ccl-print-call-history-count*, which may be
  assigned another positive integer value to serve as the maximum
  number of stack frames to be printed.

  Improvements have been made pertaining to the disabling (inhibiting)
  of individual types of warning. Now, inhibited warnings are
  implemented in a straightforward way using a separate [table] for
  this purpose, the inhibit-warnings-table, rather than using the
  [ACL2-defaults-table]. See [set-inhibit-warnings], and see
  [set-inhibit-warnings!] for a variant that is not [local] to an
  [encapsulate] or a book in which it occurs. Thanks to Sol Swords
  for sending examples showing how [set-inhibit-warnings] did not
  always behave as one might reasonably expect when books are
  involved.

  It had been the case that [lp] took a single argument, 'raw. This
  argument was not documented and also caused an error, so it has
  been eliminated.

  The functionality of [make-event] has been significantly expanded.
  First: if the expansion is of the form (:OR e1 e2 ...), then event
  forms e1, e2, and so on are evaluated, in order, until the
  evaluation of some ek completes without error. In that case, the
  expansion is treated simply as ek. With this capability,
  alternative expansions can be attempted and the successful one does
  not need to be evaluated again. See the new version of community
  book books/make-event/proof-by-arith.lisp for an example. Second,
  an expansion may be of the form (:DO-PROOFS e), in which case the
  event e is evaluated with proofs not skipped; see
  [ld-skip-proofsp]. Third, new keyword :EXPANSION? can be used to
  avoid storing expansions in certificate files. See [make-event].

  When a [defun] event prints a failure message in the summary, that
  message now indicates when the failure is due to a failed proof of
  guard verification or a failed proof of the measure theorem. Thanks
  to Shilpi Goel for requesting this enhancement.

  NEW FEATURES

  ACL2 can now be instructed to time activities using real time (wall
  clock time) instead of run time (typically, cpu time). See
  [get-internal-time]. Thanks to Jared Davis for asking to be able to
  obtain real-time reports in event summaries.

  A new utility, [sys-call+], is similar to existing utility [sys-call]
  in that it executes a command. Unlike sys-call, however, sys-call+
  returns values that include output from the command (in addition to
  the exit status), rather than simply printing the command. See
  [sys-call+].

  The new macro [verify-guards+] extends the functionality of
  [verify-guards] by permitting macro-aliases (see
  [macro-aliases-table]). See [verify-guards+]. Thanks to Jared Davis
  for requesting this feature and suggesting the use of [make-event]
  in its implementation. We have also modified [verify-guards] to
  print a friendlier error message when its argument is a
  macro-alias.

  See [last-prover-steps] for a new utility that returns the number of
  prover steps most recently taken.

  HEURISTIC IMPROVEMENTS

  The processing of :use and :by [hints] has been changed in the
  following two rather subtle ways, thanks to suggestions from Sol
  Swords.

      o For :by hints, the simplest check was an equality check, rather
      than a more general subsumption check. That equality check was
      made after removing so-called ``guard holders''
      ([must-be-equal], [prog2$], [ec-call], [the]) from both the
      previous theorem and the purported theorem. Now, guard-holder
      removal has been strengthened, so that the results are also put
      into so-called quote-normal form, for example replacing (cons
      '3 '4) by '(3 . 4).

      o For a [lemma-instance] provided to a :use or :by hint that is a
      :functional-instance, if a :do-not hint (see [hints]) has
      specified that preprocess-clause is not to be used, then
      preprocessing will not be used on the constraints.

  We eliminated certain warnings about being ``weak'' for every
  :[type-prescription] rule whose conclusion designates that the
  function call can be equal to one of its arguments, e.g., (or
  (integerp (foo y)) (equal (foo y) y)). In many cases (such as the
  one above), such warnings about ``weak'' simply aren't correct.

  BUG FIXES

  Fixed a soundness bug that was permitting a [stobj] to be bound by a
  [let] or [mv-let] form, without being among the outputs of that
  form. Thanks to Jen Davis and Dave Greve for reporting this bug.
  Their report included an example which forms the basis for a proof
  of nil, included as a comment in the form (deflabel note-6-3 ...)
  in ACL2 source file ld.lisp.

  (GCL only) Fixed an obscure soundness bug due to an error in the GCL
  implementation of [set-debugger-enable]. For details, see the
  relevant comment in the ACL2 source code under (deflabel note-6-3
  ...).

  Fixed a bug in the case of a field of a (concrete) stobj that is an
  abstract stobj (see [nested-stobjs]). Thanks to David Rager for
  bringing this bug to our attention.

  Splitter output for type if-intro (see [splitter]) could formerly
  occur even when at most one subgoal is generated. This has been
  fixed.

  Fixed a bug in [wof], hence in [psof] (which uses wof), that was
  causing the printing of a bogus error message.

  A small logical bug has been fixed in the logical definition of
  [sys-call-status]. Formerly it always returned (mv nil state)
  whenever the oracle of the state is non-empty (see [state]).

  Fixed a bug that was causing an error upon evaluation of the form
  (set-prover-step-limit nil). Thanks to David Russinoff for
  reporting this error.

  The :measure (if supplied) is now ignored when checking redundancy
  with respect to a non-recursive definition that is not defined
  within a [mutual-recursion]. (See [redundant-events] and see
  [xargs].) It had been possible to get a low-level ACL2 error in
  this situation. Thanks to Jared Davis for reporting this bug with a
  helpful example.

  Eliminated a potential error when using [comp] to compile an
  uncompiled function defined under [progn!], which we observed in
  LispWorks.

  CHANGES AT THE SYSTEM LEVEL

  The ACL2 sources are now publicly available between ACL2 releases,
  using svn; see the new ``acl2-devel'' project hosted by Google code
  at {http://acl2-devel.googlecode.com |
  http://acl2-devel.googlecode.com}. Although such a copy of ACL2 is
  likely to work well with the latest svn (trunk) revision of the
  ACL2 community books (see [community-books]), please take seriously
  the warning message printed at startup: ``The authors of ACL2
  consider svn distributions to be experimental; they may be
  incomplete, fragile, and unable to pass our own regression.'' That
  message also provides instructions for bug reports. If you decide
  to use svn versions of either the community books or ACL2, then you
  should use both, as they tend to be kept in sync. We fully expect
  ACL2 releases to continue from time to time, as usual. Thanks to
  Jared Davis for his efforts in setting up the new acl2-devel
  project and svn repository, and to him and David Rager for
  convincing us to distribute ACL2 sources via svn between releases.

  Thanks to a suggestion from Jared Davis, over 30 built-in functions
  are now declared to be inline in order to boost performance. (The
  list may be found by searching ACL2 source file axioms.lisp for
  ``(declaim (inline''.)

  Better support has been provided for command line arguments,
  especially those supplied directly by the user when calling ACL2.
  For one, problems with quoting have been solved using \"$@\" in place
  of $*. Also, the function [save-exec] now allows specification of
  arguments, both for the host Lisp as well as ``inert'' arguments
  that can be passed along to calls of programs (as with [sys-call]).
  A keyword argument, :return-from-lp, specifies a form to evaluate
  before quitting the read-eval-print loop at startup. See
  [save-exec]. Also see the source function user-args-string and its
  comments, source file acl2-init.lisp, for more information. Thanks
  to Jared Davis for suggesting the use of \"$@\", as well as
  modifications to [save-exec] and helpful conversations about that.

  A rather extensive overhaul has taken place for the function
  proclaiming mechanism. As before, this is only used when the host
  Lisp is GCL. However, building an executable is now faster for some
  Lisps, including GCL, by avoiding repeated recompilation and
  perhaps repeated initialization.

  (CCL only) We increased stack sizes when the host Lisp is CCL. The
  default for recent CCL versions is equivalent to specifying `-Z 2M'
  on the command line, but saved ACL2 scripts (including experimental
  versions ACL2(h), ACL2(p), ACL2(r), and combinations of them) to
  `-Z 64M', representing a 32-fold increase. Thanks to Jared Davis
  for pointing us to community books file
  books/centaur/ccl-config.lsp and to Sol Swords for helpful
  discussions.

  (SBCL only) Fixed save-exec for host Lisp SBCL to provide the same
  export of variable SBCL_HOME that was provided in the original
  saved_acl2 script.

  (GCL only) We made changes, following suggestions from Camm Maguire
  (whom we thank for these suggestions), to support ACL2 builds on
  recent versions of GCL (2.6.8 and 2.6.10; we recommend against
  using GCL 2.6.9, since issues there were fixed in 2.6.10).
  Specifically, we no longer set the hole size, and we allocate
  contiguous pages sufficient to run an ACL2 regression without
  failing due to memory limitations.

  EMACS SUPPORT

  Modified file emacs/emacs-acl2.el to eliminate some warnings that
  were appearing in a recent Emacs version, replacing (end-of-buffer)
  by (goto-char (point-max)) and next-line by forward-line. Thanks to
  Warren Hunt for bringing the warnings to our attention.

  EXPERIMENTAL/ALTERNATE VERSIONS

  (Allegro CL only) ACL2(h) now avoids blow-ups in hash table sizes
  that could be caused by [fast-alist-fork]. Thanks to Jared Davis
  for helping to debug this problem, and to David Rager for
  contributing the community book
  books/parsers/earley/earley-parser.lisp, which highlighted this
  problem.

  (SBCL only) Fixed a bug that was causing a Lisp break after turning
  on [waterfall-parallelism]. Thanks to David Rager for confirming
  that our proposed fix is correct.")
 (NOTE-6-4
  (RELEASE-NOTES)
  "ACL2 Version 6.4 (January, 2014) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes to ACL2 since Version 6.3 into
  the following categories of changes: existing features, new
  features, heuristic improvements, bug fixes, changes at the system
  level, Emacs support, and experimental versions. Each change is
  described in just one category, though of course many changes could
  be placed in more than one category.

  See also [note-6-4-books] for a summary of changes made to the ACL2
  Community Books since ACL2 6.3, including the build system.


Changes to Existing Features

  [Gag-mode] no longer saves prover output when PROVE output is
  inhibited (see [set-inhibit-output-lst]). This may improve
  performance slightly when certifying community books using their
  Makefile or [cert.pl]; in particular, GCL 2.6.8 running on a Mac
  can now certify the book
  books/tau/bounders/elementary-bounders.lisp without running out of
  space, even without explicitly turning off [gag-mode] (which had
  been done shortly before the Version 6.3 release).

  When [include-book] fails to find a readable [certificate] (.cert)
  file, the error message now distinguishes between the case that
  this file is missing and the case that read permission is missing.

  (GCL only) Time reporting has been improved when the host Lisp is Gnu
  Common Lisp. A key change was made in the computation of runtime
  (for example, to report in event summaries), so that it includes
  the ``child runtime''. See [get-internal-time]. Also, the utility
  [time$] now gives improved information by including child runtime
  information, which can be significant; for example, it probably
  includes compile time, while the ``seconds runtime'' statistic
  (still) does not. Recent versions of GCL might also provide system
  runtime and child system runtime. See [time$]. Thanks to Camm
  Maguire for suggesting these improvements to time$ and providing an
  initial implementation for them.

  Fixed a bug in an ACL2 system function, our-truename, which returns
  the ``true name'' for a file name, when supplied with an optional
  second argument. Thanks to Camm Maguire for bringing this bug to
  our attention.

  The wording in theory warnings has been improved, to avoid giving the
  impression that you are newly disabling a built-in rule in the case
  that it merely remains disabled.

  As requested by Sol Swords, erroneous evaluations of system function
  magic-ev-fncall that had produced a message, msg, will now also
  return that message. The following example, sent by Sol,
  illustrates the fix: before, evaluation of (magic-ev-fncall 'cons
  '(a) state nil nil) printed a message (to the comment window) and
  then returned (mv t nil), but now it returns mv t , shere
   denotes the message (printed with the [fmt] ~@ directive).

  Fixed :[pbt] to avoid printing the bodies of [defconst] forms. Thanks
  to Jared Davis for pointing out the large output when the body is a
  large character string.

  A new output type, history, now controls the printing of
  history-related information; see [set-inhibit-output-lst]. The
  unused output type, expansion, is no longer supported, i.e., is no
  longer a member of the list *valid-output-names*. Because of this
  change, printing of information when undoing, as by :[u], will now
  take place even when event output is inhibited (if history output
  is not inhibited); we thank Sol Swords for requesting that change.

  The :[loop-stopper] field of a rule of class :[rewrite], should still
  be a list of lists (var1 var2 fn1 fn2 ... fnk), where var1 and var2
  are variables and the fni are symbols. But formerly each fni was
  required to be a function symbol; now, it can be a macro alias for
  a function symbol (see [add-macro-alias]). For example, the
  following is a valid :[loop-stopper] field: ((x y +)).

  The restrictions on utilities [oracle-apply] and [oracle-funcall]
  have been updated in order to avoid potentially confusing or
  inappropriate results, by imposing the following new requirements
  on their first argument, which must still be a function symbol.
  That symbol must not be if (formerly the illegal symbol was
  [return-last]); it must not be a key of the alist,
  *ttag-fns-and-macros*; it must not be untouchable (see
  [remove-untouchable]); and it must not be a [stobj] creator (see
  [defstobj]).

  The [table] guard on [dive-into-macros-table] has been strengthened
  in order to avoid calling untouchable functions (see
  [remove-untouchable]).


New Features

  We have added a tool for writing out useful information about a
  book's event names when certifying the book. See [bookdata]. Thanks
  to Dave Greve for requesting this tool and participating in its
  specification.

  There are new analogues of [add-include-book-dir] and
  [delete-include-book-dir]: [add-include-book-dir!] and
  [delete-include-book-dir!], respectively. The new utilities are
  similar to their existing counterparts, except that their effects
  are not [local] to enclosing [books] or [encapsulate] events.
  Thanks to Shilpi Goel for requesting this enhancement.

  The class of [congruence] rules has been broadened considerably, so
  that one can restrict to patterns. For example, a congruence rule
  can now state that an equivalence is maintained for the term
  (mv-nth 1 (f (cons u v) y 'a)) when rewriting y. See
  [patterned-congruence]. Thanks to Sol Swords for requesting this
  feature.


Heuristic Improvements

  (None to report this time.)


Bug Fixes

  Fixed a soundness bug in the handling of hypotheses of conditional
  :[definition] rules invoked during rewriting by applying :[expand]
  [hints]. See (defxdoc note-6-4 ...) in community book
  system/doc/acl2-doc.lisp for a proof of nil in ACL2 Version_6.3
  that exploits this bug.

  It had been possible to update a [stobj] (either an ordinary stobj or
  an abstract stobjs) so that it no longer satisfies its recognizer
  predicate. This soundness bug has been fixed. Thanks to Jared Davis
  and Sol Swords for pointing out this bug, making useful
  observations about the issue, and sending proofs of nil, one of
  which may be found in a Lisp comment in the defxdoc form for
  note-6-4.

  Fixed a long-standing soundness bug (found at least as far back as
  Version 1.9!) in the checking done for [congruence] rules. There
  had failed to be a check that the new variable on the right-hand
  side of the conclusion is indeed new. The following example is
  shown in detail as a comment in function
  interpret-term-as-congruence-rule, ACL2 source file defthm.lisp,
  where it is used to prove nil in Version 6.3.

    (implies (e y1 y2)
             (equal (h y2 y1)
                    (h y2 y2)))

  Fixed a bug in the ACL2 character reader that was causing an
  end-of-file error when reading from a string ending in \"#\\c\", for c
  a character or non-terminating sequence of characters. Thanks to
  Jared Davis for sending the following example, whose evaluation in
  raw Lisp had caused an error.

    (let* ((*readtable* *acl2-readtable*)
           (stream (make-string-input-stream \"#\\\\a\"))
           (x1 (read stream nil :EOF))
           (x2 (read stream nil :EOF)))
      (list x1 x2))

  (GCL only) Improved the automatic proclaiming mechanism used for GCL
  builds, in particular to avoid computing a return type when a term
  is detected that could come from a call of [non-exec], and to do a
  more complete job for calls of [return-last].

  (CCL only) A CCL bug was treating filenames of the form \"~/user/...\"
  as \"~/...\". Thanks to Gary Byers for sending us a CCL-specific form
  that is now included in the ACL2 sources, which avoids this
  problem.

  Attempts to submit [congruence] rules had unfortunate consequences in
  the case that the function ``symbol'' is [if] or [quote]: for if,
  rules were appropriately ignored because of the special handling
  that ACL2 already gives to calls of [if] for congruence-based
  reasoning, while for quote, it was possible to get a hard Lisp
  error. Now, attempts to submit such rules will result in a clear
  ACL2 error.

  It had been possible to get a confusing raw Lisp error when
  submitting a [defstobj] event whose first argument is not a symbol,
  as in: (defstobj (fld :type integer :initially 0)). That user error
  is now reported gracefully by ACL2.

  When an [include-book] form is executed for a non-existent book, we
  no longer get a bogus warning about a missing compiled file. (Of
  course the compiled file is missing when the book itself is
  missing! So there's no need to report this fact.) Thanks to Caleb
  Eggensperger for bringing this issue to our attention.


Changes at the System Level

  The ACL2 system [documentation] has been reworked for the [xdoc]
  framework developed by Jared Davis. While the ACL2 User's Manual
  can still be built, it is now possible for the ACL2 community to
  contribute to the ACL2 system documentation, in community book
  books/system/doc/acl2-doc.lisp; see comments near the top of that
  book. Now that both the ACL2 system documentation and much of the
  community books documentation are written in [xdoc] format, we hope
  the ACL2 community will add links from the ACL2 system
  documentation topics to book documentation topics. Note that :[doc]
  still works at the terminal, but it is based on the new system, and
  other terminal-based access to the documentation has been
  eliminated (for example :more). Thanks to Jared for all his work
  contributing to this enhancement.

  Fixed community books books/Makefile-generic and also books/Makefile,
  which now has filename books/GNUmakefile, to work with Cygwin
  (Windows). Thanks to Harsh Raju Chamarthi for his substantial help.

  The guard for system function ev-fncall-w now includes an arity
  check.


EMACS Support

  There is now an Emacs utility for browsing the hypertext
  documentation for ACL2 and the community books. This browser,
  ACL2-Doc, essentially serves as a replacement for Emacs Info, which
  can no longer be used to browse the documentation. ACL2-Doc can be
  used not just for the ACL2 User's Manual but also for the
  ACL2+Books Manual. It is loaded automatically into Emacs if you
  load the file emacs/emacs-acl2.el. See [ACL2-doc] and
  [documentation].


Experimental/Alternate Versions

  (None to report this time.)")
 (NOTE-6-5
  (RELEASE-NOTES)
  "ACL2 Version 6.5 (August, 2014) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes to ACL2 since Version 6.4 into
  the following categories of changes: existing features, new
  features, heuristic improvements, bug fixes, changes at the system
  level, Emacs support, and experimental versions. Each change is
  described in just one category, though of course many changes could
  be placed in more than one category.

  See also [note-6-5-books] for a summary of changes made to the ACL2
  Community Books since ACL2 6.4, including the build system.


Changes to Existing Features

  The [brr@] command now supports inputs :initial-ttree and
  :final-ttree. Thanks to David Rager for a request leading to these
  enhancements. See [ttree] for a discussion of the tag-tree
  structures returned for these inputs.

  (GCL only) A restriction for structure-sharing (as described in a
  remark, ``Remark on print-circle-files''; see [print-control])
  involving GCL has been removed, since this is no longer required
  for the latest GCL versions (2.6.8 and 2.6.10). Thanks to Jared
  Davis and Camm Maguire for useful discussions and this GCL
  improvement.

  The keyword commands :exit and :quit are disabled inside [brr], in
  order to avoid accidental exits from ACL2. Thanks to David Rager
  for suggesting such a change.

  For calls of [make-event] made during the [include-book] phase of
  [certify-book], keyword :check-expansion no longer causes
  evaluation of the first argument of make-event; rather, the value
  of :check-expansion is simply used as the expansion. Thanks to Sol
  Swords for suggesting this change, which made it reasonable to
  ignore such make-event forms when determining the ``rolling back''
  before that include-book phase, as described in the next section.

  The form (reset-prehistory nil) now is a no-op if [state] global
  'skip-reset-prehistory has a non-nil value. Thanks to Sol Swords
  for requesting this feature (in support of infrastructure for
  certifying the [community-books]).

  The output from :[pr], :[pr!], :[pl], and :[show-bodies] has been
  tweaked. Thanks to a suggestion from Ben Selfridge, such output now
  shows the hypotheses (the Hyps field) above the left-hand side and
  right-hand side of a [rewrite] rule (Lhs and Rhs, respectively).
  The Equiv field has also been moved up before the Lhs field in such
  output for rewrite rules, and this field has been added for [elim]
  rules. Finally, the Hyps field now appears above the Term field in
  such output for [type-prescription] rules.

  Rules of class :[linear] may now be [monitor]ed. Thanks to David
  Rager for requesting this enhancement.

  When forcing (see [force]) is applied, we now always see the
  appropriate [executable-counterpart] [rune],
  (:executable-counterpart force), in the proof output and summary;
  this hadn't previously been the case. Thanks to Robert Krug for
  bringing this issue to our attention.

  The default value for the :write-port keyword argument of
  [certify-book] is now t, as was already claimed by the
  documentation. Thus, a .port file will be written when a book is
  certified, making it more likely that a subsequent [include-book]
  will complete without error even if the book has been modified
  without recertification. Note that a change by Sol Swords to the
  build system for the [community-books] now sets an environment
  variable to guarantee that write-port is true, independent of this
  change. On a related note: the unadvertised environment variable
  ACL2_WRITE_PORT is now handled more appropriately, by interning its
  upcased argument into the ACL2 package.

  The following changes can make it easier to include books that are
  uncertified or have corrupted compiled files. Thanks to Sol Swords
  for sending helpful, relevant examples and for subsequent
  discussions helping to lead to these changes.

    * It is no longer illegal to call set-compiler-enabled within [books].
      See [compilation], which shows how to do this in order to avoid
      loading the compiled file not only for a book specified by
      [include-book] but also for all books included under that book.
      Also see [compilation] for an analogous utility,
      (set-port-file-enabled nil state), to avoid loading .port
      files. (For background on .port files, see
      [uncertified-books]).
    * In situations where it is legal to include an uncertified book
      (typically, any time other than during [certify-book], ACL2
      nonetheless could fail to do so when an error occurred while
      reading a [certificate] file. ACL2 can now instead include the
      book successfully as an uncertified book.
    * When hard raw Lisp errors occur during loading of compiled files on
      behalf of an [include-book] event, that event can now complete
      successfully much as though the compiled file were simply
      missing.

  (SBCL only) The function [setenv$] is now supported in SBCL, which
  had been the one supported host Lisp for which setenv$ had not been
  supported. Thanks to Jared Davis for pointing the way to this
  improvement.

  Built-in [equality-variants] have been modified in order to support
  suitable guard-checking. For example, evaluation of the form
  (member-eq 3 '(4 5)), or equivalently, (member 3 '(4 5) :test 'eq),
  had produced a value of nil, but now we get what one should have
  expected: a guard violation (since [member-eq] is intended to
  compare symbols). Thanks to Yan Peng for raising a question on the
  acl2-help mailing list that led us to make this improvement.

  When the :[pe] command is supplied the macro alias for a function
  symbol (see [macro-aliases-table]), the system will now print
  [events] not only for the macro symbol but also for the
  corresponding function symbol. Thanks to Cuong Chau, Jared Davis,
  Shilpi Goel, Sol Swords, and Warren Hunt for requesting this
  enhancement.

  Some evaluations of forms (mbe :logic L :exec E) are more efficient
  or avoid guard violations, by evaluation of the :exec form (E)
  instead of the :logic form (L). If the [mbe] call is in a
  :[program] mode function definition, the :exec code will be
  evaluated, where unlike before, this is true even when
  guard-checking is :all or :none (see [set-guard-checking]). If the
  mbe call is in a :[logic] mode function definition, the change is
  that the :exec code will be evaluated when there is a superior call
  of a :program mode function, except when guard-checking is :all or
  :none or in a couple of technical cases (see a comment in the
  source code for constant **1*-as-raw* [formerly *mbe-as-exec*] for
  details). This use of :exec code had been defeated when the
  superior :program mode function had an ``invariant-risk'' of making
  ill-guarded stobj updates. However, there is no change in the case
  of safe-mode, which is used during evaluation of [defconst],
  [value-triple], and [defpkg] forms, and during macroexpansion: the
  :logic and :exec forms are still both evaluated and checked for
  equality. Thanks to Jared Davis for reporting this issue and for
  helpful chats about it. For more information, see the comment about
  ``mbe and invariant-risk'' in the form (defxdoc note-6-5 ...) in
  [community-books] file books/system/doc/acl2-doc.lisp.

  The utility [save-exec] has a new (optional) keyword argument,
  :init-forms, which specifies a list of forms to evaluate when first
  entering the ACL2 read-eval-print loop, [lp]. Thanks to Jared Davis
  for requesting this enhancement.


New Features

  A [defstobj] event may now include the keyword argument
  :non-memoizable. When its value if t, then for ACL2(h) builds (see
  [hons-and-memoization]), code will run somewhat faster. In a little
  test doing just reads and writes to a stobj array in ACL2(h), it
  took 26% less time when the stobj to be written was introduced by
  [defstobj] using :non-memoizable t. Thanks to Warren Hunt for
  requesting this feature and helping to develop the test.

  See [set-print-base-radix] for a utility that may be preferable to
  [set-print-base], since it essentially calls [set-print-radix]
  automatically. Thanks to David Rager, Shilpi Goel, and David Hardin
  for participating in an acl2-help mailing list discussion that
  motivated this feature.


Heuristic Improvements

  One of the steps performed by [certify-book] has traditionally been
  to check for local incompatibilities (see [local-incompatibility])
  after admitting all the events in the book. This step involved
  rolling back the logical [world] to what it was at the start of
  certification, and then including the book (see [include-book]). As
  an optimization, we now avoid rolling back the world more than
  necessary; see [certify-book], specifically the discussion of Step
  3. We thank Sol Swords for requesting this optimization and for
  making a suggestion that improved it, pertaining to [make-event]
  (described above). We also thank Jared Davis for alerting us to an
  issue that turned out to be caused by a bug in our initial
  implementation. Sol has reported a nearly 20% reduction in time for
  certifying a certain large collection of books.

  The test for redundancy of [encapsulate] [events] has been made more
  efficient. Also, while the criterion itself remains unchanged, the
  documentation has been made more accurate; see
  [redundant-encapsulate]. We observed more than a 2% reduction in
  time for the ``everything'' regression target, but we observed more
  than 23% of the time eliminated for the form (time$ (include-book
  \"doc/top\" :dir :system)) after building the documentation. Thanks
  to David Rager for bringing that particular book to our attention,
  as one that took a long time to include.

  The function [pairlis$] is now tail-recursive, hence potentially more
  efficient. More precisely, its definition for the logic remains
  unchanged, but using [mbe], for execution it calls a new
  tail-recursive function, pairlis$-tailrec. Thanks to Jared Davis
  for requesting this improvement.

  [Linear] arithmetic has been strengthened slightly so that
  immediately after simplification has ``settled down'' (see
  [hints-and-the-waterfall]), the unrewritten conclusion of a
  :[linear] rule may be used when normally this would not be the
  case. Thanks to Robert Krug for reminding us of examples we had
  encountered that could benefit from some such a change, and for
  pointing us to some relevant source code. This improvement
  generally causes an extra pass through the simplifier; hence we
  have observed approximately a 2% slowdown in the regression suite.
  Note that machinery is now in place for installing additional
  ``desperation heuristics''; perhaps the ACL2 community will have
  some to suggest.


Bug Fixes

  We fixed a soundness bug in how the [tau-system] processed calls of
  if. Thanks to Dmitry Nadezhin for reporting this bug by sending a
  simple example that exploited it to prove nil. To see that example,
  see the comment about ``tau soundess bug'' in the form (defxdoc
  note-6-5 ...) in [community-books] file
  books/system/doc/acl2-doc.lisp.

  We fixed a soundness bug for nested [stobj]s (see [stobj-let]). In
  the case of a stobj producer variable that is not a child stobj, it
  had been possible to update that stobj without returning it. Thanks
  to Sol Swords for reporting this bug and providing a corresponding
  proof of nil, which is included in a comment in the form (defxdoc
  note-6-5 ...) in [community-books] file
  books/system/doc/acl2-doc.lisp.)

  We fixed a soundness bug in the case of a [stobj] with a field that
  is a resizable array of stobjs. Thanks to Sol Swords for sending a
  proof of nil exploiting this bug, together with some helpful
  analysis attributing the bug to a mistake in the generated logical
  definition of the corresponding resize function. (His example is
  included in a comment in the form (defxdoc note-6-5 ...) in
  [community-books] file books/system/doc/acl2-doc.lisp.)

  (ACL2(h) only) We fixed a soundness bug involving the interaction of
  [stobj-let] and [memoize], which thus is only a bug in ACL2(h) (see
  [hons-and-memoization]), not in ACL2. The fix was to add code to
  stobj-let that clears the memoization table for the parent stobj if
  any child stobj is updated. An example proof of nil before this fix
  may be found in the ACL2 source file translate.lisp, in a comment
  in the function stobj-let-fn-raw.

  (Allegro CL and CMUCL only) We fixed bugs in function [princ$] when
  invoked in an ACL2 image with Allegro CL or CMUCL as the host Lisp
  implementation. In Allegro CL, when printing a complex number in
  base 16, lower case characters were produced, for example printing
  #C(c d) instead of the characters predicted by the axioms, namely
  #C(C D). In some recent versions of CMUCL, after executing the
  forms (set-print-base 16 state) and (set-print-case :downcase
  state), hex digits were printed in lower case, unlike other host
  Lisps and contrary to the ACL2 axioms: for example, 1000 base 10
  was printed as 3e8 rather than as predicted by the ACL2 axioms,
  3E8. Thanks to Jared Davis for bringing these bugs to our
  attention, and also for pointing out excessive printing of a big
  note about such printing in Allegro CL. We now avoid that note
  altogether, which had warned that printing numbers in base 16 can
  be slow for Allegro CL. In fact, that performance issue has been
  eliminated: for example, after evaluating (defconst *c* (expt 2
  200000)) and (set-print-base 16 state), the form (time$ (pprogn
  (princ$ *c* *standard-co* state) state)) reports taking about 3
  seconds before the change but about 1/100 seconds after the change.
  Thanks to David Margolies of Franz Inc. for passing along a remark
  from a colleague that showed how to make this improvement.

  The utility [sys-call+] can now only be called if there is an active
  [trust-tag], which is the restriction that was already in place for
  [sys-call]. This plugs a potential soundness hole.

  We have made several system functions untouchable (see
  [remove-untouchable]), in order to prevent soundness bugs. We thank
  Jared Davis and Sol Swords for sending us an example that used a
  call of one of these functions to prove nil. We have placed that
  example into a comment in Community Books file
  system/doc/acl2-doc.lisp, form (defxdoc note-6-5 ...).

  The brr command, :wonp, had not been installed for use after :eval
  even though this was claimed in the documentation (see
  [brr-commands]). This has been fixed. Thanks to David Rager for
  bringing this issue to our attention.

  Fixed a bug in [make-event] that could cause [include-book] to fail
  with a bogus message about ``the set of ttags permitted in the
  current context.'' Thanks to Sol Swords and Anna Slobodova for
  reporting this bug, and to Sol for sending a small example that
  illustrated the problem.

  Fixed a bug that was wrongly disallowing certain calls of exported
  functions for abstract stobjs (see [defabsstobj]). Thanks to Sol
  Swords for reporting this bug, supplying an example illustrating
  the bug, and suggesting a nice fix. A slight variant of his example
  is included in a comment in Community Books file
  system/doc/acl2-doc.lisp, form (defxdoc note-6-5 ...).

  When a macro symbol mac was a macro-alias for a function symbol f
  (see [macro-aliases-table]), then the form (verify-guards+ mac)
  caused an error when encountered while including an uncertified
  book. This problem has been fixed. Thanks to Jared Davis for
  pointing out the problem and sending a simple example to illustrate
  it. Technical Note: the actual problem was that [verify-guards+]
  generates a call of [make-event] with an :expansion? argument, and
  that argument needed to be ignored (as it now is, after the fix)
  when including an uncertified book.

  The [walkabout] utility could cause hard Lisp errors when the current
  package is other than \"ACL2\". This has been fixed. Thanks to Sol
  Swords for bringing this bug to our attention and suggesting a fix.


Changes at the System Level

  (SBCL only) Fixed the executable script generated for SBCL so that
  SBCL_HOME is set to the SBCL obj/sbcl-home/ directory if it exists,
  since that fix seems needed for some recent versions of SBCL
  (1.1.14 in particular).

  File GNUmakefile in the ACL2 sources directory wasn't passing the
  value of shell variable ACL2 from target certify-books-fresh to
  target certify-books, and similarly for target
  books/system/doc/render-doc.cert (invoked by target DOC). This has
  been fixed. We thank Jared Davis and Camm Maguire for helpful
  discussions.

  The \"make DOC\" command was not completing correctly when variable
  ACL2 was not set. Also, for host Lisp CMUCL at least, it stalled at
  the terminal unless a quit command was issued twice (as ACL2 was
  stuck without exiting). Those problems have been resolved. Thanks
  to Jim Ward for bringing these issues to our attention

  Improved the error message when encountering an illegal comma while
  reading input (i.e., for a comma not within a suitable nesting of
  backquotes). Thanks to Jared Davis for bringing this issue to our
  attention and for a helpful discussion.

  (GCL only) Arranged for state global 'tmp-dir to be set to GCL's
  si::*tmp-dir*, even on Windows; this may be important for
  compilation on Windows. Thanks to Camm Maguire for pointing out the
  need to set 'tmp-dir for ACL2 built on GCL on mingw.

  (GCL only) Now, [gc$] may be called with no arguments, in which case
  the missing argument for system::gc is t.


EMACS Support

  Improvements to the [ACL2-Doc] browser include the following.

    * A new `w' command displays the topic name in the minibuffer, together
      with the manual name (ACL2+Books Manual or ACL2 User's Manual).
    * Improved the `control-t .' command so that the default topic is
      selected just as in acl2-doc mode. (Technically: the same
      syntax table is used for `control-t .' as is used in the
      acl2-doc buffer for that command and the `g' command.)
    * Improved the search commands so that the display doesn't move when
      the next occurrence is already displayed on the screen.
    * Eliminated the deprecated commands `Control-x a A', `Control-x a a',
      and `Control-t G'.


Experimental/Alternate Versions

  For ACL2(r), Ruben Gamboa found a bug in constraints for functions
  introduced with defun-std, and also kindly provided a fix, which
  has been incorporated.

  Modified ACL2(hp) so that two system functions that had been
  [unmemoize]d when turning on [waterfall-parallelism] ---
  fchecksum-obj and expansion-alist-pkg-names-memoize --- now remain
  memoized. This can greatly improve performance when using ACL2(hp)
  with [waterfall-parallelism] on, in particular community book
  books/system/doc/render-doc-combined.lisp.

  Made miscellaneous small improvements to ACL2(h).

  The utilities hons-shrink-alist and hons-shrink-alist! have
  essentially been renamed to [fast-alist-fork] and
  [fast-alist-fork!], respectively. The old names are deprecated but
  remain as macros that are macro-aliases for the respective new
  names (see [macro-aliases-table]). New utilities,
  [fast-alist-clean] and [fast-alist-clean!] are similar to the above
  but take just one argument and, if it is a fast alist, associates
  the result with the hash table link of that argument. Thanks to
  Jared Davis for providing a concrete proposal, together with the
  new names, for what had been only a concept.")
 (NOTE-7-0
  (RELEASE-NOTES)
  "ACL2 Version 7.0 (January, 2015) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes to ACL2 since Version 6.5 into
  the following categories of changes: existing features, new
  features, efficiency improvements, bug fixes, changes at the system
  level, Emacs support, and experimental versions. Each change is
  described in just one category, though of course many changes could
  be placed in more than one category.

  A particularly major change with this release is that by default,
  ACL2 executables are [hons-enabled]: see [hons-and-memoization]. We
  expect this change to be backward compatible for current ACL2
  users, other than a change to the name of the executable, as
  described below.

    * As before, there are two ways to build ACL2: either [hons-enabled],
      to produce ACL2(h) with executable name saved_acl2h; or not
      hons-enabled, to produce ``classic ACL2'', which we now call
      ACL2(c), with executable name saved_acl2. [Note: These defaults
      were changed after Version_7.0.]
    * Unlike before, the default build of ACL2 is now ACL2(h), hence with
      name saved_acl2h [after Version_7.0, once again saved_acl2]. It
      is still possible to build ACL2(c) (hence with name saved_acl2)
      [after Version_7.0, saved_acl2c], but this is not the default.
    * The change to building ACL2(h) by default may require you to change
      scripts and environment variables to point to saved_acl2h
      rather than saved_acl2. [This change is only for Version_7.0,
      not later versions.]

  Note that after the next ACL2 release, we might only support
  [hons-enabled] ACL2 builds.

  See also [note-7-0-books] for a summary of changes made to the ACL2
  Community Books since ACL2 6.5, including the build system.


Changes to Existing Features

  Three new theorems have been built into ACL2 to allow some additional
  simple arithmetic reasoning. For example, the following failed
  before this change, typically causing the user to include an
  arithmetic book; but that is no longer necessary.

    (thm (implies (natp x)
                  (equal (expt 2 (+ 1 -1 x))
                         (expt 2 x))))

  Thanks to Jared Davis for suggesting these, and for providing seven
  small modifications to the community books to keep proofs from
  failing after the changes. (So, if you have a proof failure
  involving `plus' (+) that formerly succeeded, consider disabling
  one or more of these rules.) Here are the three new built-in
  theorems.

  Theorem: 

    (defthm commutativity-2-of-+
            (equal (+ x (+ y z)) (+ y (+ x z))))

  Theorem: 

    (defthm fold-consts-in-+
            (implies (and (syntaxp (quotep x))
                          (syntaxp (quotep y)))
                     (equal (+ x (+ y z)) (+ (+ x y) z))))

  Theorem: 

    (defthm distributivity-of-minus-over-+
            (equal (- (+ x y)) (+ (- x) (- y))))

  [Type-set] reasoning has been improved for a few built-in functions,
  including first-n-ac, [substitute], [nthcdr], and [subseq], and
  thus for some functions whose computed type depends on one of
  these: for example, [take] and therefore, also [butlast] and
  [subseq-list], are now known to return [true-listp] results. Thanks
  to Jared Davis for a request that led us to these changes. In
  particular, the definitions of first-n-ac and substitute-ac have
  been modified to call [revappend] instead of [reverse], and the
  following :[type-prescription] rules have been added to source file
  axioms.lisp (and can be seen using :[pe]).

    * true-listp-first-n-ac-type-prescription
    * stringp-substitute-type-prescription
    * true-listp-substitute-type-prescription
    * true-listp-nthcdr-type-prescription
    * stringp-subseq-type-prescription
    * true-listp-subseq-type-prescription

  Technical note on the above change: in some cases, the built-in
  :[type-prescription] rule has been changed, essentially for the
  better, but new rules have also been added. Consider for example
  the function, [substitute]. This function calls substitute-ac,
  which in turn now calls [revappend] instead of [reverse], which
  allows ACL2 to deduce a :type-prescription rule saying that
  substitute returns a string or a true-list. However, new
  :type-prescription rules stringp-substitute-type-prescription and
  true-listp-substitute-type-prescription allow the stronger
  conclusion that substitute returns a string or true-list,
  respectively depending on whether [type-set] reasoning can deduce
  that the given sequence is or is not a string. The deduced
  :type-prescription rule can still be of some use in cases that
  type-set reasoning cannot establish whether or not the input
  sequence is a string.

  We removed support for processing legacy [documentation] strings
  (those starting with \":Doc-Section\"), since the [xdoc] system has
  been stable for some time. Thanks to Jared Davis for assisting in
  that effort and to David Rager for his encouragement. The ACL2
  system and [community-books] still have code to support such
  processing, but it is essentially commented out: specifically, each
  such piece of code is prefixed by #+acl2-legacy-doc. We expect to
  delete such code entirely before the next release.

  The [with-output] macro now takes a new keyword, :evisc, that
  specifies [evisc-tuple]s. Thanks to Warren Hunt for requesting a
  way to submit [defun] forms in a way that avoids printing large
  [guard] goals during guard verification. The following example
  illustrates a way to arrange this.

    (defmacro defun/ (&rest args)
     (mv-let (evisc args)
             (cond ((eq (car args) :evisc)
                    (mv (cadr args) (cddr args)))
                   (t (mv '(:gag-mode (evisc-tuple 3 4 nil nil)) args)))
             `(with-output :evisc ,evisc
                           (defun ,@args))))

    ; example:
    (defun/ h (x)
     (declare (xargs :guard t))
     (append (cons (make-list 10) x) x))

  The utility :[pl2] no longer automatically instantiates free
  variables; similarly for calls of :[pl] on a term. Thanks to Eric
  Smith for sending an example showing the problem with the previous
  implementation.

  When the [ld-evisc-tuple] is non-nil, the utilities :[pe], :[pc], and
  :[pcb!] now abbreviate their output accordingly. See
  [set-evisc-tuple]. Thanks to David Rager for bringing the need for
  this change to our attention.

  The utility [disabledp] now accepts runic abbreviations such as (:d
  append). (See [theories] for a discussion of runic abbreviations.)
  Thanks to Shilpi Goel for requesting this enhancement.

  Gc-verbose now takes an optional second argument, which is only
  relevant when the host Lisp is CCL, where that argument specifies
  verbosity for EGC.

  Nests of [car] and [cdr] calls are now printed (``untranslated'')
  differently. The old method availed itself of all 28 of the car-cdr
  macros. The new method only introduces 6 of them: cadr, caddr,
  cadddr, cddr, cdddr, cddddr. It never introduces such macros as
  caar or cddaar, preferring cars and cdrs when necessary. Lisp
  programmers tend to recognize cadr, caddr, and cadddr as the
  accessors for the 1st, 2nd, and 3rd (0-based) elements of a list.
  See community book books/system/untranslate-car-cdr.lisp for
  further discussion and a correctness proof.

  It is now possible to create more efficient :[meta] rules by writing
  metafunctions that create ``implicit hypotheses.'' See
  [meta-implicit-hypothesis].

  We improved a few built in rules: lower-case-p-char-downcase,
  upper-case-p-char-upcase, lower-case-p-forward-to-alpha-char-p, and
  upper-case-p-forward-to-alpha-char-p. We also improved the rule
  alpha-char-p-forward-to-characterp by replacing it with two rules,
  alpha-char-p-forward-to-standard-char-p and
  standard-char-p-forward-to-characterp. The new rules are, as
  before, in ACL2 source file axioms.lisp.

  The reader macro sharp-comma (#,), which has been deprecated since
  ACL2 Version 3.5 (May, 2009), has been eliminated. Use sharp-dot
  (#.) instead; see [sharp-dot-reader].

  A [defthm] or [defaxiom] event is now redundant when there is already
  a syntactically identical event in the logical [world], even if the
  rules suggested by the two [events] differ. See [redundant-events].
  Thanks to Jared Davis and Sol Swords for sending the following
  example, which illustrates the change. Previously, the final event
  was not redundant, and hence failed. Now, it is redundant, even
  though the :typed-term suggested by the new [type-prescription]
  rule is (booleanp (foop x)) where the existing rule's :typed-term
  is (foop x).

    (defund foop (x) (consp x))

    (defthm booleanp-of-foop
      (booleanp (foop x))
      :rule-classes :type-prescription)

    (in-theory (disable booleanp-compound-recognizer))

    (defthm booleanp-of-foop
      (booleanp (foop x))
      :rule-classes :type-prescription)

  In the case that summary output is inhibited but error output is not
  (see [set-inhibited-summary-types]), failed [events] did not print
  an error message. Now they do.

  When a call of [encapsulate] with empty [signature] introduces no
  [events], it now has no effect on the ACL2 logical [world].
  Formerly, such an [encapsulate] form would create an event even in
  this case. For example, the form (encapsulate nil (local (defun f
  (x) x))) formerly created an event in the world, as well as a
  [command] when executed at the top-level; but now it is truly a
  no-op. See [encapsulate]. Note: An idiom sometimes used for testing
  is (encapsulate () (local ...) (local ...) ...), that is, a trivial
  encapsulate where each sub-event is [local]. With this change, that
  idiom is now properly supported. (Formerly, the second such
  encapsulate was considered redundant with the first; but that is no
  longer the case, since the first will not be stored in the
  [world].)

  We replaced an error with a warning for cases where a classic
  [congruence] rule is unnecessary. Thanks to Jared Davis for sending
  us an example suggesting the need for a change. (See ACL2 source
  function chk-acceptable-congruence-rule for his example and more
  explanation.)

  We removed support for three [declare] forms that had been permitted
  in ACL2(h) only, but were not advertised: dynamic-extent, inline
  and notinline, because they seem difficult or impossible to support
  correctly. For alternatives to using inline and notinline
  declarations, see [defun-inline] and [defun-notinline].

  The nu-rewriter contained special provisions for rewriting
  expressions composed of [nth], [update-nth], and
  [update-nth-array], together with [let] expressions and other
  applications of non-recursive functions or [lambda] expressions. An
  email query was sent to the acl2 mailing list on 10/24/2014, giving
  people an opportunity to object to the removal of this feature.
  Nobody objected, so we have removed it in order to simplify the
  ACL2 code base. Thanks to David Rager for suggesting this sort of
  code clean-up. Note that some system functions, for example
  all-equal, have been deleted in support of this change.

  [Guard]s have been added for some system functions that support the
  implementation of the [tau-system]: lower-bound-<=, upper-bound->=,
  lower-bound->, upper-bound-<, and squeeze-k. Thanks to Dmitry
  Nadezhin for supplying these improvements (which he also used in
  modifications to the community book,
  books/tau/bounders/elementary-bounders.lisp).


New Features

  The new command :btm has been added to the list of valid
  [brr-commands], to show the bottom-most frame in the path. Thanks
  to David Rager for requesting this feature.

  A new [xargs] keyword, :[measure-debug], decorates each termination
  proof goal with [extra-info] calls that show the source of the
  goal. Thanks to Jared Davis (first in 2008!), Sol Swords, and Anna
  Slobodova for requesting this feature.

  A new reader macro, #{\"\"\"...\"\"\"}, has been contributed by Jared Davis
  to support the writing of strings without escape characters. See
  his community book books/system/fancy-string-reader-test.lisp for
  examples.

  (For those who program in raw Lisp) A new Lisp variable,
  *hard-error-is-error*, has a default of nil that preserves existing
  behavior; but it can be set to a non-nil value in order to cause
  so-called ACL2 ``hard errors'' to result in Lisp errors whose
  condition, when printed with format directive ~a, is the same error
  message that ACL2 would otherwise print. See [hard-error]. Thanks
  to Jared Davis for requesting this feature.

  A new value for [include-book] keyword argument :uncertified-okp is
  :ignore-certs, which specifies that all certificate files are to be
  ignored during inclusion of this book and all of its sub-books. See
  [include-book]. Thanks to Sol Swords for requesting this feature
  and for helpful discussions on its details.


Efficiency Improvements

  The heuristics have changed for guessing the :typed-term field for a
  :[type-prescription] rule when that field is not explicitly
  specified. Specifically, consider the case that the conclusion of
  the rule is a function call (p u) for some term u, such that there
  is an enabled [compound-recognizer] rule for p. Formerly, the
  :typed-term was u in this case. Now, it must be the case that the
  most recent enabled such [compound-recognizer] rule is `strong', in
  the following sense: if ts1 is the [type-set] implied by assuming
  the conclusion true and if ts2 is the [type-set] implied by
  assuming the conclusion false, then ts1 and ts2 are complementary.
  Thanks to Jared Davis for an email that prompted us to make this
  change.

  We have made several efficiency improvements (arguably heuristic in
  nature), which may apply in many settings but especially in
  handling of several forms during the execution of [include-book]
  --- most notably with-output forms, as (with-output ... FORM) is
  now essentially just FORM during include-book. For some details,
  including statistics showing up to 1/3 of [include-book] time
  eliminated by these changes (and even significant time saved
  outside include-book), see the comment about ``efficiency
  improvements'' in Community Books file system/doc/acl2-doc.lisp,
  form (defxdoc note-7-0 ...). Thanks to Sol Swords for noticing
  inefficiencies that led us to these improvements, and for helpful
  discussions.

  The [dmr] utility has been made much more efficient, yielding a
  performance penalty of perhaps 10% instead of perhaps more than a
  factor of 30 (3000%).

  We made a low-level implementation tweak that resulted in a speed-up
  of 2.6% in wall-clock time for a CCL-based regression (using
  ``make'' with -j 8 and target ``everything''). (Technical note: We
  eliminated the Lisp special variable *attached-fn-called*, using
  another variable *aokp* instead. Special variable bindings can
  apparently be expensive!)

  Some space has been saved in ACL2 executables by avoiding the
  duplication of certain constants. Specifically: for each event
  (defconst name (quote val)) in the ACL2 source files, val is stored
  in the Lisp image in several places, but not all of these had been
  identical: they were all [equal], but not all [eq]. (We believe
  that these were already all eq for user-defined [defconst] events.)
  For example, in Linux builds of ACL2(h) on host Lisp CCL, we have
  seen a space saving of approximately 18.9 MB, which is 12.6%.
  Thanks to Jared Davis for pointing out duplicate strings that he
  noticed using his [spacewalk] tool.


Bug Fixes

  We fixed two bugs in [spec-mv-let]. The first was pointed out to us
  by Jared Davis using essentially the following example, where the
  result should be nil given that spec-mv-let is intended to have the
  semantics of [mv?-let].

    ACL2 !>(set-ignore-ok t)
     T
    ACL2 !>(let ((a t)
                 (xval nil))
             (spec-mv-let (yval)
                          xval
                          (mv?-let (xval)
                              a
                              (if xval
                                  yval
                                nil))))
    T
    ACL2 !>

  The second [spec-mv-let] bug was to allow the two lists of bound
  variables to intersect. In the following example, given that
  spec-mv-let is semantically just mv?-let, the result should have
  been 46, not 34. This has been fixed. Thanks to David Rager for
  encouraging these two fixes and checking them over.

    ACL2 !>(set-ignore-ok t)
     T
    ACL2 !>(spec-mv-let
            (x)
            17
            (mv?-let (x)
                23
                (if t
                    (+ x x)
                  \"bad\")))
    34
    ACL2 !>

  The guard for function [alpha-char-p] was strengthened to require
  that its argument is a standard character. The previous guard
  required only that the argument is a character, and was a soundness
  bug; for a proof of nil before this fix, see the comment about
  ``alpha-char-p'' in Community Books file system/doc/acl2-doc.lisp,
  form (defxdoc note-7-0 ...).

  Errors were possible when evaluating functions [pkg-imports] and
  [pkg-witness] while including a book with a compiled (or expansion)
  file. Such errors have been eliminated.

  Fixed a bug in [oracle-apply-raw].

  (GCL CLtL1 only) Fixed a bug that was preventing
  [set-debugger-enable] from taking full effect in non-ANSI GCL.

  (GCL only) The utility [gc-verbose] was broken, but has been fixed.

  Fixed a bug in [provisional-certification] that incorrectly caused an
  error during the convert step for [verify-guards+] forms. More
  generally, this error occurred when encountering a [make-event]
  form with a non-nil value supplied for the :expansion? keyword.
  Thanks to David Rager for reporting this bug.

  A raw Lisp error could occur with [guard]-checking turned off,
  because type declarations were mistakenly left in the executable
  counterparts (so-called ``*1* functions'') when ACL2 processed
  function definitions. The following example shows how a type
  violation could occur in some Lisps (we saw this in SBCL but not in
  CCL, for example).

    (defun f (x)
      (declare (xargs :guard (natp x)))
      (let ((y (1+ x)))
        (declare (type (integer 0 *) y))
        y))
    (set-guard-checking nil)
    ; Possible raw Lisp error:
    ; \"The value -2 is not of type UNSIGNED-BYTE.\"
    (f -3)

  Thanks to Jared Davis for sending us an example that brought this bug
  to our attention.

  Fixed a bug that was causing a low-level assertion, saying:
  ``Implementation error: see 'replace-free-rw-cache-entry.'' Thanks
  to Anna Slobodova for bringing this bug to our attention via an
  example, and to Sol Swords for simplifying that example.

  The [iprint] feature, which allows abbreviated output to be read back
  in, did not work as one might expect when using the [break-rewrite]
  feature (see [brr]). Thanks to David Rager for reporting this
  problem. More generally: the problem was that values associated
  with [iprint] indices during a [wormhole], for example after
  breaking on a [rewrite] rule, were forgotten when exiting the
  wormhole. (Technical note for those interested: the fix restores
  the main iprinting structure after exiting a wormhole, just before
  reading the next top-level form. That restoration uses raw Lisp,
  with logic-only code based on [read-ACL2-oracle].) The example
  below failed before the fix but now works.

    (set-evisc-tuple (evisc-tuple 3 3 nil nil)
                     :iprint t
                     :sites :all)
    (defthm my-rule (equal (car (cons x x)) x))
    (brr t)
    (monitor '(:rewrite my-rule) t)
    (thm (equal (car (cons a a)) a) :hints ((\"Goal\" :do-not '(preprocess))))
    ; Now entering a :brr break:
    (make-list 10) ; printed without evisceration
    ; Set evisceration with iprinting:
    (set-evisc-tuple (evisc-tuple 3 3 nil nil)
                     :iprint t
                     :sites :all)
    (make-list 10) ; printed with evisceration
    (a!) ; quit break-rewrite
    ; The following formerly caused a hard Lisp error, because although #@3#
    ; was printed in the output from (make-list 10) just above, iprint index 3
    ; was lost when exiting the break-rewrite wormhole.  Now, this works
    ; because iprinting information from the wormhole is retained.
    '#@3#

  There was a bug in how so-called ``hidden packages'' were handled by
  [encapsulate] forms (see [hidden-death-package]), which was
  preventing package axioms from being visible in certain contexts.
  (Technical remark: packages that were hidden after the second pass
  but not the first were treated as not-hidden, even though their
  package axioms were not introduced.) That, in turn, could cause an
  [include-book] form to fail when the book contains a
  [deftheory-static] form. Here is an example failure. First, in a
  fresh ACL2 session evaluate the form (defpkg \"FOO\" nil) and then
  evaluate the form (certify-book \"foo\" 1), where file foo.lisp is as
  follows.

    (in-package \"ACL2\")
    (defun foo::foo (x) x)
    (deftheory-static foo-theory
      (current-theory :here))

  Now evaluate the following sequence of forms. In previous versions of
  ACL2, the final ([include-book]) form failed.

    (encapsulate () (local (include-book \"foo\")) (defun h (x) x))
    (encapsulate () (local (include-book \"foo\")) (defun h2 (x) x))
    (include-book \"foo\") ; failed before the fix

  We have cleaned up handling of interrupts and aborts when inside the
  [break-rewrite] loop, or indeed any [wormhole]. Thanks to David
  Russinoff for bringing to our attention a case in which ACL2 quit a
  proof with ``Aborting due to an interrupt'' when in fact no
  interrupts had taken place. Here is an example where that no longer
  happens but did, previously. (For a different example, see the
  comment in the ACL2 sources definition of macro
  bind-acl2-time-limit.)

    (defun foo (x) (cons x x))
    (brr t)
    (monitor '(:definition foo) t)
    (thm (equal (foo y) z))
    (defun h (x) (declare (xargs :mode :program)) (car x))
    ; Raw Lisp error:
    (h 3)
    ; Previously, unexpected proof abort \"due to interrupt\":
    (thm (equal (append (append x y) x y) (append x y x y)))

  When aborting with :[a!] inside the [break-rewrite] loop from within
  the [proof-checker], a raw Lisp error could subsequently occur
  saying, ``Attempt to execute *wormhole-cleanup-form* twice!''. This
  has been fixed. Thanks to Sol Swords for reporting a bug in our
  original fix. Here is an example that formerly caused that
  behavior.

    (defthm silly (implies (null x) (equal (append x y) y)))
    (defconst *c* (make-list 10))
    :brr t
    :monitor (:rewrite silly) t
    (verify (equal (append x (append *c* y)) (append y (append *c* x))))
    bash
    :go
    :a!
    bash ; formerly caused error

  The utility [redo-flat] no longer worked when interrupting a proof
  (with Control-c), due to a bug in Version 7.0. This has been fixed.
  Thanks to Dave Greve for reporting this problem.


Changes at the System Level

  As mentioned near the top of this [documentation] topic, default
  builds of ACL2 are now [hons-enabled].

  (GCL only) GCL Versions prior to 2.6.12 are no longer supported.

  Modified code used in distributing Debian releases that allows books
  certified in one directory to be distributed in another. This
  change, together with the fact that such relocation is not truly
  supported, is explained in comments in source function
  make-certificate-file-relocated. Thanks to Camm Maguire for
  discussions leading to this change.

  (GCL only) Modified how home directory is calculated. Thanks to Camm
  Maguire for help in making this change.

  (SBCL only) Fixed a check done at build time that was preventing
  builds in SBCL 1.2.2 because of its new backquote implementation.
  Thanks to Harsh Raju Chamarthi and Pete Manolios for bringing this
  issue to our attention.

  Development snapshots of ACL2 (and of the [community-books]) are now
  available between releases from {an ACL2 github repository |
  https://github.com/acl2/acl2}; they are no longer available via
  svn. Thanks to David Rager and Jared Davis for taking the lead on
  this conversion. As a result, the banner printed at startup for
  those snapshots has changed slightly. For a quick start guide for
  using git with ACL2, see [git-quick-start].

  (CCL only) Control-d now quits ACL2 in raw Lisp just as it has done
  for a long time in the loop and, for ACL2(h) (i.e., [hons-enabled]
  ACL2), even in raw Lisp.

  (Should essentially affect GCL only) Significant re-work has been
  done for function proclaiming, which is still only done when the
  host Lisp is GCL. In particular, the build process now has extra
  steps even for other Lisps though for them, the extra steps are
  trivial (technical details may be found in the comment labeled
  ``Essay on Proclaiming'' in source file acl2-fns.lisp). We now use
  GCL's automatic proclaiming mechanism to calculate function types
  during the build (boot-strap), as we have seen it perform better
  than our own. Thanks to Camm Maguire for helpful discussions, in
  particular for explaining that mechanism and for pointing out that
  the re-proclaiming that had been done previously during the build
  could lead to buggy behavior.

  For Makefile targets for testing such as regression, the default ACL2
  image used is now the same one that would be built for the same
  Makefile variables. In particular, the command make regression is
  equivalent to make regression ACL2_HONS=h, which uses the
  executable saved_acl2h, not saved_acl2 as was formerly the case.
  Thanks to Harsh Raju Chamarthi for finding a bug in a first attempt
  to make this change.


EMACS Support


Hons-enabled and Experimental Versions

  (For [hons-enabled] executables only) Fixed a soundness bug related
  to function memoization. For a proof of nil exploiting this bug in
  Version 6.5, see the comment about ``pons-addr-of-argument'' in
  Community Books file system/doc/acl2-doc.lisp, form (defxdoc
  note-7-0 ...). Thanks to Jared Davis for improving our original
  fix: by noting its applicability to [hons-clear] (not just
  [hons-wash]); by tweaking our fix so that it works even if a
  control-c interrupts (hons-clear or) hons-wash; and later by
  finding another bug in source function pons-addr-of-argument and
  suggesting a fix, which we incorporated.

  (For [hons-enabled] executables only) Fixed a soundness bug due to
  the fact that function never-memoize-fn returned nil in the logic
  but returned t in raw Lisp. For a proof of nil exploiting this bug
  in Version 6.5, see the comment about ``never-memoize-fn'' in
  Community Books file system/doc/acl2-doc.lisp, form (defxdoc
  note-7-0 ...).

  Static honsing for [hons-enabled] ACL2, an efficiency enhancement
  formerly only available for CCL, is now incorporated into builds on
  sufficiently recent GCL versions.

  ACL2 executables that were [hons-enabled] could fail to use
  previously-compiled definitions for [memoize]d functions when
  [include-book] is invoked. This has been fixed.

  (For [hons-enabled] executables only built on other than CCL or SBCL)
  Calls of [memoize] only compile the memoized definition when the
  original function is compiled, rather than unconditionally as
  before.

  Several changes been made to function memoization (see [memoize]).
  Here is a list of changes visible at the user level; for
  implementation details, see [note-7-0-memoize].

    * It is now legal to call [memoize] on functions with special raw-Lisp
      code (such as [len]) provided the value of the :inline keyword
      argument is nil.
    * Bug fix: Fixed bug that was making [memsum] attribute the count of
      making of hash tables to ``Heap bytes allocated'' instead of to
      ``Number of calls to mht.''
    * Memoize keyword :trace is no longer supported, as the [trace$]
      utility provides much more flexibility.
    * Bug fix: Fixed a bug in handling of the :commutative argument of
      [memoize] that could cause a hard Lisp error. For a book that
      exhibits this bug, see the comment about ``:commutative'' in
      Community Books file system/doc/acl2-doc.lisp, in the form
      (defxdoc note-7-0 ...).
    * When [memoize] is called with keyword argument :commutative having
      value t, the benefit of that argument can apply to rational
      number arguments even when not using static honsing. Moreover,
      now only one argument needs to be a rational or to be
      ``static'' according to the implementation (technically: to
      have an hl-staticp value).
    * Bug fix: Calls of [memoize] with keyword argument :commutative t were
      sometimes inappropriately treated as redundant
      [redundant-events]. This has been fixed. Here is a simple
      example of what formerly went wrong.

          (defn f (x y) (equal x y))
          (memoize 'f :commutative t)
          (unmemoize 'f)
          (memoize 'f :commutative t) ; was redundant, so did not memoize

    * (For those who memoized directly in raw Lisp) Memoize-fn now requires
      its first argument to be a defined (fboundp) function symbol.
      (It seemed odd and needlessly arcane to allow memoize-fn to
      define an undefined function.)
    * (For those who memoized directly in raw Lisp) Memoize-fn now causes
      an error when it fails.
    * Bug fix: It had been possible to lose a memoization setting of :aokp
      t when many functions were memoized. For an example, see the
      comment about ``rememoize-all'' in Community Books file
      system/doc/acl2-doc.lisp, in the form (defxdoc note-7-0 ...).
    * We eliminated undocumented utilities memoize-on and memoize-off,
      which were not used as far as we know.
    * When a memoized function call fails to satisfy the specified
      condition, that call is no longer counted as a ``hit'', at
      least by default. This can be changed with raw Lisp variable,
      *condition-nil-as-hit*.
    * The utility [memsum] had reported one more pons call and (CCL only)
      one more byte than was correct, and could perhaps report one
      call when there were actually zero. That has all been fixed.
    * Bug fix: Some sorting of results based on ``self'' time and ``other
      functions'' time had been wrong. (Technical remark: the problem
      was that the implementation confused ``ticks'' with ``time''.)
      This has been fixed.
    * Statistics reporting (see [memsum]) often has a more uniform look. It
      is now done with a right margin of 79 instead of 70. For
      [memsum], thanks to a suggestion from Warren Hunt, the defun
      formerly printed to start each entry is now omitted, and after
      the name is printed at the start, a newline is printed before
      the ``hits'' or ``hits/calls'' information is printed. A
      related change: when *report-hits* and *report-calls* are both
      nil, ``calls'' is no longer printed. Other cosmetic changes
      were also made to [memsum] output.
    * The output from [memsum] on the line ``Time of all outermost calls''
      no longer includes a percentage, which had been at best
      misleading and at worse nonsensical. Suppose for example that f
      calls g, which does all the work. Then memsum had reported 50%
      of the ``Time of all outermost calls'' for each of f and g,
      even though 100% of the time was spent under each.
    * On Mac OS (Darwin), the physical memory is now accurately computed
      (using shell command ``sysctl hw.memsize'', which works in some
      versions of Mac OS, maybe all recent ones; tested on 10.6 and
      10.7). Before, the physical memmory value had been assumed to
      be 2^32 bytes. The physical memory value is used in CCL for
      triggering garbage collections. (Technical remark: this is
      implemented in function start-sol-gc.)
    * Bug fix: in the pons summary, misses had been reported instead of
      hits on the ``hits/calls'' line.
    * Fixed [memsum] so that package names are printed with the symbols.
      Also, printing is done with respect to the current package, not
      the \"ACL2\" package.
    * It is now legal to [profile] functions that take [state] as an
      argument. Thanks to Sol Swords for requesting this change. In
      the course of making this change, we took a conservative
      approach and put the same requirement regarding illegal
      memoization of functions involving user-defined [stobj]s: that
      is, when memoization must have value nil for the :condition
      keyword, it must also have value nil for the :inline keyword.
      We can perhaps remove this additional restriction if necessary.
    * For every built-in memoized function defined in the ACL2 logic, the
      memoization is done in the usual way (during the ACL2 build),
      using the [memoize] event during the ACL2 build. Such functions
      can thus be [unmemoize]d by users in the usual way. Thanks to
      David Rager for requesting this enhancement.
    * A new memoize keyword, :stats, can control whether statistics will be
      saved for reporting with (memsum).
    * Memoization in [hons-enabled] ACL2(p) is no longer affected by calls
      of [set-waterfall-parallelism].

  (ACL2(p) only, either [hons-enabled] or not) The function
  [Cpu-core-count] is now sensitive to environment variable
  ACL2_CORE_COUNT. See [cpu-core-count]. Thanks to Jared Davis for
  requesting this enhancement.

  Support for multi-threading has been added for memoization. Thanks to
  Jared Davis for contributing an initial implementation. Note that
  this may slow down [hons-enabled] ACL2(p) by several percent on
  memoization-intensive applications. Undocumented function
  mf-multiprocessing is available for low-level system hackers to
  turn on/off this feature, which by default is off for
  [hons-enabled] ACL2 and on for [hons-enabled] ACL2(p).

  (ACL2(p) only, either [hons-enabled] or not) We fixed a bug in
  [pand], which we believe was also a bug in [por], [pargs], and
  [plet]. (Technical remark: this bug had a low-level cause,
  pertaining to maintenance of a Lisp variable, *ld-level*, that
  holds the number of nested calls of [ld].) Thanks to Jared Davis
  for reporting this bug and to David Rager for assisting in its
  repair. Below is a slightly simplified version of Jared's example,
  which formerly caused an assertion error but now works as expected.

    (defmacro pand* (x y)
      `(spec-mv-let (yval)
                    ,y
                    (mv?-let (xval)
                             ,x
                             (if xval
                                 yval
                               nil))))
    (defn f3 (x)
      (pand* x x))
    (defn f4 (x)
      (pand x
            (f3 x)))
    (value-triple (f4 5))

  (Only for [hons-enabled] executables on Windows) Certain memory
  management is avoided on Windows (technically: by avoiding a call
  of source function start-sol-gc), where it was causing errors.
  Thanks to Harsh Raju Chamarthi and Sol Swords for testing on
  Windows that led us to this change.


Subtopics

  [Note-7-0-memoize]
      ACL2 Version 7.0 Notes on Changes to Memoization Implementation")
 (NOTE-7-0-MEMOIZE
  (NOTE-7-0)
  "ACL2 Version 7.0 Notes on Changes to Memoization Implementation

  See [memoize] for a user-level introduction to function memoization.
  Here we summarize technical changes made in Version 7.0 of ACL2 to
  the implementation of function memoization; most ACL2 users should
  have no need to read further in this topic. We thank Jared Davis
  for helpful conversations.

  The function memoize-init now resets the table *memo-max-sizes*,
  which is used when creating memo tables and pons tables. This
  change may be irrelevant, since generally memoize-init is only
  called at startup. But it seemed appropriate to reset it along with
  all other globals involved in the memoization implementation.

  Lisp variable *print-pretty* is no longer globally set to t by
  certain memoization code. Probably this change will not generally
  be observable.

  The utility [clear-memoize-statistics] now resets data for the pons
  summary, but implementation function clear-memo-tables no longer
  does so (it only calls clear-memoize-tables).

  Avoided some recklessness in computing statistics related to ponsing
  (specifically, replaced very-unsafe-incf by macro safe-incf-pons,
  which is a wrapper for safe-incf).

  Clear-memo-tables no longer takes &rest arguments, since it is merely
  a wrapper for [clear-memoize-tables], which does not (and did not)
  take &rest arguments.

  For the utility pons-summary, we no longer use our-syntax-nice; so
  far example, *print-case* is not bound to :downcase.

  Function internal-real-ticks (formerly internal-real-time) now uses
  [logand] in its implementation, which should improve performance.
  It also replaces, for non-static-hons implementations, the call
  (get-internal-real-time) by (the mfixnum (get-internal-real-time)),
  which can also help performance.

  More principled, consistent use is made of our-syntax for suitable
  printing.

  Added ``TO DO'' comments near the top of source file
  memoize-raw.lisp. Thanks to Jared Davis for suggesting some of
  these.

  We improved many comments in source file memoize-raw.lisp.

  We did some renaming, including the following (note that this is
  probably not a complete list):

    - number-of-arguments       -> mf-len-inputs
    - number-of-return-values   -> mf-len-outputs
    - *compute-array*           -> *callers-array*
    - maybe-count-pons-calls    -> incf-pons-calls
    - maybe-count-pons-misses   -> incf-pons-misses
    - print-alist               -> mf-print-alist
    - shorten                   -> mf-shorten
    - outside-p                 -> outside-caller-p
    - ofni                      -> mf-make-symbol
    - ofnum                     -> mf-num-to-string
    - internal-real-time        -> internal-real-ticks
    - dcls                      -> mf-dcls
    - hl-without-interrupts     -> without-interrupts [which already existed]
    - *ma-initial-max-symbol-to-fixnum* -> *initial-max-symbol-to-fixnum*
    - REPLACEMENT:
      *initial-max-memoize-fns* -> *initial-2max-memoize-fns*

  We eliminated some dead code, including the following functions
  (probably not a complete list): our-syntax-brief, ofnm, uses-state,
  global-restore-memoize, prine-alist, set-gc-threshold, our-gctime,
  and short-symbol-name, and all variants of format functions with
  names starting with \"of\" except for ofni (now mf-make-symbol) and
  ofnum (now mf-num-to-string). Also, we moved memoize-here-come to
  community book books/centaur/memoize/old/profile-raw.lsp. Regarding
  our-syntax-brief: there had been one call, in print-call-stack, but
  that call did not seem appropriate so we deleted it.

  The variable *count-pons-calls* was deleted. It had been set to t and
  was only used during macroexpansion of incf-pons-calls and
  incf-pons-misses (formerly maybe-count-pons-calls and
  maybe-count-pons-misses), where that macroexpansion was done at
  ACL2 build time --- hence user setting of *count-pons-calls* had no
  effect.

  We eliminated a needless error check that prevented loading
  memoize-raw.lisp without #+hons, since we don't currently ever
  expect to try to do that.

  Miscellaneous additional code cleanup has been done. Here is a
  (probably very incomplete) list.

    * Float-ticks/second-init uses a default rather than duplicating the
      default's code, and has improved treatment of errors.
    * Removed unused :before field of memoize-info-ht-entry record.
    * The implementations of number-of-arguments and
      number-of-return-values (now called mf-len-inputs and
      mf-len-outputs, respectively) have been made cleaner, in
      particular, starting with an empty
      *number-of-arguments-and-values-ht*.
    * New macros such as ma-index provide some abstraction, to give the
      illusion that *memoize-call-array* is two-dimensional.
    * We broke up some defintions, in particular substantially shortening
      memoize-fn by moving parts of it into new functions
      memoize-fn-inner-body, memoize-fn-outer-body, and
      memoize-fn-def. A benefit: it is easy to see the definition
      that is actually created when memoizing, by tracing
      memoize-fn-def.
    * Added raw Lisp interface function mf-note-arity for informing
      memoize-fn of input and output arities.
    * Coerce-index asserts that an index is in range rather than treating
      an out-of-range index as a symbol.
    * We renamed some variables to make them clearer. In particular, it is
      whether a variable stores time or ticks.
    * We now make complete and correct (we hope) the use of suitable fixnum
      and mfixnum declarations, many of which had been missing or
      incorrect.
    * Both [memoize] and [unmemoize] are now safe for control-c and
      unexpected errors.
    * We no longer set ccl::*save-definitions* or
      ccl::*fasl-save-definitions* to t. This may improve
      performance, but it may require explicitly calling
      mf-note-arity, as is now done in books/centaur/aig/bddify.lisp.
      However, this removes CCL-only behavior; in particular, we
      removed dependence on #+Clozure in
      books/centaur/aig/bddify.lisp for profiling count-branches-to.
    * We use #+ccl instead of #+Clozure, for consistency with most of the
      rest of ACL2.
    * We no longer set ccl::*save-source-locations* or
      ccl::*record-source-file* to t, as there is no clear advantage
      to doing so, and in fact there is a comment near the end of
      source file acl2.lisp suggesting that there could be slowdown
      from setting (at least) the first of these variables to t.
    * We slightly modified internal-real-time to improve its performance
      (see comments there).
    * We fixed a performance bug in function addr-for (parenthesis error
      was needlessly putting us in the ``large-case'').
    * Fixed a typo: declaim of fixnum type for *initial-max-memoize-fns*
      had instead been for nonexistent variable
      *initial-2max-memoize-fns*.
    * In memoize-fn, we removed support for :condition to be a function
      symbol, which was at best confused.
    * The table *never-memoize-ht* is now populated mostly automatically,
      by initialize-never-memoize-ht.
    * Slight optimization: the form (update-attached-fn-called
      ,*attached-fn-temp*), which had been in the definition of
      memoize-fn but now is in memoize-fn-inner-body, is conditioned
      on ,*attached-fn-temp*.")
 (NOTE-7-1
  (RELEASE-NOTES)
  "ACL2 Version 7.1 (May, 2015) Notes

  NOTE! New users can ignore these release notes, because the
  [documentation] has been updated to reflect all changes that are
  recorded here.

  Below we roughly organize the changes to ACL2 since Version 7.0 into
  the following categories of changes: existing features, new
  features, heuristic and efficiency improvements, bug fixes, changes
  at the system level, Emacs support, and experimental versions. Each
  change is described in just one category, though of course many
  changes could be placed in more than one category.

  The default build is [hons-enabled], as for the previous release; but
  the generated executable is now saved_acl2, as discussed below.
  Please note that ACL2(c) (``classic ACL2'', i.e., ACL2 that is not
  [hons-enabled]) now builds as saved_acl2c, is deprecated, and will
  likely be unsupported or even eliminated in future releases.

  See also [note-7-1-books] for a summary of changes made to the ACL2
  Community Books since ACL2 7.0, including the build system.


Changes to Existing Features

  For both [add-include-book-dir] and [add-include-book-dir!], the
  second argument is no longer evaluated (which we think could
  perhaps have been exploited to get unsound behavior, by arranging
  for the value of the second argument to depend on [state]).
  Moreover, that argument can not only be a string, but also can be a
  sysfile: an object (:system . filename), where filename is a file
  name. When filename is a relative pathname, the meaning of such an
  object is the file with that pathname under the system books
  directory.

  The event summary had not been printed when a proof is interrupted
  (that is, with Control-C). Now, summary information is printed for
  two summary types (see for example [set-inhibited-summary-types]):
  rules and hint-events.

  By default, (memsum) is now truncated to 100 entries rather than to
  20 entries. (Implementation note: raw Lisp variable
  *memoize-summary-limit* is 100 instead of 20.)

  Calls of THE no longer cause a [guard] violation when guard-checking
  is nil. Also see [the] and see [set-guard-checking].

  Type declarations for [let] and [mv-let] forms are now
  [guard]-checked. Consider for example the definition: (defun foo ()
  (let ((x t)) (declare (type integer x)) x)). Previously, evaluation
  of the call (foo) had failed to result in a guard violation error;
  now, it does, provided guard-checking is on (i.e., not nil or
  :none; see [set-guard-checking]).

  The symbols ctx, hist, pspv, unquote, and value have been added to
  [*ACL2-exports*]. Thanks to Jared Davis for suggesting these
  additions.

  Consider :use or :by [hints] in which a variable bound using the
  :instance keyword is in the wrong package. For example, for the
  hint :use ((:instance foo (x 3))), suppose that the lemma foo
  mentions the variable bar::x, but not x. This situation formerly
  caused an error, but now, x indicates the variable bar::x from the
  lemma foo. See [lemma-instance], in particular Condition (4), which
  has been updated accordingly. Thanks to David Rager for a remark
  that led us to implement this enhancement.

  The [ld] special ld-error-action may now have a value (:exit N),
  where N is a natural number. If an error occurs for a call of ld,
  then this value causes the ACL2 process to quit with exit status N.
  See [ld-error-action]. Note that ld-error-action is set to this new
  value when using the cert.pl utility provided with the community
  books; see [2._Pre_Certify-Book_Commands]. Thanks to David Rager
  for presenting an example showing how this change can make it
  easier to locate certain certification failures, and thanks to Sol
  Swords for helping in the design of this enhancement.

  A \"[Theory]\" warning is still printed when [definition]s of certain
  built-in functions, such as [mv-nth], are [disable]d; similarly for
  some built-in [executable-counterpart] rules. However, we now print
  such warnings only when the disabling occurs, rather than every
  time an [in-theory] event or hint is evaluated. For example, if you
  evaluate (in-theory (disable mv-nth)) followed by (in-theory
  (disable append)), then the second event will no longer produce a
  warning about mv-nth. Thanks to Eric Smith for (most recently)
  suggesting such a change.

  (SBCL only) ACL2 built on SBCL now reports bytes usage, both in
  [time$] and in [memsum], essentially exactly as has already been
  done for ACL2 built on CCL. Thanks to Jared Davis for suggesting
  this enhancement.

  (SBCL only) [Fast-alists] can now be garbage collected (we believe)
  in SBCL, as they had already been done in CCL. (Implementation
  note: The change was to use weak hash tables in the implementation
  of SBCL fast-alists.) Thanks to Jared Davis for suggesting this
  enhancement.

  The utility [ec-call] can now be applied to calls of symbols
  introduced with [defun-inline], or with [define] using keyword
  argument :inline t, thanks to a request from Jared Davis. For
  example, the following is now legal.

    (defun-inline foo (x)
      (cons x x))

    (defun bar (x)
      (ec-call (foo x)))

  The [proof-checker] is now sensitive to the current
  [case-split-limitations].


New Features

  The Common Lisp function [sleep] is now defined in ACL2. Thanks to
  Jared Davis for requesting this addition.

  Custom error messages may now be created for guard violations. See
  [set-guard-msg].

  The new macro [assert*] is like [assert$], except that assert* only
  generates a [guard] proof obligation, not a runtime check. Assert*
  is defined using a new macro [mbt*], which is a variant of [mbt]: a
  call of mbt* logically returns t, but generates the same [guard]
  proof obligation as mbt. Thanks to Shilpi Goel for a query that led
  us to add these macros.


Heuristic and Efficiency Improvements

  We fixed an inefficiency that could occur in calls of [program]-mode
  functions that update [stobj]s. See the discussion of
  invariant-risk in the [documentation] topic, [program-wrapper].
  Thanks to Jared Davis for bringing this issue to our attention.

  We improved the ``worse-than'' heuristic, providing modest speed-up
  and eliminating the use of memoization for it. Thanks to Jared
  Davis for useful discussions on the topic, and to Camm Maguire for
  an observation that led us to do some investigations that led to
  this improvement. For more information see comments in source
  function worse-than-builtin-clocked (source file type-set-b.lisp).

  We avoid the cost of translating ACL2 terms (see [term]) to
  user-level syntax after applying the ``preprocess'' simplifier (see
  [hints-and-the-waterfall]), and also after applying either :use or
  :by [hints]. Thanks to David Rager for helpful discussions towards
  this change. Note: On rare occasions, this might change the prover
  flow as follows.

    * Consider the case that the input goal, \"Goal\", simplifies with the
      ``preprocess'' simplifier to a new goal that prints the same as
      \"Goal\". Formerly, this case avoided labeling the new goal as
      \"Goal'\"; it was as though the new goal was actually the user
      input. The new criterion for avoiding \"Goal'\" is somewhat
      weaker: the internal syntax must suitably match for \"Goal\" and
      its simplification, rather than their displayed forms.
    * Consider the application of a :use or :by hint. In such cases, the
      resulting constraint (if any) is simplified with the
      ``preprocess'' simplifier. Formerly, the rules used by that
      simplifier were not recorded if the printed version of the
      simplified constraint was equal to the original constraint,
      which was really a bug since the comparison was between the
      user-level syntax of the simplified constraint and the internal
      syntax of the original constraint. Now, ACL2 compares the
      internal syntax of each.

  We fixed an inefficiency that could occur in processing of
  [make-event] forms. Thanks to Sol Swords for reporting and
  diagnosing the problem. (Technical note: The fix involves avoiding,
  in most cases, looking up world global 'boot-strap-flg by using a
  new state global instead of the same name.)

  We changed the heuristics for equality subsitution so that so-called
  cross-fertilization, where an equality substitution is made on only
  one side of the goal's conclusion, is not made when generalization
  is turned off, as with the hint :do-not '(generalize). Instead, the
  equality is used throughout the goal in that case. Thanks to David
  Hardin for bringing an example to our attention that led us to make
  this change.

  Some clause-building (essentially, goal-building) operations already
  avoided duplication, but now consider clauses to be ``duplicates''
  when the only difference is commuted arguments of [equal] or [iff].
  (Note: This change was made in support of [assert*] and [mbt*],
  mentioned above.)

  (SBCL only) It had been the case for host Lisp SBCL that the use of
  [defun-inline] to define functions in [books] had failed to result
  in inlined code, when those functions were called after including
  those books. This has been fixed (and appears not to have been a
  problem for host Lisp CCL). Thanks to Jared Davis for bringing this
  issue to our attention.


Bug Fixes

  A potential soundness issue could result from the application of
  [meta]functions and [clause-processor]s: although ACL2 checked that
  their outputs contain only legal [term]s, it did not check for the
  absence of calls of certain ``forbidden'' function symbols. For
  example, [sys-call] should be prohibited unless there is an active
  trust tag (see [defttag]), but a metafunction was able to introduce
  a call of sys-call. We have added the necessary checks, in a way
  that we hope has negligible impact on performance. To avoid that
  impact or to learn more about this issue, see
  [set-skip-meta-termp-checks]; this new utility, which requires a
  trust tag, avoids not only the new checks but even the
  above-mentioned checks for legal terms.

  The edited log below illustrates a bug that we have fixed, involving
  the processing of [include-book] [events] in the certification
  [world] whose filename starts with the tilde (~) character.

    ~/temp/incl$ cat sub/bad.acl2
    (include-book \"~/acl2/acl2/books/arithmetic/top\")
    ~/temp/incl$ acl2h
    [[.. output elided ..]]
    ACL2 !>(ld \"sub/bad.acl2\")
    [[.. output elided ..]]
    ACL2 !>(certify-book \"foo\" 1)


    HARD ACL2 ERROR in ABSOLUTE-PATHNAME-STRING-P:  Implementation error:
    Forgot to apply expand-tilde-to-user-home-dir before calling absolute-
    pathname-string-p. Please contact the ACL2 implementors.



    ACL2 Error in TOP-LEVEL:  Evaluation aborted.  To debug see :DOC print-
    gv, see :DOC trace, and see :DOC wet.

    ACL2 !>

  Fixed several issues with the :puff command, and updated its
  documentation accordingly. See [puff].

  Fixed a bug in the [proof-checker]'s wrap command. Thanks to Keshav
  Kini for sending a simple example that illustrated this bug.

  (Allegro CL only) Fixed a bug in [trace!], which for example was
  evidenced when evaluating (trace! (nth :native t)).

  Fixed a bug in the printing of user-level terms that failed to
  account for [untrans-table] entries for [nth], [update-nth], and
  [update-nth-array], when printing the first argument as a symbolic
  constant corresponding to a [stobj] argument. Thanks to Warren Hunt
  for reporting this issue with an example much like the following.
  When submitting the forms below, ACL2 output for the final form
  displayed the user-level term (update-nth *fld* v st) instead of
  the expected form, (!nth *fld* v st).

    (defstobj st fld)

    (defmacro !nth (x y z)
      `(update-nth ,x ,y ,z))

    (add-macro-fn !nth update-nth)

    (thm (equal (update-fld v st)
                xxx)
         :hints ((\"Goal\" :in-theory (disable update-nth))))

  Fixed a failure to [guard]-check [type] declarations for [let] and
  [mv-let] forms. Consider for example:

    (defun foo (x)
      (let ((a (car x)))
        (declare (type string a))
        a))

  Previously, the call (foo '(3 4)) did not cause a guard violation,
  even though it should have done so. (Indeed, the event
  (verify-guards foo) failed, and continues to fail.)

  Fixed a bug in redundancy checking for [mutual-recursion] events that
  specify :[ruler-extenders] in an [xargs] [declare] form. Thanks to
  Sol Swords for sending an example that illustrates the bug: a
  [mutual-recursion] event that, when executed twice, caused an error
  the second time rather than being redundant (see
  [redundant-events]). The bug was actually in how ACL2 stores
  information about the [ruler-extenders] used in definitions: the
  :ruler-extenders specified for the first [defun] was being
  mistakenly stored for the second defun. This mishandling of
  redundancy for [mutual-recursion] events appears to be the only
  consequence of that bug.

  The following bug was probably not observable, but violated our claim
  that the system behaves as logically specified. When a [guard]
  check failed during execution, the error message that was printed
  could differ slightly from what is logically specified. (Technical
  detail: the error actually printed by source function ev-fncall-rec
  was appropriately showing the original guard, but the specification
  function ev-fncall-rec-logical was showing the untranslation of the
  translated guard.) This has been fixed.

  The save and retrieve commands for the [proof-checker] (see
  [ACL2-pc::save] and [ACL2-pc::retrieve]) now cause an error when
  the supplied name is not a symbol; similarly for the :event-name
  argument of [verify]. The behavior wasn't as expected for
  non-symbol names; for example, after issuing the instruction (save
  'abc) in the [proof-checker], the command (retrieve 'abc) failed to
  resume the proof-checker session. (Notice the erroneous use of the
  quoted symbol 'abc, i.e., (quote abc), rather than of the symbol
  abc.) Thanks to Keshav Kini for bringing this problem to our
  attention.

  We fixed the following two bugs in the processing of backchain limits
  stored for rules. Thanks to Dave Greve for bringing these to our
  attention.

    * For rules of class :[type-prescription], the specification of
      :backchain-limit-lst within the :[rule-classes] could be
      ignored or cause a hard Lisp error.
    * For rules of class :[meta], preceding calls of
      [set-default-backchain-limit] were ignored.

  Fixed a bug in the processing of certain operations on pathnames
  containing \"..\".


Changes at the System Level

  By default, the ACL2 executable once again is named saved_acl2,
  though unlike previous versions, this executable is [hons-enabled].
  Correspondingly, the ACL2(c) executable (that is, the executable
  that is not [hons-enabled]) is by default saved_acl2c. Thanks to
  David Hardin for suggesting these changes.

  Links from the home page to user's manual topics now point to the
  ACL2+Books combined manual, not the ACL2 (only) User's Manual,
  except for the one link that explicitly points to the latter.
  Thanks to David Hardin for feedback leading to this change, which
  was incorporated into the ACL2 Version 7.0 home page several days
  after the release of that version.

  Garbage collection notification has been turned off by default, not
  only for ACL2(c) as before, but also for (the default build)
  ACL2(h). Thanks to Eric Smith for suggesting this change. See
  [ACL2-customization] and see [gc-verbose] for how to turn such
  notification back on in your own environment.

  It is now possible to move the system books directory after
  certifying its books, without invalidating their status as
  certified. Users should generally not notice this change. We thank
  Harsh Raju Chamarthi and Camm Maguire for reporting problems with
  hacks we have produced over the years to support distribution of
  books with their [certificate] files. Those hacks are no longer
  necessary: as a byproduct of this change, we have deleted both the
  [community-books] directory books/fix-cert/ and the source function
  make-certificate-file-relocated. For a bit more detail see the
  final remark in the topic [full-book-name]. We also thank Eric
  Smith, Jared Davis, and Sol Swords for reporting bugs in our
  initial implementations of this enhancement.

  The certify-books target for make now excludes other expensive
  directories in addition to workshops.

  (SBCL only) Modified the handling of environment variable SBCL_HOME.
  Thanks to Jared Davis for pointing out a problem leading to this
  change, namely, failure on his platform when evaluating (require
  :sb-sprof) in raw Lisp.

  Intended compiler optimizations are now guaranteed to be in place. We
  observed, thanks to communication from Jared Davis, that when ACL2
  is built using SBCL 1.2.10, ACL2 starts up without the compiler
  optimizations that had been installed during the build. Perhaps
  that has been true for other SBCL versions or even other Lisps.
  Now, ACL2 explicitly restores those optimizations when it starts
  up. We observed a 5% time reduction for SBCL-based regression after
  this change.

  Environment variable ACL2_WRITE_PORT is now ignored when doing
  [provisional-certification]. Thanks to Sol Swords for discussing
  this issue, which arose from a failure in [community-books]
  directory books/workshops/2011/verbeek-schmaltz/sources/, which
  uses [provisional-certification].

  (GCL only) A few tweaks were made in support of GCL changes starting
  with pre-releases of GCL 2.6.13 in late April 2015 (but these
  tweaks are backward compatible with older GCL releases). Resulting
  ACL2 builds for a new GCL show dramatic speed-ups for a single
  user, perhaps cutting between a third and half the time, with less
  dramatic improvements when running regressions with -j 8. Thanks to
  Camm Maguire for pointing us to the changes and for improving GCL.


EMACS Support

  The commands Control-t e and Control-t Control-e, defined in file
  emacs/emacs-acl2.el, now check that the *acl2-shell* buffer exists,
  has a live process, and has a last line matching the specification
  in *acl2-insert-pats*, which has Emacs documentation (using
  Control-h v) but is set to a default based on shell prompts. Thanks
  to David Rager, Jared Davis, and Shilpi Goel for helpful
  discussions leading to this change.

  We installed the following two patches to file emacs/emacs-acl2.el,
  both contributed by Keshav Kini.

    * Emacs highlighting for forms starting with \"(def\" now works when the
      \"def\" symbol has a package prefix, for example,
      \"(fty::deflist\".
    * The Control-d character is no longer explicitly bound to the default,
      delete-char, but instead is unbound in comint-mode-map, so that
      the global binding of Control-d will take effect. Thus, users
      who bind Control-d themselves will no longer have that binding
      overridden in shell-mode (or comint-mode).

  We made several improvements to the [ACL2-doc] Emacs browser for ACL2
  [documentation].

    * Fixed a bug that could occur when Emacs variable
      large-file-warning-threshold is nil. Thanks to Bob Boyer for
      bringing this bug to our attention.
    * Links are now in color (blue, by default). See [ACL2-doc] for
      instructions on how to change or remove this color. Thanks to
      Jared Davis for suggesting the use of color. We are open to
      suggestions for improvements; this might be just a first step.
    * Allow limiting search and index commands to ancestors (sub-topics,
      sub-sub-topics, etc.) of a command (including the command
      itself), by supplying a prefix argument.
    * New \"p\", \"<\", and Control-TAB commands are analogues of \"n\" and \",\"
      --- for search, index, and next-link commands, respectively ---
      to go backward instead of forward.


Experimental Versions

  (For ACL2(p) users only; see [parallelism]) If parallel execution is
  enabled (see (@see set-parallel-execution)), as it is by default in
  ACL2(p), then hons-wash and hons-clear may be no-ops (other than to
  print a warning), in order to avoid thread-unsafe behavior.
  (However, In CCL you are unlikely to see this restriction unless
  you are running more than one thread.) To get around this
  restriction, you can instead use [hons-wash!] or [hons-clear!],
  which however require a [trust-tag]. Thanks to Bob Boyer for
  bringing this issue to our attention.")
 (NOTE1
  (RELEASE-NOTES)
  "Acl2 Version 1.1 Notes

  The new features are extensively documented. The relevant topics are:

  It is especially important to read all of of the [documentation] for
  [books] before trying to use books. However, the new :more keyword
  command is so handy for reading long [documentation] strings that
  we recommend you start with :[doc] more if reading at the terminal.
  Some documentation has been written for [guard]s which you might
  find interesting.


Subtopics

  [Books]
      Books are files of ACL2 [events]---they are the main way to split up
      large ACL2 developments into separate modules.")
 (NOTE2
  (RELEASE-NOTES)
  "Acl2 Version 1.2 Notes

  Hacker mode has been eliminated and [programming] mode has been
  added. [Programming] mode is unsound but does syntax checking and
  permits redefinitions of names. See :[doc] load-mode and :[doc]
  g-mode.

  The arguments to [ld] have changed. [Ld] is now much more
  sophisticated. See [ld].

  For those occasions on which you wish to look at a large list
  structure that you are afraid to print, try (walkabout x state),
  where x is an Acl2 expression that evaluates to the structure in
  question. I am afraid there is no [documentation] yet, but it is
  similar in spirit to the Interlisp structure editor. You are
  standing on an object and commands move you around in it. E.g., 1
  moves you to its first element, 2 to its second, etc.; 0 moves you
  up to its parent; nx and bk move you to its next sibling and
  previous sibling; pp prettyprints it; [q] exits returning nil; [=]
  exits returning the thing you're standing on; (= symb) assigns the
  thing you're standing on to the [state] global variable symb.

  Several new [hints] have been implemented, including :by and :do-not.
  The old :do-not-generalize has been scrapped in favor of such new
  [hints] as :do-not (generalize elim). :By lets you say ``this goal
  is subsumed by'' a given lemma instance. The :by hint also lets you
  say ``this goal can't be proved yet but skip it and see how the
  rest of the proof goes.'' See [hints].")
 (NOTE3
  (RELEASE-NOTES)
  "Acl2 Version 1.3 Notes

  [Programming] mode has been eliminated. Instead, all functions have a
  ``color'' which indicates what can be done with the function. For
  example, :red functions can be executed but have no axioms
  describing them. Thus, :red functions can be introduced after
  passing a simple syntactic check and they can be redefined without
  undoing. But nothing of consequence can be proved about them. At
  the other extreme are :gold functions which can be executed and
  which also have passed both the termination and the [guard]
  verification proofs. The color of a function can be specified with
  the new [xargs] keyword, :color, which, if omitted defaults to the
  global setting of ld-color. Ld-color replaces load-mode. Setting
  ld-color to :red causes behavior similar to the old :g-mode.
  Setting ld-color to :gold causes behavior similar to the old
  :v-mode. It is possible to prototype your system in :red and then
  convert :red functions to :blue individually by calling
  [verify-termination] on them. They can then be converted to :gold
  with [verify-guards]. This allows us to undertake to verify the
  termination and [guard]s of system functions. See :[doc] color for
  an introduction to the use of colors.

  Type prescription rules have been added. Recall that in Nqthm, some
  [rewrite] rules were actually stored as ``[type-prescription]s.''
  Such rules allow the user to inform Nqthm's primitive type
  mechanism as to the kinds of shells returned by a function. Earlier
  versions of Acl2 did not have an analogous kind of rule because
  Acl2's type mechanism is complicated by [guard]s. Version 1.3
  supports [type-prescription] rules. See [type-prescription].

  Three more new [rule-classes] implement congruence-based rewriting.
  It is possible to identify a binary relation as an equivalence
  relation (see [equivalence]), to show that one equivalence relation
  refines another (see [refinement]) and to show that a given
  equivalence relation is maintained when rewriting a given function
  call, e.g., (fn ...xk...), by maintaining another equivalence
  relation while rewriting the kth argument (see [congruence]). If r
  has been shown to be an [equivalence] relation and then (implies
  hyps (r (foo x) (bar x))) is proved as a :[rewrite] rule, then
  instances of (foo x) will be replaced by corresponding instances of
  (bar x) provided the instance occurs in a slot where the
  maintainence of r-equivalence is known to be sufficient and hyps
  can be established as usual.

  In Version 1.2, [rule-classes] were simple keywords, e.g., :[rewrite]
  or :[elim]. In Version 1.3, [rule-classes] have been elaborated to
  allow you to specify how the theorem ought to be used as a rule.
  That is, the new [rule-classes] allows you to separate the
  mathematical statement of the formula from its interpretation as a
  rule. See [rule-classes].

  Rules used to be named by symbols, e.g., [car] and car-cons were the
  names of rules. Unfortunately, this was ambiguous because there are
  three rules associated with function symbols: the symbolic
  definition, the executable counterpart, and the
  [type-prescription]; many different rules might be associated with
  theorems, depending on the rule classes. In Version 1.3 rules are
  named by ``[rune]s'' (which is just short hand for ``rule names'').
  Example [rune]s are (:definition car), (:executable-counterpart
  car), and (:type-prescription car . 1). Every rule added by an
  event has a different name and you can [enable] and [disable] them
  independently. See [rune] and see [theories].

  The identity function [force], of one argument, has been added and
  given a special interpretation by the functions responsible for
  establishing hypotheses in backchaining: When the system fails to
  establish some hypothesis of the form (force term), it simply
  assumes it is true and goes on, delaying until later the
  establishment of term. In particular, pushes a new subgoal to prove
  term in the current context. When that subgoal is attacked, all of
  the resources of the theorem prover, not just rewriting, are
  brought to bear. Thus, for example, if you wish to prove the rule
  (implies (good-statep s) (equal (exec s n) s')) and it is your
  expectation that every time exec appears its first argument is a
  good-statep then you might write the rule as (implies (force
  (good-statep s)) (equal (exec s n) s')). This rule is essentially
  an unconditional rewrite of (exec s n) to s' that spawns the new
  goal (good-statep s). See [force]. Because you can now specify
  independently how a theorem is used as a rule, you need not write
  the [force] in the actual theorem proved. See [rule-classes].

  Version 1.3 supports a facility similar to Nqthm's [break-lemma]. See
  [break-rewrite]. You can install ``[monitor]s'' on [rune]s that
  will cause interactive breaks under certain conditions.

  Acl2 also provides ``[wormhole]s'' which allow you to write functions
  that cause interaction with the user but which do not require that
  you have access to [state]. See [wormhole].

  The rewriter now automatically backchains to stronger recognizers.
  There is no user hook to this feature but it may simplify some
  proofs with which older versions of Acl2 had trouble. For example,
  if the rewriter is trying to prove (rationalp (foo a b c)) it is
  now smart enough to try lemmas that match with (integerp (foo a b
  c)).")
 (NOTE4
  (RELEASE-NOTES)
  "Acl2 Version 1.4 Notes

  Once again [ld] only takes one required argument, as the bind-flg has
  been deleted.

  Three commands have been added in the spirit of :[pe]. :[Pe!] is
  similar to :[pe] but it prints all [events] with the given name,
  rather than just the most recent. The command :[pf] prints the
  corollary formula corresponding to a name or [rune]. The command
  :[pl] (print lemmas) prints rules whose top function symbol is the
  given name. See [pe!], see [pf], and see [pl].

  Book naming conventions have been changed somewhat. The once-required
  .lisp extension is now prohibited! Directories are supported,
  including a notion of ``connected book directory''. See
  [book-name]. Also, the second argument of [certify-book] is now
  optional, defaulting to 0.

  [Compilation] is now supported inside the Acl2 loop. See [comp] and
  see [set-compile-fns].

  The default color is now part of the Acl2 [world]; see :[doc]
  default-color. Ld-color is no longer an [ld] special. Instead,
  colors are [events]; see the documentation for red, pink, blue, and
  gold.

  A [table] exists for controlling whether Acl2 prints comments when it
  [force]s hypotheses of rules; see :[doc] force-table. Also, it is
  now possible to turn off the forcing of assumptions by disabling
  the definition of [force]; see [force].

  The event defconstant is no longer supported, but a very similar
  event, [defconst], has been provided in its place. See [defconst].

  The event for defining [congruence] relations is now [defcong]
  (formerly, defcon).

  Patterns are now allowed in :expand [hints]. See the documentation
  for :expand inside the documentation for [hints].

  We have improved the way we report rules used by the simplifier. All
  [rune]s of the same type are reported together in the running
  commentary associated with each goal, so that for example,
  executable counterparts are listed separately from definitions, and
  rewrite rules are listed separately from [linear] rules. The
  preprocessor now mentions ``simple'' rules; see [simple].

  The mechanism for printing warning messages for new rewrite rules,
  related to subsumption, now avoids worrying about nonrecursive
  function symbols when those symbols are [disable]d. These messages
  have also been eliminated for the case where the old rule is a
  :[definition] rule.

  Backquote has been modified so that it can usually provide
  predictable results when used on the left side of a rewrite rule.

  Time statistics are now printed even when an event fails.

  The Acl2 trace package has been modified so that it prints using the
  values of the Lisp globals *print-level* and *print-length*
  (respectively).

  [Table] has been modified so that the :clear option lets you replace
  the entire [table] with one that satisfies the val and key guards
  (if any); see [table].

  We have relaxed the translation rules for :measure [hints] to
  [defun], so that the the same rules apply to these terms that apply
  to terms in [defthm] [events]. In particular, in :measure [hints]
  [mv] is treated just like [list], and [state] receives no special
  handling.

  The [loop-stopper] test has been relaxed. The old test required that
  every new argument be strictly less than the corresponding old
  argument in a certain [term-order]. The new test uses a
  lexicographic order on term lists instead. For example, consider
  the following rewrite rule.

    (equal
     (variable-update var1
                      val1 (variable-update var2 val2 vs))
     (variable-update var2
                      val2 (variable-update var1 val1 vs)))

  This rule is permutative. Now imagine that we want to apply this rule
  to the term

    (variable-update u y (variable-update u x vs)).

  Since the actual corresponding to both var1 and var2 is u, which is
  not strictly less than itself in the [term-order], this rule would
  fail to be applied in this situation when using the old test.
  However, since the pair (u x) is lexicographically less than the
  pair (u y) with respect to our [term-order], the rule is in fact
  applied using our new test.

  Messages about [events] now contain a space after certain left
  parentheses, in order to assist emacs users. For example, the event

    (defthm abc (equal (+ (len x) 0) (len x)))

  leads to a summary containing the line

    Form:  ( DEFTHM ABC ...)

  and hence, if you search backwards for ``(defthm abc'', you won't
  stop at this message.

  More tautology checking is done during a proof; in fact, no goal
  printed to the screen, except for the results of applying :use and
  :by [hints] or the top-level goals from an induction proof, are
  known to Acl2 to be tautologies.

  The [ld-query-control-alist] may now be used to suppress printing of
  queries; see [ld-query-control-alist].

  Warning messages are printed with short summary strings, for example
  the string ``Use'' in the following message.

    Acl2 Warning [Use] in DEFTHM:  It is unusual to :USE an enabled
    :REWRITE or :DEFINITION rule, so you may want to consider
    disabling FOO.

  At the end of the event, just before the time is printed, all such
  summary strings are printed out.

  The keyword command :u has been introduced as an abbreviation for
  :[ubt] :[max]. Printing of query messages is suppressed by :u.

  The keyword :cheat is no longer supported by any event form.

  Some irrelevant formals are detected; see [irrelevant-formals].

  A bug in the application of metafunctions was fixed: now if the
  output of a metafunction is equal to its input, the application of
  the metafunction is deemed unsuccessful and the next metafunction
  is tried.

  An example has been added to the documentation for [equivalence] to
  suggest how to make use of [equivalence] relations in rewriting.

  The following Common Lisp functions have been added to Acl2:
  [alpha-char-p], [upper-case-p], [lower-case-p], [char-upcase],
  [char-downcase], [string-downcase], [string-upcase], and
  digit-charp-p.

  A documentation section called [proof-checker] has been added for the
  interactive facility, whose documentation has been slightly
  improved. See in particular the documentation for [proof-checker],
  [verify], and [macro-command].

  A number of [events] that had been inadvertently disallowed in
  [books] are now permitted in [books]. These are: [defcong], defcor,
  [defequiv], [defrefinement], [defstub], and [verify-termination].")
 (NOTE5
  (RELEASE-NOTES)
  "Acl2 Version 1.5 Notes

  Acl2 now allows ``complex rationals,'' which are complex numbers
  whose real parts are rationals and whose imaginary parts are
  non-zero rationals. See [complex].

  A new way of handling [force]d hypotheses has been implemented.
  Rather than cause a case split at the time the [force] occurs, we
  complete the main proof and then embark on one or more ``forcing
  rounds'' in which we try to prove the [force]d hypotheses. See
  [forcing-round]. To allow us to compare the new handling of [force]
  with the old, Version 1.5 implements both and uses a flag in
  [state] to determine which method should be used. Do (assign
  old-style-forcing t) if you want [force] to be handled as it was in
  Version 1.4. However, we expect to eliminate the old-style forcing
  eventually because we think the new style is more effective. To see
  the difference between the two approaches to forcing, try proving
  the associativity of [append] under both settings of
  old-style-forcing. To get the new behavior invoke:

    (thm (implies (and (true-listp a) (true-listp b))
                  (equal (append (append a b) c)
                         (append a (append b c)))))

  Then (assign old-style-forcing t) and invoke the thm [command] above
  again.

  A new :cases [hints] allows proof by cases. See [hints].

  [Include-book] and [encapsulate] now restore the
  [ACL2-defaults-table] when they complete. See [include-book] and
  see [encapsulate].

  The [guard]s on many Acl2 primitives defined in axioms.lisp have been
  weakened to permit them to be used in accordance with lisp custom
  and tradition.

  It is possible to attach heuristic filters to :[rewrite] rules to
  limit their applicability. See [syntaxp].

  A tutorial has been added (but as of Version_3.6.1 it has become
  obsolete).

  [Events] now print the Summary paragraph listing [rune]s used, time,
  etc., whether they succeed or fail. The format of the ``[failure]
  banner'' has been changed but still has multiple asterisks in it.
  Thm also prints a Summary, whether it succeeds or fails; but thm is
  not an event.

  A new event form [skip-proofs] has been added; see [skip-proofs].

  A user-specific customization facility has been added in the form of
  a book that is automatically included, if it exists on the current
  directory. See [ACL2-customization].

  A facility for conditional metalemmas has been implemented; see
  [meta].

  The acceptable values for [ld-skip-proofsp] have changed. In the old
  version (Version 1.4), a value of t meant that proofs and [local]
  [events] are to be skipped. In Version 1.5, a value of t means
  proofs (but not [local] [events]) are to be skipped. A value of
  '[include-book] means proofs and [local] [events] are to be
  skipped. There are two other, more obscure, acceptable values. See
  [ld-skip-proofsp].

  In order to turn off the forcing of assumptions, one should now
  [disable] the :[executable-counterpart] of [force] (rather than the
  :[definition] of [force], as in the previous release); see [force].

  The macros [enable-forcing] and [disable-forcing] make it convenient
  to [enable] or [disable] forcing. See [enable-forcing] and see
  [disable-forcing].

  The new commands :[pr] and :[pr!] print the rules created by an event
  or command. See [pr] and see [pr!].

  The new [history] [command]s :[puff] and :[puff*] will replace a
  compound [command] such as an [encapsulate] or [include-book] by
  the sequence of [events] in it. That is, they ``[puff] up'' or
  ``lift'' the subevents of a [command] to the [command] level,
  eliminating the formerly superior [command] and lengthening the
  [history]. This is useful if you want to ``partially undo'' an
  [encapsulate] or book or other compound [command] so you can
  experiment. See [puff] and see [puff*].

  Theory expressions now are allowed to use the free variable [world]
  and prohibited from using the free variable [state]. See
  [theories], although it is essentially the same as before except it
  mentions [world] instead of [state]. See [world] for a discussion
  of the Acl2 logical [world]. Allowing [in-theory] [events] to be
  state-sensitive violated an important invariant about how [books]
  behaved.

  [Table] keys and values now are allowed to use the free variable
  [world] and prohibited from using the free variable [state]. See
  the note above about theory expressions for some explanation.

  The macro for minus, [-], used to expand (- x 3) to (+ x -3) and now
  expands it to (+ -3 x) instead. The old macro, if used in the
  left-hand sides of rewrite rules, produced inapplicable rules
  because the constant occurs in the second argument of the [+], but
  potential target terms generally had the constant in the first
  argument position because of the effect of commutativity-of-+.

  A new class of rule, :linear-alias rules, allows one to implement the
  nqthm package and similar hacks in which a [disable]d function is
  to be known equivalent to an arithmetic function.

  A new class of rule, :built-in-clause rules, allows one to extend the
  set of clauses proved silently by [defun] during measure and
  [guard] processing. See [built-in-clause].

  The new command [pcb!] is like [pcb] but sketches the [command] and
  then prints its subsidiary [events] in full. See [pcb!].

  :[Rewrite] class rules may now specify the :[loop-stopper] field. See
  [rule-classes] and see [loop-stopper].

  The rules for how [loop-stopper]s control permutative rewrite rules
  have been changed. One effect of this change is that now when the
  built-in commutativity rules for [+] are used, the terms a and (-
  a) are permuted into adjacency. For example, (+ a b (- a)) is now
  normalized by the commutativity rules to (+ a (- a) b); in Version
  1.4, b was considered syntactically smaller than (- a) and so (+ a
  b (- a)) is considered to be in normal form. Now it is possible to
  arrange for unary functions be be considered ``invisible'' when
  they are used in certain contexts. By default, [unary--] is
  considered invisible when its application appears in the argument
  list of [binary-+]. See [loop-stopper] and see :DOC
  set-invisible-fns-table.

  Extensive documentation has been provided on the topic of Acl2's
  ``term ordering.'' See [term-order].

  Calls of [ld] now default [ld-error-action] to :return rather than to
  the current setting.

  The [command] descriptor :x has been introduced and is synonymous
  with :[max], the most recently executed [command]. [History]
  [command]s such as :[pbt] print a :x beside the most recent
  [command], simply to indicate that it is the most recent one.

  The [command] descriptor :x-23 is synonymous with (:x -23). More
  generally, every symbol in the keyword package whose first
  character is #\\x and whose remaining [characters] parse as a
  negative integer is appropriately understood. This allows :[pbt]
  :x-10 where :[pbt] (:max -10) or :[pbt] (:here -10) were previously
  used. The old forms are still legal.

  The order of the arguments to [defcong] has been changed.

  The simplifier now reports the use of unspecified built-in type
  information about the primitives with the phrase ``primitive type
  reasoning.'' This phrase may sometimes occur in situations where
  ``propositional calculus'' was formerly credited with the proof.

  The function [pairlis] has been replaced in the code by a new
  function [pairlis$], because Common Lisp does not adequately
  specify its [pairlis] function.

  Some new Common Lisp functions have been added, including [logtest],
  [logcount], [integer-length], [make-list], [remove-duplicates],
  [string], and [concatenate]. The source file
  /slocal/src/acl2/axioms.lisp is the ultimate reference regarding
  Common Lisp functions in Acl2.

  The functions [defuns] and [theory-invariant] have been documented.
  See [defuns] and see [theory-invariant].

  A few symbols have been added to the list *acl2-exports*.

  A new key has been implemented for the [ACL2-defaults-table],
  :irrelevant-formals-ok. See [set-irrelevant-formals-ok].

  The connected book directory, [cbd], must be nonempty and begin and
  end with a slash. It is set (and displayed) automatically upon your
  first entry to [lp]. You may change the setting with [set-cbd]. See
  [cbd].

  :[oops] will undo the last :[ubt]. See [oops].

  Documentation has been written about the ordinals. See :DOC
  e0-ordinalp and see :DOC e0-ord-<. [Note added later: Starting with
  Version_2.8, instead see [o-p] and see [o<].

  The color [events] --- (red), (pink), (blue), and (gold) --- may no
  longer be enclosed inside calls of [local], for soundness reasons.
  In fact, neither may any event that sets the [ACL2-defaults-table].
  See [embedded-event-form].

  See [ld-keyword-aliases] for an example of how to change the exit
  keyword from :[q] to something else.

  The attempt to install a [monitor] on :[rewrite] rules stored as
  simple abbreviations now causes an error because the application of
  abbreviations is not tracked.

  A new message is sometimes printed by the theorem prover, indicating
  that a given simplification is ``specious'' because the subgoals it
  produces include the input goal. In Version 1.4 this was detected
  but not reported, causing behavior some users found bizarre. See
  [specious-simplification].

  :[Definition] rules are no longer always required to specify the
  :clique and :controller-alist fields; those fields can be defaulted
  to system-determined values in many common instances. See
  [definition].

  A warning is printed if a macro form with keyword arguments is given
  duplicate keyword values. Execute (thm t :doc nil :doc \"ignored\")
  and read the warning printed.

  A new restriction has been placed on [encapsulate]. Non-[local]
  recursive definitions inside the [encapsulate] may not use, in
  their tests and recursive calls, the constrained functions
  introduced by the [encapsulate]. See [subversive-recursions]. (Note
  added in Version 2.3: Subversive recursions were first recognized
  by us here in Version 1.5, but our code for recognizing them was
  faulty and the bug was not fixed until Version 2.3.)

  The [events] [defequiv], [defcong], [defrefinement], and
  [defevaluator] have been reimplemented so that they are just macros
  that expand into appropriate [defthm] or [encapsulate] [events];
  they are no longer primitive [events]. See the [documentation] of
  each affected event.

  The defcor event, which was a shorthand for a [defthm] that
  established a [corollary] of a named, previously proved event, has
  been eliminated because its implementation relied on a technique we
  have decided to ban from our code. If you want the effect of a
  defcor in Version 1.5 you must submit the corresponding [defthm]
  with a :by hint naming the previously proved event.

  Error reporting has been improved for inappropriate [in-theory]
  [hints] and [events], and for syntax errors in rule classes, and
  for non-existent filename arguments to [ld].

  Technical Note: We now maintain the Third Invariant on type-alists,
  as described in the Essay on the Invariants on Type-alists, and
  Canonicality. This change will affect some proofs, for example, by
  causing a to rewrite more quickly to c when (equiv a b) and (equiv
  b c) are both known and c is the canonical representative of the
  three.")
 (NOTE6
  (RELEASE-NOTES)
  "Acl2 Version 1.6 Notes

  A new key has been implemented for the [ACL2-defaults-table],
  :ignore-ok. See [set-ignore-ok].

  It is now legal to have color [events], such as (red), in the
  [portcullis] of a book. More generally, it is legal to set the
  [ACL2-defaults-table] in the [portcullis] of a book. For example,
  if you execute :red and then certify a book, the event (red) will
  show up in the [portcullis] of that book, and hence the definitions
  in that book will all be red (except when overridden by appropriate
  declarations or [events]). When that book is included, then as
  always, its [portcullis] must first be ``raised,'' and that will
  cause the default color to become red before the [events] in the
  book are executed. As always, the value of [ACL2-defaults-table]
  immediately after execution of an [include-book], [certify-book],
  or [encapsulate] form will be the same as it was immediately before
  execution (and hence, so will the default color). See [portcullis]
  and, for more about books, see [books].

  A theory [ground-zero] has been defined to contain exactly those
  rules that are [enable]d when Acl2 starts up. See [ground-zero].

  The function [nth] is now [enable]d, correcting an oversight from
  Version 1.5.

  Customization files no longer need to meet the syntactic restrictions
  put on [books]; rather, they can contain arbitrary Acl2 forms. See
  [ACL2-customization].

  Structured directory names and structured file names are supported;
  see especially the documentation for [pathname], [book-name], and
  [cbd].

  Acl2 now works with some Common Lisp implementations other than akcl,
  including Lucid, Allegro, and MCL.

  A facility has been added for displaying proof trees, especially
  using emacs; see [proof-tree].

  There is a considerable amount of new [documentation], in particular
  for the printing functions [fmt], [fmt1], and [fms], and for the
  notion of Acl2 term (see [term]).

  It is possible to introduce new well-founded relations, to specify
  which relation should be used by [defun], and to set a default
  relation. See [well-founded-relation].

  It is possible to make functions suggest new inductions. See
  [induction].

  It is possible to change how Acl2 expresses [type-set] information;
  in particular, this affects what clauses are proved when [force]d
  assumptions are generated. See [type-set-inverter].

  A new restriction has been added to [defpkg], having to do with
  undoing. If you undo a [defpkg] and define the same package name
  again, the imports list must be identical to the previous imports
  or else an explanatory error will occur. See
  [package-reincarnation-import-restrictions].

  [Theory-invariant] and [set-irrelevant-formals-ok] are now embedded
  event forms.

  The command :[good-bye] may now be used to quit entirely out of Lisp,
  thus losing your work forever. This command works in akcl but may
  not work in every Common Lisp.

  A theory [ground-zero] has been added that contains exactly the
  [enable]d rules in the [startup] theory. See [ground-zero].

  Define-pc-macro and define-pc-atomic-macro now automatically define
  :red functions. (It used to be necessary, in general, to change
  color to :red before invoking these.)

  For a proof of the well-foundedness of e0-ord-< on the e0-ordinalps,
  see [proof-of-well-foundedness]. [Note added later: Starting with
  Version_2.8, [o<] and [o-p] replace e0-ord-< and e0-ordinalp,
  respectively.]

  Free variables are now handled properly for hypotheses of
  :[type-prescription] rules.

  When the system is loaded or saved, [state] is now bound to
  *the-live-state*.

  [Certify-book] has been modified so that when it compiles a file, it
  loads that object file.

  [Defstub] has been modified so that it works when the color is hot
  (:red or :pink).

  Several basic, but not particularly commonly used, [events] have been
  added or changed. The obscure axiom symbol-name-intern has been
  modified. The definition of firstn has been changed. [Butlast] is
  now defined. The definition of [integer-length] has been modified.
  The left-hand side of the rewrite rule rational-implies2 has been
  changed from (* (numerator x) (/ (denominator x))) to (* (/
  (denominator x)) (numerator x)), in order to respect the fact that
  [unary-/] is invisible with respect to [binary-*]. See
  [loop-stopper].

  The `preprocess' process in the waterfall (see [hints] for a
  discussion of the :do-not hint) has been changed so that it works
  to avoid case-splitting. The `simplify' process refuses to force
  (see [force]) when there are [if] terms, including [and] and [or]
  terms, in the goal being simplified.

  The function apply is no longer introduced automatically by
  translation of user input to internal form when functions are
  called on inappropriate explicit values, e.g., (car 3).

  The choice of which variable to use as the measured variable in a
  recursive definition has been very slightly changed.")
 (NOTE7
  (RELEASE-NOTES)
  "ACL2 Version 1.7 (released October 1994) Notes

  [Include-book] now takes (optionally) an additional keyword argument,
  indicating whether a compiled file is to be loaded. The default
  behavior is unchanged, except that a warning is printed when a
  compiled file is not loaded. See [include-book].

  A markup language for [documentation] strings has been implemented,
  and many of the source files have been marked up using this
  language (thanks largely to the efforts of Laura Lawless). See
  markup. Moreover, there are translators that we have used to
  provide versions of the ACL2 [documentation] in info (for use in
  emacs), html (for Mosaic), and tex (for hardcopy) formats.

  A new event [defdoc] has been implemented. It is like [deflabel], but
  allows redefinition of [doc] strings and has other advantages. See
  [defdoc].

  We used to ignore corollaries when collecting up the axioms
  introduced about constrained functions. That bug has been fixed. We
  thank John Cowles for bringing this bug to our attention.

  The macro [defstub] now allows a :[doc] keyword argument, so that
  [documentation] may be attached to the name being introduced.

  A new command [nqthm-to-ACL2] has been added to help Nqthm users to
  make the transition to ACL2. See [nqthm-to-ACL2], which also
  includes a complete listing of the relevant tables.

  Many function names, especially of the form ``foo-lst'', have been
  changed in order to support the following convention, for any
  ``foo'':

  (foo-listp lst) represents the notion (for x in lst always foop x).

  A complete list of these changes may be found at the end of this
  note. All of them except symbolp-listp and list-of-symbolp-listp
  have the string ``-lst'' in their names. Note also that
  keyword-listp has been renamed [keyword-value-listp].

  Accumulated persistence has been implemented. It is not connected to
  :[brr] or rule monitoring. See [accumulated-persistence].

  :Trigger-terms has been added for :[linear] rule classes, so you can
  hang a [linear] rule under any addend you want. See [linear], which
  has been improved and expanded.

  ACL2 now accepts 256 [characters] and includes the Common Lisp
  functions [code-char] and [char-code]. However, ACL2 controls the
  lisp reader so that #\\c may only be used when c is a single
  standard character or one of Newline, Space, Page, Rubout, Tab. If
  you want to enter other [characters] use [code-char], e.g., (coerce
  (list (code-char 7) (code-char 240) #a) 'string). See [characters].
  Note: our current handling of [characters] makes the set of
  theorems different under Macintosh Common Lisp (MCL) than under
  other Common Lisps. We hope to rectify this situation before the
  final release of ACL2.

  A new [table], [macro-aliases-table], has been implemented, that
  associates macro names with function names. So for example, since
  [append] is associated with [binary-append], the form (disable
  append) it is interpreted as though it were (disable
  binary-append). See [macro-aliases-table], see [add-macro-alias]
  and see [remove-macro-alias].

  The implementation of conditional metalemmas has been modified so
  that the metafunction is applied before the hypothesis metafunction
  is applied. See [meta].

  The Common Lisp functions [acons] and [endp] have been defined in the
  ACL2 logic.

  We have added the symbol [declare] to the list *acl2-exports*, and
  hence to the package \"ACL2-USER\".

  A new hint, :restrict, has been implemented. See [hints].

  It used to be that if :[ubt] were given a number that is greater than
  the largest current [command] number, it treated that number the
  same as :[max]. Now, an error is caused.

  The [table] :force-table has been eliminated.

  A command :[disabledp] (and macro [disabledp]) has been added; see
  [disabledp].

  [Compilation] via :[set-compile-fns] is now suppressed during
  [include-book]. In fact, whenever the [state] global variable
  [ld-skip-proofsp] has value '[include-book].

  Here are some less important changes, additions, and so on.

  Unlike previous releases, we have not proved all the theorems in
  axioms.lisp; instead we have simply assumed them. We have deferred
  such proofs because we anticipate a fairly major changed in Version
  1.8 in how we deal with [guard]s.

  We used to (accidentally) prohibit the ``redefinition'' of a [table]
  as a function. That is no longer the case.

  The check for whether a [corollary] follows tautologically has been
  sped up, at the cost of making the check less ``smart'' in the
  following sense: no longer do we expand primitive functions such as
  [implies] before checking this propositional implication.

  The [command] [ubt!] has been modified so that it never causes or
  reports an error. See [ubt!].

  ACL2 now works in Harlequin LispWorks.

  The user can now specify the :trigger-terms for :[linear] rules. See
  [linear].

  The name of the system is now ``ACL2''; no longer is it ``Acl2''.

  The raw lisp counterpart of [theory-invariant] is now defined to be a
  no-op as is consistent with the idea that it is just a call of
  [table].

  A bug was fixed that caused [proof-checker] [instructions] to be
  executed when [ld-skip-proofsp] was t.

  The function [rassoc] has been added, along with a corresponding
  function used in its [guard], r-eqlable-alistp.

  The [in-theory] event and hint now print a warning not only when
  certain ``primitive'' :[definition] rules are [disable]d, but also
  when certain ``primitive'' :[executable-counterpart] rules are
  [disable]d.

  The modified version of trace provided by ACL2, for use in raw Lisp,
  has been modified so that the lisp special variable *trace-alist*
  is consulted. This alist associates, using [eq], values with their
  print representations. For example, initially *trace-alist* is a
  one-element list containing the pair (cons state
  '|*the-live-state*|).

  The system now prints an observation when a form is skipped because
  the default color is :red or :pink. (Technically: when-cool has
  been modified.)

  Additional protection exists when you submit a form to raw Common
  Lisp that should only be submitted inside the ACL2 read-eval-print
  loop.

  Here is a complete list of the changes in function names described
  near the top of this note, roughly of the form

    foo-lst --> foo-listp

  meaning: the name ``foo-lst'' has been changed to ``foo-listp.''

    symbolp-listp    --> symbol-listp
    list-of-symbolp-listp  --> symbol-list-listp
                           {for consistency with change to symbol-listp}
    rational-lst     --> rational-listp
                         {which in fact was already defined as well}
    integer-lst      --> integer-listp
    character-lst    --> character-listp
    stringp-lst      --> string-listp
    32-bit-integer-lst   --> 32-bit-integer-listp
    typed-io-lst     --> typed-io-listp
    open-channel-lst --> open-channel-listp
    readable-files-lst   --> readable-files-listp
    written-file-lst --> written-file-listp
    read-file-lst    --> read-file-listp
    writeable-file-lst   --> writable-file-listp
                         {note change in spelling of ``writable''}
    writeable-file-lst1  --> writable-file-listp1
    pseudo-termp-lst     --> pseudo-term-listp
    hot-termp-lst --> hot-term-listp {by analogy with pseudo-term-listp}
    weak-termp-lst   --> weak-term-listp
    weak-termp-lst-lst   --> weak-termp-list-listp
    ts-builder-case-lstp -> ts-builder-case-listp
    quotep-lst       --> quote-listp
    termp-lst        --> term-listp
    instr-lst        --> instr-listp
    spliced-instr-lst    --> spliced-instr-listp
    rewrite-fncallp-lst  --> rewrite-fncallp-listp
    every-occurrence-equiv-hittablep1-lst -->
                every-occurrence-equiv-hittablep1-listp
    some-occurrence-equiv-hittablep1-lst  -->
                some-occurrence-equiv-hittablep1-listp
                {by analogy with the preceding, even though it's a
                 ``some'' instead of ``all'' predicate]
    almost-quotep1-lst   --> almost-quotep1-listp
    ffnnames-subsetp-lst --> ffnnames-subsetp-listp
    boolean-lstp     --> boolean-listp
    subst-expr1-lst-okp  --> subst-expr1-ok-listp")
 (NOTE8
  (RELEASE-NOTES)
  "ACL2 Version 1.8 (May, 1995) Notes

  See [note8-update] for yet more recent changes.

  [Guard]s have been eliminated from the ACL2 logic. A summary is
  contained in this brief note. Also see [defun-mode] and see
  [set-guard-checking].

  [Guard]s may be included in [defuns] as usual but are ignored from
  the perspective of admission to the logic: functions must terminate
  on all arguments.

  As in Nqthm, primitive functions, e.g., [+] and [car], logically
  default unexpected arguments to convenient values. Thus, (+ 'abc 3)
  is 3 and (car 'abc) is nil. See [programming], and see the
  [documentation] for the individual primitive functions.

  In contrast to earlier versions of ACL2, Version 1.8 logical
  functions are executed at Nqthm speeds even when [guard]s have not
  been verified. In versions before 1.8, such functions were
  interpreted by ACL2.

  Colors have been eliminated. Two ``[defun-mode]s'' are supported,
  :[program] and :[logic]. Roughly speaking, :[program] does what
  :red used to do, namely, allow you to prototype functions for
  execution without any proof burdens. :[Logic] mode does what :blue
  used to do, namely, allow you to add a new definitional axiom to
  the logic. A global [default-defun-mode] is comparable to the old
  default color. The system comes up in :[logic] mode. To change the
  global [defun-mode], type :[program] or :[logic] at the top-level.
  To specify the [defun-mode] of a [defun] locally use

     (declare (xargs :mode mode)).

  The [prompt] has changed. The initial [prompt], indicating :[logic]
  mode, is

    ACL2 !>

  If you change to :[program] mode the [prompt] becomes

    ACL2 p!>

  [Guard]s can be seen as having either of two roles: (a) they are a
  specification device allowing you to characterize the kinds of
  inputs a function ``should'' have, or (b) they are an efficiency
  device allowing logically defined functions to be executed directly
  in Common Lisp. If a [guard] is specified, as with [xargs]
  :[guard], then it is ``verified'' at defun-time (unless you also
  specify [xargs] :verify-guards nil). [Guard] verification means
  what it always has: the input [guard] is shown to imply the
  [guard]s on all subroutines in the body. If the [guard]s of a
  function are verified, then a call of the function on inputs
  satisfying the [guard] can be computed directly by Common Lisp.
  Thus, verifying the [guard]s on your functions will allow them to
  execute more efficiently. But it does not affect their logical
  behavior and since you will automatically get Nqthm speeds on
  unverified logical definitions, most users will probably use
  [guard]s either as a specification device or only use them when
  execution efficiency is extremely important.

  Given the presence of [guard]s in the system, two issues are
  unavoidable. Are [guard]s verified as part of the [defun] process?
  And are [guard]s checked when terms are evaluated? We answer both
  of those questions below.

  Roughly speaking, in its initial [state] the system will try to
  verify the [guard]s of a [defun] if a :[guard] is supplied in the
  [xargs] and will not try otherwise. However, [guard] verification
  in [defun] can be inhibited ``locally'' by supplying the [xargs]
  :[verify-guards] nil. ``Global'' inhibition can be obtained via the
  :[set-verify-guards-eagerness]. If you do not use the :[guard]
  [xargs], you will not need to think about [guard] verification.

  We now turn to the evaluation of expressions. Even if your functions
  contain no [guard]s, the primitive functions do and hence you have
  the choice: when you submit an expression for evaluation do you
  mean for [guard]s to be checked at runtime or not? Put another way,
  do you mean for the expression to be evaluated in Common Lisp (if
  possible) or in the logic? Note: If Common Lisp delivers an answer,
  it will be the same as in the logic, but it might be erroneous to
  execute the form in Common Lisp. For example, should (car 'abc)
  cause a [guard] violation error or return nil?

  The top-level ACL2 loop has a variable which controls which sense of
  execution is provided. To turn ``[guard] checking on,'' by which we
  mean that [guard]s are checked at runtime, execute the top-level
  form :set-guard-checking t. To turn it off, do :set-guard-checking
  nil. The status of this variable is reflected in the [prompt].

    ACL2 !>

  means [guard] checking is on and

    ACL2 >

  means [guard] checking is off. The exclamation mark can be thought of
  as ``barring'' certain computations. The absence of the mark
  suggests the absence of error messages or unbarred access to the
  logical axioms. Thus, for example

    ACL2 !>(car 'abc)

  will signal an error, while

    ACL2 >(car 'abc)

  will return nil.

  Note that whether or not [guard]s are checked at runtime is
  independent of whether you are operating in :[program] mode or
  :[logic] mode and whether theorems are being proved or not.
  (Although it must be added that functions defined in :[program]
  mode cannot help but check their [guard]s because no logical
  definition exists.)

  Version 1.8 permits the verification of the [guard]s of theorems,
  thus insuring that all instances of the theorem will evaluate
  without error in Common Lisp. To verify the [guard]s of a theorem
  named name execute the event

    (verify-guards name).

  If a theorem's [guard]s have been verified, the theorem is guaranteed
  to evaluate without error to non-nil in Common Lisp (provided
  resource errors do not arise).

  Caveat about [verify-guards]: [implies] is a function symbol, so in
  the term (implies p q), p cannot be assumed true when q is
  evaluated; they are both evaluated ``outside.'' Hence, you cannot
  generally verify the [guard]s on a theorem if [implies] is used to
  state the hypotheses. Use [if] instead. In a future version of
  ACL2, [implies] will likely be a macro.

  See sum-list-example.lisp for a nice example of the use of Version
  1.8. This is roughly the same as the documentation for
  [guard-example].

  We have removed the capability to do ``old-style-forcing'' as existed
  before Version 1.5. See [note5].

  NOTE: Some low level details have, of course, changed. One such
  change is that there are no longer two distinct type prescriptions
  stored when a function is admitted with its [guard]s verified. So
  for example, the type prescription [rune] for [binary-append] is
  now

    (:type-prescription binary-append)

  while in Versions 1.7 and earlier, there were two such [rune]s:

    (:type-prescription binary-append . 1)
    (:type-prescription binary-append . 2)

  Nqthm-style forcing on [linear] arithmetic assumptions is no longer
  executed when forcing is [disable]d.

  Functional instantiation now benefits from a trick also used in
  Nqthm: once a [constraint] generated by a :functional-instance
  lemma instance (see [lemma-instance]) has been proved on behalf of
  a successful event, it will not have to be re-proved on behalf of a
  later event.

  [1+] and [1-] are now macros in the logic, not functions. Hence, for
  example, it is ``safe'' to use them on left-hand sides of rewrite
  rules, without invoking the common warning about the presence of
  nonrecursive function symbols.

  A new [documentation] section [file-reading-example] illustrates how
  to process forms in a file.

  A new [proof-checker] command forwardchain has been added; see
  [ACL2-pc::forwardchain].

  It is now possible to use quantifiers. See [defun-sk] and see
  [defchoose].

  There is a new event [set-inhibit-warnings], which allows the user to
  turn off warnings of various types. see [set-inhibit-warnings].

  An unsoundness relating [encapsulate] and :functional-instance
  [hints] has been remedied, with a few small effects visible at the
  user level. The main observable effect is that [defaxiom] and
  non-local [include-book] [events] are no longer allowed in the
  scope of any [encapsulate] event that has a non-empty [signature].

  When [certify-book] is called, we now require that the default
  [defun-mode] (see [default-defun-mode]) be :[logic]. On a related
  note, the default [defun-mode] is irrelevant to [include-book]; the
  mode is always set to :[logic] initially, though it may be changed
  within the book and reverts to its original value at the conclusion
  of the [include-book]. A bug in [include-book] prevented it from
  acting this way even though the [documentation] said otherwise.

  The [documentation] has been substantially improved. A new section
  ``Programming'' contains [documentation] of many useful functions
  provided by ACL2; see [programming]. Also, the [documentation] has
  been ``marked up'' extensively. Thus in particular, users of Mosaic
  will find many links in the [documentation].

  The symbols [force], [mv-nth], and acl2-count have been added to the
  list *acl2-exports*.

  We now permit most names from the main Lisp package to be used as
  names, except for names that define functions, macros, or
  constants. See [name].

  We have changed the list of imports from the Common Lisp package to
  ACL2, i.e., the list *common-lisp-symbols-from-main-lisp-package*,
  to be exactly those external symbols of the Common Lisp package as
  specified by the draft Common Lisp standard. In order to
  accommodate this change, we have renamed some ACL2 functions as
  shown below, but these and other ramifications of this change
  should be transparent to most ACL2 users.

    warning      --> warning$
    print-object --> print-object$

  Proof trees are no longer enabled by default. To start them up,
  :[start-proof-tree].

  We have added the capability of building smaller images. The easiest
  way to do this on a Unix (trademark of AT&T) system is: make small.

  Here we will put some less important changes, additions, and so on.

  We have added definitions for the Common Lisp function [position]
  (for the test [eql]), as well as corresponding versions
  [position-equal] and [position-eq] that use tests [equal] and [eq],
  respectively. See [position], see [position-equal], and see
  [position-eq].

  The [defthm] event rational-listp-implies-rationalp-car no longer
  exists.

  We fixed a bug in the hint mechanism that applied :by, :cases, and
  :use [hints] to the first induction goal when the prover reverted
  to proving the original goal by induction.

  We fixed a bug in the handling of (set-irrelevant-formals-ok :warn).

  In support of removing the old-style forcing capability, we deleted
  the initialization of [state] global old-style-forcing and deleted
  the definitions of recover-assumptions,
  recover-assumptions-from-goal, remove-assumptions1,
  remove-assumptions, and split-on-assumptions, and we renamed
  split-on-assumptions1 to split-on-assumptions.

  The special value 'none in the [proof-checker] commands claim and [=]
  has been replaced by :none.

  A bug in the handling of [hints] by subgoals has been fixed. For
  example, formerly a :do-not hint could be ``erased'' by a :use hint
  on a subgoal. Thanks go to Art Flatau for noticing the bug.

  The functions weak-termp and weak-term-listp have been deleted, and
  their calls have been replaced by corresponding calls of
  [pseudo-termp] and pseudo-term-listp. The notion of [pseudo-termp]
  has been slightly strenthened by requiring that terms of the form
  (quote ...) have length 2.

  Performance has been improved in various ways. At the prover level,
  backchaining through the recognizer alist has been eliminated in
  order to significantly speed up ACL2's rewriter. Among the other
  prover changes (of which there are several, all technical): we no
  longer clausify the input term when a proof is interrupted in favor
  of inducting on the input term. At the [io] level, we have improved
  performance somewhat by suitable declarations and proclamations.
  These include technical modifications to the macros [mv] and
  [mv-let], and introduction of a macro the-mv analogous to the macro
  [the] but for forms returning multiple values.

  The function spaces now takes an extra argument, the current column.

  A bug in the [proof-checker] equiv command was fixed.

  The function intersectp has been deleted, because it was essentially
  duplicated by the function [intersectp-equal].

  We now proclaim functions in AKCL and GCL before compiling [books].
  This should result in somewhat increased speed.

  The function repeat has been eliminated; use [make-list] instead.

  The [proof-checker] command expand has been fixed so that it
  eliminates [let] (lambda) expressions when one would expect it to.

  A new primitive function, [mv-nth], has been introduced. [Mv-nth] is
  equivalent to [nth] and is used in place of [nth] in the
  translation of [mv-let] expressions. This allows the user to
  control the simplification of [mv-let] expressions without
  affecting how [nth] is treated. In that spirit, the rewriter has
  been modified so that certain [mv-nth] expressions, namely those
  produced in the translation of (mv-let (a b c)(mv x y z) p), are
  given special treatment.

  A minor bug in untranslate has been fixed, which for example will fix
  the printing of conjunctions.

  Translate now takes a logicp argument, which indicates whether it
  enforces the restriction that :[program] mode functions do not
  occur in the result.

  The modified version of trace provided by ACL2, for use in raw Lisp,
  has been modified so that the lisp special variable *trace-alist*
  has a slightly different functionality. This alist associates,
  using [eq], symbols with the print representations of their values.
  For example, initially *trace-alist* is a one-element list
  containing the pair (cons 'state '|*the-live-state*|). Thus, one
  may cons the pair (cons '*foo* \"It's a FOO!\") on to *trace-alist*;
  then until *foo* is defined, this change will have no effect, but
  after for example

    (defconst *foo* 17)

  then trace will print 17 as \"It's a FOO!\".

  Trace also traces the corresponding logic function.

  [Proof-tree] display has been improved slightly in the case of
  successful proofs and certain event failures.

  The function positive-integer-log2 has been deleted.

  The macro [skip-proofs] now prints a warning message when it is
  encountered in the context of an [encapsulate] event or a book. See
  [skip-proofs].

  Some functions related to the-fn and wormhole1 now have [defun-mode]
  :[program], but this change is almost certain to be inconsequential
  to all users.")
 (NOTE8-UPDATE
  (RELEASE-NOTES)
  "ACL2 Version 1.8 (Summer, 1995) Notes

  ACL2 can now use Ordered Binary Decision Diagram technology. See
  [bdd]. There is also a [proof-checker] bdd command.

  ACL2 is now more respectful of the intention of the function [hide].
  In particular, it is more careful not to dive inside any call of
  [hide] during equality substitution and case splitting.

  The [ld] special (see [ld]) [ld-pre-eval-print] may now be used to
  turn off printing of input forms during processing of [encapsulate]
  and [certify-book] forms, by setting it to the value :never, i.e.,
  (set-ld-pre-eval-print :never state). See [ld-pre-eval-print].

  The TUTORIAL documentation section (now obsolete) has, with much help
  from Bill Young, been substantially improved to a bona fide
  introduction.

  The term pretty-printer has been modified to introduce (<= X Y) as an
  abbreviation for (not (< Y X)).

  Forward chaining and linear arithmetic now both benefit from the
  evaluation of ground subterms.

  A new macro [set-inhibit-output-lst] has been defined. This should be
  used when setting the [state] global inhibit-output-lst; see
  [set-inhibit-output-lst] and see [proof-tree].

  The test for redundancy in definitions includes the [guard] and type
  declarations. See [redundant-events].

  See [generalized-booleans] for a discussion of a potential soundness
  problem for ACL2 related to the question: Which Common Lisp
  functions are known to return Boolean values?

  Here we will put some less important changes, additions, and so on.

  A bug has been fixed so that now, execution of :comp t (see [comp])
  correctly handles non-standard characters.

  A bug in [digit-char-p] has been fixed, so that the ``default'' is
  nil rather than 0.

  [True-listp] now tests the final [cdr] against nil using [eq] instead
  of [equal], for improved efficiency. The logical meaning is,
  however, unchanged.

  [Put-assoc-equal] has been added to the logic (it used to have
  :[defun-mode] :[program], and has been documented.")
 (NOTE9
  (RELEASE-NOTES)
  "ACL2 Version 1.9 (Fall, 1996) Notes

  By default, when the system is started it is illegal to use the
  variable [state] as a formal parameter of a function definition.
  The aim is to prevent novice users from stumbling into the
  Byzantine syntactic restrictions on that variable symbol. Use

    :set-state-ok t

  or, equivalently,

    (set-state-ok t)

  to switch back to the old default mode. See [set-state-ok]

  Set-state-ok is an event that affects the ACL2 defaults table (see
  [ACL2-defaults-table]). Recall that when books are included, the
  defaults table is restored to its pre-inclusion state. Thus, while
  a set-state-ok form will permit the book to define a state-using
  function, it will not permit the user of the book to make such a
  definition. We recommend putting (set-state-ok t) in any book that
  defines a state using function.

  Books certified under Version 1.8 must be recertified under Version
  1.9. See :DOC version.

  The simplifier has been made to look out for built-in clauses,
  whereas in past versions such clauses were only noticed by the
  ``preprocessor'' at the top of the waterfall. THIS CHANGE MAY
  PREVENT OLD SCRIPTS FROM REPLAYING! The undesirable side-effect is
  caused by the fact that :HINTS require you to refer to clauses by
  their exact name (see [goal-spec]) and because the new simplifier
  proves more clauses than before, the goals produced have different
  names. Thus, if a script uses :HINTS that refer to clauses other
  than \"Goal\", e.g., \"Subgoal 1.3\" then the hint may be applied to a
  different subgoal than originally intended.

  The use of built-in-clauses has been made more efficient. If a set of
  clauses arise often in a piece of work, it might be advantageous to
  build them in even if that results in a large set (hundreds?) of
  built-in clauses. See [built-in-clause]

  Wormholes can now be used in :logic mode functions. See [wormhole]

  It is now possible to provide ``computed hints.'' For example, have
  you ever wished to say ``in all goals with a name like this, :use
  that'' or ``if this term is in the subgoal, then :use that''? Well,
  see [computed-hints] and the extraordinarily long example in see
  [using-computed-hints].

  Hide terms may be rewritten with :rewrite rules about hide. See
  [hide], where we also now explain why hide terms are sometimes
  introduced into your proof attempts.

  A bug that sometimes caused the ``non-lazy IF'' hard error message
  was fixed.

  A bug that sometimes caused a hard error in forward chaining was
  fixed.

  A bug in print-rules (:pr) was fixed.

  We report the use of :executable-counterparts in the evaluation of
  SYNTAXP forms.

  Some documentation errors were fixed.

  A bug in parent-tree tracking in add-literal-and-pt was fixed.

  A bug in ok$, go$ and eval$ was fixed.

  Clausify now optimizes (mv-nth 'k (list x0 ... xk ... xn)) to xk.")
 (NQTHM-TO-ACL2
  (ACL2-TUTORIAL)
  "ACL2 analogues of Nqthm functions and commands

    Example Forms:
    :nqthm-to-acl2 prove-lemma   ; Display ACL2 topic(s) and/or print
                                 ; information corresponding to Nqthm
                                 ; PROVE-LEMMA command.
    (nqthm-to-acl2 'prove-lemma) ; Same as above.

    General Form:
    (nqthm-to-acl2 name)

  where name is a notion documented for Nqthm: either a function in the
  Nqthm logic, or a command. If there is corresponding information
  available for ACL2, it will be printed in response to this command.
  This information is not intended to be completely precise, but
  rather, is intended to help those familiar with Nqthm to make the
  transition to ACL2.

  We close with two tables that contain all the information used by
  this nqthm-to-acl2 command. The first shows the correspondence
  between functions in the Nqthm logic and corresponding ACL2
  functions (when possible); the second is similar, but for commands
  rather than functions.

    Nqthm functions  -->     ACL2
    ----------------------------------------
    ADD1          -->  1+
    ADD-TO-SET    -->  ADD-TO-SET-EQUAL and ADD-TO-SET-EQ
    AND           -->  AND
    APPEND        -->  APPEND and BINARY-APPEND
    APPLY-SUBR    -->  No correspondent, but see the documentation for
                       DEFEVALUATOR and META.
    APPLY$        -->  No correspondent, but see the documentation for
                       DEFEVALUATOR and META.
    ASSOC         -->  ASSOC-EQUAL, ASSOC and ASSOC-EQ
    BODY          -->  No correspondent, but see the documentation for
                       DEFEVALUATOR and META.
    CAR           -->  CAR
    CDR           -->  CDR
    CONS          -->  CONS
    COUNT         -->  ACL2-COUNT
    DIFFERENCE    -->  -
    EQUAL         -->  EQUAL, EQ, EQL and =
    EVAL$         -->  No correspondent, but see the documentation for
                       DEFEVALUATOR and META.
    FALSE         -->  Nqthm's F corresponds to the ACL2 symbol NIL.
    FALSEP        -->  NOT and NULL
    FORMALS       -->  No correspondent, but see the documentation for
                       DEFEVALUATOR and META.
    GEQ           -->  >=
    GREATERP      -->  >
    IDENTITY      -->  IDENTITY
    IF            -->  IF
    IFF           -->  IFF
    IMPLIES       -->  IMPLIES
    LEQ           -->  <=
    LESSP         -->  <
    LISTP         -->  CONSP
    LITATOM       -->  SYMBOLP
    MAX           -->  MAX
    MEMBER        -->  MEMBER-EQUAL, MEMBER and MEMBER-EQ
    MINUS         -->  - and UNARY--
    NEGATIVEP     -->  MINUSP
    NEGATIVE-GUTS -->  ABS
    NLISTP        -->  ATOM
    NOT           -->  NOT
    NUMBERP       -->  ACL2-NUMBERP, INTEGERP and RATIONALP
    OR            -->  OR
    ORDINALP      -->  O-P
    ORD-LESSP     -->  O<
    PACK          -->  See intern and coerce.
    PAIRLIST      -->  PAIRLIS$
    PLUS          -->  + and BINARY-+
    QUOTIENT      -->  /
    REMAINDER     -->  REM and MOD
    STRIP-CARS    -->  STRIP-CARS
    SUB1          -->  1-
    TIMES         -->  * and BINARY-*
    TRUE          -->  The symbol T.
    UNION         -->  UNION-EQUAL and UNION-EQ
    UNPACK        -->  See symbol-name and coerce.
    V&C$          -->  No correspondent, but see the documentation for
                       DEFEVALUATOR and META.
    V&C-APPLY$    -->  No correspondent, but see the documentation for
                       DEFEVALUATOR and META.
    ZERO          -->  The number 0.
    ZEROP         -->  ZP



    Nqthm commands   -->     ACL2
    ----------------------------------------
    ACCUMULATED-PERSISTENCE
                  -->  ACCUMULATED-PERSISTENCE
    ADD-AXIOM     -->  DEFAXIOM
    ADD-SHELL     -->  There is no shell principle in ACL2.
    AXIOM         -->  DEFAXIOM
    BACKQUOTE-SETTING
                  -->  Backquote is supported in ACL2, but not
                       currently documented.
    BOOT-STRAP    -->  GROUND-ZERO
    BREAK-LEMMA   -->  MONITOR
    BREAK-REWRITE -->  BREAK-REWRITE
    CH            -->  PBT
                       See also :DOC history.
    CHRONOLOGY    -->  PBT
                       See also :DOC history.
    COMMENT       -->  DEFLABEL
    COMPILE-UNCOMPILED-DEFNS
                  -->  COMP
    CONSTRAIN     -->  See :DOC encapsulate and :DOC local.
    DATA-BASE     -->  Perhaps the closest ACL2 analogue of DATA-BASE
                       is PROPS.  But see :DOC history for a collection
                       of commands for querying the ACL2 database
                       (``world'').  Note that the notions of
                       supporters and dependents are not supported in
                       ACL2.
    DCL           -->  DEFSTUB
    DEFN          -->  DEFUN and DEFMACRO
    DEFTHEORY     -->  DEFTHEORY
    DISABLE       -->  DISABLE
    DISABLE-THEORY
                  -->  See :DOC theories.  The Nqthm command
                       (DISABLE-THEORY FOO) corresponds roughly to the
                       ACL2 command
                       (in-theory (set-difference-theories
                                    (current-theory :here)
                                    (theory 'foo))).
    DO-EVENTS     -->  LD
    DO-FILE       -->  LD
    ELIM          -->  ELIM
    ENABLE        -->  ENABLE
    ENABLE-THEORY -->  See :DOC theories.  The Nqthm command
                       (ENABLE-THEORY FOO) corresponds roughly to the
                       ACL2 command
                       (in-theory (union-theories
                                    (theory 'foo)
                                    (current-theory :here))).
    EVENTS-SINCE  -->  PBT
    FUNCTIONALLY-INSTANTIATE
                  -->  ACL2 provides a form of the :USE hint that
                       corresponds roughly to the
                       FUNCTIONALLY-INSTANTIATE event of Nqthm. See
                       :DOC lemma-instance.
    GENERALIZE    -->  GENERALIZE
    HINTS         -->  HINTS
    LEMMA         -->  DEFTHM
    MAINTAIN-REWRITE-PATH
                  -->  BRR
    MAKE-LIB      -->  There is no direct analogue of Nqthm's notion of
                       ``library.''  See :DOC books for a description
                       of ACL2's mechanism for creating and saving
                       collections of events.
    META          -->  META
    NAMES         -->  NAME
    NOTE-LIB      -->  INCLUDE-BOOK
    PPE           -->  PE
    PROVE         -->  THM
    PROVEALL      -->  See :DOC ld and :DOC certify-book.  The latter
                       corresponds to Nqthm's PROVE-FILE,which may be
                       what you're interested in,really.
    PROVE-FILE    -->  CERTIFY-BOOK
    PROVE-FILE-OUT
                  -->  CERTIFY-BOOK
    PROVE-LEMMA   -->  DEFTHM
                       See also :DOC hints.
    R-LOOP        -->  The top-level ACL2 loop is an evaluation loop as
                       well, so no analogue of R-LOOP is necessary.
    REWRITE       -->  REWRITE
    RULE-CLASSES  -->  RULE-CLASSES
    SET-STATUS    -->  IN-THEORY
    SKIM-FILE     -->  LD-SKIP-PROOFSP
    TOGGLE        -->  IN-THEORY
    TOGGLE-DEFINED-FUNCTIONS
                  -->  EXECUTABLE-COUNTERPART-THEORY
    TRANSLATE     -->  TRANS and TRANS1
    UBT           -->  UBT and U
    UNBREAK-LEMMA -->  UNMONITOR
    UNDO-BACK-THROUGH
                  -->  UBT
    UNDO-NAME     -->  See :DOC ubt.  There is no way to undo names in
                       ACL2 without undoing back through such names.
                       However, see :DOC ld-skip-proofsp for
                       information about how to quickly recover the
                       state.")
 (NTH
  (LISTS ACL2-BUILT-INS)
  "The nth element (zero-based) of a list

  (Nth n l) is the nth element of l, zero-based. If n is greater than
  or equal to the length of l, then nth returns nil.

  (Nth n l) has a [guard] that n is a non-negative integer and l is a
  [true-listp].

  Nth is a Common Lisp function. See any Common Lisp documentation for
  more information.

  Function: 

    (defun nth (n l)
           (declare (xargs :guard (and (integerp n)
                                       (>= n 0)
                                       (true-listp l))))
           (if (endp l)
               nil
               (if (zp n)
                   (car l)
                   (nth (- n 1) (cdr l)))))


Subtopics

  [Eighth]
      Eighth member of the list

  [Fifth]
      Fifth member of the list

  [First]
      First member of the list

  [Fourth]
      Fourth member of the list

  [Ninth]
      Ninth member of the list

  [Nth-aliases-table]
      A [table] used to associate names for nth/update-nth printing

  [Rest]
      Rest ([cdr]) of the list

  [Second]
      Second member of the list

  [Seventh]
      Seventh member of the list

  [Sixth]
      Sixth member of the list

  [Tenth]
      Tenth member of the list

  [Third]
      Third member of the list")
 (NTH-ALIASES-TABLE
  (STOBJ NTH UPDATE-NTH)
  "A [table] used to associate names for nth/update-nth printing

    Example:
    (table nth-aliases-table 'st0 'st)

  This example associates the symbol st0 with the symbol st. As a
  result, when the theorem prover prints terms of the form (nth n
  st0) or (update-nth n val st0), where st is a [stobj] whose nth
  accessor function is f-n, then it will print n as *f-n*.

    General Form:
    (table nth-aliases-table 'alias-name 'name)

  This event causes alias-name to be treated like name for purposes of
  the printing of terms that are calls of nth and update-nth. (Note
  however that name is not recursively looked up in this table.) Both
  must be symbols other than [state]. See [term], in particular the
  discussion there of untranslated terms.

  For a convenient way to add entries to this [table], see
  [add-nth-alias]. To remove entries from the [table] with ease, see
  [remove-nth-alias].


Subtopics

  [Add-nth-alias]
      Associate one symbol with another for printing of [nth]/[update-nth]
      terms

  [Remove-nth-alias]
      Remove a symbol alias for printing of [nth]/[update-nth] terms")
 (NTHCDR
  (LISTS ACL2-BUILT-INS)
  "Final segment of a list

  (Nthcdr n l) removes the first n elements from the list l.

  The following is a theorem.

    (implies (and (integerp n)
                  (<= 0 n)
                  (true-listp l))
             (equal (length (nthcdr n l))
                    (if (<= n (length l))
                        (- (length l) n)
                      0)))

  For related functions, see [take] and see [butlast].

  The [guard] of (nthcdr n l) requires that n is a nonnegative integer
  and l is a true list.

  Nthcdr is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: 

    (defun nthcdr (n l)
           (declare (xargs :guard (and (integerp n)
                                       (<= 0 n)
                                       (true-listp l))))
           (if (zp n) l (nthcdr (+ n -1) (cdr l))))")
 (NULL
  (BASICS ACL2-BUILT-INS)
  "Recognizer for the empty list

  Null is the function that checks whether its argument is nil. For
  recursive definitions it is often preferable to test for the end of
  a list using [endp] instead of null; see [endp].

  Null is a Common Lisp function. See any Common Lisp documentation for
  more information.

  Function: 

    (defun null (x)
           (declare (xargs :guard t))
           (eq x nil))")
 (NUMBER-SUBTREES
  (HONS-AND-MEMOIZATION ACL2-BUILT-INS)
  "(number-subtrees x) returns the number of distinct subtrees of X, in
  the sense of [equal]

  In the logic, number-subtrees is defined as the length of
  [cons-subtrees].

  Under the hood, we first [hons-copy] X to obtain a normed version,
  then count the number of unique conses in X using an EQ hash table.

  Function: 

    (defun number-subtrees (x)
           (declare (xargs :guard t))
           (len (cons-subtrees x 'number-subtrees)))")
 (NUMBERS
  (PROGRAMMING)
  "Numbers in ACL2 and operations on them

  See [numbers-introduction] for introductory background. See
  [arithmetic] for libraries of [books] for arithmetic reasoning.


Subtopics

  [*]
      Multiplication macro

  [+]
      Addition macro

  [-]
      Macro for subtraction and negation

  [/]
      Macro for division and reciprocal

  [/=]
      Test inequality of two numbers

  [1+]
      Increment by 1

  [1-]
      Decrement by 1

  [<]
      Less-than

  [<=]
      Less-than-or-equal test

  [=]
      Test equality of two numbers

  [>]
      Greater-than test

  [>=]
      Greater-than-or-equal test

  [Abs]
      The absolute value of a real number

  [ACL2-number-listp]
      Recognizer for a true list of numbers

  [ACL2-numberp]
      Recognizer for numbers

  [Allocate-fixnum-range]
      Set aside fixnums in GCL

  [Ash]
      Arithmetic shift operation

  [Boole$]
      Perform a bit-wise logical operation on 2 two's complement integers

  [Ceiling]
      Division returning an integer by truncating toward positive infinity

  [Char-code]
      The numeric code for a given character

  [Code-char]
      The character corresponding to a given numeric code

  [Complex]
      Create an ACL2 number

  [Complex-rationalp]
      Recognizes complex rational numbers

  [Complex/complex-rationalp]
      Recognizer for complex numbers

  [Conjugate]
      Complex number conjugate

  [Denominator]
      Divisor of a ratio in lowest terms

  [Evenp]
      Test whether an integer is even

  [Explode-nonnegative-integer]
      The list of [characters] in the radix-r form of a number

  [Expt]
      Exponential function

  [Fix]
      Coerce to a number

  [Floor]
      Division returning an integer by truncating toward negative infinity

  [Ifix]
      Coerce to an integer

  [Imagpart]
      Imaginary part of a complex number

  [Int=]
      Test equality of two integers

  [Integer-length]
      Number of bits in two's complement integer representation

  [Integer-listp]
      Recognizer for a true list of integers

  [Integer-range-p]
      Recognizer for integers between two bounds.

  [Integerp]
      Recognizer for whole numbers

  [Logand]
      Bitwise logical `and' of zero or more integers

  [Logandc1]
      Bitwise logical `and' of two ints, complementing the first

  [Logandc2]
      Bitwise logical `and' of two ints, complementing the second

  [Logbitp]
      The ith bit of an integer

  [Logcount]
      Number of ``on'' bits in a two's complement number

  [Logeqv]
      Bitwise logical equivalence of zero or more integers

  [Logior]
      Bitwise logical inclusive or of zero or more integers

  [Lognand]
      Bitwise logical `nand' of two integers

  [Lognor]
      Bitwise logical `nor' of two integers

  [Lognot]
      Bitwise not of a two's complement number

  [Logorc1]
      Bitwise logical inclusive or of two ints, complementing the first

  [Logorc2]
      Bitwise logical inclusive or of two ints, complementing the second

  [Logtest]
      Test if two integers share a `1' bit

  [Logxor]
      Bitwise logical exclusive or of zero or more integers

  [Max]
      The larger of two numbers

  [Min]
      The smaller of two numbers

  [Minusp]
      Test whether a number is negative

  [Mod]
      Remainder using [floor]

  [Mod-expt]
      Exponential function

  [Nat-listp]
      Recognizer for a true list of natural numbers

  [Natp]
      A recognizer for the natural numbers

  [Nfix]
      Coerce to a natural number

  [Nonnegative-integer-quotient]
      Natural number division function

  [Numbers-introduction]
      Numbers in ACL2

  [Numerator]
      Dividend of a ratio in lowest terms

  [Oddp]
      Test whether an integer is odd

  [Plusp]
      Test whether a number is positive

  [Posp]
      A recognizer for the positive integers

  [Random$]
      Obtain a random value

  [Rational-listp]
      Recognizer for a true list of rational numbers

  [Rationalp]
      Recognizer for rational numbers (ratios and integers)

  [Real/rationalp]
      Recognizer for rational numbers (including real number in ACL2(r))

  [Realfix]
      Coerce to a real number

  [Realpart]
      Real part of a complex number

  [Rem]
      Remainder using [truncate]

  [Rfix]
      Coerce to a rational number

  [Round]
      Division returning an integer by rounding off

  [Sharp-u-reader]
      Allow underscore characters in numbers

  [Signed-byte-p]
      Recognizer for signed integers that fit in a specified bit width

  [Signum]
      Indicator for positive, negative, or zero

  [Truncate]
      Division returning an integer by truncating toward 0

  [Unary--]
      Arithmetic negation function

  [Unary-/]
      Reciprocal function

  [Unsigned-byte-p]
      Recognizer for natural numbers that fit in a specified bit width

  [Zero-test-idioms]
      How to test for 0

  [Zerop]
      Test an acl2-number against 0

  [Zip]
      Testing an ``integer'' against 0

  [Zp]
      Testing a ``natural'' against 0

  [Zpf]
      Testing a nonnegative fixnum against 0")
 (NUMBERS-INTRODUCTION
  (NUMBERS)
  "Numbers in ACL2

  ACL2 numbers are precisely represented and unbounded. They can be
  partitioned into the following subtypes:

    ACL2 Numbers
     |
     |- Rationals
     |  |
     |  |- Integers
     |  |  |- Positive integers                 3
     |  |  |- Zero                              0
     |  |  |- Negative Integers                 -3
     |  |
     |  |- Non-Integral Rationals
     |  |  |
     |  |  |- Positive Non-Integral Rationals   19/3
     |  |  |- Negative Non-Integral Rationals   -22/7
     |
     |- Complex Rational Numbers                 #c(3 5/2) ; i.e., 3 + (5/2)i

  Signed integer constants are usually written (as illustrated above)
  as sequences of decimal digits, possibly preceded by + or -.
  Decimal points are not allowed. Integers may be written in binary,
  as in #b1011 (= 23) and #b-111 (= -7). Octal may also be used,
  #o-777 = -511. Non-integral rationals are written as a signed
  decimal integer and an unsigned decimal integer, separated by a
  slash. Complex rationals are written as #c(rpart ipart) where rpart
  and ipart are rationals.

  Of course, 4/2 = 2/1 = 2 (i.e., not every rational written with a
  slash is a non-integer). Similarly, #c(4/2 0) = #c(2 0) = 2.

  The common arithmetic functions and relations are denoted by +, -, *,
  /, =, <, <=, > and >=. However there are many others, e.g., floor,
  ceiling, and lognot. See any Common Lisp language documentation.

  The primitive predicates for recognizing numbers are illustrated
  below. The following ACL2 function will classify an object, x,
  according to its numeric subtype, or else return 'NaN (not a
  number). We show it this way just to illustrate programming in
  ACL2.

    (defun classify-number (x)
      (cond ((rationalp x)
             (cond ((integerp x)
                    (cond ((< 0 x) 'positive-integer)
                          ((= 0 x) 'zero)
                          (t 'negative-integer)))
                   ((< 0 x) 'positive-non-integral-rational)
                   (t 'negative-non-integral-rational)))
            ((complex-rationalp x) 'complex-rational)
            (t 'NaN)))")
 (NUMBERS_IN_ACL2
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Numbers in ACL2

  ACL2 numbers are precisely represented and unbounded. They can be
  partitioned into the following subtypes:

    ACL2 Numbers
     |
     |- Rationals
     |  |
     |  |- Integers
     |  |  |- Positive integers                 3
     |  |  |- Zero                              0
     |  |  |- Negative Integers                 -3
     |  |
     |  |- Non-Integral Rationals
     |  |  |
     |  |  |- Positive Non-Integral Rationals   19/3
     |  |  |- Negative Non-Integral Rationals   -22/7
     |
     |- Complex Rational Numbers                 #c(3 5/2) ; i.e., 3 + (5/2)i

  Signed integer constants are usually written (as illustrated above)
  as sequences of decimal digits, possibly preceded by + or -.
  Decimal points are not allowed. Integers may be written in binary,
  as in #b1011 (= 23) and #b-111 (= -7). Octal may also be used,
  #o-777 = -511. Non-integral rationals are written as a signed
  decimal integer and an unsigned decimal integer, separated by a
  slash. Complex rationals are written as #c(rpart ipart) where rpart
  and ipart are rationals.

  Of course, 4/2 = 2/1 = 2 (i.e., not every rational written with a
  slash is a non-integer). Similarly, #c(4/2 0) = #c(2 0) = 2.

  The common arithmetic functions and relations are denoted by +, -, *,
  /, =, <, <=, > and >=. However there are many others, e.g., floor,
  ceiling, and lognot. See any Common Lisp language documentation.

  The primitive predicates for recognizing numbers are illustrated
  below. The following ACL2 function will classify an object, x,
  according to its numeric subtype, or else return 'NaN (not a
  number). We show it this way just to illustrate programming in
  ACL2.

    (defun classify-number (x)
      (cond ((rationalp x)
             (cond ((integerp x)
                    (cond ((< 0 x) 'positive-integer)
                          ((= 0 x) 'zero)
                          (t 'negative-integer)))
                   ((< 0 x) 'positive-non-integral-rational)
                   (t 'negative-non-integral-rational)))
            ((complex-rationalp x) 'complex-rational)
            (t 'NaN)))")
 (NUMERATOR
  (NUMBERS ACL2-BUILT-INS)
  "Dividend of a ratio in lowest terms

  Completion Axiom (completion-of-numerator):

    (equal (numerator x)
           (if (rationalp x)
               (numerator x)
             0))

  [Guard] for (numerator x):

    (rationalp x)")
 (O-FINP
  (ORDINALS ACL2-BUILT-INS)
  "Recognizes if an ordinal is finite

  We introduce the function o-finp which returns t for any ordinal that
  is finite, else nil. This function is equivalent to the function
  [atom], and is introduced so that we can [disable] its definition
  when dealing with ordinals (also see [make-ord]).

  Function: 

    (defun o-finp (x)
           (declare (xargs :guard t))
           (atom x))")
 (O-FIRST-COEFF
  (ORDINALS ACL2-BUILT-INS)
  "Returns the first coefficient of an ordinal

  An ACL2 ordinal is either a natural number or, for an infinite
  ordinal, a list whose elements are exponent-coefficient pairs (see
  [o-p]). In the latter case, this function returns the [cdr] of the
  first pair in the list. In the case of a natural number, this
  function returns the ordinal itself (since a natural number, n, can
  be thought of as (w^0)n).

  For the corresponding exponent, see [o-first-expt].

  Function: 

    (defun o-first-coeff (x)
           (declare (xargs :guard (or (o-finp x) (consp (car x)))))
           (if (o-finp x) x (cdar x)))")
 (O-FIRST-EXPT
  (ORDINALS ACL2-BUILT-INS)
  "The first exponent of an ordinal

  An ACL2 ordinal is either a natural number or, for an infinite
  ordinal, a list whose elements are exponent-coefficient pairs (see
  [o-p]). In the latter case, this function returns the [car] of the
  first pair in the list. In the case of a natural number, the value
  returned is 0 (since a natural number, n, can be thought of as
  (w^0)n).

  For the corresponding coefficient, see [o-first-coeff].

  Function: 

    (defun o-first-expt (x)
           (declare (xargs :guard (or (o-finp x) (consp (car x)))))
           (if (o-finp x) 0 (caar x)))")
 (O-INFP
  (ORDINALS ACL2-BUILT-INS)
  "Recognizes if an ordinal is infinite

  O-infp is a macro. (O-infp x) opens up to (not (o-finp x)).")
 (O-P
  (ORDINALS ACL2-BUILT-INS)
  "A recognizer for the ordinals up to epsilon-0

  Using the nonnegative integers and lists we can represent the
  ordinals up to epsilon-0. The ordinal representation used in ACL2
  has changed as of Version_2.8 from that of Nqthm-1992, courtesy of
  Pete Manolios and Daron Vroon; additional discussion may be found
  in ``Ordinal Arithmetic in ACL2'', {proceedings of ACL2 Workshop
  2003 | http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/}.
  Previously, ACL2's notion of ordinal was very similar to the
  development given in ``New Version of the Consistency Proof for
  Elementary Number Theory'' in The Collected Papers of Gerhard
  Gentzen, ed. M.E. Szabo, North-Holland Publishing Company,
  Amsterdam, 1969, pp 132-213.

  The following essay is intended to provide intuition about ordinals.
  The truth, of course, lies simply in the ACL2 definitions of o-p
  and [o<].

  Very intuitively, think of each non-zero natural number as by being
  denoted by a series of the appropriate number of strokes, i.e.,

    0             0
    1             |
    2             ||
    3             |||
    4             ||||
    ...           ...

  Then ``omega,'' here written as w, is the ordinal that might be
  written as

    w             |||||...,

  i.e., an infinite number of strokes. Addition here is just
  concatenation. Observe that adding one to the front of w in the
  picture above produces w again, which gives rise to a standard
  definition of w: w is the least ordinal such that adding another
  stroke at the beginning does not change the ordinal.

  We denote by w+w or w*2 the ``doubly infinite'' sequence that we
  might write as follows.

    w*2           |||||... |||||...

  One way to think of w*2 is that it is obtained by replacing each
  stroke in 2 (||) by w. Thus, one can imagine w*3, w*4, etc., which
  leads ultimately to the idea of ``w*w,'' the ordinal obtained by
  replacing each stroke in w by w. This is also written as ``omega
  squared'' or w^2, or:

     2
    w             |||||... |||||... |||||... |||||... |||||... ...

  We can analogously construct w^3 by replacing each stroke in w by w^2
  (which, it turns out, is the same as replacing each stroke in w^2
  by w). That is, we can construct w^3 as w copies of w^2,

     3              2       2       2       2
    w              w  ...  w  ...  w  ...  w ... ...

  Then we can construct w^4 as w copies of w^3, w^5 as w copies of w^4,
  etc., ultimately suggesting w^w. We can then stack omegas, i.e.,
  (w^w)^w etc. Consider the ``limit'' of all of those stacks, which
  we might display as follows.

           .
          .
         .
        w
       w
      w
     w
    w

  That is epsilon-0.

  Below we begin listing some ordinals up to epsilon-0; the reader can
  fill in the gaps at his or her leisure. We show in the left column
  the conventional notation, using w as ``omega,'' and in the right
  column the ACL2 object representing the corresponding ordinal.

    ordinal            ACL2 representation

    0                  0
    1                  1
    2                  2
    3                  3
    ...                ...
    w                 '((1 . 1) . 0)
    w+1               '((1 . 1) . 1)
    w+2               '((1 . 1) . 2)
    ...                ...
    w*2               '((1 . 2) . 0)
    (w*2)+1           '((1 . 2) . 1)
    ...                ...
    w*3               '((1 . 3) . 0)
    (w*3)+1           '((1 . 3) . 1)
    ...                ...

     2
    w                 '((2 . 1) . 0)
    ...                ...

     2
    w +w*4+3          '((2 . 1) (1 . 4) . 3)
    ...                ...

     3
    w                 '((3 . 1) . 0)
    ...                ...

     w
    w                 '((((1 . 1) . 0) . 1) . 0)
    ...                ...

     w  99
    w +w  +w4+3       '((((1 . 1) . 0) . 1) (99 . 1) (1 . 4) . 3)
    ...                ...

      2
     w
    w                 '((((2 . 1) . 0) . 1) . 0)

    ...                ...

      w
     w
    w                 '((((((1 . 1) . 0) . 1) . 0) . 1) . 0)
    ...               ...

  Observe that the sequence of o-ps starts with the natural numbers
  (which are recognized by [natp]). This is convenient because it
  means that if a term, such as a measure expression for justifying a
  recursive function (see [o<]) must produce an o-p, it suffices for
  it to produce a natural number.

  The ordinals listed above are listed in ascending order. This is the
  ordering tested by [o<].

  The ``epsilon-0 ordinals'' of ACL2 are recognized by the recursively
  defined function o-p. The base case of the recursion tells us that
  natural numbers are epsilon-0 ordinals. Otherwise, an epsilon-0
  ordinal is a list of [cons] pairs whose final [cdr] is a natural
  number, ((a1 . x1) (a2 . x2) ... (an . xn) . p). This corresponds
  to the ordinal (w^a1)x1 + (w^a2)x2 + ... + (w^an)xn + p. Each ai is
  an ordinal in the ACL2 representation that is not equal to 0. The
  sequence of the ai's is strictly decreasing (as defined by [o<]).
  Each xi is a positive integer (as recognized by [posp]).

  Note that infinite ordinals should generally be created using the
  ordinal constructor, [make-ord], rather than [cons]. The functions
  [o-first-expt], [o-first-coeff], and [o-rst] are ordinals
  destructors. Finally, the function [o-finp] and the macro [o-infp]
  tell whether an ordinal is finite or infinite, respectively.

  The function [o<] compares two epsilon-0 ordinals, x and y. If both
  are integers, (o< x y) is just x

    (defun o-p (x)
           (declare (xargs :guard t))
           (if (o-finp x)
               (natp x)
               (and (consp (car x))
                    (o-p (o-first-expt x))
                    (not (eql 0 (o-first-expt x)))
                    (posp (o-first-coeff x))
                    (o-p (o-rst x))
                    (o< (o-first-expt (o-rst x))
                        (o-first-expt x)))))")
 (O-RST
  (ORDINALS ACL2-BUILT-INS)
  "Returns the rest of an infinite ordinal

  An ACL2 infinite ordinal is a list whose elements are
  exponent-coefficient pairs (see [o-p] and see [o-infp]). The first
  exponent and first coefficient of an ordinal can be obtained by
  using [o-first-expt] and [o-first-coeff] respectively. To obtain
  the rest of the ordinal (for recursive analysis), use the o-rst
  function. It returns the rest of the ordinal after the first
  exponent and coefficient are removed.

  Function: 

    (defun o-rst (x)
           (declare (xargs :guard (consp x)))
           (cdr x))")
 (O<
  (ORDINALS ACL2-BUILT-INS)
  "The well-founded less-than relation on ordinals up to epsilon-0

  If x and y are both o-ps (see [o-p]) then (o< x y) is true iff x is
  strictly less than y. o< is well-founded on the [o-p]s. When x and
  y are both nonnegative integers, o< is just the familiar ``less
  than'' relation ([<]).

  o< plays a key role in the formal underpinnings of the ACL2 logic. In
  order for a recursive definition to be admissible it must be proved
  to ``terminate.'' By terminate we mean that the arguments to the
  function ``get smaller'' as the function recurses and this sense of
  size comparison must be such that there is no ``infinitely
  descending'' sequence of ever smaller arguments. That is, the
  relation used to compare successive arguments must be well-founded
  on the domain being measured.

  The most basic way ACL2 provides to prove termination requires the
  user to supply (perhaps implicitly) a mapping of the argument
  tuples into the ordinals with some ``measure'' expression in such a
  way that the measures of the successive argument tuples produced by
  recursion decrease according to the relation o<. The validity of
  this method rests on the well-foundedness of o< on the [o-p]s.

  Without loss of generality, suppose the definition in question
  introduces the function f, with one formal parameter x (which might
  be a list of objects). Then we require that there exist a measure
  expression, (m x), that always produces an [o-p]. Furthermore,
  consider any recursive call, (f (d x)), in the body of the
  definition. Let hyps be the conjunction of terms, each of which is
  either the test of an [if] in the body or else the negation of such
  a test, describing the path through the body to the recursive call
  in question. Then it must be a theorem that

    (IMPLIES hyps (O< (m (d x)) (m x))).

  When we say o< is ``well-founded'' on the [o-p]s we mean that there
  is no infinite sequence of [o-p]s such that each is smaller than
  its predecessor in the sequence. Thus, the theorems that must be
  proved about f when it is introduced establish that it cannot recur
  forever because each time a recursive call is taken (m x) gets
  smaller. From this, and the syntactic restrictions on definitions,
  it can be shown (as on page 44 in ``A Computational Logic'', Boyer
  and Moore, Academic Press, 1979) that there exists a function
  satisfying the definition; intuitively, the value assigned to any
  given x by the alleged function is that computed by a sufficiently
  large machine. Hence, the logic is consistent if the axiom defining
  f is added.

  See [o-p] for a discussion of the ordinals and how to compare two
  ordinals.

  The definitional principle permits the use of relations other than o<
  but they must first be proved to be well-founded on some domain.
  See [well-founded-relation]. Roughly put, alternative relations are
  shown well-founded by providing an order-preserving mapping from
  their domain into the ordinals. See [defun] for details on how to
  specify which well-founded relation is to be used.

  Function: 

    (defun o< (x y)
           (declare (xargs :guard (and (o
  (ORDINALS ACL2-BUILT-INS)
  "The greater-than relation for the ordinals

  O> is a macro and (o> x y) expands to (o< y x). See [o<].")
 (O>=
  (ORDINALS ACL2-BUILT-INS)
  "The greater-than-or-equal relation for the ordinals

  O>= is a macro and (o>= x y) expands to (not (o< x y)). See [o<].")
 (OBDD
  (BDD)
  "Ordered binary decision diagrams with rewriting

  See [bdd] for information on this topic.")
 (OBSERVATION
  (IO ACL2-BUILT-INS)
  "Print an observation

  Here is a typical application of observation.

    ACL2 !>(let ((ctx 'top-level)
                 (name 'foo))
             (observation ctx
                          \"Skipping processing of name ~x0.\"
                          name))

    ACL2 Observation in TOP-LEVEL:  Skipping processing of name FOO.
    
    ACL2 !>

  Observation prints an initial ``ACL2 Observation...: '', and then
  prints the indicated message using formatted printing (see [fmt]).
  Notice in the example above that evaluation of a call of
  observation returns [state]. Indeed, observation is actually a
  macro whose expansion takes and returns the ACL2 [state]. A similar
  utility, observation-cw, is available that does not take or return
  state; rather, it returns nil as the suffix ``cw'' suggests that a
  ``comment window'' is the target of this printing, rather than the
  state. For example:

    ACL2 !>(let ((ctx 'top-level)
                 (name 'foo))
             (observation-cw ctx
                             \"Skipping processing of name ~x0.\"
                             name))

    ACL2 Observation in TOP-LEVEL:  Skipping processing of name FOO.
    NIL
    ACL2 !>

  Observation-cw takes exactly the same arguments as observation, but
  observation-cw does its printing in a so-called ``wormhole''; see
  [wormhole].

    General Forms:
    (observation    ctx fmt-string fmt-arg1 fmt-arg2 ... fmt-argk)
    (observation-cw ctx fmt-string fmt-arg1 fmt-arg2 ... fmt-argk)

  where ctx generally evaluates to a symbol (but see below), and
  fmt-string together with the fmt-argi are suitable for passing to
  [fmt]. Output begins and ends with a newline.

  Recall from the example above that the output from a call of
  observation (or observation-cw) begins with ``ACL2 Observation''
  and additional characters ending in ``: '', for example `` in
  TOP-LEVEL: '', followed by formatted output produced from
  fmt-string with the given fmt-argi. The characters printed
  immediately following the string ``ACL2 Observation'' depend on the
  value of ctx. If ctx is nil, nothing is printed. If ctx is a
  non-nil symbol, it is printed using [fmt] directive ~x. If ctx is a
  [cons] pair whose [car] is a symbol, formatted printing is applied
  to the string \"(~x0 ~x1 ...)\", where #\\0 and #\\1 are bound
  respectively to that car and cdr. Otherwise, ctx is printed using
  [fmt] directive ~@.

  We next discuss situations in which printing is inhibited for
  observation and observation-cw. No printing is done when
  observation is among the inhibited output types; see
  [set-inhibit-output-lst]. Moreover, no printing is done by
  observation during [include-book]. If you want to avoid printing
  from observation-cw during [include-book], then you need to manage
  that yourself.")
 (OBSERVATION-CW (POINTERS)
                 "See [observation].")
 (ODDP
  (NUMBERS ACL2-BUILT-INS)
  "Test whether an integer is odd

  (oddp x) is true if and only if x is odd, i.e., not even in the sense
  of [evenp].

  The [guard] for oddp requires its argument to be an integer.

  Oddp is a Common Lisp function. See any Common Lisp documentation for
  more information.

  Function: 

    (defun oddp (x)
           (declare (xargs :guard (integerp x)))
           (not (evenp x)))")
 (OK-IF
  (BREAK-REWRITE)
  "Conditional exit from break-rewrite

    Example Form:
    :ok-if (null (brr@ :wonp))

    General Form:
    :ok-if expr

  where expr is a term involving no free variables other than state and
  returning one non-state result which is treated as Boolean. This
  form is intended to be executed from within break-rewrite (see
  [break-rewrite]).

  Consider first the simple situation that the (ok-if term) is a
  command read by break-rewrite. Then, if the term is non-nil,
  break-rewrite exits and otherwise it does not.

  More generally, ok-if returns an ACL2 error triple (mv erp val
  state). (See [ld] or see [programming-with-state] for more on error
  triples.) If any form being evaluated as a command by break-rewrite
  returns the triple returned by (ok-if term) then the effect of that
  form is to exit [break-rewrite] if term is non-nil. Thus, one might
  define a function or macro that returns the value of ok-if
  expressions on all outputs and thus create a convenient new way to
  exit break-rewrite.

  The exit test, term, generally uses brr@ to access context sensitive
  information about the attempted rule application. See [brr@]. Ok-if
  is useful inside of command sequences produced by break conditions.
  See [monitor]. :ok-if is most useful after an :eval command has
  caused break-rewrite to try to apply the rule because in the
  resulting break environment expr can access such things as whether
  the rule succeeded, if so, what term it produced, and if not, why.
  There is no need to use :ok-if before :evaling the rule since the
  same effects could be achieved with the break condition on the rule
  itself. Perhaps we should replace this concept with
  :eval-and-break-if? Time will tell.")
 (ON_THE_NAMING_OF_SUBGOALS
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "On the Naming of Subgoals

  Subgoal *1/2 is the induction step from the scheme, obtained by
  instantiating the scheme with our conjecture.

  We number the cases ``backward'', so this is case ``2'' of the proof
  of ``*1''. We number them backward so you can look at a subgoal
  number and get an estimate for how close you are to the end.")
 (OOPS
  (HISTORY)
  "Undo a :u or :[ubt]

  The keyword [command] :oops will undo the most recent :[ubt] (or :u,
  which we here consider just another :[ubt]). A second :oops will
  undo the next most recent :[ubt], a third will undo the :[ubt]
  before that one, and a fourth :oops will return the logical [world]
  to its configuration before the first :oops.

  Consider the logical world (see [world]) that represents the current
  extension of the logic and ACL2's rules for dealing with it. The
  :[ubt] and :u [command]s ``roll back'' to some previous [world]
  (see [ubt]). Sometimes these [command]s are used to inadvertently
  undo useful work and user's wish they could ``undo the last undo.''
  That is the function provided by :oops.

  :Oops is best described in terms of an implementation. Imagine a ring
  of four [world]s and a marker (*) indicating the current ACL2
  [world]:

          *
        w0
      /    \\
    w3      w1
      \\    /
        w2

  This is called the ``kill ring'' and it is maintained as follows.
  When you execute an event the current [world] is extended and the
  kill ring is not otherwise affected. When you execute :[ubt] or :u,
  the current [world] marker is moved one step counterclockwise and
  that [world] in the ring is replaced by the result, say w0', of the
  :[ubt] or :u.

         w0
       /    \\
    *w0'     w1
       \\    /
         w2

  If you were to execute [events] at this point, w0' would be extended
  and no other changes would occur in the kill ring.

  When you execute :oops, the marker is moved one step clockwise. Thus
  the kill ring becomes

          *
        w0
      /    \\
    w0'     w1
      \\    /
        w2

  and the current ACL2 [world] is w0 once again. That is, :oops
  ``undoes'' the :[ubt] that produced w0' from w0. Similarly, a
  second :oops will move the marker to w1, undoing the undo that
  produced w0 from w1. A third :oops makes w2 the current [world].
  Note however that a fourth :oops restores us to the configuration
  previously displayed above in which w0' has the marker.

  In general, the kill ring contains the current [world] and the three
  most recent [world]s in which a :[ubt] or :u were done.

  While :[ubt] may appear to discard the information in the [events]
  undone, we can see that the [world] in which the :[ubt] occurred is
  still available. No information has been lost about that [world].
  But :[ubt] does discard information! :[Ubt] discards the
  information necessary to recover from the third most recent [ubt]!
  An :oops, on the other hand, discards no information, it just
  selects the next available [world] on the kill ring and doing
  enough :oopses will return you to your starting point.

  We can put this another way. You can freely type :oops and inspect
  the [world] that you thus obtain with :[pe], :[pc], and other
  [history] [command]s. You can repeat this as often as you wish
  without risking the permanent loss of any information. But you must
  be more careful typing :[ubt] or :u. While :oops makes :[ubt] seem
  ``safe'' because the most recent :[ubt] can always be undone,
  information is lost when you execute :[ubt].

  We note that :ubt and :u may remove compiled definitions (but note
  that in some Lisps, including CCL (OpenMCL) and SBCL, functions are
  always compiled). When the original world is restored using :oops,
  restored functions will not generally be compiled (except for Lisps
  as above), though the user can remedy this situation; see [comp].

  Finally, we note that our implementation of oops can use a
  significant amount of memory, because of the saving of old logical
  [world]s. Most users are unlikely to experience a memory problem,
  but if you do, then you may want to disable oops by evaluting
  (reset-kill-ring 0 state); see [reset-kill-ring].")
 (OPEN-INPUT-CHANNEL (POINTERS)
                     "See [io].")
 (OPEN-INPUT-CHANNEL-P (POINTERS)
                       "See [io].")
 (OPEN-OUTPUT-CHANNEL (POINTERS)
                      "See [io].")
 (OPEN-OUTPUT-CHANNEL!
  (IO ACL2-BUILT-INS)
  "When trust tags are needed to open output channels

  Use this function in place of open-output-channel if you want to open
  a channel for output at times this would otherwise be prohibited,
  for example during [make-event] expansion and [clause-processor]
  [hints]. If this functionality doesn't quite seem like what you
  need, take a look at the definition of open-output-channel! in
  axioms.lisp, specifically the binding of [state] global variable
  writes-okp. The following example, taken from (no longer available)
  community book books/hons-archive/hons-archive.lisp, illustrates
  the latter approach.

    (defmacro har-zip! (x filename &key sortp)
      \"See :doc hons-archive\"
      `(mv-let (erp val state)
               (progn!
                :state-global-bindings
                ((temp-touchable-vars t set-temp-touchable-vars))
                (state-global-let*
                 ((writes-okp t))
                 (let ((state (har-zip-fn ,x ,filename ,sortp state)))
                   (mv nil nil state))))
               (declare (ignore erp val))
               state))

  The book below illustrates the soundness loophole plugged in ACL2
  Version_3.2 related to file writes during book certification.

    ; The following example is adapted (with only very slight changes)
    ; from one written by Peter Dillinger.  It illustrates the prohibition
    ; against writing files enforced by with-output-channel during book
    ; certification (more specifically, during make-event expansion).

    ; This book certifies in ACL2 Version_3.1 before the fix discussed in the
    ; paragraph about it being ``possible to write files during book
    ; certification'' in :DOC NOTE-3-2.  The fix was actually made to ACL2
    ; function open-output-channel.

    ; After the fix, in order for certification to succeed one needs to do
    ; two things.  First, in raw lisp:
    ;   (push :after-writes-okp-fix *features*)
    ; Second, certify with this command:
    ;   (certify-book \"writes-okp\" 0 nil :ttags (:writes-okp))

    (in-package \"ACL2\")

    (local
     (defun write-objects-to-channel (obj-lst chan state)
       (declare (xargs :mode :program
                       :stobjs state
                       :guard (true-listp obj-lst)))
       (if (consp obj-lst)
           (pprogn (print-object$ (car obj-lst) chan state)
                   (write-objects-to-channel (cdr obj-lst) chan state)
                   state)
         state)))

    #+after-writes-okp-fix
    (defttag :writes-okp)

    (local
     (defun write-objects-to-file (obj-lst filename state)
       (declare (xargs :mode :program
                       :stobjs state
                       :guard (and (stringp filename)
                                   (true-listp obj-lst))))
       (mv-let (chan state)
               #-after-writes-okp-fix
               (open-output-channel filename :object state)
               #+after-writes-okp-fix
               (open-output-channel! filename :object state)
               (if chan
                   (pprogn (write-objects-to-channel obj-lst chan state)
                           (close-output-channel chan state)
                           (value :done))
                 (er soft 'write-object-to-file
                     \"Could not open for writing: ~x0\"
                     filename)))))

    (local
     (defconst *nil.lisp*
       '((in-package \"ACL2\")
         (defthm bad nil :rule-classes nil))))

    (local
     (defconst *nil.cert*
       '((IN-PACKAGE \"ACL2\")
         \"ACL2 Version 3.1\"
         :BEGIN-PORTCULLIS-CMDS
         :END-PORTCULLIS-CMDS
         NIL
         ((\"/home/peterd/test/nil.lisp\" \"nil\" \"nil\"
           ((:SKIPPED-PROOFSP) (:AXIOMSP) (:TTAGS)) . 134094174))
         62589544
         )))

    (local
     (make-event (er-progn
                  (write-objects-to-file *nil.lisp* \"nil.lisp\" state)
                  (write-objects-to-file *nil.cert* \"nil.cert\" state)
                  (value '(value-triple :invisible)))))

    (local (include-book
            \"nil\" :load-compiled-file nil))

    (defthm bad nil :rule-classes nil)")
 (OPEN-OUTPUT-CHANNEL-P (POINTERS)
                        "See [io].")
 (OPEN-TRACE-FILE
  (TRACE)
  "Redirect trace output to a file

    Example:
    (open-trace-file \"foo\") ; trace output will go to file foo

    General Form:
    (open-trace-file filename) ; trace output will go to file filename

  Output from [trace$] normally goes to the screen, i.e.,
  [standard-co]. But it can be redirected to a file as shown above.
  See [close-trace-file] for how to send trace output back to the
  screen.")
 (OPTIMIZE (POINTERS) "See [declare].")
 (OR
  (BASICS ACL2-BUILT-INS)
  "Disjunction

  Or is the macro for disjunctions. Or takes any number of arguments
  and returns the first that is non-nil, or nil if there is no
  non-nil element.

  In the ACL2 logic, the macroexpansion of (or x y) is an IF term that
  appears to cause x to be evaluated twice:

    ACL2 !>:trans (or x y)

    (IF X X Y)

    => *

    ACL2 !>

  If x were replaced by an expression whose evaluation takes a long
  time, then such an expansion would be ineffecient. However, don't
  be fooled: you can expect Common Lisp implementations to avoid this
  problem, say by generating a new variable, for example:

    ACL2 !>:q ; Exit the ACL2 loop and go into raw Common Lisp

    Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
    ACL2>(macroexpand '(or x y))

    (LET ((#:G5374 X)) (IF #:G5374 #:G5374 Y))
    T

    ACL2>

  Or is a Common Lisp macro. See any Common Lisp documentation for more
  information.

  Macro: 

    (defmacro or (&rest args)
              (or-macro args))

  Function: 

    (defun or-macro (lst)
           (declare (xargs :guard t))
           (if (consp lst)
               (if (consp (cdr lst))
                   (list 'if
                         (car lst)
                         (car lst)
                         (or-macro (cdr lst)))
                   (car lst))
               nil))")
 (ORACLE-APPLY
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Call a function argument on the given list of arguments

  Oracle-apply evaluates its first argument to produce an ACL2 function
  symbol, FN, and then applies FN to the value of the second
  argument, which should be a true list whose length is the number of
  inputs for FN. The return value is of the form (mv call-result
  state).

    Examples:
    (oracle-apply 'cons '(3 4) state) = (mv '(3 . 4) )
    (oracle-apply (car '(floor foo)) (list (+ 6 7) 5) state) = (mv 2 )

  Also see [oracle-funcall] for a related utility.

  Note that calls of oracle-funcall and oracle-apply return two values:
  the result of the function application, and a modified [state].

  Oracle-apply is defined in :[logic] mode, and in fact is
  [guard]-verified. However, you will not be able to prove much about
  this function, because it is defined in the logic using the
  acl2-oracle field of the ACL2 [state]; see [read-ACL2-oracle]. The
  behavior described above --- i.e., making a function call --- takes
  place when the third argument is the ACL2 [state], so during proofs
  (when that can never happen), a term (oracle-apply 'fn '...) will
  not simplify using a call of fn.

  The guard for (oracle-apply fn args state) is the term
  (oracle-apply-guard fn args state), which we describe below.

  Function: 

    (defun oracle-apply-guard (fn args state)
           (declare (xargs :stobjs state))
           (and (f-boundp-global 'temp-touchable-fns
                                 state)
                (ev-fncall-w-guard fn args (w state)
                                   (f-get-global 'temp-touchable-fns
                                                 state))))

  where:

  Function: 

    (defun
     ev-fncall-w-guard
     (fn args wrld temp-touchable-fns)
     (declare (xargs :guard t))
     (and
      (plist-worldp wrld)
      (symbolp fn)
      (not (eq fn 'if))
      (not (assoc-eq fn *ttag-fns-and-macros*))
      (true-listp args)
      (let* ((formals (getprop fn 'formals
                               t 'current-acl2-world
                               wrld))
             (stobjs-in (stobjs-in fn wrld))
             (untouchable-fns (global-val 'untouchable-fns wrld)))
            (and (not (eq formals t))
                 (eql (len formals) (len args))
                 (true-listp untouchable-fns)
                 (or (not (member-eq fn untouchable-fns))
                     (and temp-touchable-fns
                          (or (eq t temp-touchable-fns)
                              (and (true-listp temp-touchable-fns)
                                   (member-eq fn temp-touchable-fns)))))
                 (not (and (null formals)
                           (getprop fn 'stobj-function
                                    nil 'current-acl2-world
                                    wrld)))
                 (true-listp stobjs-in)
                 (all-nils stobjs-in)))))

  These definitions say that fn is a function symbol other than if; it
  is not among the keys of the alist, *ttag-fns-and-macros*; and it
  does not take or create a [stobj] (see [defstobj]). Moreover, the
  second argument, args, must be a true list whose length is the
  number of formal parameters of fn. These requirements may be a bit
  onerous for guard verification of functions that call oracle-apply,
  but this is easily overcome by using [ec-call], for example as
  follows.

    (defun f (x state)
      (declare (xargs :stobjs state))
      (ec-call (oracle-apply 'car (list x) state)))

  This use of [ec-call] will, however, cause the [guard] of
  oracle-apply to be checked at runtime.

  If the [guard] for oracle-apply fails to hold but there is no guard
  violation because guard-checking is suppressed (see
  [set-guard-checking]), then the value returned is computed using
  its logical definition --- which, as mentioned above, uses the ACL2
  oracle --- and hence the value computed is unpredictable (indeed,
  the function argument will not actually be called).

  The value returned by oracle-apply is always a single value obtained
  by calling the executable counterpart of its function argument, as
  we now explain. Consider a form (oracle-apply fn args state) that
  evaluates to (mv VAL state'), where fn evaluates to the function
  symbol F. If F returns multiple values, then VAL is the first value
  computed by the call of F on the value of args. More precisely,
  oracle-apply actually invokes the executable counterpart of F;
  thus, if args is the expression (list x1 ... xk), then VAL is the
  same as (first) value returned by evaluating (ec-call (F x1 x2 ...
  xk)). See [ec-call].

  (Remark. If you identify a need for a version of oracle-apply to
  return multiple values, we can perhaps provide such a utility; feel
  free to contact the ACL2 implementors to request it.)

  A subtlety is that the evaluation takes place in so-called ``safe
  mode'', which avoids raw Lisp errors due to calls of :[program]
  mode functions. The use of safe mode is unlikely to be noticed if
  the value of the first argument of oracle-apply is a :[logic] mode
  function symbol. However, for :program mode functions with side
  effects due to special raw Lisp code, as may be the case for
  built-in functions or for custom functions defined with active
  trust tags (see [defttag]), use of the function [oracle-apply-raw]
  may be preferable. It is a much less restrictive version of
  oracle-apply, which avoids safe mode and (for example) can apply a
  function that has a definition in the host Lisp but not in the ACL2
  [world].

  Function: 

    (defun oracle-apply (fn args state)
           (declare (xargs :stobjs state
                           :guard (oracle-apply-guard fn args state)))
           (mv-let (erp val state)
                   (read-acl2-oracle state)
                   (declare (ignore erp))
                   (mv (and (true-listp val)
                            (eq (car val) fn)
                            (equal (cadr val) args)
                            (caddr val))
                       state)))")
 (ORACLE-APPLY-RAW
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Call a function argument on the given list of arguments, no
  restrictions

  See [oracle-apply], as we assume familiarity with that function.
  Oracle-apply-raw is a variant of oracle-apply that is untouchable,
  and hence requires a trust tag to remove the untouchability (see
  [defttag] and see [remove-untouchable]). Unlike oracle-apply,
  oracle-apply-raw simply calls the raw Lisp function funcall to
  compute the result, without restriction: the specified :[guard] is
  t, the function itself is applied (not its executable counterpart),
  there is no restriction for untouchable functions or [return-last],
  and safe mode is not used. Thus, in general, oracle-apply-raw can
  be dangerous to use: any manner of error can occur!

  As is the case for [oracle-apply], the function symbol
  [oracle-apply-raw] is defined in :[logic] mode and is
  [guard]-verified. Oracle-apply-raw is logically defined to be
  [oracle-apply]; more precisely:

    (oracle-apply-raw fn args state)
    = {logical definition}
    (ec-call (oracle-apply fn args state))

  Function: 

    (defun oracle-apply-raw (fn args state)
           (declare (xargs :stobjs state :guard t))
           (ec-call (oracle-apply fn args state)))")
 (ORACLE-FUNCALL
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Call a function argument on the remaining arguments

  Oracle-funcall evaluates its first argument to produce an ACL2
  function symbol, and then applies that function symbol to the
  values of the rest of the arguments. The return value is of the
  form (mv call-result state).

    Examples:
    (oracle-funcall 'cons 3 4) ==> (mv '(3 . 4) )
    (oracle-funcall (car '(floor foo bar)) (+ 6 7) 5) ==> (mv 2 )

  Oracle-funcall is a macro; each of its calls macroexpands to a call
  of the related utility oracle-apply that takes the ACL2 [state] as
  an argument, as follows:

    (oracle-funcall fn x1 x2 .. xk)

  macroexpands to

    (oracle-apply fn (list x1 x2 .. xk) state)

  Note that calls of oracle-funcall and oracle-apply return two values:
  the result of the function application, and a modified [state].

  See [oracle-apply] for details, including information about [guard]s.

  Macro: 

    (defmacro oracle-funcall (fn &rest args)
              (cons 'oracle-apply
                    (cons fn
                          (cons (cons 'list args)
                                (cons 'state 'nil)))))")
 (ORDINALS
  (MISCELLANEOUS)
  "Ordinals in ACL2

  Ordinals are used in ACL2 for proving termination in the admission of
  recursive function definitions. For a proof that the ACL2 ordinals
  are well-founded, see [proof-of-well-foundedness].

  The representation of ordinals changed in ACL2 Version_2.8, and is
  due to Pete Manolios and Daron Vroon. They have also defined
  algorithms for ordinal arithmetic, created a library of theorems to
  reason about ordinal arithmetic, and written the rest of this
  documentation in order to explain this change. We thank them for
  their efforts. Although they have provided the implementation and
  even modified the community books as needed, we have looked over
  their work and are maintaining it (and this documentation); if
  there are any bugs, they should be considered ours (Matt Kaufmann
  and J Moore).

  A book is included for compatibility with the representation before
  Version_2.8. For books that contain events relying on the previous
  ordinal implementation, insert the following lines before the first
  such event:

    (include-book \"ordinals/e0-ordinal\" :dir :system)
    (set-well-founded-relation e0-ord-<)

  The new ordinal representation is based on a slightly different
  version of Cantor Normal Form than that used by the old ordinals.
  An advantage of the new representation is that it is exponentially
  more succinct than the old representation.

  While pre-Version_2.8 ACL2 versions provided built-in functions for
  checking if an object is an ordinal and for comparing two ordinals,
  they did not provide support for reasoning about and constructing
  ordinals. The community books directory books/ordinals provides
  such support. First, it provides efficient algorithms for ordinal
  arithmetic (including addition, subtraction, multiplication, and
  exponentiation). The algorithms and their complexity are described
  in the following paper.

    Manolios, Panagiotis & Vroon, Daron.
    Algorithms for ordinal arithmetic.
    Baader, Franz (ed),
    19th International Conference on Automated Deduction--CADE-19.
    Pages 243-257 of LNAI, vol. 2741.  Springer-Verlag.

  Second, the algorithms are mechanically verified and libraries of
  theorems which can be used to automate reasoning involving the
  ordinals are provided. For details, see the following paper.

    Manolios, Panagiotis & Vroon, Daron.
    Ordinal arithmetic in ACL2.
    Kaufmann, Matt, & Moore, J Strother (eds).
    Fourth International Workshop on the ACL2 Theorem
    Prover and Its Applications (ACL2-2003),
    July, 2003.
    See {http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/ | http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/}.

  We now describe aspects of the above mentioned books in more detail.

  The new ordering function is [o<] and the new ordinal recognizer is
  [o-p]. See also [natp], [posp], [o<=], [o>], [o>=], [o-first-expt],
  [o-first-coeff], [o-rst], [make-ord], [o-finp], and [o-infp].

  The old ordinals were based on the following formulation of Cantor
  Normal Form:

  For any ordinal, a < epsilon-0, there exist natural numbers p and n,
  and ordinals a1 >= a2 >= ... >= an > 0 such that a > a1 and a =
  w^(a1) + w^(a2) + ... + w^(an) + p.

  Thus, a predicate recognizing ACL2's old ordinals is given by the
  following definition.

    (defun e0-ordinalp (x)
      (if (consp x)
          (and (e0-ordinalp (car x))
               (not (equal (car x) 0))
               (e0-ordinalp (cdr x))
               (or (atom (cdr x))
                   (not (e0-ord-< (car x) (cadr x)))))
        (and (integerp x)
             (>= x 0))))

  The new representation is based on a corollary to the above theorem,
  which we get by the left distributive property of ordinal
  multiplication over ordinal addition. Thus, w^a + w^a = (w^a)2, w^a
  + w^a + w^a = (w^a)3 and so forth. The corollary is as follows:

  For any ordinal, a < epsilon-0, there exist natural numbers p and n,
  positive integers x1, x2, ..., xn and ordinals a1 > a2 > ... > an >
  0 such that a > a1 and a = w^(a1)x1 + w^(a2)x2 + ... + w^(an)xn +
  p.

  Instead of representing an ordinal as a list of non-increasing
  ordinals, we represent it as a list of exponent-coefficient pairs,
  such that the exponents are strictly decreasing (see [o-p]). Note
  that this representation is exponentially more efficient than the
  old representation.

  The ordinal arithmetic functions: o+, o-, o*, and o^ are defined in
  the ordinals library (in the community books directory
  books/ordinals). To use them, include the book
  ordinals-without-arithmetic or ordinals, depending on whether you
  want the arithmetic books included or not (ordinals includes
  community book books/arithmetic/top-with-meta). To use the old
  ordinals, include the book e0-ordinal and run the command
  (set-well-founded-relation e0-ord-<)

  The community book [arithmetic/natp-posp] is a book for reasoning
  about posp and natp. We recommend using this book if you have to
  reason about posp and natp. It is included in community book
  books/arithmetic/top, which is included in community book
  books/arithmetic/top-with-meta, which is included in community book
  books/ordinals/ordinals.

  If you have a good reason to use the old definitions of the ordinals
  (e.g., because of legacy code and theorems), then we provide a
  convenient way to do this. The book ordinal-isomorphism proves that
  the new ordinals are order-isomorphic to the old ordinals and thus
  theorems proved in one context can be directly transferred to the
  other. For an example of how to do this, look at the book defmul in
  the community books directory books/workshops/2000/ruiz/multiset.

  The ordinals books have been used to prove non-trivial theorems. For
  a good example, see the books in the community books directory
  books/workshops/2003/sustik/support, where Matyas Sustik proves
  Dickson's lemma.

  Finally, many termination proofs can be carried out with weaker
  orderings than the ordinals up to epsilon-0. For example, many
  inductive theorem provers only know that the lexicographic ordering
  on natural numbers is well-founded. The book lexicographic-ordering
  contains a definition of such an ordering l< whose arguments are
  either a list of natural numbers, or a natural number. In the book
  we prove that l< is well-founded (that is, we prove a
  :well-founded-relation [defthm] and provide a macro llist to
  simplify the generation of measure functions. We also show how to
  use l< to prove that the famous Ackermann function terminates.
  Finally, since l< does something reasonable with natural numbers,
  it gets along with [ACL2-count], the default measure chosen by
  ACL2.


Subtopics

  [Make-ord]
      A constructor for ordinals.

  [O-finp]
      Recognizes if an ordinal is finite

  [O-first-coeff]
      Returns the first coefficient of an ordinal

  [O-first-expt]
      The first exponent of an ordinal

  [O-infp]
      Recognizes if an ordinal is infinite

  [O-p]
      A recognizer for the ordinals up to epsilon-0

  [O-rst]
      Returns the rest of an infinite ordinal

  [O<]
      The well-founded less-than relation on ordinals up to epsilon-0

  [O<=]
      The less-than-or-equal relation for the ordinals

  [O>]
      The greater-than relation for the ordinals

  [O>=]
      The greater-than-or-equal relation for the ordinals

  [Proof-of-well-foundedness]
      A proof that [o<] is well-founded on [o-p]s")
 (OTF-FLG
  (DEFTHM THM XARGS)
  "Allow more than one initial subgoal to be pushed for induction

  The value of this flag is normally nil. If you want to prevent the
  theorem prover from abandoning its initial work upon pushing the
  second subgoal, set :otf-flg to t.

  Suppose you submit a conjecture to the theorem prover and the system
  splits it up into many subgoals. Any subgoal not proved by other
  methods is eventually set aside for an attempted induction proof.
  But upon setting aside the second such subgoal, the system chickens
  out and decides that rather than prove n>1 subgoals inductively, it
  will abandon its initial work and attempt induction on the
  originally submitted conjecture. The :otf-flg (Onward Thru the Fog)
  allows you to override this chickening out. When :otf-flg is t, the
  system will push all the initial subgoals and proceed to try to
  prove each, independently, by induction.

  Even when you don't expect induction to be used or to succeed,
  setting the :otf-flg is a good way to force the system to generate
  and display all the initial subgoals.

  For [defthm] and [thm], :otf-flg is a keyword argument that is a peer
  to :[rule-classes] and :[hints]. It may be supplied as in the
  following examples; also see [defthm].

    (thm (my-predicate x y) :rule-classes nil :otf-flg t)

    (defthm append-assoc
      (equal (append (append x y) z)
             (append x (append y z)))
      :hints ((\"Goal\" :induct t))
      :otf-flg t)

  The :otf-flg may be supplied to [defun] via the [xargs] declare
  option. When you supply an :otf-flg hint to defun, the flag is
  effective for the termination proofs and the guard proofs, if any.")
 (OTHER_REQUIREMENTS
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Other Requirements

  [{IMAGE}]

  ACL2 is distributed on the Web without fee.

  There is a license agreement based on the 3-clause BSD license. See
  the file LICENSE in the ACL2 distribution.

  ACL2 currently runs on Unix, Linux, Windows, and Macintosh OS X
  operating systems.

  It can be built in any of the following Common Lisps:

    * Allegro Common Lisp,
    * CCL (formerly OpenMCL)
    * CLISP,
    * CMU Common Lisp,
    * GCL (Gnu Common Lisp),
    * LispWorks, and
    * SBCL (Steel Bank Common Lisp)

  [{IMAGE}]")
 (OUTPUT-TO-FILE
  (IO)
  "Redirecting output to a file

  For a general discussion of ACL2 input/output and of the ACL2
  read-eval-print loop, see [io] and see [ld] (respectively). Here we
  use an example to illustrate how to use some of the options
  provided by ld to redirect ACL2 output to a file, other than the
  printing of the prompt (which continues to go to the terminal).

  There are two ld specials that control output from the ld command:
  [proofs-co] for proof output and [standard-co] for other output.
  The following example shows how to use these to redirect output to
  a file \"tmp.out\". The following command opens a character output
  channel to to the file \"tmp.out\" and redirects proof output to that
  channel, i.e., to file \"tmp.out\".

    (mv-let (chan state)
            (open-output-channel \"tmp.out\" :character state)
            (set-proofs-co chan state))

  Next, we redirect standard output to that same channel.

    (set-standard-co (proofs-co state) state)

  Now we can load an input file, in this case file \"tmp.lisp\", and
  output will be redirected to file \"tmp.out\". (The use of
  :ld-pre-eval-print t is optional; see [ld].)

    (ld \"tmp.lisp\" :ld-pre-eval-print t)

  Having completed our load operation, we restore both proof output and
  standard output to the terminal, as follows.

    (set-standard-co *standard-co* state)
    (close-output-channel (proofs-co state) state)
    (set-proofs-co *standard-co* state)

  The following variant of the above example shows how to redirect
  output as above except without changing the global settings of the
  two [ld] specials, [proofs-co] and [standard-co]. This approach
  uses a notion of ``global variables'' stored in the ACL2 [state];
  see [assign] and see [@].

    (mv-let (chan state)
            (open-output-channel \"tmp.out\" :character state)
            (assign tmp-channel chan))
    (ld \"tmp.lisp\" :ld-pre-eval-print t
                   :proofs-co (@ tmp-channel)
                   :standard-co (@ tmp-channel))
    (close-output-channel (@ tmp-channel) state)")
 (OVERRIDE-HINTS
  (HINTS)
  "A list of hints given priority in every proof attempt

  This is an advanced feature, originally implemented to help system
  designers to create ``modes'' that control the way hints are
  supplied to the theorem prover. Please see [default-hints] for the
  much more usual way to install hints that may be applied by
  default.

    Examples:
    ACL2 !>(override-hints (w state))
    ((computed-hint-1 clause keyword-alist processor)
     (computed-hint-2 clause keyword-alist stable-under-simplificationp))

  Override-hints returns a list of computed hints (see
  [computed-hints]) which, unlike other computed hints, may mention
  the variable KEYWORD-ALIST.

  Before reading further, please see [hints-and-the-waterfall] to
  review the basics of how [hints] are applied during a proof. In
  particular, we assume familiarity with the notion of selecting a
  hint to be applied to the current goal. If there are
  override-hints, that hint selection is tentative, because if it
  reduced to nil after the application of override-hints, then that
  hint will be skipped and the attempt will continue for selecting an
  applicable hint. (Craft your override-hints so that :no-op t is
  returned in such cases instead of nil, if you don't want the hint
  to be skipped.) But we must explain what is meant by ``the
  application of override-hints'', and we do that now.

  Suppose that there are override-hints when a hint is selected for the
  current goal. That selected hint is a keyword-alist, which is an
  alternating list of hint keywords and their values, whose source is
  either an explicit hint (goal-name :key1 val1 ... :keyn valn) where
  the :keyi are allowed to be custom hint keywords (which are
  expanded away; see [custom-keyword-hints]), or else is the non-nil
  keyword-alist produced by evaluating a computed hint. Then the
  override-hints are applied to that keyword-alist as follows, one at
  a time, in order of their occurrence in the list of override-hints
  (as determined by the use of [set-override-hints] and
  [add-override-hints]). The first override-hint is evaluated, in the
  usual manner of evaluating computed hints but with the variable
  KEYWORD-ALIST bound to the above keyword-alist. That evaluation
  produces a result that should also be a keyword-alist, or else an
  error occurs. Any custom keyword hints are then eliminated from
  that keyword-alist. The resulting keyword-alist must not contain
  the :ERROR hint keyword and must not start with the
  :COMPUTED-HINT-REPLACEMENT keyword; otherwise an error occurs. With
  KEYWORD-ALIST bound to this result, the second override-hint is
  similarly evaluated. This process continues, and the keyword-alist
  returned by the final override-hint is the one used when processing
  the goal at hand. Except: If that keyword-alist is nil, then the
  next hint among the pending hints is tentatively selected and the
  process repeats, applying each override hint to that new tentative
  selection. Of course we might obtain nil again, in which case we
  tentatively select the next pending hint; and so on.

  If finally no hint is selected for the current goal, then
  KEYWORD-ALIST is bound to nil and the override-hints are applied as
  described above. But note that this final step is skipped if hint
  selection is being performed because stable-under-simplificationp
  has just become true, rather than at the top of the waterfall.
  (Otherwise the override-hints could easily keep firing uselessly
  yet putting us back at the top of the waterfall, with no change to
  the given goal, resulting in an infinite loop.)

  As mentioned above, the :COMPUTED-HINT-REPLACEMENT keyword is illegal
  for the value of an override-hint. But a selected hint may be a
  computed hint that evaluates to a keyword-alist beginning with
  prefix :COMPUTED-HINT-REPLACEMENT val. What value does ACL2 return
  for such a computed hint in the presence of override-hints? First,
  this prefix is stripped off before passing the resulting
  keyword-alist to the override-hints as described above. If the
  result of applying override-hints to that keyword-alist is not nil,
  then the prefix is put back on the front of that resulting
  keyword-alist after doing internal processing of the hint,
  including expansion of any custom keyword hints. Otherwise, the
  application of override-hints to the computed hint is nil, so this
  hint is not selected after all.

  WARNING: Unlike ordinary computed hints, a value of nil for an
  override-hint is not ignored. That is: When an ordinary computed
  hint evaluates to nil, it is deemed not to apply, and the next
  available hint is consulted. But when an override-hint is
  evaluated, the result is always supplied for the next binding of
  the variable KEYWORD-ALIST, even if that result is nil. If you want
  an override-hint to be a no-op, return as the expression the
  variable KEYWORD-ALIST rather than an expression that evaluates to
  nil.

  This feature can be used in order to implement a form of additive
  hints. Suppose for example that you want a hint that turns off
  generalization. A simple but inadequate solution is:

    (add-default-hints '((quote (:do-not '(generalize)))))

  The problem is that if there is any explicit hint supplied for a
  given goal, then it will be the one selected, and the above will be
  ignored. But suppose that the explicit hint supplied is of the form
  (\"Subgoal x.y\" :do-not '(fertilize)). What we would really want in
  this case is to generate the hint for the indicated subgoal that
  binds :do-not to a list indicating that both fertilization _and_
  generalization are disabled for that goal. A solution is to merge,
  for example as follows. (The use of [prog2$] and [cw] is of course
  optional, included here to provide debug printing.)

    (add-override-hints
     '((let* ((tmp (assoc-keyword :do-not KEYWORD-ALIST))
              (new-keyword-alist
               (cond (tmp (list* :do-not
                                 `(cons 'generalize ,(cadr tmp))
                                 (remove-keyword :do-not KEYWORD-ALIST)))
                     (t (list* :do-not ''(generalize) KEYWORD-ALIST)))))
         (prog2$ (cw \"New: ~x0~|\" new-keyword-alist)
                 new-keyword-alist))))

  REMARKS

  (1) The utilities [add-override-hints], [add-override-hints!],
  [set-override-hints], [set-override-hints!],
  [remove-override-hints], and [remove-override-hints!] are also
  available, in complete analogy to their default-hints versions.

  (2) The community book hints/basic-tests.lisp illustrates the use of
  override-hints and illuminates a number of corner cases; search in
  that file for ``Test override-hints.''

  (3) The community book hints/merge-hint.lisp provides support for
  merging hints that might be useful for writers of override-hint
  expressions (see the examples at the end of that file).

  (4) Override-hints are used in the processing of :BACKTRACK hints
  (see [hints]).


Subtopics

  [Add-override-hints]
      Add to the [override-hints]

  [Add-override-hints!]
      Add non-[local]ly to the [override-hints]

  [Remove-override-hints]
      Delete from the list of [override-hints]

  [Remove-override-hints!]
      Delete non-[local]ly from the list of [override-hints]

  [Set-override-hints]
      Set the [override-hints]

  [Set-override-hints!]
      Set the [override-hints] non-[local]ly")
 (OVERVIEW_OF_THE_EXPANSION_OF_ENDP_IN_THE_BASE_CASE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Overview of the Expansion of ENDP in the Base Case

  Subgoal *1/1 is the Base Case of our induction. It simplifies to
  Subgoal *1/1' by expanding the ENDP term in the hypothesis, just as
  we saw in the earlier proof of Subgoal *1/2.")
 (OVERVIEW_OF_THE_EXPANSION_OF_ENDP_IN_THE_INDUCTION_STEP
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Overview of the Expansion of ENDP in the Induction Step

  In this message the system is saying that Subgoal *1/2 has been
  rewritten to the Subgoal *1/2', by expanding the definition of
  endp. This is an example of simplification, one of the main proof
  techniques used by the theorem prover.

  Click [here] if you would like to step through the simplification of
  Subgoal *1/2.")
 (OVERVIEW_OF_THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Overview of the Final Simplification in the Base Case

  The But is our signal that the goal is proved.

  Click [here] to step through the proof. It is very simple.")
 (OVERVIEW_OF_THE_PROOF_OF_A_TRIVIAL_CONSEQUENCE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Overview of the Proof of a Trivial Consequence

  [{IMAGE}]

  {IMAGE}

    ACL2 !>(defthm trivial-consequence
             (equal (app (app (app (app x1 x2) (app x3 x4)) (app x5 x6)) x7)
                    (app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7))))))

    [ACL2 Warning] [Subsume] in ( DEFTHM TRIVIAL-CONSEQUENCE ...):  The previously
    added rule ASSOCIATIVITY-OF-APP subsumes the newly proposed :REWRITE
    rule TRIVIAL-CONSEQUENCE, in the sense that the old rule rewrites a
    more general target.  Because the new rule will be tried first, it
    may nonetheless find application.

    By the simple :rewrite rule [ASSOCIATIVITY-OF-APP] we reduce the conjecture
    to

    Goal'
    (EQUAL (APP X1
                (APP X2
                     (APP X3 (APP X4 (APP X5 (APP X6 X7))))))
           (APP X1
                (APP X2
                     (APP X3 (APP X4 (APP X5 (APP X6 X7))))))).

    But we reduce the conjecture to T, by primitive type reasoning.

    Q.E.D.

    Summary
    Form:  ( DEFTHM TRIVIAL-CONSEQUENCE ...)
    Rules: ((:REWRITE ASSOCIATIVITY-OF-APP)
            (:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  [Subsume]
    Time:  0.20 seconds (prove: 0.02, print: 0.00, other: 0.18)
     TRIVIAL-CONSEQUENCE

  {IMAGE}

  You might explore the links before moving on.

  [{IMAGE}]")
 (OVERVIEW_OF_THE_SIMPLIFICATION_OF_THE_BASE_CASE_TO_T
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Overview of the Simplification of the Base Case to T

  [{IMAGE}]

    [Subgoal *1/1]
    (IMPLIES (ENDP A)
             (EQUAL (APP (APP A B) C)
                    (APP A (APP B C)))).

    By the simple :definition ENDP we reduce the conjecture to

    Subgoal *1/1'
    (IMPLIES (NOT (CONSP A))
             (EQUAL (APP (APP A B) C)
                    (APP A (APP B C)))).

    [But] simplification reduces this to T, using the :definition APP and
    primitive type reasoning.

  [{IMAGE}]")
 (OVERVIEW_OF_THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Overview of the Simplification of the Induction Conclusion

  In this message the system is saying that Subgoal *1/2' has been
  rewritten to T using the rules noted. The word ``But'' at the
  beginning of the sentence is a signal that the goal has been
  proved.

  Click [here] to step through the proof of Subgoal *1/2'.")
 (OVERVIEW_OF_THE_SIMPLIFICATION_OF_THE_INDUCTION_STEP_TO_T
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Overview of the Simplification of the Induction Step to T

  [{IMAGE}]

    [Subgoal *1/2]
    (IMPLIES (AND (NOT (ENDP A))
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (APP (APP A B) C)
                    (APP A (APP B C)))).

    By the simple :definition [ENDP] we reduce the conjecture to

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (APP (APP A B) C)
                    (APP A (APP B C)))).

    [But] simplification reduces this to T, using the :definition APP, the
    :rewrite rules CDR-CONS and CAR-CONS and primitive type reasoning.

  [{IMAGE}]")
 (P!
  (LD)
  "To pop up (at least) one level of ACL2's command loop

  Logically speaking, (p!) = nil. If you are already at the top level
  of the ACL2 command loop, rather than being in a subsidiary call of
  [ld], then the keyword then a call of (p!) returns nil and has no
  other effect.

  Otherwise, (p!) is evaluated inside a call of [ld] that was made
  inside ACL2's command loop. In that case, the current computation
  is aborted and treating as causing an error, and control returns to
  the superior call of ld.

  Here is a more detailed description of the effect of (p!) when not at
  the top level of the ACL2 command loop. The current call of LD is
  treated as though ld-error-action is :RETURN! (the default; here we
  ignore the case (:exit N)) and hence immediately returns control to
  the superior call of [ld]. If all calls of [ld] were made with the
  default ld-error-action of :RETURN!, then all superior calls of ld
  will then complete until you are back at top level of the ACL2
  loop. For more information, see [ld-error-action].

  If you are at an ACL2 prompt (as opposed to a raw Lisp break), then
  you may type :p! in place of (p!); see [keyword-commands].")
 (PACKAGE (POINTERS) "See [packages].")
 (PACKAGE-REINCARNATION-IMPORT-RESTRICTIONS
  (PACKAGES)
  "Re-defining undone [defpkg]s

  Suppose (defpkg \"pkg\" imports) is the most recently executed
  successful definition of \"pkg\" in this ACL2 session and that it has
  since been undone, as by :[ubt]. Any future attempt in this session
  to define \"pkg\" as a package must specify an identical imports
  list.

  The restriction stems from the need to implement the reinstallation
  of saved logical [world]s as in error recovery and the :[oops]
  [command]. Suppose that the new [defpkg] attempts to import some
  symbol, a::sym, not imported by the previous definition of \"pkg\".
  Because it was not imported in the original package, the symbol
  pkg::sym, different from a::sym, may well have been created and may
  well be used in some saved [world]s. Those saved [world]s are
  Common Lisp objects being held for you ``behind the scenes.'' In
  order to import a::sym into \"pkg\" now we would have to unintern
  pkg::sym, rendering those saved [world]s ill-formed. It is because
  of saved [world]s that we do not actually clear out a package when
  it is undone.

  At one point we thought it was sound to allow the new [defpkg] to
  import a subset of the old. But that is incorrect. Suppose the old
  definition of \"pkg\" imported a::sym but the new one does not.
  Suppose we allowed that and implemented it simply by setting the
  imports of \"pkg\" to the new subset. Then consider the conjecture
  (eq a::sym pkg::sym). This ought not be a theorem because we did
  not import a::sym into \"pkg\". But in fact in AKCL it is a theorem
  because pkg::sym is read as a::sym because of the old imports.")
 (PACKAGES
  (PROGRAMMING)
  "Packages are collections of symbols. They can be used to avoid name
  conflicts when working on large ACL2 projects.


Subtopics

  [*ACL2-exports*]
      Symbols that are often imported into new [packages] to provide easy
      access to ACL2 functionality.

  [*common-lisp-symbols-from-main-lisp-package*]
      Symbols that are often imported into new packages to provide easy
      access to Common Lisp functionality.

  [ACL2-user]
      A package the ACL2 user may prefer

  [Defpkg]
      Define a new symbol package

  [Hidden-death-package]
      Handling [defpkg] [events] that are [local]

  [Hidden-defpkg]
      Handling defpkg events that are local

  [In-package]
      Select current package

  [Intern]
      Create a new symbol in a given package

  [Intern$]
      Create a new symbol in a given package

  [Intern-in-package-of-symbol]
      Create a symbol with a given name

  [Managing-ACL2-packages]
      User-contributed documentation on packages

  [Package-reincarnation-import-restrictions]
      Re-defining undone [defpkg]s

  [Pkg-imports]
      List of symbols imported into a given package

  [Pkg-witness]
      Return a specific symbol in the indicated package

  [Sharp-bang-reader]
      Package prefix that is not restricted to symbols

  [Symbol-package-name]
      The name of the package of a symbol (a string)")
 (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS
  (ACL2-TUTORIAL)
  "Pages Written Especially for the Tours

  The ACL2 Home Page is generated from ACL2's online documentation
  strings. (How else could we achieve the total integration of ACL2's
  online documentation with the home page?) This page is just an
  artifact of the structure of our documentation strings: each string
  must belong to a ``major section'' of the documentation database.
  This page is not structured to be used by a person browsing via the
  Web. It contains, in an arbitrary order, the pages written
  specificially for the Web user.

  Furthermore, browsing the pages below as text, in particular using
  the ACL2 :DOC command, is often unsatisfying because because of the
  lack of support for displaying gif files or for going ``back'' to a
  node just visited. If you wish to look at the pages below, we
  strongly recommend that you do so via a HTML-based Web browser.
  Indeed, you should simply visit ACL2's Home Page and take one of
  the Tours.

  Generally, the topics listed above will not be of use to the ACL2
  user.


Subtopics

  [A_Flying_Tour_of_ACL2]
      A Flying Tour of ACL2

  [A_Sketch_of_How_the_Rewriter_Works]
      A Sketch of How the Rewriter Works

  [A_Tiny_Warning_Sign]
      A Tiny Warning Sign

  [A_Trivial_Proof]
      A Trivial Proof

  [A_Typical_State]
      A Typical State

  [A_Walking_Tour_of_ACL2]
      A Walking Tour of ACL2

  [ACL2_Characters]
      ACL2 Characters

  [ACL2_Conses_or_Ordered_Pairs]
      ACL2 Conses or Ordered Pairs

  [ACL2_Strings]
      ACL2 Strings

  [ACL2_Symbols]
      ACL2 Symbols

  [ACL2_System_Architecture]
      ACL2 System Architecture

  [ACL2_as_an_Interactive_Theorem_Prover]
      ACL2 as an Interactive Theorem Prover

  [ACL2_as_an_Interactive_Theorem_Prover_{cont}]
      ACL2 as an Interactive Theorem Prover (cont)

  [ACL2_is_an_Untyped_Language]
      ACL2 is an Untyped Language

  [About_Models]
      About Models

  [About_Types]
      About Types

  [About_the_ACL2_Home_Page]
      About the ACL2 Home Page

  [About_the_Admission_of_Recursive_Definitions]
      About the Admission of Recursive Definitions

  [About_the_Prompt]
      About the Prompt

  [An_Example_Common_Lisp_Function_Definition]
      An Example Common Lisp Function Definition

  [An_Example_of_ACL2_in_Use]
      An Example of ACL2 in Use

  [Analyzing_Common_Lisp_Models]
      Analyzing Common Lisp Models

  [Common_Lisp]
      Common Lisp

  [Common_Lisp_as_a_Modeling_Language]
      Common Lisp as a Modeling Language

  [Conversion]
      Conversion to Uppercase

  [Corroborating_Models]
      Corroborating Models

  [Evaluating_App_on_Sample_Input]
      Evaluating App on Sample Input

  [Flawed_Induction_Candidates_in_App_Example]
      Flawed Induction Candidates in App Example

  [Free_Variables_in_Top-Level_Input]
      Free Variables in Top-Level Input

  [Functions_for_Manipulating_these_Objects]
      Functions for Manipulating these Objects

  [Guards_in_ACL2]
      Guards

  [Guessing_the_Type_of_a_Newly_Admitted_Function]
      Guessing the Type of a Newly Admitted Function

  [Guiding_the_ACL2_Theorem_Prover]
      Guiding the ACL2 Theorem Prover

  [Hey_Wait!__Is_ACL2_Typed_or_Untyped{Q}]
      Hey Wait! Is ACL2 Typed or Untyped?

  [How_Long_Does_It_Take_to_Become_an_Effective_User{Q}]
      How Long Does It Take to Become an Effective User?

  [How_To_Find_Out_about_ACL2_Functions]
      How To Find Out about ACL2 Functions

  [How_To_Find_Out_about_ACL2_Functions_{cont}]
      How To Find Out about ACL2 Functions (cont)

  [Modeling_in_ACL2]
      Modeling in ACL2

  [Models_in_Engineering]
      Models in Engineering

  [Models_of_Computer_Hardware_and_Software]
      Models of Computer Hardware and Software

  [Name_the_Formula_Above]
      Name the Formula Above

  [Nontautological_Subgoals]
      Prover output omits some details

  [Numbers_in_ACL2]
      Numbers in ACL2

  [On_the_Naming_of_Subgoals]
      On the Naming of Subgoals

  [Other_Requirements]
      Other Requirements

  [Overview_of_the_Expansion_of_ENDP_in_the_Base_Case]
      Overview of the Expansion of ENDP in the Base Case

  [Overview_of_the_Expansion_of_ENDP_in_the_Induction_Step]
      Overview of the Expansion of ENDP in the Induction Step

  [Overview_of_the_Final_Simplification_in_the_Base_Case]
      Overview of the Final Simplification in the Base Case

  [Overview_of_the_Proof_of_a_Trivial_Consequence]
      Overview of the Proof of a Trivial Consequence

  [Overview_of_the_Simplification_of_the_Base_Case_to_T]
      Overview of the Simplification of the Base Case to T

  [Overview_of_the_Simplification_of_the_Induction_Conclusion]
      Overview of the Simplification of the Induction Conclusion

  [Overview_of_the_Simplification_of_the_Induction_Step_to_T]
      Overview of the Simplification of the Induction Step to T

  [Perhaps]
      Perhaps

  [Popping_out_of_an_Inductive_Proof]
      Popping out of an Inductive Proof

  [Proving_Theorems_about_Models]
      Proving Theorems about Models

  [Revisiting_the_Admission_of_App]
      Revisiting the Admission of App

  [Rewrite_Rules_are_Generated_from_DEFTHM_Events]
      Rewrite Rules are Generated from DEFTHM Events

  [Running_Models]
      Running Models

  [Subsumption_of_Induction_Candidates_in_App_Example]
      Subsumption of Induction Candidates in App Example

  [Suggested_Inductions_in_the_Associativity_of_App_Example]
      Suggested Inductions in the Associativity of App Example

  [Symbolic_Execution_of_Models]
      Symbolic Execution of Models

  [The_Admission_of_App]
      The Admission of App

  [The_Associativity_of_App]
      The Associativity of App

  [The_Base_Case_in_the_App_Example]
      The Base Case in the App Example

  [The_End_of_the_Flying_Tour]
      The End of the Flying Tour

  [The_End_of_the_Proof_of_the_Associativity_of_App]
      The End of the Proof of the Associativity of App

  [The_End_of_the_Walking_Tour]
      The End of the Walking Tour

  [The_Event_Summary]
      The Event Summary

  [The_Expansion_of_ENDP_in_the_Induction_Step_{Step_0}]
      The Expansion of ENDP in the Induction Step (Step 0)

  [The_Expansion_of_ENDP_in_the_Induction_Step_{Step_1}]
      The Expansion of ENDP in the Induction Step (Step 1)

  [The_Expansion_of_ENDP_in_the_Induction_Step_{Step_2}]
      The Expansion of ENDP in the Induction Step (Step 2)

  [The_Falling_Body_Model]
      The Falling Body Model

  [The_Final_Simplification_in_the_Base_Case_{Step_0}]
      The Final Simplification in the Base Case (Step 0)

  [The_Final_Simplification_in_the_Base_Case_{Step_1}]
      The Final Simplification in the Base Case (Step 1)

  [The_Final_Simplification_in_the_Base_Case_{Step_2}]
      The Final Simplification in the Base Case (Step 2)

  [The_Final_Simplification_in_the_Base_Case_{Step_3}]
      The Final Simplification in the Base Case (Step 3)

  [The_First_Application_of_the_Associativity_Rule]
      The First Application of the Associativity Rule

  [The_Induction_Scheme_Selected_for_the_App_Example]
      The Induction Scheme Selected for the App Example

  [The_Induction_Step_in_the_App_Example]
      The Induction Step in the App Example

  [The_Instantiation_of_the_Induction_Scheme]
      The Instantiation of the Induction Scheme

  [The_Justification_of_the_Induction_Scheme]
      The Justification of the Induction Scheme

  [The_Proof_of_the_Associativity_of_App]
      The Proof of the Associativity of App

  [The_Q.E.D._Message]
      The Q.E.D. Message

  [The_Rules_used_in_the_Associativity_of_App_Proof]
      The Rules used in the Associativity of App Proof

  [The_Simplification_of_the_Induction_Conclusion_{Step_0}]
      The Simplification of the Induction Conclusion (Step 0)

  [The_Simplification_of_the_Induction_Conclusion_{Step_1}]
      The Simplification of the Induction Conclusion (Step 1)

  [The_Simplification_of_the_Induction_Conclusion_{Step_10}]
      The Simplification of the Induction Conclusion (Step 10)

  [The_Simplification_of_the_Induction_Conclusion_{Step_11}]
      The Simplification of the Induction Conclusion (Step 11)

  [The_Simplification_of_the_Induction_Conclusion_{Step_12}]
      The Simplification of the Induction Conclusion (Step 12)

  [The_Simplification_of_the_Induction_Conclusion_{Step_2}]
      The Simplification of the Induction Conclusion (Step 2)

  [The_Simplification_of_the_Induction_Conclusion_{Step_3}]
      The Simplification of the Induction Conclusion (Step 3)

  [The_Simplification_of_the_Induction_Conclusion_{Step_4}]
      The Simplification of the Induction Conclusion (Step 4)

  [The_Simplification_of_the_Induction_Conclusion_{Step_5}]
      The Simplification of the Induction Conclusion (Step 5)

  [The_Simplification_of_the_Induction_Conclusion_{Step_6}]
      The Simplification of the Induction Conclusion (Step 6)

  [The_Simplification_of_the_Induction_Conclusion_{Step_7}]
      The Simplification of the Induction Conclusion (Step 7)

  [The_Simplification_of_the_Induction_Conclusion_{Step_8}]
      The Simplification of the Induction Conclusion (Step 8)

  [The_Simplification_of_the_Induction_Conclusion_{Step_9}]
      The Simplification of the Induction Conclusion (Step 9)

  [The_Summary_of_the_Proof_of_the_Trivial_Consequence]
      The Summary of the Proof of the Trivial Consequence

  [The_Theorem_that_App_is_Associative]
      The Theorem that App is Associative

  [The_Time_Taken_to_do_the_Associativity_of_App_Proof]
      The Time Taken to do the Associativity of App Proof

  [The_Tours]
      The Tours

  [The_WARNING_about_the_Trivial_Consequence]
      The WARNING about the Trivial Consequence

  [Undocumented_Topic]
      Undocumented Topic

  [Using_the_Associativity_of_App_to_Prove_a_Trivial_Consequence]
      Using the Associativity of App to Prove a Trivial Consequence

  [What_Is_ACL2{Q}]
      What Is ACL2?

  [What_is_Required_of_the_User{Q}]
      What is Required of the User?

  [What_is_a_Mathematical_Logic{Q}]
      What is a Mathematical Logic?

  [What_is_a_Mechanical_Theorem_Prover{Q}]
      What is a Mechanical Theorem Prover?

  [What_is_a_Mechanical_Theorem_Prover{Q}_{cont}]
      What is a Mechanical Theorem Prover? (cont)

  [You_Must_Think_about_the_Use_of_a_Formula_as_a_Rule]
      You Must Think about the Use of a Formula as a Rule")
 (PAIRLIS
  (LISTS ALISTS)
  "See [pairlis$]

  The Common Lisp language allows its pairlis function to construct an
  alist in any order! So we have to define our own version: See
  [pairlis$].")
 (PAIRLIS$
  (LISTS ALISTS ACL2-BUILT-INS)
  "Zipper together two lists

  The Common Lisp language allows its [pairlis] function to construct
  an alist in any order! So we have to define our own version,
  pairlis$. It returns the list of pairs obtained by [cons]ing
  together successive respective members of the given lists until the
  first list runs out. (Hence in particular, if the second argument
  is nil then each element of the first argument is paired with nil.)

  The [guard] for pairlis$ requires that its arguments are true lists.

  Function: 

    (defun pairlis$ (x y)
           (declare (xargs :guard (and (true-listp x) (true-listp y))))
           (mbe :logic (cond ((endp x) nil)
                             (t (cons (cons (car x) (car y))
                                      (pairlis$ (cdr x) (cdr y)))))
                :exec (pairlis$-tailrec x y nil)))")
 (PAND
  (PARALLEL-PROGRAMMING ACL2-BUILT-INS)
  "Parallel, Boolean version of [and]

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism],
  and see [parallel-programming], which has a disclaimer.

    Example Forms:
    (pand (subsetp-equal x y)
          (subsetp-equal y x))

    (pand (declare
           (granularity
            (and (> (length x) 500)
                 (> (length y) 500))))
           (subsetp-equal x y)
           (subsetp-equal y x))

    General Form:
    (pand (declare (granularity expr)) ; optional granularity declaration
          arg1 ... argN)

  where N >= 0 and each argi and expr are arbitrary terms.

  Pand evaluates its arguments in parallel. It returns a Boolean
  result: nil if any argument evaluates to nil, else t. Note that
  pand always returns a Boolean result, even though and can return a
  non-nil value other than t, namely the value of its last argument.
  (A moment's reflection will make it clear that in order for [por]
  to parallelize efficiently, it needs to return a Boolean value; so
  pand returns a Boolean value for consistency with [por].)

  Another difference between pand and [and] is that for a call of pand,
  even if an argument evaluates to nil, a subsequent argument may be
  evaluated. Consider the following example (where cw prints a
  string; see [cw]).

    (defun bar ()
      (pand (equal (make-list 100000) nil) ; evaluates to nil
            (cw \"hello world~%\")))

  When (bar) is evaluated, the above arguments of pand can execute in
  parallel, causing ``hello world'' to be printed to the terminal. If
  we had used and rather than pand, then since (equal (make-list
  100000) nil) evaluates to nil, the above call of [cw] would be
  avoided and no such printing would take place. Even with pand, such
  printing might not take place, depending on resources, timing of
  thread creation, and whether or not parallel execution is enabled
  (see [set-parallel-execution]).

  Note that unlike the case for [and], the definition of pand does not
  provide (consp x) as a [guard] to (car x) in the call of pand
  below:

    (defun h (x)
      (declare (xargs :guard t))
      (pand (consp x) (equal (car x) 'foo)))

  As a result, [guard] verification will fail for the above definition.
  If pand were replaced by and, then [guard] verification would
  succeed.

  See [parallelism-tutorial] for another example. Also see
  [parallelism-at-the-top-level] for restrictions on evaluating
  parallelism primitives from within the ACL2 top-level loop. Finally
  see [early-termination] to read how pand can offer more efficiency
  than [and] by avoiding evaluation of some of its arguments.")
 (PARALLEL (PARALLELISM)
           "Evaluating forms in parallel

  See [parallelism].")
 (PARALLEL-EXECUTION
  (PARALLEL-PROGRAMMING)
  "For ACL2(p): configure parallel execution

  See [set-parallel-execution] for how to configure parallel execution
  for calls of [plet], [pargs], [pand], [por] (but not
  [spec-mv-let]).")
 (PARALLEL-PROGRAMMING
  (PARALLELISM)
  "Parallel programming in ACL2(p)

  Here we document support for parallel programming in ACL2(p), an
  experimental extension of ACL2; also see [parallelism].

  One of ACL2's strengths lies in its ability to execute industrial
  models efficiently. The ACL2 source code provides an experimental
  parallel execution capability that can increase the speed of
  explicit evaluation, including simulator runs using such models,
  and it can also decrease the time required for proofs that make
  heavy use of the evaluation of ground terms.

  The parallelism primitives are [plet], [pargs], [pand], [por], and
  [spec-mv-let]. [Pand] and [por] terminate early when an argument is
  found to evaluate to nil or non-nil, respectively, thus potentially
  improving on the efficiency of lazy evaluation. [Spec-mv-let] is a
  modification of [mv-let] that supports speculative and parallel
  execution.

  Of the above five parallelism primitives, all but [spec-mv-let] allow
  for limiting parallel execution (spawning of so-called ``threads'')
  depending on resource availability. Specifically, the primitives
  allow specification of a size condition to control the
  [granularity] under which threads are allowed to spawn. You can use
  such [granularity] declarations in recursively-defined functions to
  implement data-dependent parallelism in their execution.

  We recommend that in order to learn to use the parallelism
  primitives, you begin by reading examples: see
  [parallelism-tutorial]. That section will direct you to further
  documentation topics.

  In addition to providing parallel programming primitives, ACL2(p)
  also provides the ability to execute the main ACL2 proof process in
  parallel. See [set-waterfall-parallelism] for further details.

  Disclaimer. The parallelism primitives have been designed for
  executing purely functional code, but some ACL2 functions do
  interesting things ``under the hood'' in order to achieve their
  effects. For example, [hons] primitives such as [hons-wash] may not
  have the intended effect when executed under the parallelism
  primitives.


Subtopics

  [Deflock]
      Define a wrapper macro that provides mutual exclusion in ACL2(p)

  [Early-termination]
      Early termination for [pand] and [por].

  [Error-triples-and-parallelism]
      How to avoid error triples in ACL2(p)

  [Granularity]
      Limit the amount of parallelism

  [Pand]
      Parallel, Boolean version of [and]

  [Parallel-execution]
      For ACL2(p): configure parallel execution

  [Parallelism-at-the-top-level]
      Parallel execution in the ACL2 top-level loop

  [Parallelism-performance]
      Performance issues for parallel execution

  [Parallelism-tutorial]
      A tutorial on how to use the parallelism library.

  [Pargs]
      Parallel evaluation of arguments in a function call

  [Plet]
      Parallel version of [let]

  [Por]
      Parallel, Boolean version of [or]

  [Spec-mv-let]
      Modification of [mv-let] supporting speculative and parallel
      execution

  [With-output-lock]
      Provides a mutual-exclusion mechanism for performing output in
      parallel")
 (PARALLEL-PROOF
  (PARALLELISM)
  "Parallel proof in ACL2(p)

  Here we document support for parallel proof in ACL2(p), an
  experimental extension of ACL2; also see [parallelism], and for
  parallel programming in particular, see [parallel-programming].


Subtopics

  [ACL2p-key-checkpoints]
      Key checkpoints in ACL2(p)

  [Default-total-parallelism-work-limit]
      For ACL2(p): returns the default value for global
      total-parallelism-work-limit

  [Parallel-pushing-of-subgoals-for-induction]
      Consequences of how parallelized proofs of subgoals are pushed for
      induction

  [Unsupported-waterfall-parallelism-features]
      Proof features not supported with waterfall-parallelism enabled

  [Waterfall-parallelism]
      For ACL2(p): configuring the parallel execution of the waterfall

  [Waterfall-printing]
      For ACL2(p): configuring the printing within the parallelized
      waterfall")
 (PARALLEL-PUSHING-OF-SUBGOALS-FOR-INDUCTION
  (PARALLEL-PROOF)
  "Consequences of how parallelized proofs of subgoals are pushed for
  induction

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

  The following discussion, concerning the naming of subgoals pushed
  for proof by induction and the timeliness of aborting when two or
  more goals are pushed for proof by induction, only applies when
  waterfall parallelism is enabled (see [set-waterfall-parallelism]).

  When two sibling subgoals (e.g. 4.5 and 4.6) both push goals to be
  proved by induction (e.g., 4.6 pushes *1 and 4.5 pushes *2), a name
  is assigned to the second pushed subgoal (e.g., *2) as if the first
  push hasn't happened (e.g., *2 is mistakenly called *1). In such a
  case, we say what the name _could_ be. The following non-theorem
  illustrates how this works.

    (set-waterfall-parallelism :full)
    (thm (equal (append (car (cons x x)) y z) (append x x y)))

  There is another consequence of the way the parallelized waterfall
  pushes subgoals for proof by induction. Without waterfall
  parallelism enabled, ACL2 sometimes decides to abort instead of
  pushing a goal for later proof by induction, preferring instead to
  induct on the original conjecture. But with waterfall parallelism
  enabled, the prover no longer necessarily immediately aborts to
  prove the original conjecture. Suppose for example that sibling
  subgoals, Subgoal 4.6 and Subgoal 4.5, each push a subgoal for
  induction. If the waterfall is performing the proof of each of
  these subgoals in parallel, the proof will no longer abort
  immediately after the second push occurs, that is at Subgoal 4.5.
  As a result, the prover will continue through Subgoal 4.4, Subgoal
  4.3, and beyond. It is not until the results of combining the proof
  results of Subgoal 4.6 with the results from the remaining sibling
  subgoals (4.5, 4.4, and so on), that the proof attempt will abort
  and revert to prove the original conjecture by induction. This
  example illustrates behavior that is rather like the case that
  :[otf-flg] is t, in the sense that the abort does not happen
  immediately, but also rather like the case that :[otf-flg] is nil,
  in the sense that the abort does occur before getting to Subgoal 3.")
 (PARALLELISM
  (ACL2)
  "Experimental extension for parallel execution and proofs

  This documentation topic relates to an experimental extension of
  ACL2, ACL2(p), created initially by David L. Rager. See
  [compiling-ACL2p] for how to build an executable image that
  supports parallel execution. Also see community books directory
  books/parallel/ for examples. For a completely different sort of
  parallelism, at the system level, see [provisional-certification].

  IMPORTANT NOTE. We hope and expect that every evaluation result is
  correctly computed by ACL2(p), and that every formula proved using
  ACL2(p) is a theorem of the ACL2 logic (and in fact is provable
  using ACL2). However, we do not guarantee these properties. Since
  ACL2(p) is intended to be an aid in efficient evaluation and proof
  development, we focus less on ironclad soundness and more on
  providing an efficient and working implementation. Nevertheless, if
  you encounter a case where ACL2(p) computes an incorrect result, or
  produces a proof where ACL2 fails to do so (and this failure is not
  discussed in [unsupported-waterfall-parallelism-features]), please
  notify the implementors.

  The ACL2 source code provides experimental parallel execution and
  proof capabilities. For example, one of ACL2's strengths lies in
  its ability to simulate industrial models efficiently, and it can
  also decrease the time required for proofs about such models both
  by making use of parallel evaluation and by dispatching proof
  subgoals in parallel.

  While we aim to support Clozure Common Lisp (CCL), Steel Bank Common
  Lisp (SBCL), and Lispworks, SBCL and Lispworks both currently
  sometimes experience problems when evaluating the ACL2 proof
  process (the ``waterfall'') in parallel. Therefore, CCL is the
  recommend Lisp for anyone that wants to use parallelism and isn't
  working on fixing those problems.


Subtopics

  [Compiling-ACL2p]
      Compiling ACL2(p)

  [Cpu-core-count]
      The number of cpu cores

  [Parallel]
      Evaluating forms in parallel

  [Parallel-programming]
      Parallel programming in ACL2(p)

  [Parallel-proof]
      Parallel proof in ACL2(p)

  [Parallelism-build]
      Building an ACL2 executable with parallel execution enabled

  [Set-parallel-execution]
      For ACL2(p): enabling parallel execution for four parallelism
      primitives

  [Set-total-parallelism-work-limit]
      For ACL2(p): set thread limit for parallelism primitives

  [Set-total-parallelism-work-limit-error]
      For ACL2(p): control the action taken when the thread limit is
      exceeded

  [Set-waterfall-parallelism]
      For ACL2(p): configuring the parallel execution of the waterfall

  [Set-waterfall-parallelism-hacks-enabled]
      For ACL2(p): enable waterfall-parallelism hacks

  [Set-waterfall-parallelism-hacks-enabled!]
      For ACL2(p): enabling waterfall parallelism hacks

  [Set-waterfall-printing]
      For ACL2(p): configuring the printing that occurs within the
      parallelized waterfall

  [Unsupported-parallelism-features]
      ACL2 features not supported in ACL2(p)

  [Waterfall-parallelism-for-book-certification]
      For ACL2(p): using waterfall parallelism during book certification")
 (PARALLELISM-AT-THE-TOP-LEVEL
  (PARALLEL-PROGRAMMING)
  "Parallel execution in the ACL2 top-level loop

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

  Calls of parallelism primitives made explicitly in the ACL2 top-level
  loop, as opposed to inside function bodies, will never cause
  parallel execution. Such calls will either execute with serial
  execution or will cause an error; see [set-parallel-execution]. For
  a way around this restriction, see [top-level].

  Consider for example the following call of [pargs] in the ACL2
  top-level loop. Instead of executing pargs, ACL2 macroexpands away
  this call, leaving us with serial execution of the arguments to the
  [cons] call, or else causes an error (see
  [set-parallel-execution]). If there is no error, then

    (pargs (cons (expensive-fn-1 4) (expensive-fn-2 5)))

  expands into:

    (cons (expensive-fn-1 4) (expensive-fn-2 5))

  One trivial way to enable parallel execution of a form is to surround
  it with a call to macro [top-level]. Consider the following
  example.

    (top-level (pargs (cons (expensive-fn-1 4) (expensive-fn-2 5))))

  Then in an executable image that supports parallel execution --- see
  [compiling-ACL2p] for instructions on how to build such an
  executable --- (expensive-fn-1 4) and (expensive-fn-2 5) can
  evaluate in parallel.

  A second way to enable parallel execution of a form is to place it
  inside a function body. For example, consider the following
  definition.

    (defun foo (x y)
      (pargs (cons (expensive-fn-1 x) (expensive-fn-2 y))))

  Then in an executable image that supports parallel execution,
  submission of the form (foo 4 5) can cause parallel execution of
  (expensive-fn-1 4) and (expensive-fn-2 5).

  Note that [guard]s need not be verified in order to obtain [parallel]
  execution. The only restrictions on parallel execution are to use
  an executable supporting it, to avoid calling parallelism
  primitives directly in the top-level loop, to have sufficient
  resources (especially, threads) available, and to avoid explicitly
  disabling parallel execution (see [set-parallel-execution]).")
 (PARALLELISM-BUILD
  (PARALLELISM)
  "Building an ACL2 executable with parallel execution enabled

  See [compiling-ACL2p].")
 (PARALLELISM-PERFORMANCE
  (PARALLEL-PROGRAMMING)
  "Performance issues for parallel execution

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

  See [granularity] for an important construct that limits the spawning
  of parallel computations, which can be important when a computation
  is too short-lived to warrant a separate thread.

  There are times in which parallelism provides no speedup because of
  garbage collection in the underlying Lisp implementation. The
  following example illustrates this phenomenon. If you change the
  [granularity] declaration so that the depth bound is 3, 4, or
  larger instead of 2, you may still find no speedup. In all cases
  you may find that parallelism results in a significantly greater
  time spent in garbage collection.

    (include-book \"finite-set-theory/osets/sets\" :dir :system)
    (defun set::pmergesort-exec (x depth)
        (declare (xargs :mode :program))
        (cond ((endp x) nil)
              ((endp (cdr x)) (set::insert (car x) nil))
              (t (mv-let (part1 part2)
                         (set::split-list x nil nil)
                         (pargs
                          (declare (granularity (< depth 2)))
                          (set::union (set::pmergesort-exec part1
                                                              (1+ depth))
                                       (set::pmergesort-exec part2
                                                              (1+ depth))))))))
    (defconst *x* (reverse (fromto 1 400000)))
    (time$ (length (set::pmergesort-exec *x* 0)))
    (set-parallel-execution nil)
    (time$ (length (set::pmergesort-exec *x* 0)))")
 (PARALLELISM-TUTORIAL
  (PARALLEL-PROGRAMMING)
  "A tutorial on how to use the parallelism library.

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

  In this topic we introduce the ACL2 parallelism primitives using the
  example of a doubly-recursive Fibonacci function, whose basic
  definition is as follows. See [parallelism] for a very high-level
  summary of the parallelism capability described here, and see
  [compiling-ACL2p] for how to build an executable image that
  supports parallel execution. Here, we assume that such an
  executable is being used.

  Serial Fibonacci

    (defun fib (x)
      (declare (xargs :guard (natp x)))
      (cond ((or (zp x) (<= x 0)) 0)
            ((= x 1) 1)
            (t (+ (fib (- x 1)) (fib (- x 2))))))

  Introducing [Pargs]

  A simple way to introduce parallelism into this function definition
  is to wrap the addition expression with a call of [pargs], and the
  arguments to the addition will be computed in parallel whenever
  resources are available. As a result, we end up with a very similar
  and thus intuitive function definition. Note that we replaced [+]
  by [binary-+], since [pargs] expects a function call, not a macro
  call.

    (defun pfib (x)
      (declare (xargs :guard (natp x)))
      (cond ((or (zp x) (<= x 0)) 0)
            ((= x 1) 1)
            (t (pargs (binary-+ (pfib (- x 1))
                                (pfib (- x 2)))))))

  Introducing the Granularity Problem

  After you submit the above two versions of the Fibonacci function,
  test them with the following forms.

    (time$ (fib 10))
    (time$ (pfib 10))

  Now increase the argument by increments of 5 to 10 until you find
  your curiosity satisfied or your patience wearing thin. You can
  interrupt evaluation if necessary and return to the ACL2 loop. You
  will immediately notice that you have not increased execution
  speed, at least not by much, by introducing parallelism.

  First, consider the computation of (pfib 4). Assuming resources are
  available, (pfib 4) will create a thread for computing (pfib 3) and
  another thread for (pfib 2). It is easy to imagine that setting up
  each thread takes much longer than the entire computation of (fib
  4).

  Second, we must realize that if we have two threads available for
  computing (fib 10), then the evaluation of (fib 8) will probably
  complete before the evaluation of (fib 9). Once (fib 8) finishes,
  parallelism resources will become available for the next recursive
  call made on behalf of (fib 9). If for example that call is (fib
  3), we will waste a lot of cycles just handing work to the thread
  that does this relatively small computation. We need a way to
  ensure that parallelism resources are only used on problems of a
  \"large\" size. Ensuring that only \"large\" problems are spawned is
  called the ``granularity problem.''

  In summary: We want to tell ACL2 that it can evaluate the arguments
  of [pargs] in parallel only when the parameter of pfib is greater
  than some threshold. Our tests using CCL have suggested that 27 is
  a reasonable threshold.

  Explicit Programming for the Granularity Problem

  One way to avoid the granularity problem is to duplicate code as
  follows.

    (defun pfib (x)
      (declare (xargs :guard (natp x)))
      (cond ((or (zp x) (<= x 0)) 0)
            ((= x 1) 1)
            (t (if (> x 27) ; the granularity test
                   (pargs (binary-+ (pfib (- x 1))
                                    (pfib (- x 2))))
                 (binary-+ (pfib (- x 1))
                           (pfib (- x 2)))))))

  Duplicating code is fundamentally a bad design principle, because it
  can double the work for future maintenance. A ``granularity form''
  is an expression

    (declare (granularity ))

  that can allow threads to be spawned (without duplicating code)
  whenever the evaluation of  results in a non-nil value. It
  may be placed inside any call of a parallelism primitive, in a
  position documentated separately for each primitive. Here is a
  definition of pfib using this feature for a call of the parallelism
  primitive [pargs].

    (defun pfib (x)
      (declare (xargs :guard (natp x)))
      (cond ((or (zp x) (<= x 0)) 0)
            ((= x 1) 1)
            (t (pargs
                (declare (granularity (> x 27)))
                (binary-+ (pfib (- x 1))
                          (pfib (- x 2)))))))

  Test each version as follows (or substitute your own natural number
  for 33).

    (time$ (fib 33))
    (time$ (pfib 33))

  Another Granularity Issue Related to Thread Limitations

  Our implementation of parallelism primitives has the property that
  once a thread is assigned a computation, that assignment stays in
  effect until the computation is complete. In particular, if a
  thread encounters a parallelism primitive that spawns child
  threads, the parent thread stays assigned, waiting until the child
  computations complete before it can continue its own computation.
  In the meantime, the parent thread reduces the number of additional
  threads that Lisp can provide by 1, rather than being reassigned to
  do other work.

  How can this lack of reassignment affect the user? Consider, for
  example, the application of a recursive function to a long list.
  Imagine that this function is written so that the body contains a
  recursive call, for example as (pargs (process (car x)) (recur (cdr
  x))). Each such [pargs] call that spawns child work must wait for
  its children, one of which is the work of evaluating (recur (cdr
  x)), to complete. There is an ACL2 limit on how much pending work
  can be in the system, limiting the number of [pargs] calls that can
  result in parallel execution. For example, if the ACL2 limit is k
  and each call of [pargs] actually spawns threads for evaluating its
  arguments, then after k cdrs there will be no further parallel
  execution.

  Possible solutions may include reworking of algorithms (for example
  to be tree-based rather than list-based) or using appropriate
  granularity forms. We hope that future implementations will allow
  thread ``re-deployment'' in order to mitigate this problem. This
  problem applies to [plet], [pargs], [pand], [por], and
  [spec-mv-let].

  Introducing [Plet]

  We can use a [let] binding to compute the recursive calls of fib and
  then add the bound variables together, as follows.

    (defun fib (x)
      (declare (xargs :guard (natp x)))
      (cond ((or (zp x) (<= x 0)) 0)
            ((= x 1) 1)
            (t (let ((a (fib (- x 1)))
                     (b (fib (- x 2))))
                 (+ a b)))))

  By using the parallelism primitive [plet], we can introduce
  parallelism much as we did using [pargs], with an optional
  granularity form, as follows.

    (defun pfib (x)
      (declare (xargs :guard (natp x)))
      (cond ((or (zp x) (<= x 0)) 0)
            ((= x 1) 1)
            (t (plet
                (declare (granularity (> x 27)))
                ((a (pfib (- x 1)))
                 (b (pfib (- x 2))))
                (+ a b)))))

  Notice that this time, we were able to use + rather than being forced
  to use binary-+. Unlike [pargs], which expects a function call (not
  a macro call), [plet] allows macros at the top level of its body.

  Introducing [Pand] (By Way of a Tree Validation Example)

  Consider ``genetic trees'' that contains leaves of DNA elements, in
  the sense that each tip is one of the symbols A, G, C, or T. First
  we define the function valid-tip which recognizes whether a tip
  contains one of these symbols.

    (defun valid-tip (tip)
      (declare (xargs :guard t))
      (or (eq tip 'A)
          (eq tip 'G)
          (eq tip 'C)
          (eq tip 'T)))

  Now we define a function that traverses the tree, checking that every
  tip is valid.

    (defun valid-tree-serial (tree)
      (declare (xargs :guard t))
      (if (atom tree)
          (valid-tip tree)
        (and (valid-tree-serial (car tree))
             (valid-tree-serial (cdr tree)))))

  We also define a parallel version.

    (defun valid-tree-parallel (tree)
      (declare (xargs :guard t))
      (if (atom tree)
          (valid-tip tree)
        (pand (valid-tree-parallel (car tree))
              (valid-tree-parallel (cdr tree)))))

  Before we can time the functions, we need to create test trees. We
  have found that test trees need to be approximately 1 gigabyte
  before we clearly see speedup, and we make them asymmetric to
  demonstrate the ability of our implementation to adapt to
  asymmetric data. We can create the trees with the execution of the
  following forms.

    (defun make-valid-binary-tree (x)
      (declare (xargs :mode :program))
      (if (< x 0)
          (cons (cons 'C 'G) (cons 'A 'T))
        (cons (make-valid-binary-tree (- x 2)) ; 2 to make asymmetric
              (make-valid-binary-tree (- x 1)))))

    (defconst *valid-tree* (make-valid-binary-tree 30)) ; takes awhile
    (defconst *invalid-tree* (cons *valid-tree* nil)) ; nil is invalid tip

  We can time our functions with the forms:

    (time$ (valid-tree-serial *valid-tree*))
    (time$ (valid-tree-parallel *valid-tree*))

  Unfortunately, the serial version runs faster than the parallelism
  version; however, there is more to this story.

  Demonstrating Early Termination with an Invalid Tree

  Now observe this magic:

    (time$ (valid-tree-serial   *invalid-tree*))
    (time$ (valid-tree-parallel *invalid-tree*))

  The serial version took awhile, while the parallel version finished
  almost immediately. The test for validation was split into testing
  the [car] and the [cdr] of the *invalid-tree* root, and since the
  cdr was equal to nil, its test returned immediately. This immediate
  return quickly interrupted the computation associated with the car,
  and returned the result.

  Granularity with [Pand]

  We can also define a parallel version with a granularity form:

    (defun valid-tree-parallel (tree depth)
      (declare (xargs :guard (natp depth)))
      (if (atom tree)
          (valid-tip tree)
        (pand
         (declare (granularity (< depth 5)))
         (valid-tree-parallel (car tree) (1+ depth))
         (valid-tree-parallel (cdr tree) (1+ depth)))))

  We can test this form by executing our previous forms. You will
  probably find some speedup on a machine with several cores
  available, but more speedup can likely be obtained with an
  expensive test on the leaves in place of valid-tip.

    (time$ (valid-tree-serial   *valid-tree*))
    (time$ (valid-tree-parallel *valid-tree* 0))

  Introducing [Por]

  [Por] can be used in the same way as [pand], but with early
  termination occurring when an argument evaluates to a non-nil
  value, in which case the value returned is t. Finally, [por] also
  supports the use of a [granularity] form.")
 (PARGS
  (PARALLEL-PROGRAMMING ACL2-BUILT-INS)
  "Parallel evaluation of arguments in a function call

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism],
  and see [parallel-programming], which has a disclaimer.

    Example Forms:
    (pargs (binary-+ (fibonacci (- x 1)) (fibonacci (- x 2))))

    (pargs (declare (granularity (> x 35)))
           (binary-+ (fibonacci (- x 1)) (fibonacci (- x 2))))

    General Form:
    (pargs (declare (granularity expr)) ; optional granularity declaration
           (f arg1 ... argN))

  where N >= 0 and each argi and expr are arbitrary terms. Logically,
  pargs is just the identity macro, in the sense that the above forms
  can logically be replaced by (f arg1 ... argN). However, this pargs
  form may parallelize the evaluation of arguments arg1 through argN
  before applying function f to those results. If the above
  [granularity] declaration is present, then its expression (expr
  above) is first evaluated, and if the result is nil, then such
  parallelism is avoided. Even if parallelism is not thus avoided,
  parallelism may be limited by available resources.

  Since macros can change expressions in unexpected ways, it is illegal
  to call pargs on a form that is a macro call. To parallelize
  computation of arguments to a macro, see [plet].

  See [parallelism-at-the-top-level] for restrictions on evaluating
  parallelism primitives from within the ACL2 top-level loop.")
 (PATHNAME
  (BOOKS-REFERENCE)
  "Introduction to filename conventions in ACL2

  The notion of pathname objects from Common Lisp is not supported in
  ACL2, nor is the function pathname. However, ACL2 supports file
  operations, using conventions for naming files based on those of
  the Unix (trademark of AT&T) operating system, so that the
  character / is used to terminate directory names. Some file names
  are ``absolute'' (complete) descriptions of a file or directory;
  others are ``relative'' to the current working directory or to the
  connected book directory (see [cbd]). We emphasize that even for
  users of Windows-based systems or Macintosh computers, ACL2 file
  names are in the Unix style. We will call these ACL2 pathnames,
  often omitting the ``ACL2.''

  Pathnames starting with the directory separator (/) or the tilde
  character (~) are absolute pathnames. All other pathnames are
  relative pathnames. An exception is in the Microsoft Windows
  operating system, where it is illegal for the pathname to start
  with a tilde character but the drive may be included, e.g.,
  \"c:/home/smith/acl2/book-1.lisp\". In fact, the drive must be
  included in the portcullis of a book; see [portcullis]. Note also
  that some host Common Lisps will not support pathnames starting
  with \"~\", for example ~smith, though ACL2 will generally support
  those starting with \"~/\" regardless of the host Common Lisp.

  Consider the following examples. The filename string

    \"/home/smith/acl2/book-1.lisp\"

  is an absolute pathname, with top-level directory \"home\", under that
  the directory \"smith\" and then the directory \"acl2\", and finally,
  within that directory the file \"book-1.lisp\". If the connected book
  directory is \"/home/smith/\" (see [cbd]), then the filename string
  above also corresponds to the relative filename string
  \"acl2/book1.lisp\".

  Finally, we note that (on non-Windows systems) the pathname \"~\" and
  pathnames starting with \"~/\" are illegal in books being certified.
  Otherwise, a subsidiary [include-book] form would have a different
  meaning at certification time than at a later time when the
  certified book is included by a different user.")
 (PATTERNED-CONGRUENCE
  (RULE-CLASSES)
  "Removing restrictions on classic [congruence] rules

  This topic assumes familiarity with the basics of congruence rules;
  see [congruence].

  We begin our discussion by showing some patterned congruence rules
  and using them to illustrate some terminology.

    Example forms:

    ; ``Shallow'' patterned congruence rule:
    (implies (e1 y1 y2)
             (e2 (f1 3 y1 (cons x x))
                 (f1 3 y2 (cons x x))))

    ; ``Deep'' patterned congruence rule:
    (implies (e1 y1 y2)
             (e2 (mv-nth 1 (foo x y1 z))
                 (mv-nth 1 (foo x y2 z))))

    ; ``Deep'' patterned congruence rule:
    (implies (e1 y1 y2)
             (e2 (mv-nth 1 (foo x (g y1) z))
                 (mv-nth 1 (foo x (g y2) z))))

  In the example forms above, e1 and e2 are known equivalence
  relations, which (as for classic congruence rules) we call the
  ``inner'' and ``outer'' equivalences. The examples above are not
  classic, because the ``function symbol'' of the rule --- f1 in the
  first example, mv-nth in the second and third examples --- is not
  being applied to distinct variables. The first example is called
  ``shallow'' because the ``variable'' of the rule, y1, is a
  top-level argument of the ``lhs'' of the rule, which is the first
  call of f1; the others do not have this property, as y1 is buried
  under further function calls.

  We invite you to browse the community book
  demos/patterned-congruences.lisp, which provides several examples
  of patterned congruence rules and their use, as well as several
  examples of formulas that are illegal as patterned congruence rules
  for various reasons.

  We now define the class of patterned congruence rules. The general
  form of a patterned congruence rule is

    (implies (equiv1 x y)
             (equiv2 lhs rhs)),

  where the rule is not classic (see [congruence]) and the following
  conditions hold. Equiv1 and equiv2 are known equivalence relations,
  which (as in the classic case) we call the ``inner'' and ``outer''
  equivalences, respectively. The terms lhs and rhs are function
  calls, and we call these the lhs and rhs of the rule, respectively.
  The variable x occurs in lhs and the variable y occurs in rhs.
  These must be the only occurrences of x and y in either lhs or rhs,
  and rhs must be the result of substituting y for x in lhs. None of
  the following may occur as a function symbol of lhs (or,
  equivalently, rhs): if, implies, equal, or a [lambda].

  Patterned congruence rules are used, much like classic congruence
  rules, by the ACL2 rewriter to determine which equivalence
  relations to maintain as it dives into a term. Recall (see
  [congruence]) that if it suffices for the rewriter to maintain e2
  when rewriting a term, then it suffices to maintain e1 when
  rewriting an argument of that term provided there is an applicable
  congruence rule with outer equivalence e2 and inner equivalence e1.
  An analogous principle holds for patterned congruence rules, which
  by the way consider refinements of the outer equivalence just as is
  done by classic congruence rules. But there is a new wrinkle
  because the lhs of a patterned congruence rule is a function call
  that can have non-variable arguments. Consider the following
  events.

    (defun e1 (x y)
      (equal x y))

    (defequiv e1)

    (defun f10 (x)
      (list 3 x x))

    (defun f11 (x y)
      (declare (ignore y))
      x)

    (defthm e1-implies-iff-f11-cong-2
      (implies (e1 y1 y2)
               (iff (f11 (f10 x) y1)
                    (f11 (f10 x) y2)))
      :rule-classes (:congruence))

    (in-theory (disable f11 (:t f11) e1))

  The following proof fails, because the indicated call of f10 expands
  before the rewriter is applied to b2 --- otherwise b2 would rewrite
  to b1 because (e1 b1 b2) is known in that context and by the rule
  above, it suffices to maintain e1 when rewriting b2.

    (thm (implies (e1 b1 b2)
                  (iff (f11 (f10 a)
                            b1)
                       (f11 (f10 a) ; expands before b2 is rewritten
                            b2))))

  On the other hand, the following succeeds because the rewrite
  discussed above does indeed take place when the indicated call of
  f10 does not expand.

    (thm
      (implies (e1 b1 b2)
               (iff (f11 (f10 a)
                         b1)
                    (f11 (f10 a) ; does not expand
                         b2)))
      :hints ((\"Goal\" :in-theory (disable f10))))

  This inherent sequentiality of matching is important for soundness,
  as is illustrated by examples using the function some-consp in the
  aforementioned community book, demos/patterned-congruences.lisp.

  The example above illustrates the following point: as the rewriter
  dives into a term, then when matching is attempted using a
  patterned congruence rule, rewriting has already taken place to the
  left of the current subterm. By contrast, note that this pass
  through the rewriter will not yet have completed rewriting of terms
  to the right of the current subterm when matching a patterned
  congruence rule.

  Patterned congruence rules are used primarily during the process of
  rewriting. In particular, unlike classic congruence rules, they are
  not used to do equality substitution at the goal level. The
  simplest way to understand this point may be with the following
  trivial example.

    (defstub foo (x y z) t)

    (thm (implies (equal u (* a b))
                  (foo u u b)))

  The theorem fails, of course, but what is interesting is that ACL2
  simplifies it by replacing the variable u by the term (* a b)
  throughout the goal and then dropping the equality, to produce the
  following goal.

    (FOO (* A B) (* A B) B)

  This sort of substitution can also be made when equal is replaced by
  a known equivalence relation, if a classic congruence rule for foo
  justifies the substitution. But that is not the case for our
  implementation of patterned congruence rules.

  The discussion above is intended to suffice for effective use of
  patterned congruence rules. If you are interested in their
  implementation, we invite you to read the long comment entitled
  ``Essay on Patterned Congruences and Equivalences'' in ACL2 source
  file rewrite.lisp.")
 (PBT
  (HISTORY)
  "Print the [command]s back through a [command] descriptor

    Examples:
    :pbt :max      ; print back through the most recent command
    :pbt :x        ; print back through the most recent command
    :pbt fn        ; print back through the introduction of fn
    :pbt 5         ; print back through the fifth command executed
    :pbt (:x -4)   ; print back through the most recent five commands

  See [command-descriptor].

  Pbt takes one argument, a [command] descriptor, and prints the
  [command]s from :max (aka :x) through the one described. See
  [command-descriptor] for a description of what a [command]
  descriptor is. See [pc] for a description of the format used to
  display [command]s. Pbt will print the [command]s that [ubt] will
  undo.")
 (PC
  (HISTORY)
  "Print the [command] described by a [command] descriptor

    Examples:
    :pc 3    ; print the third command executed
    :pc :max ; print the most recent command
    :pc :x   ; print the most recent command
    :pc fn   ; print the command that introduced fn

  See [command-descriptor].

  Pc takes one argument, a [command] descriptor, and prints the
  [command] identified by that descriptor, doing so in full unless
  the [ld-evisc-tuple] is non-nil, in which case it abbreviates using
  that evisc-tuple; see [evisc-tuple]. See [command-descriptor]. For
  example:

    ACL2 !>:pc foo
     LVd     52 (DEFUN FOO (X) X)

  Pc always prints a space first, followed by three (possibly blank)
  [characters] (``LVd'' above) explained below (four, in
  [hons-enabled] executables, as discussed further below). Then pc
  prints the [command] number, a number uniquely identifying the
  [command]'s position in the sequence of [command]s since the
  beginning of the user's session. Finally, the [command] itself is
  printed.

  While pc always prints a space first, some [history] [command]s, for
  example :[pcs] and :[pe], use the first column of output to delimit
  a region of [command]s or to point to a particular event within a
  [command].

  For example, :pcs 52 54 will print something like

    /LVd     52 (DEFUN FOO (X) X)
     LV      53 (DEFUN BAR (X) (CONS X X))
    \\        54 (DEFTHM FOO-BAR (EQUAL (CAR (BAR X)) (FOO X)))
              : ...
            127 (DEFUN LATEST (X) X)

  Here, the two slash [characters] in the first column are intended to
  suggest a bracket delimiting [command]s 52 through 54. The last
  [command] printed by [pcs] is always the most recent [command],
  i.e., the [command] at :here, and is separated from the rest of the
  display by an elipsis if some [command]s are omitted.

  Similarly, the :[pe] [command] will print a particular event within a
  [command] block and will indicate that event by printing a ``[>]''
  in the first column. The symbol is intended to be an arrow pointing
  at the event in question.

  For example, :[pe] true-listp-app might print:

             1 (INCLUDE-BOOK \"list-book\")
                \\
    >           (DEFTHM TRUE-LISTP-APP
                        (EQUAL (TRUE-LISTP (APP A B)) (TRUE-LISTP B)))

  using the arrow to indicate the event itself. The slash printed to
  connect the [command], [include-book], with the event, [defthm], is
  intended to suggest a tree branch indicating that the event is
  inferior to (and part of) the [command].

  The mysterious [characters] sometimes preceding a [command] have the
  following interpretations. The first two have to do with the
  function symbols introduced by the [command] and are blank if no
  symbols were introduced.

  At any time we can classify our function symbols into disjoint sets,
  which we will here name with [characters]. The ``P'' functions are
  those in :[program] mode. The ``L'' functions are those in :[logic]
  mode whose [guard]s have not been verified. The ``V'' functions are
  those in :[logic] mode whose [guard]s have been verified. You may
  also see the use of (lower-case) ``v'' to indicate functions
  introduced by [encapsulate]. Note that [verify-termination] and
  [verify-guards] cause function symbols to be reclassified. If a
  [command] introduces function symbols then the first mysterious
  character indicates the class of the symbols at the time of
  introduction and the second character indicates the current class
  of the symbols (if the current class is different from the
  introductory class).

  Thus, the display

    PLd     52 (DEFUN FOO (X) X)

  tells us that [command] 52 introduced a :[program] function but that
  some [command] after 52 changed its mode to :[logic] and that the
  [guard]s of foo have not been verified. That is, foo's termination
  has been verified even though it was not verified as part of the
  [command] that introduced foo. Had a subsequent [command] verified
  the [guard]s of foo, the display would contain a V where the L is.

  The display

    P d     52 (DEFUN FOO (X) X)

  indicates that foo was introduced in :[program] mode and still is in
  that mode.

  The third character indicates the enabled/disabled status of the
  [rune]s introduced by the [command]. If the status character is
  blank then all the [rune]s (if any) introduced are [enable]d. If
  the status character is ``D'' then some [rune]s were introduced and
  they are all [disable]d. If the status character is ``d'' then at
  least one, but not all, of the [rune]s introduced is [disable]d.
  Thus, in the display

    L d     52 (DEFUN FOO (X) X)

  we see that some [rune] introduced by [command] 52 is [disable]d. As
  noted in the documentation for [rune], a [defun] [command]
  introduces many [rune]s, e.g., the axiomatic definition rule,
  (:definition fn), the executable counterpart rule,
  (:executable-counterpart fn), and [type-prescription]s,
  (:type-prescription fn). The display above does not say which of
  the [rune]s based on foo is [disable]d, but it does tell us one of
  them is; see [disabledp] for how to obtain the disabled runes for a
  given function symbol.

  Finally, [hons-enabled] executables, a fourth character is printed,
  indicating whether functions are [memoize]d. A symbol may be
  memoized if it is a function symbol that is not constrained (i.e.,
  introduced by [defchoose] or in the [signature] of an [encapsulate]
  event). If the command introduces no symbol that may be memoized,
  then a space is printed. Otherwise, if every memoizable symbol is
  memoized, an ``M'' is printed. Otherwise, an ``m'' is printed.")
 (PCB
  (HISTORY)
  "Print the [command] block described by a [command] descriptor

    Examples:
    :pcb :max ; print the most recent command block
    :pcb :x   ; print the most recent command block
    :pcb fn   ; print the command block that introduced fn
    :pcb 5    ; print the fifth command block

  See [command-descriptor].

  Pcb takes one argument, a [command] descriptor, and prints in an
  abbreviated format the [command] block of the [command] described.
  See [command-descriptor] for details of [command] descriptors. See
  [pc] for description of the format in which [command]s are
  displayed. The [command] block of a [command] consists of the
  [command] itself and all of the [events] it created. If the
  [command] created a single event and that event is in fact the
  [command] (i.e., if the [command] typed was just an event such as a
  [defun] or [defthm] rather than a macro that expanded to some event
  forms), then pcb just prints the [command]. Pcb sketches [command]
  and all of the [events] it created, rather than printing them
  fully. If you wish to see just the [command], in its entirety, use
  [pc]. If you wish to see one of the [events] within the block, in
  its entirety, use [pe]. If you wish to see the [command] sketched
  and all of the [events] it created, in their entirety, use [pcb!].")
 (PCB!
  (HISTORY)
  "Print in full the [command] block described by a [command] descriptor

    Examples:
    :pcb! :max ; print the most recent command block
    :pcb! :x   ; print the most recent command block
    :pcb! fn   ; print the command block that introduced fn
    :pcb! 5    ; print the fifth command block

  See [command-descriptor].

  Pcb! takes one argument, a [command] descriptor, and prints the
  [command] block of the [command] described. Unlike [pcb], pcb!
  prints the event forms in full (see [pcb] for details) --- unless
  the [ld-evisc-tuple] is non-nil, in which case it abbreviates using
  that evisc-tuple; see [evisc-tuple].")
 (PCS
  (HISTORY)
  "Print the sequence of [command]s between two [command] descriptors

    Examples:
    :pcs 1 5              ; print commands 1 through 5
    :pcs 5 1              ; same as above
    :pcs :x (:x -3)       ; print the 3 most recently executed commands
    :pcs fn assoc-of-fn   ; print the commands between the one that introduced
                          ; fn and the one that introduced assoc-of-fn

  Pcs takes two arguments, both of which are [command] descriptors, and
  prints the [command]s between them with [pc]. The order of the two
  descriptors is irrelevant. See [command-descriptor] for a
  description of [command] descriptors. See [pc] for a description of
  the format in which [command]s are displayed.

  For a related utility that simply returns a sequence of commands, see
  [get-command-sequence].")
 (PE
  (HISTORY)
  "Print the events named by a logical name

    Example:
    :pe fn   ; sketches the command that introduced fn and
             ; prints in full the event within it that created fn.

  See [logical-name].

  Pe takes one argument, a logical name, and prints the event
  corresponding to the name, doing so in full unless the
  [ld-evisc-tuple] is non-nil, in which case it abbreviates using
  that evisc-tuple; see [evisc-tuple]. Pe also sketches the [command]
  responsible for that event if the [command] is different from the
  event itself. See [pc] for a description of the format used to
  display a [command]. To remind you that the event is inferior to
  the [command], i.e., you can only undo the entire [command], not
  just the event, the event is indented slightly from the [command]
  and a slash (meant to suggest a tree branch) connects them.

  If the given logical name corresponds to more than one event, then
  :pe will print the above information for every such event. Here is
  an example of such behavior.

    ACL2 !>:pe nth
          -4270  (ENCAPSULATE NIL ...)
                 \\
    >V            (VERIFY-TERMINATION NTH)

    Additional events for the logical name NTH:
     PV   -4949  (DEFUN NTH (N L)
                        \"Documentation available via :doc\"
                        (DECLARE (XARGS :GUARD (AND (INTEGERP N)
                                                    (>= N 0)
                                                    (TRUE-LISTP L))))
                        (IF (ENDP L)
                            NIL
                            (IF (ZP N)
                                (CAR L)
                                (NTH (- N 1) (CDR L)))))
    ACL2 !>

  If you prefer to see only the formula for the given name, for example
  if it is part of a large [mutual-recursion], see [pf].")
 (PE!
  (HISTORY)
  "Deprecated (see [pe])

  Please see [pe]. :Pe now has the functionality formerly provided by
  :pe!.")
 (PEEK-CHAR$ (POINTERS) "See [io].")
 (PERHAPS
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Perhaps

  The theorem prover's proof is printed in real time. At the time it
  prints ``Perhaps'' it does not know the proof will succeed.")
 (PF
  (HISTORY)
  "Print the formula corresponding to the given name

    Examples:
    :pf (:definition fn) ; prints the definition of fn as an equality
    :pf fn               ; same as above

    :pf (:rewrite foo)   ; prints the statement of the rewrite rule foo
    :pf foo              ; same as above

  pf takes one argument, an event name or a [rune], and prints the
  formula associated with name. If the argument is the name of a
  macro associated with a function name by [macro-aliases-table],
  then the function name is used as the argument.")
 (PKG-IMPORTS
  (PACKAGES)
  "List of symbols imported into a given package

  Completion Axiom (completion-of-pkg-imports):

    (equal (pkg-imports x)
           (if (stringp x)
               (pkg-imports x)
             nil))

  [Guard] for (pkg-imports x):

    (stringp x)

  (Pkg-imports pkg) returns a duplicate-free list of all symbols
  imported into pkg, which should be the name of a package known to
  ACL2. For example, suppose \"MY-PKG\" was created by

    (defpkg \"MY-PKG\" '(ACL2::ABC LISP::CAR)).

  Then (pkg-imports \"MY-PKG\") equals the list (ACL2::ABC LISP::CAR).

  If pkg is not a string, then (pkg-imports pkg) is nil. If pkg is a
  string but not the name of a package known to ACL2, then the value
  of the form (pkg-imports pkg) is unspecified, and it evaluation
  will fail to yield a value. By ``the symbols imported into pkg'' we
  mean the symbols imported into pkg by the [defpkg] event that
  introduced pkg. There are no imports for built-in packages except
  for the \"ACL2\" package, which imports the symbols in the list value
  of the constant *common-lisp-symbols-from-main-lisp-package*. In
  particular, this is the case for the \"COMMON-LISP\" package. Users
  familiar with Common Lisp may find this surprising, since in actual
  Common Lisp implementations it is often the case that many symbols
  in that package are imported from other packages. However, ACL2
  treats all symbols in the constant
  *common-lisp-symbols-from-main-lisp-package* as having a
  [symbol-package-name] of \"COMMON-LISP\", as though they were not
  imported. ACL2 admits a symbol imported into in the \"COMMON-LISP\"
  package only if it belongs to that list: any attempt to read any
  other symbol imported into the \"COMMON-LISP\" package, or to produce
  such a symbol with [intern$] or [intern-in-package-of-symbol], will
  cause an error.

  The following axioms formalize properties of pkg-imports discussed
  above (use :[pe] to view them).

    symbol-package-name-intern-in-package-of-symbol
    intern-in-package-of-symbol-is-identity
    symbol-listp-pkg-imports
    no-duplicatesp-pkg-imports
    completion-of-pkg-imports")
 (PKG-WITNESS
  (PACKAGES ACL2-BUILT-INS)
  "Return a specific symbol in the indicated package

  For any string pkg that names a package currently known to ACL2,
  (pkg-witness pkg) is a symbol in that package whose [symbol-name]
  is the value of constant *pkg-witness-name*. Logically, this is the
  case even if the package is not currently known to ACL2. However,
  if pkg-witness is called on a string that is not the name of a
  package known to ACL2, a hard Lisp error will result.

  (Pkg-witness pkg) has a guard of (and (stringp pkg) (not (equal pkg
  \"\"))). If pkg is not a string, then (pkg-witness pkg) is equal to
  (pkg-witness \"ACL2\")")
 (PL
  (HISTORY)
  "Print the rules for the given name or term

    Examples:
    :pl foo     ; prints rules that rewrite some call of foo
    :pl (+ x y) ; prints rules that rewrite (+ x y)

  Also see [pl2], which restricts output to rules that you specify for
  a given term.

  Pl takes one argument, which should be a symbol or a term.

  First suppose that the argument is a symbol. Then it should be either
  a function symbol or else a macro alias for a function symbol (see
  [macro-aliases-table]), which is treated as the corresponding
  function symbol. In this case :pl displays rules that apply to
  terms whose top function symbol is the one specified, specifically,
  rules of class :[rewrite], :[definition], :[meta], :[linear],
  :[type-prescription], :[forward-chaining], :[elim], and
  :[induction].

  Otherwise the argument should be a term (in user syntax, so that for
  example macros are permitted). In this case, :pl displays the
  :[rewrite], :[definition], and :meta rules that rewrite the
  specified term, followed by the applicable :[type-prescription]
  rules. Each rule is displayed with additional information, such as
  the hypotheses that remain after applying some simple techniques to
  discharge them that are likely to apply in any context. Note that
  for :[meta] rules, only those are displayed that meet two
  conditions: the application of the metafunction returns a term
  different from the input term, and if there is a hypothesis
  metafunction then it also returns a term. (A subtlety: In the case
  of extended metafunctions (see [extended-metafunctions]), a trivial
  metafunction context is used for the application of the
  metafunction.)

  Note that some rule classes are not handled by :pl. In particular, if
  you want to see all :[clause-processor] rules, issue the command
  :print-clause-processor-rules, and for trusted clause-processors,
  (table trusted-clause-processor-table); see [clause-processor] and
  see [define-trusted-clause-processor].")
 (PL2
  (HISTORY)
  "Print rule(s) for the given form

    Examples:
    :pl2 (+ x y) nil ; prints rules that apply to (+ x y)
    :pl2 (+ x y) foo ; prints rules named foo that apply to (+ x y)
    :pl2 (+ x y) (:rewrite foo) ; if the rule with rune (:rewrite foo) applies
                                ;   to (+ x y), then print it
    :pl2 (+ x y) (:type-prescription foo)
                                ; as above, but for the indicated
                                ;   type-prescription rule

  Pl2 takes two arguments. The first is a term. The second is either
  nil or a ``rule-id'' that is either a symbol or a [rune]. The
  result is to print rules of class :[rewrite], :[definition], :meta,
  :[linear], and :[type-prescription] that apply to the given term.
  Indeed, :pl2 prints exactly what is printed by applying :[pl] to
  the first argument --- see [pl] --- except that if the second
  argument is not nil then it is used to filter the rules printed, as
  follows.

      If the rule-id is a symbol, then only rules whose name is that symbol
      will be printed.

      If the rule-id is a [rune], then at most one rule will be printed:
      the rule named by that rune (if the rule would be printed by
      :[pl]).")
 (PLET
  (PARALLEL-PROGRAMMING ACL2-BUILT-INS)
  "Parallel version of [let]

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism],
  and see [parallel-programming], which has a disclaimer.

    Example Forms:
    (plet ((a (fibonacci (- x 1)))
           (b (fibonacci (- x 2))))
          (+ a b))

    (plet (declare (granularity (> x 35)))
          ((a (fibonacci (- x 1)))
           (b (fibonacci (- x 2))))
          (+ a b))

    General Form:
    (plet (declare (granularity expr)) ; optional granularity declaration
          ((var1 val1)
           ...
           (varN valN))
          (declare ...) ... (declare ...) ; optional declarations
          body)

  The syntax of plet is identical to the syntax of [let], except that
  plet permits an optional granularity declaration in the first
  argument position; see [granularity]. In the logic a call of plet
  macroexpands to the corresponding call of [let], where the
  granularity declaration (if any) is dropped.

  Plet cause the evaluation of each vali above to be done in parallel
  before processing the body. If the above [granularity] declaration
  is present, then its expression (expr above) is first evaluated,
  and if the result is nil, then such parallelism is avoided. Even if
  parallelism is not thus avoided, parallelism may be limited by
  available resources.

  See [parallelism-at-the-top-level] for restrictions on evaluating
  parallelism primitives from within the ACL2 top-level loop.")
 (PLUSP
  (NUMBERS ACL2-BUILT-INS)
  "Test whether a number is positive

  (Plusp x) is true if and only if x > 0.

  The [guard] of plusp requires its argument to be a rational ([real],
  in ACL2(r)) number.

  Plusp is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: 

    (defun plusp (x)
           (declare (xargs :guard (real/rationalp x)))
           (> x 0))")
 (POINTERS
  (DOCUMENTATION)
  "Links pointing to relevant documentation topics


Subtopics

  [&allow-other-keys]
      See [macro-args].

  [&body]
      See [macro-args].

  [&key]
      See [macro-args].

  [&optional]
      See [macro-args].

  [&rest]
      See [macro-args].

  [&whole]
      See [macro-args].

  [ACL2s]
      See [ACL2-sedan].

  [Add-ld-keyword-alias]
      See [ld-keyword-aliases].

  [Add-ld-keyword-alias!]
      See [ld-keyword-aliases].

  [Add-to-set-eq]
      See [add-to-set].

  [Add-to-set-eql]
      See [add-to-set].

  [Add-to-set-equal]
      See [add-to-set].

  [Apropos]
      See [finding-documentation].

  [Assoc-eq]
      See [assoc].

  [Assoc-equal]
      See [assoc].

  [Backchain-limit-rw]
      See [hints] for keyword :backchain-limit-rw.

  [Backtrack]
      See [hints] for keyword :backtrack.

  [Book-makefiles]
      See [books-certification].

  [By]
      See [hints] for keyword :by.

  [Cases]
      See [hints] for keyword :cases.

  [Certifying-books]
      See [books-certification].

  [Close-input-channel]
      See [io].

  [Close-output-channel]
      See [io].

  [Default-verify-guards-eagerness]
      See [set-verify-guards-eagerness].

  [Delete-assoc-eq]
      See [delete-assoc].

  [Delete-assoc-equal]
      See [delete-assoc].

  [Do-not-induct]
      See [hints] for keyword :do-not-induct.

  [Dynamically-monitor-rewrites]
      See [dmr].

  [Expand]
      See [hints] for keyword :expand.

  [External-format]
      See [character-encoding].

  [Fake-rune]
      See [rune].

  [Fms!-to-string]
      See [printing-to-strings].

  [Fms-to-string]
      See [printing-to-strings].

  [Fmt!-to-string]
      See [printing-to-strings].

  [Fmt-to-string]
      See [printing-to-strings].

  [Fmt1!-to-string]
      See [printing-to-strings].

  [Fmt1-to-string]
      See [printing-to-strings].

  [Fncall-term]
      See [meta-extract].

  [Forced]
      See [force].

  [Gcs]
      See [get-command-sequence].

  [Get-output-stream-string$]
      See [io].

  [Getting-started]
      See [ACL2-tutorial].

  [Guard-hints]
      See [xargs] for keyword :guard-hints.

  [Guard-msg-table]
      See [set-guard-msg].

  [Guards]
      See [guard].

  [Hands-off]
      See [hints] for keyword :hands-off.

  [If-intro]
      See [splitter].

  [Ignorable]
      See [declare].

  [Ignore]
      See [declare].

  [Immed-forced]
      See [splitter].

  [Induct]
      See [hints] for keyword :induct.

  [Intersection-eq]
      See [intersection$].

  [Intersection-equal]
      See [intersection$].

  [Intersectp-eq]
      See [intersectp].

  [Intersectp-equal]
      See [intersectp].

  [Invariant-risk]
      See [program-wrapper].

  [Iprint]
      See [set-iprint].

  [Iprinting]
      See [set-iprint].

  [Keyword]
      See [keywordp].

  [Lambda]
      See [term].

  [Measure]
      See [xargs] for keyword :measure.

  [Member-eq]
      See [member].

  [Member-equal]
      See [member].

  [Meta-extract-contextual-fact]
      See [meta-extract].

  [Meta-extract-formula]
      See [meta-extract].

  [Meta-extract-global-fact]
      See [meta-extract].

  [Meta-extract-global-fact+]
      See [meta-extract].

  [Meta-extract-rw+-term]
      See [meta-extract].

  [Mode]
      See [xargs] for keyword :mode.

  [No-duplicatesp-eq]
      See [no-duplicatesp].

  [No-duplicatesp-equal]
      See [no-duplicatesp].

  [No-thanks]
      See [hints] for keyword :no-thanks.

  [Non-executable]
      See [xargs] for keyword :non-executable.

  [Nonlinearp]
      See [hints] for keyword :nonlinearp.

  [Normalize]
      See [xargs] for keyword :normalize.

  [Observation-cw]
      See [observation].

  [Open-input-channel]
      See [io].

  [Open-input-channel-p]
      See [io].

  [Open-output-channel]
      See [io].

  [Open-output-channel-p]
      See [io].

  [Optimize]
      See [declare].

  [Package]
      See [packages].

  [Peek-char$]
      See [io].

  [Position-eq]
      See [position].

  [Position-equal]
      See [position].

  [Print-object$]
      See [io].

  [Print-summary-user]
      See [finalize-event-user].

  [Proof-supporters-alist]
      See [dead-events].

  [Put-assoc-eq]
      See [put-assoc].

  [Put-assoc-eql]
      See [put-assoc].

  [Put-assoc-equal]
      See [put-assoc].

  [Rassoc-eq]
      See [rassoc].

  [Rassoc-equal]
      See [rassoc].

  [Read-byte$]
      See [io].

  [Read-char$]
      See [io].

  [Read-object]
      See [io].

  [Regression]
      See [books-certification].

  [Remove-duplicates-eq]
      See [remove-duplicates].

  [Remove-duplicates-equal]
      See [remove-duplicates].

  [Remove-eq]
      See [remove].

  [Remove-equal]
      See [remove].

  [Remove1-eq]
      See [remove1].

  [Remove1-equal]
      See [remove1].

  [Reorder]
      See [hints] for keyword :reorder.

  [Reset-print-control]
      See [print-control].

  [Restrict]
      See [hints] for keyword :restrict.

  [Saving-and-restoring]
      See [save-exec].

  [Set-accumulated-persistence]
      See [accumulated-persistence].

  [Set-difference-eq]
      See [set-difference$].

  [Set-difference-equal]
      See [set-difference$].

  [Set-ld-keyword-aliases]
      See [ld-keyword-aliases].

  [Set-ld-keyword-aliases!]
      See [ld-keyword-aliases].

  [Set-ld-redefinition-action]
      See [ld-redefinition-action].

  [Set-ld-skip-proofs]
      See [ld-skip-proofsp].

  [Set-ld-skip-proofsp]
      See [ld-skip-proofsp].

  [Set-let*-abstraction]
      See [set-let*-abstractionp].

  [Set-non-linear]
      See [set-non-linearp].

  [Set-print-circle]
      See [print-control].

  [Set-print-escape]
      See [print-control].

  [Set-print-length]
      See [print-control].

  [Set-print-level]
      See [print-control].

  [Set-print-lines]
      See [print-control].

  [Set-print-readably]
      See [print-control].

  [Set-print-right-margin]
      See [print-control].

  [Set-ruler-extenders]
      See [ruler-extenders].

  [Set-serialize-character]
      See [with-serialize-character].

  [Show-accumulated-persistence]
      See [accumulated-persistence].

  [Single-threaded-objects]
      See [stobj].

  [Split-types]
      See [xargs] for keyword :split-types.

  [Stobj-let]
      See [nested-stobjs].

  [Stobjs]
      See [xargs] for keyword :stobjs.

  [Subsetp-eq]
      See [subsetp].

  [Subsetp-equal]
      See [subsetp].

  [Trust-tag]
      See [defttag].

  [Ttag]
      See [defttag].

  [Type]
      Disambiguation page for type-related concepts.

  [Typespec-check]
      See [meta-extract].

  [Union-eq]
      See [union$].

  [Union-equal]
      See [union$].

  [Untranslate]
      See [user-defined-functions-table].

  [Untranslate-preprocess]
      See [user-defined-functions-table].

  [Use]
      See [hints] for keyword :use.

  [Verify-guards-eagerness]
      See [set-verify-guards-eagerness].

  [Waterfall]
      See [hints-and-the-waterfall].

  [Write-byte$]
      See [io].")
 (POPPING_OUT_OF_AN_INDUCTIVE_PROOF
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Popping out of an Inductive Proof

  Recall that our induction scheme (click [here] to revisit it) had two
  cases, the induction step (Subgoal *1/2) and the base case (Subgoal
  *1/1). Both have been proved!")
 (POR
  (PARALLEL-PROGRAMMING ACL2-BUILT-INS)
  "Parallel, Boolean version of [or]

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism],
  and see [parallel-programming], which has a disclaimer.

    Example Forms:
    (por (subsetp-equal x y)
         (subsetp-equal y x))

    (por (declare
          (granularity
           (and (> (length x) 500)
                (> (length y) 500))))
          (subsetp-equal x y)
          (subsetp-equal y x))

    General Form:
    (por (declare (granularity expr)) ; optional granularity declaration
         arg1 ... argN)

  where N >= 0 and each argi and expr are arbitrary terms.

  Por evaluates its arguments in parallel. It returns a Boolean result:
  t if any argument evaluates to non-nil, else nil. Note that while
  [or] returns the first non-nil value from evaluating its arguments
  left-to-right (if any such value is not nil) [por] always returns a
  Boolean result, in support of efficiency (see [early-termination])
  in light of the nondeterministic order in which argument values are
  returned.

  Another difference between por and [or] is that for a call of por,
  even if the an argument's value is not nil, a subsequent argument
  may be evaluated. See [pand] for a discussion of the analogous
  property of pand. In particular, [guard]s generated from calls of
  por may not assume for an argument that the preceding arguments
  evaluated to nil.

  See [parallelism-tutorial] for another example. Also see
  [parallelism-at-the-top-level] for restrictions on evaluating
  parallelism primitives from within the ACL2 top-level loop. Finally
  see [early-termination] to read how por can offer more efficiency
  than [or] by avoiding evaluation of some of its arguments.")
 (PORTCULLIS
  (BOOKS-TOUR)
  "The gate guarding the entrance to a certified book

  The certificate (see [certificate] for general information) of a
  certified file is divided into two parts, a portcullis and a
  [keep]. These names come from castle lore. The portcullis of a
  castle is an iron grate that slides up through the ceiling of the
  tunnel-like entrance. The portcullis of a book ensures that
  [include-book] does not start to read the book until the
  appropriate context has been created.

  Technically, the portcullis consists of the [version] number of the
  certifying ACL2, a list of [command]s used to create the
  ``certification [world]'' and an alist specifying the check sums of
  all the [books] included in that [world]. The portcullis is
  constructed automatically by [certify-book] from the [world] in
  which [certify-book] is called, but that [world] must have certain
  properties described below. After listing the properties we discuss
  the issues in a more leisurely manner.

  Each [command] in the portcullis must be either a [defpkg] form or an
  embedded event form (see [embedded-event-form]).

  Consider a book to be certified. The book is a file containing event
  forms. Suppose the file contains references to such symbols as
  my-pkg::fn and acl2-arith::cancel, but that the book itself does
  not create the packages. Then a hard Lisp error would be caused
  merely by the attempt to read the expressions in the book. The
  corresponding [defpkg]s cannot be written into the book itself
  because the book must be compilable and Common Lisp compilers
  differ on the rules concerning the inline definition of new
  packages. The only safe course is to make all [defpkg]s occur
  outside of compiled files.

  More generally, when a book is certified it is certified within some
  logical [world]. That ``certification [world]'' contains not only
  the necessary [defpkg]s but also, perhaps, function and constant
  definitions and maybe even references to other [books]. When
  [certify-book] creates the [certificate] for a file it recovers
  from the certification [world] the [command]s used to create that
  [world] from the initial ACL2 [world]. Those [command]s become part
  of the portcullis for the certified book. In addition,
  [certify-book] records in the portcullis the check sums (see
  [check-sum]) of all the [books] included in the certification
  [world].

  [Include-book] presumes that it is impossible even to read the
  contents of a certified book unless the portcullis can be
  ``raised.'' To raise the portcullis we must be able to execute
  (possibly redundantly, but certainly without error), all of the
  [command]s in the portcullis and then verify that the [books] thus
  included were identical to those used to build the certification
  [world] (up to check sum). This raising of the portcullis must be
  done delicately since [defpkg]s are present: we cannot even read a
  [command] in the portcullis until we have successfully executed the
  previous ones, since packages are being defined.

  Clearly, a book is most useful if it is certified in the most
  elementary extension possible of the initial logic. If, for
  example, your certification [world] happens to contain a [defpkg]
  for \"MY-PKG\" and the function foo, then those definitions become
  part of the portcullis for the book. Every time the book is
  included, those names will be defined and will have to be either
  new or redundant (see [redundant-events]). But if those names were
  not necessary to the certification of the book, their presence
  would unnecessarily restrict the utility of the book.

  See [keep] to continue the guided tour of [books].")
 (POSITION
  (LISTS STRINGS ACL2-BUILT-INS)
  "Position of an item in a string or a list

    General Forms:
    (position x seq)
    (position x seq :test 'eql)   ; same as above (eql as equality test)
    (position x seq :test 'eq)    ; same, but eq is equality test
    (position x seq :test 'equal) ; same, but equal is equality test

  (Position x seq) is the least index (zero-based) of the element x in
  the string or list seq, if x is an element of seq. Otherwise
  (position x seq) is nil. The optional keyword, :TEST, has no effect
  logically, but provides the test (default [eql]) used for comparing
  x with items of seq.

  The [guard] for a call of position depends on the test. In all cases,
  the second argument must satisfy [stringp] or [true-listp]. If the
  test is [eql], then either the first argument must be suitable for
  [eql] (see [eqlablep]) or the second argument must satisfy
  [eqlable-listp]. If the test is [eq], then either the first
  argument must be a symbol or the second argument must satisfy
  [symbol-listp].

  See [equality-variants] for a discussion of the relation between
  position and its variants:

      (position-eq x seq) is equivalent to (position x seq :test 'eq);

      (position-equal x seq) is equivalent to (position x seq :test
      'equal).

  In particular, reasoning about any of these primitives reduces to
  reasoning about the function position-equal.

  Position is defined by Common Lisp. See any Common Lisp documentation
  for more information.

  Function: 

    (defun position-equal (item lst)
           (declare (xargs :guard (or (stringp lst) (true-listp lst))))
           (if (stringp lst)
               (position-ac item (coerce lst 'list) 0)
               (position-equal-ac item lst 0)))

  Function: 

    (defun position-equal-ac (item lst acc)
           (declare (xargs :guard (and (true-listp lst)
                                       (acl2-numberp acc))))
           (cond ((endp lst) nil)
                 ((equal item (car lst)) acc)
                 (t (position-equal-ac item (cdr lst)
                                       (1+ acc)))))")
 (POSITION-EQ (POINTERS)
              "See [position].")
 (POSITION-EQUAL (POINTERS)
                 "See [position].")
 (POSP
  (NUMBERS ACL2-BUILT-INS)
  "A recognizer for the positive integers

  (posp x) is logically equivalent to (not (zp x)) (see [zp]) and also
  to (and (natp x) (not (equal x 0))).

  The community book [arithmetic/natp-posp] has some lightweight rules
  for reasoning about posp and natp, and is included in the
  [arithmetic-1] library. For a somewhat heavier and more
  comprehensive alternative, you may wish to instead see the
  [arith-equivs] book.

  Function: 

    (defun posp (x)
           (declare (xargs :guard t))
           (and (integerp x) (< 0 x)))")
 (POST-INDUCTION-KEY-CHECKPOINTS
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Reading post-induction key checkpoints

  Each post-induction key checkpoint is a theorem if and only if the
  original conjecture was a theorem. The reason is that each subgoal
  produced by induction concludes with the original formula and
  simplification preserves equivalence.

  So if you see a post-induction key checkpoint that is not a theorem,
  stop looking at the checkpoints! Your original conjecture is not a
  theorem! Fix it.

  If you're convinced all the post-induction conjectures are theorems,
  ask whether each has the hypotheses you'd need to prove it. If the
  case analysis feels inappropriate or induction hypotheses seem to
  be missing, then ACL2 might have done the wrong induction. Find the
  induction scheme it did by reading the first induction message
  printed after the conjecture was submitted. If it is wrong, then
  extend ACL2's induction analysis or tell ACL2 what induction to do,
  as explained shortly.

  But before you decide the induction hypothesis is missing, look
  closely for contradictions among the hypotheses of the checkpoint
  formula. For example, perhaps one of the hypotheses is (MEMBER e x)
  and another is (NOT (MEMBER e' x')) where e, x, e', and x' are
  possibly complicated expressions.

  Is it possible that e and e' are equal and x and x' are equal? If so,
  then the two hypotheses are contradictory and the checkpoint would
  be proved if you could find rules that would simplify those
  expressions to their common forms. So look for theorems about those
  subexpressions.

  Or maybe you can get e and e' to reduce to some common d but but find
  that x and x' are really different. Then ask whether

    (implies (member d x) (member d x'))

  If you could prove that, the key checkpoint would be proved. Of
  course, you may need other hypotheses from the checkpoint to state
  your theorems.

  If you have been working your way through the tutorial introduction
  to the theorem prover, use your browser's Back Button now to
  [introduction-to-key-checkpoints].")
 (PPROGN
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Evaluate a sequence of forms that return [state]

    Example Form:
    (pprogn
     (cond ((or (equal (car l) #\\) (equal (car l) slash-char))
            (princ$ #\\ channel state))
           (t state))
     (princ$ (car l) channel state)
     (mv (cdr l) state))

  The convention for pprogn usage is to give it a non-empty sequence of
  forms, each of which (except possibly for the last) returns state
  (see [state]) as its only value. The [state] returned by each but
  the last is passed on to the next. The value or values of the last
  form are returned as the value of the pprogn.

  If you are using single-threaded objects you may wish to define an
  analogue of this function for your own [stobj].

  General Form:

    (PPROGN form1
            form2
            ...
            formk
            result-form)

  This general form is equivalent, via macro expansion, to:

    (LET ((STATE form1))
         (LET ((STATE form2))
              ...
              (LET ((STATE formk))
                   result-form)))")
 (PR
  (HISTORY)
  "Print the rules stored by the event with the given name

    Examples:

    :pr fn ; prints the rules from the definition of fn (including any
           ; :type-prescription rule and :definition rule)

    :pr assoc-append ; if assoc-append is a rewrite rule, prints that rule

  Also see [pr!], which is similar but works at the command level
  instead of at the event level, and see [pl], which displays all
  rewrite rules for calls of fn, not just those introduced at
  definition time.

  Pr takes one argument, a logical name, and prints the rules
  associated with it. In each case it prints the rune, the current
  enabled/disabled status, and other appropriate fields from the
  rule. It may be helpful to read the documentation for various kinds
  of rules in order to understand the information printed by this
  command. For example, the information printed for a linear rule
  might be:

    Rune:     (:LINEAR ABC)
    Enabled:  T
    Hyps:     ((CONSP X))
    Concl:    (< (ACL2-COUNT (CAR X)) (ACL2-COUNT X))
    Max-term: (ACL2-COUNT (CAR X))
    Backchain-limit-lst:    (3)

  The hyps and concl fields for this rule are fairly self-explanatory,
  but it is useful to see [linear] to learn about maximal terms
  (which, as one might guess, are stored under ``Max-term'').

  Currently, this function does not print congruence rules or
  equivalence rules.

  The expert user might also wish to use [find-rules-of-rune]. See
  [find-rules-of-rune].")
 (PR!
  (HISTORY)
  "Print rules stored by the command with a given command descriptor

    Examples:

    :pr! fn ; prints the rules from the definition of fn (including any
            ; :type-prescription rule and :definition rule), as well as all other
            ; rules created by the command that created by fn (which could be
            ; many rules if, for example, fn was defined by an include-book
            ; command).

    :pr! :max ; prints all the rules stored by the most recent command

  Also see [pr], which is similar but works at the event level instead
  of at the command level.

  [Pr] takes one argument, a command descriptor, and prints the rules
  created by the corresponding event. In each case it prints the
  rune, the current enabled/disabled status, and other appropriate
  fields from the rule. See [pr] for further details.")
 (PRACTICE-FORMULATING-STRONG-RULES
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "A few simple checkpoints suggesting strong rules

  Consider these definitions:

    (defun rev (x)
      (if (endp x)
          nil
          (append (rev (cdr x)) (list (car x)))))

    (defun nats-below (j)
      (if (zp j)
          '(0)
          (cons j (nats-below (- j 1)))))

  We assume you are familiar with such ACL2 built-ins as append,
  member, subsetp and true-listp. When we use throw-away names like
  FOO, BAR, and MUM below we mean to suggest some arbitrary function
  you shouldn't think about! We're just trying to train your eye to
  ignore irrelevant things.

  Below are some terms that should suggest rewrite rules to you.
  Imagine that each of these terms occurs in some Key Checkpoint.
  What rules come to mind? Try to think of the strongest rules you
  can.

  Term 1:
  (TRUE-LISTP (APPEND (FOO A) (BAR B)))

  Answers: See [practice-formulating-strong-rules-1]

  Term 2:
  (TRUE-LISTP (REV (FOO A)))

  Answers: See [practice-formulating-strong-rules-2]

  Term 3:
  (MEMBER (FOO A) (APPEND (BAR B) (MUM C)))

  Answers: See [practice-formulating-strong-rules-3]

  Term 4:
  (SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))

  Answers: See [practice-formulating-strong-rules-4]

  Term 5:
  (SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))

  Answers: See [practice-formulating-strong-rules-5]

  Term 6:
  (MEMBER (FOO A) (NATS-BELOW (BAR B)))

  Answers: See [practice-formulating-strong-rules-6]

  We recommend doing all of these little exercises. When you're
  finished, use your browser's Back Button to return to
  [strong-rewrite-rules].")
 (PRACTICE-FORMULATING-STRONG-RULES-1
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Rules suggested by (TRUE-LISTP (APPEND (FOO A) (BAR B)))

  What rules come to mind when looking at the following subterm of a
  Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).

    (TRUE-LISTP (APPEND (FOO A) (BAR B)))

  Obviously, you must think about the conditions under which (APPEND x
  y) returns a true-list. Recall that APPEND concatentates x and y,
  with y being the terminal sublist. Its definition is equivalent to

    (defun append (x y)
      (if (endp x)
          y
          (cons (car x)
                (append (cdr x) y))))

  Technical Note: Append is really a macro that permits you to write
  calls of append with more than two arguments.

  In a sense, append ``expects'' its arguments to be lists ending in
  nil, so-called true-listps. (Such expectations are formalized in
  ACL2 by the notion of the ``[guard]'' [{ICON}] of the function, but
  we strongly recommend not investigating guards until you're good at
  using the system.)

  New users frequently start every new theorem by listing all their
  expectations on the arguments of functions in the problem. For
  example, if the new user wants to make some statement about when
  (append x y) is a true-listp, it is not uncommon for him or her
  first to write:

    (implies (and (true-listp x)
                  (true-listp y))
             ...)

  to get ``comfortable.'' Then, thinking about when (append x y) is a
  true-listp is easy: it always returns a true-listp. It's always a
  true-listp.'' This thinking produces the theorem:

    (defthm true-listp-append-really-weak
      (implies (and (true-listp x)
                    (true-listp y))
               (true-listp (append x y))))

  You'll note we gave it a name suggesting it is ``really weak.''

  One sense in which it is weak is that it has an unnecessary
  hypothesis. If y is a true-listp, then (append x y) is too, whether
  x is a true-listp or not. In ACL2, all functions are total.
  Logically speaking, it doesn't matter whether endp expects its
  argument to be a true-listp or not, it behaves. (Append x y) either
  returns y or a cons whose second argument is generated by append.
  Thus, if y is a true-listp, the answer is too. So here is an
  improved version of the rule:

    (defthm true-listp-append-weak
      (implies (true-listp y)
               (true-listp (append x y))))

  We still think of it as ``weak'' because it has a hypothesis that
  limits its applicability.

  The strong version of the rule is

    (defthm true-listp-append-strong
      (equal (true-listp (append x y))
             (true-listp y))).

  That is, append returns a true-listp precisely when its second
  argument is a true-listp. We recommend that the strong version be
  made a :[rewrite] [{ICON}] rule.

  The weak version of the rule allows us to reduce (TRUE-LISTP (APPEND
  x y)) to true if we can show that (TRUE-LISTP y) is true. But
  suppose (TRUE-LISTP y) is actually false. Then (TRUE-LISTP (APPEND
  x y)) would not simplify under the weak version of the rule. But
  under the strong version it would simplify to NIL.

  Technical Note: The weak version of the rule is a useful
  :[type-prescription] [{ICON}] rule. The type mechanism cannot
  currently exploit the strong version of the rule.

  The strategy of ``getting comfortable'' by adding a bunch of
  hypotheses before you know you need them is not conducive to
  creating strong rules. We tend to state the main relationship that
  we intuit about some function and then add the hypotheses we need
  to make it true. In this case, there were no necessary hypotheses.
  But if there are, we first identify them and then we ask ``what can
  I say about the function if these hypotheses aren't true?'' and try
  to strengthen the statement still further.

  Use your browser's Back Button now to return to
  [practice-formulating-strong-rules].")
 (PRACTICE-FORMULATING-STRONG-RULES-2
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Rules suggested by (TRUE-LISTP (REV (FOO A)))

  What rules come to mind when looking at the following subterm of a
  Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).

    (TRUE-LISTP (REV (FOO A)))

  The definition of rev in this problem is

    (defun rev (x)
      (if (endp x)
          nil
          (append (rev (cdr x)) (list (car x)))))

  Since the definition terminates with an endp test and otherwise cdrs
  the argument, the author of rev was clearly expecting x to be a
  true-listp. (Indeed, the ``[guard]'' [{ICON}] for rev must include
  (true-listp x) since that is endp's guard.) So you're naturally
  justified in limiting your thoughts about (rev x) to x that are
  true-lists. This gives rise to the theorem:

    (defthm true-listp-rev-weak
      (implies (true-listp x)
               (true-listp (rev x))))

  This is the kind of thinking illustrated in the earlier append
  example (see [practice-formulating-strong-rules-1]), and, to
  paraphrase Z in Men in Black, it exemplifies ``everything we've
  come to expect from years of training with typed languages.''

  But logically speaking, the definition of rev does not require x to
  be a true-listp. It can be any object at all: ACL2 functions are
  total. Rev either returns nil or the result of appending a
  singleton list onto the right end of its recursive result. That
  call of append always returns a true-listp since the singleton list
  is a true list. (See [practice-formulating-strong-rules-1].)

  So this is a theorem and a very useful :[rewrite] [{ICON}] rule:

    (defthm true-listp-rev-strong
      (true-listp (rev x))).

  Use your browser's Back Button now to return to
  [practice-formulating-strong-rules].")
 (PRACTICE-FORMULATING-STRONG-RULES-3
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Rules suggested by (MEMBER (FOO A) (APPEND (BAR B) (MUM C)))

  What rules come to mind when looking at the following subterm of a
  Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).

    (MEMBER (FOO A) (APPEND (BAR B) (MUM C)))

  Since (append x y) contains all the members of x and all the members
  of y, e is a member of (append x y) precisely when e is a member of
  x or of y. So a strong statement of this is:

    (defthm member-append-strong-false
      (equal (member e (append x y))
             (or (member e x)
                 (member e y))))

  However, this is not a theorem because member is not Boolean. (Member
  e x), for example, returns the first tail of x that starts with e,
  or else nil. To see an example of this formula that evaluates to
  nil, let

    e = 3
    x = '(1 2 3)
    y = '(4 5 6).

  Then the left-hand side, (member e (append x y)) evaluates to (3 4 5
  6) while the right-hand side evaluates to (3).

  However, the two sides are propositionally equivalent (both either
  nil or non-nil together). So this is a useful :[rewrite] [{ICON}]
  rule:

    (defthm member-append-strong
      (iff (member e (append x y))
           (or (member e x)
               (member e y)))).

  It tells the system that whenever it encounters an instance of
  (MEMBER e (APPEND x y)) in a propositional occurrence (where only
  its truthvalue is relevant), it should be replaced by this
  disjunction of (MEMBER e x) and (MEMBER e y).

  The following two formulas are true but provide much weaker rules and
  we would not add them:

    (implies (member e x) (member e (append x y)))

    (implies (member e y) (member e (append x y)))

  because they each cause the system to backchain upon seeing (MEMBER e
  (APPEND x y)) expressions and will not apply unless one of the two
  side-conditions can be established.

  There is a rewrite rule that is even stronger than
  member-append-strong. It is suggested by the counterexample, above,
  for the EQUAL version of the rule.

    (defthm member-append-really-strong
      (equal (member e (append x y))
             (if (member e x)
                 (append (member e x) y)
                 (member e y))))

  While member-append-strong only rewrites member-append expressions
  occurring propositionally, the -really-strong version rewrites
  every occurrence.

  However, this rule will be more useful than member-append-strong only
  if you have occurrences of member in non-propositional places. For
  example, suppose you encountered a term like:

    (CONS (MEMBER e (APPEND x y)) z).

  Then the -strong rule does not apply but the -really-strong rule
  does.

  Furthermore, the -really-strong rule, by itself, is not quite as good
  as the -strong rule in propositional settings! For example, if you
  have proved the -really-strong rule, you'll notice that the system
  still has to use induction to prove

    (IMPLIES (MEMBER E A)
             (MEMBER E (APPEND B A))).

  The -really-strong rule would rewrite it to

    (IMPLIES (MEMBER E A)
             (IF (MEMBER E A)
                 (APPEND (MEMBER E A) B)
                 (MEMBER E B)))

  which would further simplify to

    (IMPLIES (MEMBER E A)
             (APPEND (MEMBER E A) B))

  What lemma does this suggest? The answer is the rather odd:

    (implies x (append x y))

  which rewrites propositional occurrences of (APPEND x y) to T if x is
  non-nil. This is an inductive fact about append.

  A problem with the -really-strong rule is that it transforms even
  propositional occurrences of member into mixed propositional and
  non-propositional occurrences.

    (defthm member-append-really-strong
      (equal (member e (append x y))      ; <-- even if this is a propositional occurrence
             (if (member e x)
                 (append (member e x) y)  ; <-- the member in here is not!
                 (member e y))))

  So if you are using the -really-strong lemma in a situation in which
  all your member expressions are used propositionally, you'll
  suddenly find yourself confronted with non-propositional uses of
  member.

  Our advice is not to use the -really-strong version unless your
  application is inherently using member in a non-propositional way.

  Use your browser's Back Button now to return to
  [practice-formulating-strong-rules].")
 (PRACTICE-FORMULATING-STRONG-RULES-4
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Rules suggested by (SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))

  What rules come to mind when looking at the following subterm of a
  Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).

    (SUBSETP (APPEND (FOO A) (BAR B)) (MUM C))

  When is (append x y) a subset of z? When everything in x is in z and
  everything in y is in z. We would make it a rewrite rule:

    (defthm subsetp-append-1-strong
      (equal (subsetp (append x y) z)
             (and (subsetp x z)
                  (subsetp y z))))

  We put the ``-1-'' in the name because there is a comparable theorem
  for when the append is in the second argument of the subsetp; see
  [practice-formulating-strong-rules-5].

  This strong rule is better than the conditional rule;

    (defthm subsetp-append-1-weak
      (implies (and (subsetp x z)
                    (subsetp y z))
               (subsetp (append x y) z)))

  for all the usual reasons.

  Use your browser's Back Button now to return to
  [practice-formulating-strong-rules].")
 (PRACTICE-FORMULATING-STRONG-RULES-5
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Rules suggested by (SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))

  What rules come to mind when looking at the following subterm of a
  Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).

    (SUBSETP (FOO A) (APPEND (BAR B) (MUM C)))

  When is x a subset of (append y z)? Clearly it is if x is a subset of
  y or x is a subset of z. We could write that:

    (defthm subsetp-append-2-weak
      (implies (or (subsetp x y)
                   (subsetp x z))
               (subsetp x (append y z))))

  The rule generated from this is: ``if you ever encounter (an instance
  of) (SUBSETP x (APPEND y z)), backchain to the or above and try to
  establish it. If you can establish it, replace the target by T.''

  This does not fully characterize the situation though. For example,
  '(1 2 3 4) is a subset of (append '(1 3) '(2 4)) without being a
  subset of either argument of the append.

  However, no obvious equivalence comes to mind -- indeed, to express
  any of the ideas floating around here requires defining and
  introducing more functions, which is not recommended unless those
  functions are already in the problem.

  For example, if you defined the concept of ``set-minus'' so that
  (set-minus x y) consists of those elements of x not in y, then you
  could prove:

    (defthm subset-append-2-strong-but-messy
      (equal (subsetp x (append y z))
             (and (subsetp (set-minus x z) y)
                  (subsetp (set-minus x y) z))))

  But this rewrite rule would ``trade'' append away and introduce
  set-minus. That might be a good strategy if set-minus were already
  in the problem. But if it were not, it might not be. We wouldn't
  recommend this rule unless it were helpful in normalizing the
  expressions in the problem.

  We recommend sticking with the weak version of the rule,

    (defthm subsetp-append-2-weak
      (implies (or (subsetp x y)
                   (subsetp x z))
               (subsetp x (append y z)))).

  This illustrates the fact that sometimes there is no strong version
  of a rule!

  Use your browser's Back Button now to return to
  [practice-formulating-strong-rules].")
 (PRACTICE-FORMULATING-STRONG-RULES-6
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Rules suggested by (MEMBER (FOO A) (NATS-BELOW (BAR B)))

  What rules come to mind when looking at the following subterm of a
  Key Checkpoint? Think of strong rules (see [strong-rewrite-rules]).

    (MEMBER (FOO A) (NATS-BELOW (BAR B)))

  The definition of NATS-BELOW is

    (defun nats-below (j)
      (if (zp j)
          '(0)
          (cons j (nats-below (- j 1)))))

  Thus, (nats-below 7) is (7 6 5 4 3 2 1 0). So when is k a member of
  (nats-below j)?

  The weakest version is

    (defthm member-nats-below-weak
      (implies (and (natp k)
                    (natp j)
                    (<= k j))
               (member k (nats-below j))))

  But clearly we could improve this to:

    (defthm member-nats-below-weak-better
      (implies (and (natp k)
                    (natp j))
               (iff (member k (nats-below j))
                    (<= k j))))

  or even

    (defthm member-nats-below-weak-better
      (implies (natp j)
               (iff (member k (nats-below j))
                    (and (natp k)
                         (<= k j)))))

  Clearly though, we'd like to get rid of the (natp j) hypothesis and
  the neatest plausible version is:

    (defthm member-nats-below-weak-neatest
      (iff (member k (nats-below j))
           (and (natp j)
                (natp k)
                (<= k j))))

  But it is not a theorem! For example, if j is -1 and k is 0, then the
  left-hand side above returns t, because (nats-below j) is (0), but
  the right-hand side is nil.

  But this suggests a strategy for dealing with necessary hypotheses,
  like (natp j). We can move them into an IF on the right-hand side!
  Something like this might be a useful rewrite rule:

    (iff (member k (nats-below j))
         (if (natp j)
             (and (natp k)
                  (<= k j))
             ...)).

  We know, from member-nats-below-weak-better, that if (natp j) is
  true, the member is equivalent to (and (natp k) (<= k j)). So now
  consider what we know if (natp j) is false. If we can think of some
  term it's equivalent to and that term is simpler than the member
  expression, we have a strong rule.

  But by inspection of the definition of nats-below, we see that when
  (natp j) is false, (nats-below j) is the list (0) because (zp j) is
  t. That is, nats-below treats all non-natural arguments like they
  were 0. Thus, when (natp j) is false, (member k (nats-below j)) is
  (member k '(0)), which is (equal k 0).

  So the strong version is

    (defthm member-nats-below-strong
       (iff (member k (nats-below j))
            (if (natp j)
                (and (natp k)
                     (<= k j))
                (equal k 0))))

  This is a great :[rewrite] [{ICON}] rule. It gets rid of the member
  and nats-below and introduces arithmetic.

  This example illustrates the idea of putting an if on the
  right-hand-side of the equivalence. Many users tend to limit
  themselves to propositional forms inside iff or to simple
  expressions inside of equal. But it is quite natural to use if to
  express what the answer is: if j is a natural, then k is in
  (nats-below j) precisely if k is a natural less than or equal to j;
  if j is not a natural, then k is in (nats-below j) precisely if k
  is 0.

  Use if to lay out the cases you must consider, if you can think of a
  simpler, equivalent expression for every possible case.

  Use your browser's Back Button now to return to
  [practice-formulating-strong-rules].")
 (PRINC$
  (IO ACL2-BUILT-INS)
  "Print an atom

  Use princ$ to do basic printing of atoms (i.e., other than cons
  pairs). In particular, princ$ prints a string without the
  surrounding double-quotes and without escaping double-quote
  characters within the string. Note that princ$ is sensitive to the
  print-base, print-radix, and print-case; see [set-print-base-radix]
  and see [set-print-case]. Princ$ returns [state].

    Examples:
    ACL2 !>(princ$ \"Howdy ho\" (standard-co state) state)
    Howdy ho
    ACL2 !>(pprogn (princ$ \"Howdy ho\" (standard-co state) state)
                   (newline (standard-co state) state))
    Howdy ho
    
    ACL2 !>(princ$ \"ab\\\"cd\" *standard-co* state)
    ab\"cd
    ACL2 !>
    ACL2 !>(princ$ 17 *standard-co* state)
    17
    ACL2 !>(set-print-base 16 state) ; might be nicer to use set-print-base-radix
    
    ACL2 !>(princ$ 17 *standard-co* state)
    11
    ACL2 !>(set-print-radix t state)
    
    ACL2 !>(princ$ 17 *standard-co* state)
    #x11
    ACL2 !>(princ$ 'xyz *standard-co* state)
    XYZ
    ACL2 !>(set-print-case :downcase state)
    
    ACL2 !>(princ$ 'xyz *standard-co* state)
    xyz
    ACL2 !>

  The [guard] for (princ$ x channel state) is essentially as follows;
  see [io] for an explanation of guards of certain built-in functions
  that take [state], such as princ$.

    (and (or (acl2-numberp x)
             (characterp x)
             (stringp x)
             (symbolp x))
         (state-p1 state-state)
         (symbolp channel)
         (open-output-channel-p1 channel :character state-state))

  See [fmt] for more sophisticated printing routines, and see [io] for
  general information about input and output.")
 (PRINT-BASE-P
  (IO ACL2-BUILT-INS)
  "Recognizer for print bases that are understood by functions such as
  [explode-nonnegative-integer] and [explode-atom].

  Function: 

    (defun print-base-p (print-base)
           (declare (xargs :guard t))
           (and (member print-base '(2 8 10 16))
                t))")
 (PRINT-CONTROL
  (IO)
  "Advanced controls of ACL2 printing

  See [io] for a summary of printing in ACL2. Here we document some
  advanced ways to control what is printed by ACL2's primary printing
  routines.

  See [set-print-base-radix], [set-print-base], [set-print-radix], and
  [set-print-case] for discussions of the most common ways to control
  what is printed. Indeed, these are the only ways to control the
  behavior of [princ$] and prin1$.

  See [set-fmt-hard-right-margin] for how to set the right margin for
  prover output and, more generally, all output from formatted
  printing functions (see [fmt]). Note that set-print-right-margin,
  mentioned below, does not affect such printing.

  The rest of this topic is for advanced users of ACL2. We refer to
  Common Lisp behavior, as described in any good Common Lisp
  documentation.

  Print-control variables. [Set-print-base], [set-print-radix], and
  [set-print-case] assign to corresponding so-called ``[state] global
  variables'' 'print-base, 'print-radix, and 'print-case, which can
  be accessed using the expressions (@ print-base), (@ print-radix),
  and (@ print-case), respectively; see [assign]. Here is a table
  showing all print-control variables, their setters, and their
  defaults. Also see [set-print-base-radix].

    print-base          set-print-base          10
    print-case          set-print-case          :upcase
    print-circle        set-print-circle        nil
      [but see remark on print-circle-files, below]
    print-escape        set-print-escape        t
    print-length        set-print-length        nil
    print-level         set-print-level         nil
    print-lines         set-print-lines         nil
    print-pretty        set-print-pretty        nil
    print-radix         set-print-radix         nil
    print-readably      set-print-readably      nil
    print-right-margin  set-print-right-margin  nil

  Each ACL2 print-control variable print-xxx can correspond in function
  to Common Lisp variable *PRINT-XXX*. Specifically, the evaluation
  of forms (set-print-base t), (set-print-radix t), and
  (set-print-case t) affects ACL2 printing functions in much the same
  way that setting to t Common Lisp variables *PRINT-BASE*,
  *PRINT-RADIX*, and *PRINT-CASE*, respectively, affects Common Lisp
  printing. The same is true for print-escape, except that this does
  not affect [princ$] or prin1$, which correspond to Common Lisp
  functions princ and prin1: princ treats *PRINT-ESCAPE* as nil while
  prin1 treats *PRINT-ESCAPE* as t. Moreover, all print-control
  variables not mentioned in this paragraph are set to their defaults
  in [princ$] and prin1$, as indicated by ACL2 constant
  *print-control-defaults*, except that print-readably is set to nil
  in princ$.

  [Fmt] and its related functions are sensitive to state globals
  'print-base, 'print-radix, 'print-case, 'print-escape, and
  'print-readably, in analogy with Common Lisp functions that don't
  fix *PRINT-ESCAPE* or *PRINT-READABLY*. But the [fmt] functions do
  not respect settings of other print-control variables; for example,
  they act as though 'print-circle is nil. Since ACL2 output is
  produced using the same underlying print routines as the [fmt]
  functions, it also is insensitive to all print-control variables
  except for the five above. To control the print-level and
  print-length used for producing ACL2 output, see [set-evisc-tuple].

  [Print-object$] is sensitive to all of the print-control variables.

  Evaluate (reset-print-control) to restore all print-control variables
  to their original settings, as stored in constant
  *print-control-defaults*.

  (Remark on print-circle-files: ACL2 typically binds 'print-circle to
  t before writing [certificate] files, or auxiliary files that are
  compiled when [make-event] forms are present in a book, or files in
  support of :[comp] commands. This binding allows for structure
  sharing that can keep these files from growing large. End of
  Remark.)

  (Remark for those using ACL2 built on CLtL1 (non-ANSI) Gnu Common
  Lisp (GCL): Note that Common Lisp variables *PRINT-LINES*,
  *PRINT-MISER-WIDTH*, *PRINT-READABLY*, *PRINT-PPRINT-DISPATCH*, and
  *PRINT-RIGHT-MARGIN* do not have any effect for such GCL versions.)")
 (PRINT-GV
  (GUARD DEBUGGING)
  "Print a form whose evaluation caused a guard violation

  By default, ACL2 checks input constraints on functions, known as
  [guard]s. When guards are violated, an informative message is
  printed; but sometimes it is useful to investigate why the guard
  check fails. The utility print-gv is provided for that purpose.
  (Alternatively, you may prefer to avoid guards entirely with
  (set-guard-checking :none); see [set-guard-checking].)

    Example Forms:
    (print-gv)
    (print-gv :evisc-tuple (evisc-tuple 4 4 nil nil))
    (print-gv :evisc-tuple (evisc-tuple 4 ; print-level
                                        5 ; print-length
                                        (world-evisceration-alist state nil)
                                        nil ; hiding-cars
                                        ))

    General Form:
    (print-gv :evisc-tuple x)

  where the :evisc-tuple argument is optional and defaults to one that
  hides only the ACL2 logical [world], by printing  instead of
  a very large structure. See [evisc-tuple] for a discussion of
  evisc-tuples.

  To see how one might use print-gv, consider the following definition.

    (defun foo (x)
      (declare (xargs :guard (and (my-first-predicate x)
                                  (my-second-predicate x))))
      (cdr x))

  Now suppose we evaluate a call of foo and obtain a guard violation.

    ACL2 !>(foo 3)

    ACL2 Error in TOP-LEVEL:  The guard for the function call (FOO X),
    which is (AND (MY-FIRST-PREDICATE X) (MY-SECOND-PREDICATE X)), is violated
    by the arguments in the call (FOO 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 !>

  We can obtain (in essence) the guard form that was false, as follows.

    ACL2 !>(print-gv)

    (LET ((X '3))
         (DECLARE (IGNORABLE X))
         (AND (MY-FIRST-PREDICATE X)
              (MY-SECOND-PREDICATE X)))

    ACL2 !>

  But which conjunct is to blame? With a bit of editing we can try each
  conjunct in turn.

    ACL2 !>(LET ((X '3))
                (DECLARE (IGNORABLE X))
                (MY-FIRST-PREDICATE X))
    T
    ACL2 !>(LET ((X '3))
                (DECLARE (IGNORABLE X))
                (MY-SECOND-PREDICATE X))
    NIL
    ACL2 !>

  Aha! Now we can investigate why the second predicate fails for 3.

  The following hack will give you access in raw Lisp to the form
  printed by (print-gv). After a guard violation, just submit this
  form to raw Lisp:

    (print-gv1 (wormhole-data (cdr (assoc 'ev-fncall-guard-er-wormhole
                                          *wormhole-status-alist*)))
               state)

  If you use local [stobj]s (see [with-local-stobj]) or stobj fields of
  stobjs, you may need to edit the output of print-gv in order to
  evaluate it. Consider the following example.

    (defstobj st fld)

    (defun g (x st)
      (declare (xargs :guard (consp x) :stobjs st)
               (ignore x))
      (fld st))

    (defun test ()
      (with-local-stobj
       st
       (mv-let (result st)
               (mv (g 3 st) st)
               result)))

    (test)

  Then :print-gv yields the result shown below.

    (FLET ((G{GUARD} (X ST)
                     (DECLARE (IGNORABLE X ST))
                     (AND (STP ST) (CONSP X))))
          (G{GUARD} '3 ||))

  In this example you could replace ``||'' by ``st'' to
  obtain a result of nil. But similar cases may require the use of a
  local stobj that is no longer available, in which case you may need
  to be creative in order to take advantage of :print-gv. Here is
  such an example.

    (defstobj st2 fld2)

    (defun g2 (st2)
      (declare (xargs :guard (null (fld2 st2)) :stobjs st2))
      (mv 0 st2))

    (defun test2 ()
      (with-local-stobj
       st2
       (mv-let (result st2)
               (let ((st2 (update-fld2 17 st2)))
                 (g2 st2))
               result)))

    (test2)

  In this case, :print-gv yields the following.

    (FLET ((G2{GUARD} (ST2)
                      (DECLARE (IGNORABLE ST2))
                      (AND (ST2P ST2) (NULL (FLD2 ST2)))))
          (G2{GUARD} ||))

  But if you replace ``||'' by ``st'', the guard holds; it
  is only the local stobj, which is no longer available, that
  produced a guard violation (because its field had been updated to a
  cons).

    ACL2 !>(FLET ((G2{GUARD} (ST2)
                             (DECLARE (IGNORABLE ST2))
                             (AND (ST2P ST2) (NULL (FLD2 ST2)))))
                 (G2{GUARD} st2))
    T
    ACL2 !>

  Finally, we note that while print-gv is a utility for debugging guard
  violations, in contrast, see [guard-debug] for a utility to assist
  in debugging failed proofs arising from guard verification.")
 (PRINT-OBJECT$ (POINTERS) "See [io].")
 (PRINT-SUMMARY-USER (POINTERS)
                     "See [finalize-event-user].")
 (PRINTING-TO-STRINGS
  (IO)
  "Printing to strings instead of files or standard output

  Each of ACL2's formatted printing functions, FM*, has an analoguous
  macro FM*-TO-STRING indicated below. These functions do not include
  a channel or [state] as an argument, and FM*-TO-STRING returns the
  string that FM* would print to the state, in place of state; see
  [fmt]. The legal keyword arguments are described below.

    General Forms:                                 result
    (fms-to-string string alist &key ...)          ; string
    (fmt-to-string string alist &key ...)          ; (mv col string)
    (fmt1-to-string string alist column &key ...)  ; (mv col string)
    (fms!-to-string string alist &key ...)         ; string
    (fmt!-to-string string alist &key ...)         ; (mv col string)
    (fmt1!-to-string string alist column &key ...) ; (mv col string)

  The legal keyword arguments are as follows. They are all optional
  with a default of nil.

      Evisc-tuple is evaluated, and corresponds exactly to the evisc-tuple
      argument of the corresponding FM* function; see [fmt].

      Fmt-control-alist should typically evaluate to an alist that maps
      print-control variables to values; see [print-control]. Any
      alist mapping variables to values is legal, however. By default
      the print controls are set according to the value of constant
      *fmt-control-defaults*; fmt-control-alist overrides these
      defaults. For example, *fmt-control-defaults* sets the right
      margin just as it is set in the initial ACL2 [state], by
      binding fmt-soft-right-margin and fmt-hard-right-margin to
      their respective defaults of *fmt-soft-right-margin-default*
      and *fmt-hard-right-margin-default*. The following example
      shows how you can override those defaults, in this case
      arranging to print flat by setting the right margin to a large
      number.

        (fmt-to-string \"~x0\"
                       (list (cons #\\0 (make-list 30)))
                       :fmt-control-alist
                       `((fmt-soft-right-margin . 10000)
                         (fmt-hard-right-margin . 10000)))

      Iprint is typically nil, but t is also a legal value. See
      [set-iprint] for the effect of value t, which however is local
      to this call of a FM*-TO-STRING function; the behavior if
      iprinting afterwards is not affected by this call. In
      particular, you will not be able to look at the values of
      iprint tokens printed by this call, so the value t is probably
      of limited utility at best.

  Also see [io] for a discussion of the utility
  get-output-stream-string$, which allows for accumulating the
  results of more than one printing call into a single string but
  requires the use of [state].")
 (PROFILE
  (EVENTS)
  "Turn on profiling for one function

  NOTE: An alternative to this utility, which has significantly less
  functionality but doesn't use [hons-enabled] features of ACL2, may
  be found in community book books/misc/profiling.lisp. See
  [hons-and-memoization] for a general discussion of memoization, on
  which this profile utility is built, and the related features of
  hash consing and applicative hash tables.

  Profile can be useful in Common Lisp debugging and performance
  analysis, including examining the behavior of ACL2 functions.

    Example:
    (profile 'fn)       ; keep count of the calls of fn
    (profile 'fn        ; as above, with with some memoize options
             :trace t
             :forget t)
    (memsum) ; report statistics on calls of memoized functions (e.g., fn)
    (clear-memoize-statistics) ; clear memoization (and profiling) statistics

  Evaluation of (profile 'fn) redefines fn so that a count will be kept
  of the calls of FN. The information recorded may be displayed, for
  example, by invoking ([memoize-summary]) or (equivalently)
  (memsum). If you wish to gather fresh statistics for the evaluation
  of a top-level form, see [clear-memoize-statistics].

  Profile is just a macro that calls [memoize] to do its work. Profile
  gives the two keyword parameters :condition and :recursive of
  [memoize] the value nil. Other keyword parameters for memoize,
  which must not include :condition, :condition-fn, or :recursive,
  are passed through. To eliminate profiling, use [unmemoize]; for
  example, to eliminate profiling for function fn, evaluate
  (unmemoize 'fn).

  You may find raw Lisp functions profile-all and profile-acl2 to be
  useful. These may be found in file
  centaur/memoize/old/profile-raw.lsp distributed with the
  [community-books].")
 (PROG2$
  (PROGN$ ACL2-BUILT-INS)
  "Execute two forms and return the value of the second one

  See [hard-error], see [illegal], and see [cw] for examples of
  functions to call in the first argument of prog2$. Also see
  [progn$] for an extension of prog2$ that handles than two
  arguments.

  Semantically, (Prog2$ x y) equals y; the value of x is ignored.
  However, x is first evaluated for side effect. Since the ACL2
  [programming] language is applicative, there can be no logical
  impact of evaluating x. However, x may involve a call of a function
  such as [hard-error] or [illegal], which can cause so-called ``hard
  errors'', or a call of [cw] to perform output.

  Here is a simple, contrived example using [hard-error]. The intention
  is to check at run-time that the input is appropriate before
  calling function bar.

    (defun foo-a (x)
      (declare (xargs :guard (consp x)))
      (prog2$
       (or (good-car-p (car x))
           (hard-error 'foo-a
                       \"Bad value for x: ~p0\"
                       (list (cons #\\0 x))))
       (bar x)))

  The following similar function uses [illegal] instead of hard-error.
  Since illegal has a guard of nil, [guard] verification would
  guarantee that the call of illegal below will never be made (at
  least when guard checking is on; see [set-guard-checking]).

    (defun foo-b (x)
      (declare (xargs :guard (and (consp x) (good-car-p (car x)))))
      (prog2$
       (or (good-car-p (car x))
           (illegal 'foo-b
                    \"Bad value for x: ~p0\"
                    (list (cons #\\0 x))))
       (bar x)))

  We conclude with a simple example using [cw] from the ACL2 sources.

    (defun print-terms (terms iff-flg wrld)

    ; Print untranslations of the given terms with respect to iff-flg, following
    ; each with a newline.

    ; We use cw instead of the fmt functions because we want to be able to use this
    ; function in print-type-alist-segments (used in brkpt1), which does not return
    ; state.

      (if (endp terms)
          terms
        (prog2$
         (cw \"~q0\" (untranslate (car terms) iff-flg wrld))
         (print-terms (cdr terms) iff-flg wrld))))")
 (PROGN
  (EVENTS)
  "Evaluate some [events]

    Example Form:
    (progn (defun foo (x) x)
           (defmacro my-defun (&rest args)
             (cons 'defun args))
           (my-defun bar (x) (foo x)))

    General form:
    (progn event1 event2 ... eventk)

  where k >= 0 and each eventi is a legal embedded event form (see
  [embedded-event-form]). Each event is printed (by default) and
  evaluated, in sequence. If any event fails, the entire progn call
  is deemed to have failed, and the logical [world] is rolled back to
  what it was immediately before the progn call was evaluated. A
  utility is provided to assist in debugging failures of such
  execution; see [redo-flat].

  NOTE: If the eventi above are not all legal embedded event forms (see
  [embedded-event-form]), consider using [er-progn] or (with great
  care!) [progn!] instead. If your goal is simply to execute a
  sequence of top-level forms that are not necessarily all legal
  embedded event forms, consider using ld instead; see [ld].

  For a related event form that does allow introduction of
  [constraint]s and [local] [events], see [encapsulate].

  ACL2 does not allow the use of progn in definitions. Instead, the
  macro [er-progn] can be used for sequencing [state]-oriented
  operations; see [er-progn] and see [state]. If you are using
  single-threaded objects (see [stobj]) you may wish to define a
  version of [er-progn] that cascades the object through successive
  changes. ACL2's [pprogn] is the state analogue of such a macro.")
 (PROGN!
  (EVENTS)
  "Evaluate some forms, not necessarily [events]

  WARNING! This event is intended for advanced users who, in essence,
  want to build extensions of ACL2. See see [defttag], in particular,
  the ``WARNING'' there, and see the warning about [stobj]s at the
  end of this documentation topic.

  Progn! can be used like [progn], even in [books]. But unlike [progn],
  progn! does not require its constituent forms to be [events] (see
  [embedded-event-form]), except that the first form cannot be a
  symbol unless it is :state-global-bindings (advanced feature,
  described below). However, see [make-event] for a ``Restriction to
  the Top Level'' that still applies under a call of progn!.

  Because progn! allows non-events, it differs from progn in another
  important respect: progn! is illegal unless there is an active
  ttag; see [defttag].

  See community book [hacker] for two macros, [with-raw-mode] and
  [with-redef-allowed], each defined in terms of progn!, that allow
  arbitrary forms in contexts that would normally require legal
  embedded event forms.

  Given a form (progn! form1 form2 ... formk), ACL2 will evaluate each
  formi in turn (for i from 1 to k). If a form returns more than one
  value (see [mv]) where the first value returned is not nil, then no
  later form will be evaluated and the result returned by the progn!
  call will be (mv erp val state) for some non-nil value erp,
  signifying an error (see [ld-error-triples]). Otherwise the
  evaluation is considered to have succeeded, and will continue with
  later forms. The value returned by a call of progn! with no such
  error is of the form (mv nil v state), where v depends on the last
  form as follows. If the last form evaluates to a single value, then
  v is that value, except if the value is a [stobj], say ST, then v
  is the symbol REPLACED-ST. Otherwise the last form evaluates to
  some (mv nil x ...), and v is x unless after the final form's
  evaluation we are in raw-mode (see [set-raw-mode]), in which case
  the progn! call returns nil (so that ACL2 can at least print the
  result --- imagine Lisp returning a pathname object from a load
  call, for example).

  The normal undoing mechanism does not generally apply to forms within
  a progn! that are not legal ACL2 [events] (see
  [embedded-event-form]). In particular, note that a non-[local] call
  of progn! in an [encapsulate] event will generally be evaluated
  twice: once on each pass. This fact is worth keeping in mind if you
  are using progn! to change the state of the system; ask yourself if
  it is acceptable to apply that state-changing operation more than
  once.

  Please note that progn! may differ from [progn] in the following
  sense: definitions within a call of progn! might not be compiled.
  For example, consider the following book.

    (in-package \"ACL2\")
    (defttag :test)
    (progn  (defun f1 (x) x))
    (progn! (defun f2 (x) x))

  If the underlying Lisp is GCL 2.6.7, then after including this
  certified book (where the default certification took place,
  creating a compiled file), then f1 is a compiled function but f2 is
  not. For other Lisps supported by ACL2, both f1 and f2 are
  compiled, though we are not sure that every function under every
  call of progn! would similarly be compiled.

  We now describe, for system hackers only, a sophisticated extension
  of progn! not mentioned above: support for keyword argument
  :state-global-bindings. If the first argument of progn! is this
  keyword, then the second argument is treated as a list of bindings
  as expected by ACl2 system function [state-global-let*]. Thus, in
  the ACL2 loop,

    (progn! :state-global-bindings bindings form1 form2 ... formk)

  is treated as follows:

    (progn! (state-global-let* bindings (progn! form1 form2 ... formk)))

  However, in raw Lisp the former is just:

    (progn form1 form2 ... formk)

  Thus, one should use the :state-global-bindings argument with care,
  since the behavior in the ACL2 loop can differ from that in Common
  Lisp. The intention is that one bind only [state] global variables
  that are relevant to evaluation of the forms within the ACL2 loop
  and are harmlessly ignored for evaluation of those forms in raw
  Lisp. Here is a typical sort of example, as [state] global
  ld-redefinition-action is not relevant to the evaluation of [defun]
  in raw Lisp.

    (progn! (remove-untouchable 'ld-redefinition-action nil)
            (progn! :state-global-bindings
                    ((ld-redefinition-action '(:doit . :overwrite)))
                    (defun foo (x)
                      (cons x x)))
            (push-untouchable 'ld-redefinition-action nil))

  Finally, we point out a pitfall of progn! related to [stobj]s. The
  following book can cause a hard Lisp error, depending on the host
  Common Lisp, when certified with a non-nil value for compile-flg
  (see [certify-book]).

    (in-package \"ACL2\")
    (defstobj st fld)
    (defttag :my-ttag)
    (progn! (update-fld 3 st))

  The problem is that the [stobj] variable st is not known to raw Lisp.
  The compilation problem disappears if the last form above is
  replaced with the following two forms.

    (include-book \"hacking/hacker\" :dir :system)
    (with-raw-mode (update-fld 3 *the-live-st*))")
 (PROGN$
  (BASICS ACL2-BUILT-INS)
  "Execute a sequence of forms and return the value of the last one

  This macro expands to a corresponding nest of calls of prog2$; see
  [prog2$]. The examples below show how this works: the first case
  below is typical, but we conclude with two special cases.

    ACL2 !>:trans1 (progn$ (f1 x) (f2 x) (f3 x))
     (PROG2$ (F1 X) (PROG2$ (F2 X) (F3 X)))
    ACL2 !>:trans1 (progn$ (f1 x) (f2 x))
     (PROG2$ (F1 X) (F2 X))
    ACL2 !>:trans1 (progn$ (f1 x))
     (F1 X)
    ACL2 !>:trans1 (progn$)
     NIL
    ACL2 !>


Subtopics

  [Prog2$]
      Execute two forms and return the value of the second one")
 (PROGRAM
  (DEFUN-MODE)
  "To set the default [defun-mode] to :[program]

    Example:
    ACL2 !>:program
    ACL2 p!>

  Typing the keyword :program sets the default [defun-mode] to
  :program.

  Functions defined in :program mode are logically undefined but can be
  executed on constants outside of deductive contexts. See
  [defun-mode].

  Calls of the following macros are ignored (skipped) when in :program
  mode.

    local
    verify-guards
    verify-termination
    defaxiom
    defthm
    deftheory
    in-theory
    in-arithmetic-theory
    regenerate-tau-database
    theory-invariant
    defchoose

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.

  See [defun-mode] for a discussion of the [defun-mode]s available and
  what their effects on the logic are. See [default-defun-mode] for a
  discussion of how the default [defun-mode] is used. This event is
  equivalent to (table acl2-defaults-table :defun-mode :program), and
  hence is [local] to any [books] and [encapsulate] [events] in which
  it occurs. See [ACL2-defaults-table].

  Recall that the top-level form :program is equivalent to (program);
  see [keyword-commands]. Thus, to change the default [defun-mode] to
  :program in a book, use (program), which is an embedded event form,
  rather than :program, which is not a legal form for [books]. See
  [embedded-event-form].

  See [program-wrapper] for how to use program-mode functions to avoid
  expensive [guard] checks.


Subtopics

  [Program-wrapper]
      Avoiding expensive guard checks using [program]-mode functions")
 (PROGRAM-WRAPPER
  (PROGRAM ADVANCED-FEATURES)
  "Avoiding expensive guard checks using [program]-mode functions

  Application programs can benefit from the avoidance of expensive
  [guard] checks, as illustrated by the following contrived example.
  In this example, imagine that expensive-guard is a [guard] that is
  expensive to evaluate, and that expensive-update is a function that
  you want to run in a context where you know the guard is true, so
  you want to avoid the expense of evaluating that guard. Then when
  you call expensive-update-wrapper, the call will be evaluated
  directly in raw Lisp, hence without any subsidiary guard-checking
  for the function expensive-update.

    (defun fib (n)
      (declare (xargs :guard (natp n)))
      (if (zp n)
          0
        (if (eql n 1)
            1
          (+ (fib (- n 1))
             (fib (- n 2))))))

    (defun expensive-guard (n)
      (declare (xargs :guard t))
      (and (natp n)
           (natp (fib n))))

    (defstobj st (fld :type integer :initially 0))

    (defun expensive-update (n st)
      (declare (xargs :stobjs st
                      :guard (expensive-guard n)))
      (update-fld n st))

    (defun expensive-update-wrapper (n st)
      (declare (xargs :stobjs st :mode :program))
      (expensive-update n st))

  Remark. The example was chosen to illustrates an additional point: a
  potential slowdown due to what could be called ``invariant-risk''.
  This is very unlikely to be an issue in practice, so you may wish
  to stop reading here unless you experience unexpected slowdown
  using the approach discussed above. If you suspect such a problem,
  you can submit the following forms to defeat ACL2's special
  handling for stobj-updating functions described below, to restore
  speed but risk inconsistent states due to insufficient
  guard-checking on stobj updater calls.

    :q
    (setq *ignore-invariant-risk* t)
    (lp)

  The issue is that if a [stobj] updater (such as update-fld above) is
  called on ill-guarded arguments, the resulting ACL2 [state] could
  be ill-formed. For example, consider the call
  (expensive-update-wrapper nil 10 st). That call will lead to the
  call (update-fld nil st), which has the risk of violating the
  invariant that (fld st) is an integer, as specified by the :type in
  the [defstobj] form above. ACL2 takes measures to prevent this
  (starting in Version 6.5), which through Version 7.0 had caused
  significant slowdown due to some unnecessary guard-checking; see
  the concluding technical note below. Now, guards are checked only
  on the stobj updater itself, so for example, the following call
  executes very quickly (unlike pre-7.0 ACL2):

    (expensive-update-wrapper 40 st)

  We conclude with a technical note about how the implementation
  handles [program]-mode functions with ``invariant-risk'', that is,
  for which a call might lead to a call of a [stobj] updater that has
  a non-trivial [guard]. We need to avoid ill-guarded stobj updates;
  but guards aren't checked in raw Lisp. In the top-level loop, every
  function (f t1 ... tk) call is essentially replaced by (ec-call (f
  t1 ... tk)) before its evaluation, resulting in a corresponding
  call of the so-called executable-counterpart of f, sometimes called
  the ``*1* function'' for f, or ``*1*f''. Normally, if f is a
  [program]-mode function, then the body of *1*f leads directly to a
  call of f. But if f has invariant-risk, then in most cases (with
  exceptions including the case that (set-guard-checking :all) has
  been executed), a call of *1*f will lead to evaluation of a
  modified body of f, where each call of an invariant-risk function
  has essentially been wrapped in ec-call. The explanation above is a
  simplification; for example, it does not describe how *1* code
  generation is modified for [logic]-mode functions with
  invariant-risk. To see exactly what is generated, evaluate (trace!
  (oneify-cltl-code :native t)) immediately before submitting the
  definition.")
 (PROGRAMMING
  (ACL2)
  "Programming in ACL2

  This [documentation] topic is a parent topic under which we include
  documentation topics for built-in functions, macros, and special
  forms, as well as topics for notions important to programming with
  ACL2. If you don't find what you're looking for, see the Index or
  see individual topics that may be more directly appropriate; for
  example, see [events] for top-level event constructors like
  [defun]. A subtopic, [ACL2-built-ins], contains as subtopics
  (displayed in a flat list) most of the topics in the
  [documentation] hierarchy that appear under this `programming'
  topic.

  Also see [debugging] for utilities that can aid in programming.


Subtopics

  [ACL2-built-ins]
      ''Catch-all'' topic for built-in ACL2 functions

  [Alists]
      Operations on association lists, which bind keys to values.

  [Arrays]
      ACL2 arrays and operations on them

  [Basics]
      Basic control structures for [programming] like [if] and [cond],
      binding operators like [let] and [flet], multiple-value
      constructs like [mv], and so forth.

  [Characters]
      Characters in ACL2 and operations on them

  [Compilation]
      Compiling ACL2 functions

  [Conses]
      A cons is an ordered pair. In ACL2, data structures like [lists],
      [alists], etc., are made up of conses.

  [Declare]
      Extra declarations that can occur in function definitions, [let]
      bindings, and so forth.

  [Defabbrev]
      A convenient form of macro definition for simple expansions

  [Defconst]
      Define a constant

  [Defmacro]
      Define a macro

  [Defpkg]
      Define a new symbol package

  [Defun]
      Define a function symbol

  [Equality-variants]
      Versions of a function using different equality tests

  [Errors]
      Support for causing runtime errors, breaks, assertions, etc.

  [Fast-alists]
      Alists with hidden hash tables for faster execution

  [Get-internal-time]
      Runtime vs. realtime in ACL2 timings

  [Guard]
      Restricting the domain of a function

  [Hons]
      ([hons] x y) returns a [normed] object equal to ([cons] x y).

  [Io]
      Input/output facilities in ACL2

  [Irrelevant-formals]
      Formals that are used but only insignificantly

  [Lists]
      Lists of objects, the classic Lisp data structure.

  [Mbe]
      Attach code for execution

  [Memoize]
      Turn on memoization for a specified function

  [Mutual-recursion]
      Define some mutually recursive functions

  [Numbers]
      Numbers in ACL2 and operations on them

  [Packages]
      Packages are collections of symbols. They can be used to avoid name
      conflicts when working on large ACL2 projects.

  [Programming-with-state]
      Programming using the von Neumannesque ACL2 [state] object

  [Redefining-programs]
      An explanation of why we restrict redefinitions

  [Sleep]
      Sleep for some number of seconds

  [State]
      The von Neumannesque ACL2 state object

  [Stobj]
      Single-threaded objects or ``von Neumann bottlenecks''

  [Strings]
      Strings are atomic objects that contain character sequences, like
      \"Hello World\".

  [Symbols]
      Symbols in ACL2 and operations on them

  [Time$]
      Time an evaluation

  [Unmemoize]
      Turn off memoization for the specified function")
 (PROGRAMMING-KNOWLEDGE-TAKEN-FOR-GRANTED
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Background knowledge in ACL2 programming for theorem prover tutorial

  This brief review of the programming language is presented as a
  sequence of questions and answers meant to test your knowledge of
  the ACL2 programming language. If you want a gentle introduction to
  the programming language, see
  {http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html
  |
  http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html}.

  Before we get started with the programming drill, let us remind you
  that all we're interested in here is the language, not the
  ``program development environment.'' It's impossible to program in
  ACL2 or any other language without a decent environment, one that
  at the very least includes a way to prepare and edit files of
  programs. The two most popular program development environments
  among ACL2 users are [Emacs] [{ICON}] and the Eclipse-based
  [ACL2-Sedan] [{ICON}]. The Sedan provides the most support for the
  new user, including real-time syntax checking and a facility for
  testing among many other features. But in this drill we're not
  interested in the program development environment, we're interested
  in your understanding of the ACL2 language.

  Q: What do you think this command does?

    (defun rev (x)
      (if (endp x)
          nil
          (append (rev (cdr x)) (list (car x)))))

  A: It defines a function named rev that takes one argument, treats it
  like a list, and reverses the order of the elements in that list.
  To figure this out from the definition, you have to know that
  append concatenates two lists. Logically speaking, the defun of rev
  adds the axiom:

    (rev x)
    =
    (if (endp x)
        nil
        (append (rev (cdr x)) (list (car x)))),

  implicitly quantified for all x.

  Q: Given the defun of rev above, what are the formal parameters? What
  is the body of the definition? Write down a call of append that
  occurs in the body of rev. What are the actuals of that call? A:
  The formals of rev is the list of variables after the first rev in
  the defun, namely (x). We say x is the first (and only) formal
  here. The body of rev is the entire if-expression. The only call of
  append in the body is

    (append (rev (cdr x)) (list (car x)))

  and the actuals of that call are, respectively, (rev (cdr x)) and
  (list (car x)).

  Q: What do you get if you evaluate (rev '(a b c d))? A: (D C B A).

  Q: How did rev change the case of the elements, e.g., lowercase a was
  in the input list but uppercase A was in the output? A: This is a
  trick question. Rev doesn't change the case of the elements. ACL2
  is case-insensitive when dealing with symbols. The symbol a is read
  in as the symbol A. Thus, when writing function names, for example,
  we can write rev, Rev, REV, or even ReV and always be referring to
  the function REV. By default, ACL2 prints symbols in uppercase.

  Q: What does (rev '((a b c) \"Abc\" \"a\" b #\\c)) return? A: (#\\c B \"a\"
  \"Abc\" (A B C)). If you thought the answer was any of these, then
  you need to think or read more carefully:

    (#\\C B \"A\" \"ABC\" (A B C))

    (#\\C B \"A\" \"ABC\" (C B A))

  The first wrong answer above is wrong because Lisp is ``case
  insensitive'' only for symbols, not for character objects like #\\c
  (the lowercase character c) or for strings. Furthermore, \"A\" is a
  string, not a symbol; it is different from A. The second wrong
  answer above is wrong because rev does not go into the individual
  elements of the list, it just reverses the order of the elements.
  So it doesn't change the element (A B C) to (C B A).

  Q: In the question about what (rev '(a b c d)) returns, we put a
  quote mark before the (a b c d) but not before the answer, (D C B
  A). Why? A: The phrase ``x evaluates to y'' treats x as a term to
  be evaluated and y as an object. (Rev '(a b c d)) is a term to be
  evaluated and denotes a call of the function rev on the value of
  the argument term '(a b c d). The value of that argument term is
  the object (a b c d). The value of the call of rev is the object (d
  c b a). If you have an object, obj, and you wish to create a term
  whose value is obj, then you put a quote mark in front of it, 'obj.

  Q: Can rev be applied to something other than a list? A: Yes, every
  ACL2 function can be applied to any object. ACL2 is an untyped
  programming language: every variable ranges over the entire
  universe of objects. In normal usage, rev is applied to lists but
  there is nothing about the syntax of the language that prevents it
  being applied to non-lists.

  Q: So what does (rev 23) evaluate to? A: Nil.

  Q: Why? A: Because (endp 23) is t, because endp is defined:

    (defun endp (x) (not (consp x)))

  Thus, if rev is applied to anything that is not a cons, it returns
  nil.

  Q: So what does (rev '(a b c . d)) evaluate to? A: (c b a). To
  explain why requires demonstrating that you know what (a b c . d)
  means. It is the object computed by evaluating:

    (cons 'a
          (cons 'b
                (cons 'c
                      'd))).

  That is, it is a list whose ``terminal marker'' is the atom D. Rev
  treats that list exactly as it treats the nil-terminated list of
  the same elements, (a b c), because (endp 'D) = (endp nil) = t.

  Q: What does (rev 1 2 3) evaluate to? A: That's a trick question. Rev
  takes one argument, not three. So (rev 1 2 3) is an ill-formed
  term.

  Q: What does (rev '(a b c . d . nil)) evaluate to? A: That is a trick
  question. There is no such object. In Lisp's ``dot notation'' every
  dot must be followed by a well-formed object and then a close
  parenthesis. Usually that ``well-formed object'' is an atom. If it
  is not an atom, i.e., if it is a cons, then the entire expression
  could have been written without that dot. For example, (a b c . (d
  e)) is an object, but it could be written (a b c d e).

  Q: Do (rev (rev x)) and x always evaluate to the same object? A: No.
  (Rev (rev 23)) evaluates to nil, not 23.

  Q: Do (rev (rev x)) and x always evaluate to the same object when x
  is a cons? A: No. (rev (rev '(a b c . d))) evaluates to (a b c),
  not (a b c . d).

  Q: When are (rev (rev x)) and x equal? A: When the terminal marker of
  x is nil.

  Q: Can you define a Lisp function that recognizes nil-terminated
  lists? A: Yes, but it is not necessary for the user to define that
  concept because Common Lisp provides such a function which is
  logically defined as follows:

    (defun true-listp (x)
      (if (consp x)
          (true-listp (cdr x))
          (equal x nil))).

  This can be paraphrased: (true-listp x) means that if x is a cons,
  its cdr is a true-listp and if x is not a cons, it must be nil.
  Thus, (true-listp '(a b c)) is t and (true-listp '(a b c . d)) is
  nil.

  Q: Can you write a Lisp formula that says ``If z is a nil-terminated
  list then reversing the result of reversing z is z''?

  A: Yes:

    (implies (true-listp z)
             (equal (rev (rev z)) z)).

  Q: Is this all there is to ACL2 programming? A: No! ACL2 provides
  many other features. For a full list of all the primitive functions
  in ACL2 see [programming] [{ICON}]. Some highlights for the
  beginner are mentioned below, but all of the links below ought to
  be tagged with the [{ICON}] sign.

  * [list]: build a nil-terminated list from the values of n terms,
  e.g., (list x (+ 1 x) (+ 2 x)) returns (3 4 5) if x is 3.

  * [list*]: build a non-nil terminated list of n objects from the
  values of n+1 terms, e.g., (list* x (+ 1 x) (+ 2 x) (* -1 x))
  returns the list (3 4 5 . -3) if x is 3.

  * [and], [or], [not], [implies], [iff]: The propositional
  connectives. And and or are allowed to take a varying number of
  arguments, e.g., (and p q r) is just an abbreviation for (and p
  (and q r)). In Lisp, and returns nil if any of its arguments
  evaluates to nil; otherwise it returns the value of the last
  argument! Thus, (and t t 3) returns 3! If you object to the idea
  that and is not Boolean, don't give it non-Boolean arguments!
  Similarly, or returns the value of the first argument that
  evaluates to non-nil, or nil if they all evaluate to nil. Both and
  and or can be thought of as ``lazy'' in that they don't always have
  to evaluate all their arguments. This is really accomplished by
  treating and and or as abbrevations for if nests.

  * [+], [*], [-], [/], [floor], [mod], [<], [<=], [>=], [>]: the Lisp
  elementary arithmetic operators. Both + and * allow varying numbers
  of arguments. All the arithmetic operators default non-numeric
  arguments to 0. If you don't like the idea that (+ 1 2 t) is 3,
  don't ask + to add t to something!

  * [natp], [integerp], [rationalp], [characterp], [stringp],
  [symbolp], [consp]: the recognizers for the primitive data types.
  The first three recognize subsets of the ACL2 numeric universe. The
  naturals are a subset of the integers, the integers are a subset of
  the rationals, and the rationals are a subset of the objects
  recognized by [ACL2-numberp], which also includes the
  [complex-rationalp]s. The other recognizers listed above recognize
  characters, strings, symbols, and conses.

  * [cond]: a convenient way to write a cascading nest of ifs, e.g.,

    (cond ((not (natp x)) 'non-natural)
          ((equal x 0) 'zero)
          ((evenp x) 'positive-even)
          (t 'positive-odd))

  abbreviates

    (if (not (natp x))
        'non-natural
        (if (equal x 0)
            'zero
            (if (evenp x)
                'positive-even
                'positive-odd))).

  * [case]: a convenient way to case split on the identity of an
  object.

    (case key
      (non-natural -1)
      (zero 0)
      ((positive-even positive-odd) 'positive-natural)
      (otherwise 'unknown))

  abbreviates

    (cond ((eql key 'non-natural) -1)
          ((eql key 'zero) 0)
          ((member key '(positive-even positive-odd))
           'positive-natural)
          (t 'unknown)).

  * user defined macros: using [defmacro] [{ICON}] you can introduce
  your own abbreviations. We recommend you not do this until you're
  good at list processing since macros are functions that build
  objects representing terms.

  * [mutual-recursion]: allows you to define mutually-recursive
  functions.

  * [mv] and [mv-let]: allow functions to return ``multiple-values''.
  In Lisp, such functions return vectors of values, the vectors are
  represented as lists of values, but the implementations are
  generally more efficient. For example, (mv x y z) returns a
  ``vector'' consisting of the values of x, y, and z.

    (mv-let (a b c)
            (foo x)
            (bar a b c x))

  evaluates (foo x), treats the result as a vector of three values,
  binds the variables a, b, and c to those three values, and
  evaluates and returns (bar a b c x).

  ACL2 also provides many other features, such as single-threaded
  objects which may be ``destructively modified'' (see [stobj]
  [{ICON}], including a very special single-threaded object that
  records the [state] [{ICON}] of the ACL2 system), file input and
  output (see [io] [{ICON}]), applicative arrays (see [arrays]
  [{ICON}]) and property lists (see [getprop] [{ICON}]) and other
  facilities necessary for it to be a practical programming language.
  However, we strongly recommend that as a new user you stay away
  from these features until you are good at proving theorems about
  elementary list processing!

  If this little drill made sense to you, you know enough of the
  programming language to get started. Use your browser's Back Button
  now to return to [introduction-to-the-theorem-prover].

  If you are uncomfortable with ACL2 programming, we recommend that you
  study
  {http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html
  |
  http://www.cs.utexas.edu/users/moore/publications/gentle-intro-to-acl2-programming.html}
  and
  {http://www.cs.utexas.edu/users/moore/publications/acl2-programming-exercises1.html
  |
  http://www.cs.utexas.edu/users/moore/publications/acl2-programming-exercises1.html}.

  However, we strongly recommend that you first invest in learning
  either the [Emacs] or Eclipse-based [ACL2-Sedan] program
  development environments, since it is foolish to try to learn how
  to program in a stand-alone read-eval-print loop!

  While getting started, many users find the Hyper-Card a handy index
  into the documentation for the ACL2 language:

  {http://www.cs.utexas.edu/users/moore/publications/hyper-card.html |
  http://www.cs.utexas.edu/users/moore/publications/hyper-card.html}

  Once you are comfortable with the ACL2 programming language, use your
  browser's Back Button to return to
  [introduction-to-the-theorem-prover].")
 (PROGRAMMING-WITH-STATE
  (STATE PROGRAMMING)
  "Programming using the von Neumannesque ACL2 [state] object

  This [documentation] section introduces some common techniques for
  programming using the ACL2 state object. A prerequisite is thus a
  basic understanding of that object; see [state]. We hope this
  section is useful, and we invite suggestions for improvements and
  additions.

  A supplement to this section is the ACL2 source code, which uses most
  (and probably all) of the techniques discussed here. That code is
  thus a source of many examples, which can serve as ``templates'' to
  guide one's own programming with state.

  Recall that ``ACL2'' stands for ``A Computational Logic for
  Applicative Common Lisp''. In particular, the language is
  applicative: there are no global variables or side effects. For
  many purposes this does not feel restrictive; for example, an ACL2
  user who is programming in raw Lisp may well be more comfortable
  coding a factorial function applicatively, using recursion, rather
  than using iteration with repeated assignment to the same variable.

  However, there are situations that call for reading or modifying the
  system state, such as performing input and output, signalling
  errors, saving information from one computation for use in a later
  one, or reading and updating system-level or environmental data.
  This section provides an introductory guide for writing functions
  that traffic in state. We emphasize that this guide is intended as
  an introduction; more complete documentation may often be found by
  following links to documentation of individual utilities, and
  again, more examples may be found by searching the ACL2 source code
  for uses of the functions and macros mentioned below. The rest of
  this section is organized as follows.

    ENABLING PROGRAMMING WITH STATE
    STATE GLOBALS AND THE ACL2 LOGICAL WORLD
    A REMARK ON GUARDS
    ERRORS AND ERROR TRIPLES
    SEQUENTIAL PROGRAMMING
    BINDING VARIABLES USING ERROR TRIPLES
    BINDING STATE GLOBAL VARIABLES
    INPUT AND OUTPUT
    TIMINGS
    ENVIRONMENT AND SYSTEM
    REMARKS ON EVENTS AND LD
    ADVANCED TOPICS

  ENABLING PROGRAMMING WITH STATE

  In order to submit a definition that takes [state] as a formal
  parameter, you must either declare state as a :[stobj] (see
  [xargs]) or first evaluate the following form at the top level:
  (set-state-ok t).

  Consider for example the following trivial definition.

    (defun foo (state)
      (mv 3 state))

  If you submit the above definition in a fresh ACL2 session, you will
  get this error message.

    ACL2 Error in ( DEFUN FOO ...):  The variable symbol STATE should not
    be used as a formal parameter of a defined function unless you are
    aware of its unusual status and the restrictions enforced on its use.
    See :DOC set-state-ok.

  If first you evaluate (set-state-ok t), you can admit the above
  definition. Alternatively, you can declare state as a :[stobj], as
  follows.

    (defun foo (state)
      (declare (xargs :stobjs state))
      (mv 3 state))

  A difference in the two approaches is that for the latter, a [guard]
  proof obligation is generated by default. See the section below
  entitled ``A remark on guards''.

  STATE GLOBALS AND THE ACL2 LOGICAL WORLD

  Recall (see [state]) that one of the fields of the ACL2 state object
  is the global-table, which logically is an alist associating
  symbols, known as ``state globals'' or ``state global variables'',
  with values. But no such alist actually exists in the
  implementation. Instead, ACL2 provides utilities for reading state
  globals --- see [@] and see [f-get-global] --- and utilities for
  writing them --- see [assign] and see [f-put-global]. The following
  log shows how they work; further explanation follows below.

    ACL2 !>(assign my-var (+ 3 4))
     7
    ACL2 !>(@ my-var)
    7
    ACL2 !>(f-put-global 'my-var (+ 1 5) state)
    
    ACL2 !>(f-get-global 'my-var state)
    6
    ACL2 !>

  Note that the first result is indented by one space. This is ACL2's
  way to indicate that the [assign] expression returned an ``error
  triple'' and that no error was signalled. We discuss error triples
  in more detail below; also see [error-triples].

  As illustrated above, the output signatures of the utilities for
  assigning to state globals differ from each other as follows:
  [f-put-global] returns state, but [assign] returns an error triple
  (mv nil val state) where val is the value assigned to the state
  global. The output signatures of the utilities for reading, @ and
  f-get-global, are identical. In fact, the form (f-get-global
  'my-var state) is the single-step macroexpansion of the form (@
  my-var), as can be confirmed using [trans1].

    ACL2 !>:trans1 (@ my-var)
     (F-GET-GLOBAL 'MY-VAR STATE)
    ACL2 !>

  State globals are useful for conveying persistent state information.
  Consider for example the utility [set-inhibit-output-lst]. The form
  (set-inhibit-output-lst '(prove proof-tree)) is approximately
  equivalent to (assign inhibit-output-lst '(prove proof-tree)). We
  say ``approximately'' because set-inhibit-output-lst additionally
  does some error checking to insure that all the tokens in the new
  list are legal. When deciding whether to print output, the ACL2
  system reads the value of state global variable inhibit-output-lst.

  A particularly useful state global is current-acl2-world, whose value
  is the ACL2 logical [world]. Because the ACL2 world is commonly
  accessed in applications that use the ACL2 state, ACL2 provides a
  function that returns the world: (w state) = (f-get-global
  'current-acl2-world state). While it is common to read the world,
  only functions set-w and set-w! are available to write the world,
  but these are untouchable and these should generally be avoided
  except by system implementors (pl[remove-untouchable]).

  A REMARK ON GUARDS

  For a function definition (see [defun]), if state is specified as a
  [stobj] as with the form (declare (xargs :stobjs state)), then the
  [guard] for that function is considered to include the condition
  (state-p state). By default, [guard] verification will then be
  performed.

  We can illustrate this point by modifying the example above as
  follows, to read the value of state global gag-mode.

    (defun foo (state)
      (declare (xargs :stobjs state))
      (f-get-global 'gag-mode state))

  If you try this in a fresh ACL2 session, the proof will fail with the
  following key checkpoint, which says that the state global gag-mode
  is bound in the global-table of the state.

    (IMPLIES (STATE-P1 STATE)
             (ASSOC-EQUAL 'GAG-MODE (NTH 2 STATE)))

  How can we deal with this proof failure? One way is simply to ignore
  the issue by defining the function in :[program] mode, as follows.

    (defun foo (state)
      (declare (xargs :stobjs state
                      :mode :program))
      (f-get-global 'gag-mode state))

  Perhaps a better way is to strengthen the guard to assert that the
  indicated state global is bound, as follows.

    (defun foo (state)
      (declare (xargs :guard (boundp-global 'gag-mode state)
                      :stobjs state))
      (f-get-global 'gag-mode state))

  Also see [guard-miscellany] for a discussion of how guards are
  generated from [xargs] fields of [declare] forms, specifically, for
  keywords :guard and :stobjs.

  ERRORS AND ERROR TRIPLES

  When evaluation returns three values, where the first two are
  ordinary objects and the third is the ACL2 state, the result may be
  called an ``error triple''. (Whether it is treated as an error
  triple depends on the programmer.) Error triples are often denoted
  (mv erp val state), and common ACL2 programming idioms treat erp as
  a flag indicating whether an error is being signalled and val as
  the ``value'' computed. Also see [error-triples].

  Even ACL2 users who are not programmers encounter error triples,
  because these are the values returned by evaluation of ACL2
  [events]. Consider the following log, where the only user input is
  the defun form following the [prompt].

    ACL2 !>(defun foo (x) x)

    Since FOO is non-recursive, its admission is trivial.  We observe that
    the type of FOO is described by the theorem (EQUAL (FOO X) X).

    Summary
    Form:  ( DEFUN FOO ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     FOO
    ACL2 !>

  All output above results from explicit calls of output functions,
  except for the next-to-last line, which contains FOO. Notice the
  single-space indentation preceding FOO. That space indicates that
  in fact, the value returned by evaluation of the defun form is the
  error triple whose error flag is nil and whose computed value is
  FOO. By default, ACL2 prints any error triple (mv nil val state) by
  inserting a space before printing val. You can change the default
  by setting state global [ld-post-eval-print] to t; notice how the
  same result is printed below.

    ACL2 !>:u
              0:x(EXIT-BOOT-STRAP-MODE)
    ACL2 !>(set-ld-post-eval-print t state)
    (NIL T )
    ACL2 !>(defun foo (x) x)

    Since FOO is non-recursive, its admission is trivial.  We observe that
    the type of FOO is described by the theorem (EQUAL (FOO X) X).

    Summary
    Form:  ( DEFUN FOO ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
    (NIL FOO )
    ACL2 !>

  The way error triples are printed by ld is controlled not only by
  state global ld-post-eval-print, but also by state global
  ld-error-triples. These are examples of ``ld specials''; see [ld],
  see [ld-post-eval-print], and see [ld-error-triples].

  It is so common to produce an error triple whose first (error flag)
  component is nil that ACL2 provides a handy macro, value, for this
  purpose. Thus, (value ) is equivalent to (mv nil
   state). Also see [value-triple] for a similar
  construct that is a legal event form.

  We turn now to the topic of errors. The macro [er] ``causes'' an
  error, but there are really two quite different kinds of errors:
  ``soft'' and ``hard'' errors. We use the term ``soft error'' to
  refer to a form that returns an error triple (mv erp val state) for
  which erp is non-nil. Soft errors do not interrupt the normal flow
  of evaluation: the error triple is returned to the caller which
  interprets the erp flag and val as directed by the programmer.
  Macros discussed below make it convenient to think about soft
  errors as short-circuiting the computation. Hard errors, on the
  other hand, do actually rip control away from the current
  evaluation and return it to the top-level loop. Logically speaking,
  expressions that cause hard errors return nil in the error case,
  but the nil is never seen in actual evaluation because control does
  not return to the caller.

  Note that the function [abort!], which you can invoke by typing
  :[a!], always returns to the top level. Note that ACL2 can prove
  that (abort!) returns nil but that this cannot be confirmed by
  computation.

    ACL2 !>(thm (equal (abort!) nil))

    Q.E.D.

    Summary
    Form:  ( THM ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL)
            (:TYPE-PRESCRIPTION ABORT!))
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

    Proof succeeded.
    ACL2 !>(equal (abort!) nil)
    Abort to ACL2 top-level
    ...
    ACL2 !>

  (What actually happens with a hard error, including non-default
  cases, is a bit subtle; most readers will probably want to skip
  this paragraph. The read-eval-print loop implemented by [ld] is
  implemented by a call of the ACL2 evaluator function, trans-eval,
  on each input form. If a hard error occurs during evaluation of an
  input form, its trans-eval call will return with a soft error.
  [Ld], in turn handles that soft error appropriately; see
  [ld-error-action].)

  The most common way to signal errors is the macro [er], which prints
  a formatted error message and returns a soft or hard error as
  specified by the call. Note however that soft errors are signalled
  using :[program] mode functions.

  Since the output signatures of soft and hard errors are different ---
  hard errors ``return'' a single value while soft errors return a
  triple --- mixing them in an expression requires embedding the hard
  error form in (an irrelevant) triple, as illustrated below. All
  branches of the expression must produce an error triple if any
  branch does.

    ACL2 !>(defun chk-find-or-abort (e x state)
             (declare (xargs :mode :program))
             (if (endp x)
                 (value                          ; Note use of VALUE!
                   (er hard 'chk-find-or-abort
                       \"Did not find ~x0!\"
                        e))
                 (if (not (integerp (car x)))
                     (er soft 'chk-find-or-abort
                         \"Non-integer, ~x0, in list!\"
                         (car x))
                     (if (eql (car x) e)
                         (value x)
                         (chk-find-or-abort e (cdr x) state)))))

    Summary
    Form:  ( DEFUN CHK-FIND-OR-ABORT ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     CHK-FIND-OR-ABORT
    ACL2 !>(chk-find-or-abort 3 '(1 2 3 4 5) state)
     (3 4 5)
    ACL2 !>(chk-find-or-abort 3 '(1 A 3 4 5) state)

    ACL2 Error in CHK-FIND-OR-ABORT:  Non-integer, A, in list!

    ACL2 !>(chk-find-or-abort 3 '(1 2 4 5) state)

    HARD ACL2 ERROR in CHK-FIND-OR-ABORT:  Did not find 3!
    ...
    ACL2 !>

  See [er] for further discussion of errors. For some other individual
  topics related to errors see [assert$], see [break-on-error], see
  [error1], see [hard-error], see [illegal], and see
  [ld-error-triples].

  In the next section we discuss soft errors further, in the context of
  programming.

  SEQUENTIAL PROGRAMMING

  This section describes handy ways to modify state in steps, using
  macros that implement a sequence of [let] or [mv-let] bindings. For
  example, suppose you want to assign the values 1 and 2 to two state
  globals one-var and two-var, respectively. Because of ACL2's
  syntactic restrictions on [state], it is not legal simply to write
  (f-put-global 'two-var 2 (f-put-global 'one-var 1 state)). However,
  [let] comes to the rescue as follows.

    (let ((state (f-put-global 'one-var 1 state)))
      (let ((state (f-put-global 'two-var 2 state)))
        state))

  It is so common to bind state successively in such a manner that ACL2
  provides a macro, [pprogn], for this purpose. Thus, an equivalent
  solution to the problem above is

    (pprogn (f-put-global 'one-var 1 state)
            (f-put-global 'two-var 2 state)
            state)

  or, more simply, as follows.

    (pprogn (f-put-global 'one-var 1 state)
            (f-put-global 'two-var 2 state))

  See [pprogn]. Note that the last form is allowed to return multiple
  values; the only requirement on the last form is that its value
  include state.

  It is also common to update the state using a sequence of forms such
  that each returns an error triple, where the intention is for
  evaluation to short-circuit immediately if a soft error is
  encountered. Suppose  and  are expressions that
  return error triples, where the state components of the error
  triples might be updated, and one wishes to evaluate  and
  then , returning the (multiple) values returned by 
  unless the error triple returned by  is a soft error, in
  which case that error triple is returned. One can of course do so
  as follows.

    (mv-let (erp val state)
            
            (cond (erp (mv erp val state))
                  (t )))

  But ACL2 provides a handy macro, [er-progn], for this purpose. The
  following code is equivalent to the code just above.

    (er-progn  )

  See [er-progn] for more details. Note that unlike [pprogn], the
  return [signature] for the last expression must be the same as that
  of the others: an error triple.

  Let's consider how to use pprogn and er-progn together. In the
  following example f1 and f2 both return state, while each of g1 and
  g2 returns an error triple. The following code modifies state by
  executing these in the order f1, g1, f2, and finally g2, returning
  (mv nil val state) where val is the value component of the error
  triple returned by g2 --- except we return a soft error if g1 or g2
  returns a soft error.

    (pprogn (f1 x state)
            (er-progn (g1 x state)
                      (pprogn (f2 x state)
                              (g2 x state))))

  Finally, consider the [events] [progn] and [progn!]. These have
  similar behavior to that of [er-progn]. However, [progn] and
  [progn!] may only be used in event contexts, for example at the top
  level or immediately underneath a call of [encapsulate] or [progn],
  while [er-progn] has no such restriction. So when writing code, use
  er-progn rather than [progn] or [progn!]. In particular, the body
  of a [defun] must not have any calls of progn (or of progn!
  either), and the same restriction holds for any code to be
  executed, such as the body of a [make-event] form.

  BINDING VARIABLES USING ERROR TRIPLES

  In this section we discuss the macro er-let*, which is a variant of
  the special form, [let*], that is useful when programming with
  state.

  The macro er-let* is useful when binding variables to the value
  components of error triples. It is actually quite similar to
  er-progn, described above, except that er-let* binds variables.
  First consider the following example.

    (er-let* ((x1 (f1 state))
              (x2 (f2 x1 state)))
      (value (cons x1 x2)))

  The code just above is essentially equivalent to writing the
  following.

    (mv-let (erp x1 state)
            (f1 state)
            (cond (erp (mv erp x1 state))
                  (t (mv-let (erp x2 state)
                             (f2 x1 state)
                             (cond (erp (mv erp x2 state))
                                   (t (value (cons x1 x2))))))))

  As suggested by the example above, er-let* has the same syntax as
  let*, except that declarations are not supported. (But note that
  ignore declarations are not needed; all variables that are bound
  are also used, at least in the error case. Consider replacing (cons
  x1 x2) by nil in the example displayed immediately above, and note
  that x1 and x2 are still used.) However, unlike let*, er-let*
  requires that for each binding (var expr), the expression expr must
  evaluate to an error triple and, moreover, it requires that the
  second argument (the ``body'') of er-let* must evaluate to an error
  triple. If one of the variable expressions (e.g., the f1 and f2
  calls above) signals an error, its error triple is returned as the
  value of the er-let*.

  Of course, soft errors can be ``caught'' by using [mv-let] instead of
  er-let* and simply ignoring the error flag or, more generally, by
  returning a non-erroneous error triple even if the error flag was
  on.

  BINDING STATE GLOBAL VARIABLES

  In this section we introduce a utility, [state-global-let*], that is
  an analogue of let* for state global variables. Consider the
  following example.

    (state-global-let*
     ((inhibit-output-lst (add-to-set-eq 'summary (@ inhibit-output-lst))))
     (thm (equal x x)))

  This form binds state global variable inhibit-output-lst to the
  result of adding the symbol, summary, to the current value of that
  state global. Thus (see [set-inhibit-output-lst]), the usual
  summary is not printed when evaluating this call of [thm].

  See [state-global-let*] for more complete [documentation].

  INPUT AND OUTPUT

  In ACL2, most input and output involves the ACL2 state. See [io].

  TIMINGS

  For how to obtain the time elapsed since the start of the ACL2
  session, see [read-run-time].

  For a utility for saving times into the ACL2 state and for printing
  those saved times, see the community book misc/save-time.lisp.

  To time an evaluation (though this really isn't about state), see
  [time$].

  ENVIRONMENT AND SYSTEM

  Next, we mention briefly some ways in which ACL2 interacts with its
  environment using the ACL2 state.

  For how to read and write environment variables, see [getenv$] and
  see [setenv$].

  For how to run a command in the host operating system, see [sys-call]
  and [sys-call+].

  REMARKS ON EVENTS AND LD

  In general, undefined or surprising behavior may occur when using
  ACL2 [events] or calling [ld] in your programs. In some cases ACL2
  enforces restrictions against these uses. We strongly discourage
  using [ld] in programs, as it has been designed to be called only
  at the top level of a read-eval-print loop. However, you may wish
  to read or write [ld] specials in your programs; see [ld].

  There is also a restriction on contexts in which [make-event] may be
  called: it may only be called in a context where an event is
  expected, such as the top level, in a book, or as an argument of
  [encapsulate] or [progn]. The reason is that ACL2 does very subtle
  and careful tracking of [make-event] expansions; and it is only
  able to do this in event contexts, where it is able to carry out
  such tracking accurately.

  ADVANCED TOPICS

  ACL2 provides the function trans-eval to evaluate an arbitrary form
  (after translating it to a [term], i.e., into internal form). For
  more information, we refer to reader to comments in the definition
  of trans-eval in the ACL2 source code. There are also many examples
  of its use in the ACL2 sources.

  For a function that provides the true absolute filename, with soft
  links resolved, see [canonical-pathname].

  For a function that returns a check-sum on the characters in a
  channel, see [check-sum].

  To obtain a random number, see [random$].

  If you are programming in raw-mode (see [set-raw-mode]) or in raw
  Lisp, use the variable *the-live-state* in place of the variable
  state.

  We invite suggestions for additional advanced topics.


Subtopics

  [@]
      Get the value of a global variable in [state]

  [Assign]
      Assign to a global variable in [state]

  [Canonical-pathname]
      The true absolute filename, with soft links resolved

  [Cbd]
      Connected book directory string

  [Er-progn]
      Perform a sequence of state-changing ``error triples''

  [Error-triples]
      A common ACL2 programming idiom

  [F-get-global]
      Get the value of a global variable in [state]

  [F-put-global]
      Assign to a global variable in [state]

  [Getenv$]
      Read an environment variable

  [Last-prover-steps]
      The number of prover steps most recently taken

  [Oracle-apply]
      Call a function argument on the given list of arguments

  [Oracle-apply-raw]
      Call a function argument on the given list of arguments, no
      restrictions

  [Oracle-funcall]
      Call a function argument on the remaining arguments

  [Pprogn]
      Evaluate a sequence of forms that return [state]

  [Read-ACL2-oracle]
      Pop the oracle field of the state

  [Read-run-time]
      Read elapsed runtime

  [Setenv$]
      Set an environment variable

  [State-global-let*]
      Bind [state] global variables

  [With-live-state]
      Allow a reference to state in raw Lisp")
 (PROMPT
  (LD)
  "The prompt printed by [ld]

  The prompt printed by ACL2 conveys information about various
  ``modes.'' See [default-print-prompt] and see [ld-prompt] for
  details.

  The prompt during raw Lisp breaks is, with most Common Lisp
  implementations, adjusted by ACL2 to include the string \"[RAW
  LISP\"], in order to reminder users not to submit ACL2 forms there;
  see [breaks]. For Lisps that seem to use the same code for printing
  prompts at the top-level as in [breaks], the top-level prompt is
  similarly adjusted. For Lisps with the above prompt adjustment, The
  following forms may be executed in raw Lisp (i.e., after typing
  :q).

    (install-new-raw-prompt) ; install prompt with [RAW LISP] as described above
    (install-old-raw-prompt) ; revert to original prompt from host Common Lisp")
 (PROOF-CHECKER
  (ACL2 DEBUGGING)
  "An interactive tool for controlling ACL2's proof processes.

  Call this up with (verify ...).

  This is an interactive system for checking ACL2 theorems, or at least
  exploring their proofs. One enters it using the VERIFY command (see
  [verify]), and then invokes commands at the resulting prompt to
  operate on a stack of goals, starting with the single goal that was
  supplied to VERIFY. The final command (or ``instruction'') can be
  an exit command, which can print out a [defthm] event if the goal
  stack is empty; see [proof-checker-commands], in particular the
  exit command. That resulting defthm event includes an
  :[instructions] parameter, which directs replay of the
  proof-checker commands (for example during certification of a book
  containing that event; see [books]).

  If you exit the proof-checker interactive loop, you may re-enter that
  session at the same point using the command (verify), i.e., with no
  arguments. The commands save and retrieve may be invoked to manage
  more than one session.

  The proof-checker can be invoked on a specific subgoal, and the
  resulting :instructions can be given as a hint to the theorem
  prover for that subgoal. See [instructions].

  A tutorial is available on the world-wide web:
  {http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html |
  http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html}.
  The tutorial illustrates more than just the proof-checker. The
  portion relevant to the proof-checker may be accessed directly:
  {http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html#slide29
  |
  http://www.cs.utexas.edu/users/kaufmann/tutorial/rev3.html#slide29}

  See [set-evisc-tuple] for how to arrange that output is printed in
  abbreviated form. In general, the proof-checker uses the :TERM
  [evisc-tuple] described in that documentation.

  Individual proof-checker commands are documented in subsection
  [proof-checker-commands].


Subtopics

  [Define-pc-help]
      Define a macro command whose purpose is to print something

  [Define-pc-macro]
      Define a proof-checker macro command

  [Define-pc-meta]
      Define a proof-checker meta command

  [Dive-into-macros-table]
      Right-associated function information for the [proof-checker]

  [Instructions]
      Instructions to the proof checker

  [Macro-command]
      Compound command for the proof-checker

  [Proof-checker-commands]
      List of commands for the proof-checker

  [Retrieve]
      Re-enter a (specified) [proof-checker] state

  [Toggle-pc-macro]
      Change an ordinary macro command to an atomic macro, or vice-versa

  [Unsave]
      Remove a [proof-checker] state

  [Verify]
      Enter the interactive proof checker")
 (PROOF-CHECKER-COMMANDS
  (PROOF-CHECKER)
  "List of commands for the proof-checker

  This documentation section contains documentation for individual
  commands that can be given inside the interactive [proof-checker]
  loop that is entered using [verify].


Subtopics

  [ACL2-pc::=]
      (atomic macro) attempt an equality (or equivalence) substitution

  [ACL2-pc::ACL2-wrap]
      (macro) same as (lisp x)

  [ACL2-pc::add-abbreviation]
      (primitive) add an abbreviation

  [ACL2-pc::al]
      (macro) same as apply-linear

  [ACL2-pc::apply-linear]
      (primitive) apply a linear rule

  [ACL2-pc::bash]
      (atomic macro) call the ACL2 theorem prover's simplifier

  [ACL2-pc::bdd]
      (atomic macro) prove the current goal using bdds

  [ACL2-pc::bk]
      (atomic macro) move backward one argument in the enclosing term

  [ACL2-pc::bookmark]
      (macro) insert matching ``bookends'' comments

  [ACL2-pc::casesplit]
      (primitive) split into two cases

  [ACL2-pc::cg]
      (macro) change to another goal.

  [ACL2-pc::change-goal]
      (primitive) change to another goal.

  [ACL2-pc::cl-proc]
      (macro) same as clause-processor

  [ACL2-pc::claim]
      (atomic macro) add a new hypothesis

  [ACL2-pc::clause-processor]
      (atomic macro) use a clause-processor

  [ACL2-pc::comm]
      (macro) display instructions from the current interactive session

  [ACL2-pc::commands]
      (macro) display instructions from the current interactive session

  [ACL2-pc::comment]
      (primitive) insert a comment

  [ACL2-pc::contradict]
      (macro) same as contrapose

  [ACL2-pc::contrapose]
      (primitive) switch a hypothesis with the conclusion, negating both

  [ACL2-pc::demote]
      (primitive) move top-level hypotheses to the conclusion

  [ACL2-pc::dive]
      (primitive) move to the indicated subterm

  [ACL2-pc::do-all]
      (macro) run the given instructions

  [ACL2-pc::do-all-no-prompt]
      (macro) run the given instructions, halting once there is a
      ``failure''

  [ACL2-pc::do-strict]
      (macro) run the given instructions, halting once there is a
      ``failure''

  [ACL2-pc::doc]
      (macro) access documentation inside the proof-checker

  [ACL2-pc::drop]
      (primitive) drop top-level hypotheses

  [ACL2-pc::dv]
      (atomic macro) move to the indicated subterm

  [ACL2-pc::elim]
      (atomic macro) call the ACL2 theorem prover's elimination process

  [ACL2-pc::equiv]
      (primitive) attempt an equality (or congruence-based) substitution

  [ACL2-pc::ex]
      (macro) exit after possibly saving the state

  [ACL2-pc::exit]
      (meta) exit the interactive proof-checker

  [ACL2-pc::expand]
      (primitive) expand the current function call without simplification

  [ACL2-pc::fail]
      (macro) cause a failure

  [ACL2-pc::finish]
      (macro) require completion of instructions; save error if inside
      :[hints]

  [ACL2-pc::forwardchain]
      (atomic macro) forward chain from an implication in the hyps

  [ACL2-pc::free]
      (atomic macro) create a ``free variable''

  [ACL2-pc::geneqv]
      (macro) show the generated equivalence relation maintained at the
      current subterm

  [ACL2-pc::generalize]
      (primitive) perform a generalization

  [ACL2-pc::goals]
      (macro) list the names of goals on the stack

  [ACL2-pc::help]
      (macro) proof-checker help facility

  [ACL2-pc::hyps]
      (macro) print the hypotheses

  [ACL2-pc::illegal]
      (macro) illegal instruction

  [ACL2-pc::in-theory]
      (primitive) set the current proof-checker theory

  [ACL2-pc::induct]
      (atomic macro) generate subgoals using induction

  [ACL2-pc::lemmas-used]
      (macro) print the runes (definitions, lemmas, ...) used

  [ACL2-pc::lisp]
      (meta) evaluate the given form in Lisp

  [ACL2-pc::negate]
      (macro) run the given instructions, and ``succeed'' if and only if
      they ``fail''

  [ACL2-pc::nil]
      (macro) used for interpreting control-d

  [ACL2-pc::noise]
      (meta) run instructions with output

  [ACL2-pc::nx]
      (atomic macro) move forward one argument in the enclosing term

  [ACL2-pc::orelse]
      (macro) run the first instruction; if (and only if) it ``fails'',
      run the second

  [ACL2-pc::p]
      (macro) prettyprint the current term

  [ACL2-pc::p-top]
      (macro) prettyprint the conclusion, highlighting the current term

  [ACL2-pc::pl]
      (macro) print the rules for a given name

  [ACL2-pc::pp]
      (macro) prettyprint the current term

  [ACL2-pc::pr]
      (macro) print the rules for a given name

  [ACL2-pc::print]
      (macro) print the result of evaluating the given form

  [ACL2-pc::print-all-concs]
      (macro) print all the conclusions of (as yet unproved) goals

  [ACL2-pc::print-all-goals]
      (macro) print all the (as yet unproved) goals

  [ACL2-pc::print-main]
      (macro) print the original goal

  [ACL2-pc::pro]
      (atomic macro) repeatedly apply promote

  [ACL2-pc::promote]
      (primitive) move antecedents of conclusion's implies term to
      top-level hypotheses

  [ACL2-pc::protect]
      (macro) run the given instructions, reverting to existing state upon
      failure

  [ACL2-pc::prove]
      (primitive) call the ACL2 theorem prover to prove the current goal

  [ACL2-pc::pso]
      (macro) print the most recent proof attempt from inside the
      proof-checker

  [ACL2-pc::pso!]
      (macro) print the most recent proof attempt from inside the
      proof-checker

  [ACL2-pc::psog]
      (macro) print the most recent proof attempt from inside the
      proof-checker

  [ACL2-pc::put]
      (macro) substitute for a ``free variable''

  [ACL2-pc::quiet]
      (meta) run instructions without output

  [ACL2-pc::r]
      (macro) same as rewrite

  [ACL2-pc::reduce]
      (atomic macro) call the ACL2 theorem prover's simplifier

  [ACL2-pc::reduce-by-induction]
      (macro) call the ACL2 prover without induction, after going into
      induction

  [ACL2-pc::remove-abbreviations]
      (primitive) remove one or more abbreviations

  [ACL2-pc::repeat]
      (macro) repeat the given instruction until it ``fails''

  [ACL2-pc::repeat-rec]
      (macro) auxiliary to repeat

  [ACL2-pc::replay]
      (macro) replay one or more instructions

  [ACL2-pc::restore]
      (meta) remove the effect of an UNDO command

  [ACL2-pc::retain]
      (atomic macro) drop all but the indicated top-level hypotheses

  [ACL2-pc::retrieve]
      (macro) re-enter the proof-checker

  [ACL2-pc::rewrite]
      (primitive) apply a rewrite rule

  [ACL2-pc::run-instr-on-goal]
      (macro) auxiliary to THEN

  [ACL2-pc::run-instr-on-new-goals]
      (macro) auxiliary to then

  [ACL2-pc::runes]
      (macro) print the runes (definitions, lemmas, ...) used

  [ACL2-pc::s]
      (primitive) simplify the current subterm

  [ACL2-pc::s-prop]
      (atomic macro) simplify propositionally

  [ACL2-pc::save]
      (macro) save the proof-checker state (state-stack)

  [ACL2-pc::sequence]
      (meta) run the given list of instructions according to a multitude
      of options

  [ACL2-pc::show-abbreviations]
      (macro) display the current abbreviations

  [ACL2-pc::show-linears]
      (macro) display the applicable [linear] rules

  [ACL2-pc::show-rewrites]
      (macro) display the applicable [rewrite] rules

  [ACL2-pc::show-type-prescriptions]
      (macro) display the applicable [type-prescription] rules

  [ACL2-pc::skip]
      (macro) ``succeed'' without doing anything

  [ACL2-pc::sl]
      (atomic macro) simplify with lemmas

  [ACL2-pc::sls]
      (macro) same as SHOW-LINEARS

  [ACL2-pc::split]
      (atomic macro) split the current goal into cases

  [ACL2-pc::sr]
      (macro) same as SHOW-REWRITES

  [ACL2-pc::st]
      (macro) same as SHOW-TYPE-PRESCRIPTIONS

  [ACL2-pc::succeed]
      (macro) run the given instructions, and ``succeed''

  [ACL2-pc::th]
      (macro) print the top-level hypotheses and the current subterm

  [ACL2-pc::then]
      (macro) apply one instruction to current goal and another to new
      subgoals

  [ACL2-pc::top]
      (atomic macro) move to the top of the goal

  [ACL2-pc::type-alist]
      (macro) display the [type-alist] from the current context

  [ACL2-pc::undo]
      (meta) undo some instructions

  [ACL2-pc::unsave]
      (macro) remove a proof-checker state

  [ACL2-pc::up]
      (primitive) move to the parent (or some ancestor) of the current
      subterm

  [ACL2-pc::use]
      (atomic macro) use a lemma instance

  [ACL2-pc::wrap]
      (atomic macro) execute the indicated instructions and combine all
      the new goals

  [ACL2-pc::wrap-induct]
      (atomic macro) same as induct, but create a single goal

  [ACL2-pc::wrap1]
      (primitive) combine goals into a single goal

  [ACL2-pc::x]
      (atomic macro) expand and (maybe) simplify function call at the
      current subterm

  [ACL2-pc::x-dumb]
      (atomic macro) expand function call at the current subterm, without
      simplifying")
 (PROOF-OF-WELL-FOUNDEDNESS
  (ORDINALS)
  "A proof that [o<] is well-founded on [o-p]s

  The soundness of ACL2 rests in part on the well-foundedness of [o<]
  on [o-p]s. This can be taken as obvious if one is willing to grant
  that those concepts are simply encodings of the standard
  mathematical notions of the ordinals below epsilon-0 and its
  natural ordering relation. But it is possible to prove that [o<] is
  well-founded on [o-p]s without having to assert any connection to
  the ordinals and that is what we do here. The community book
  books/ordinals/proof-of-well-foundedness carries out the proof
  outlined below in ACL2, using only that the natural numbers are
  well-founded.

  Before outlining the above mentioned proof, we note that in the
  analogous documentation page of ACL2 Version_2.7, there is a proof
  of the well-foundedness of e0-ord-< on e0-ordinalps, the less-than
  relation and recognizer for the old ordinals (that is, for the
  ordinals appearing in ACL2 up through that version). Manolios and
  Vroon have given a proof in ACL2 Version_2.7 that the current
  ordinals (based on [o<] and [o-p]) are order-isomorphic to the old
  ordinals (based on e0-ord-< and e0-ordinalp). Their proof
  establishes that switching from the old ordinals to the current
  ordinals preserves the soundness of ACL2. For details see their
  paper:

    Manolios, Panagiotis & Vroon, Daron.
    Ordinal arithmetic in ACL2.
    Kaufmann, Matt, & Moore, J Strother (eds).
    Fourth International Workshop on the ACL2 Theorem
    Prover and Its Applications (ACL2-2003),
    July, 2003.
    See {http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/ | http://www.cs.utexas.edu/users/moore/acl2/workshop-2003/}.

  We now give an outline of the above mentioned proof of
  well-foundedness. We first observe three facts about [o<] on
  ordinals that have been proved by ACL2 using only structural
  induction on lists. These theorems can be proved by hand.

    (defthm transitivity-of-o<
      (implies (and (o< x y)
                    (o< y z))
               (o< x z))
      :rule-classes nil)

    (defthm non-circularity-of-o<
      (implies (o< x y)
               (not (o< y x)))
      :rule-classes nil)

    (defthm trichotomy-of-o<
      (implies (and (o-p x)
                    (o-p y))
               (or (equal x y)
                   (o< x y)
                   (o< y x)))
      :rule-classes nil)

  These three properties establish that [o<] orders the [o-p]s. To put
  such a statement in the most standard mathematical nomenclature, we
  can define the macro:

    (defmacro o<= (x y)
      `(not (o< ,y ,x)))

  and then establish that o<= is a relation that is a simple, complete
  (i.e., total) order on ordinals by the following three lemmas,
  which have been proved:

    (defthm antisymmetry-of-o<=
      (implies (and (o-p x)
                    (o-p y)
                    (o<= x y)
                    (o<= y x))
               (equal x y))
      :rule-classes nil
      :hints ((\"Goal\" :use non-circularity-of-o<)))

    (defthm transitivity-of-o<=
      (implies (and (o-p x)
                    (o-p y)
                    (o<= x y)
                    (o<= y z))
               (o<= x z))
      :rule-classes nil
      :hints ((\"Goal\" :use transitivity-of-o<)))

    (defthm trichotomy-of-o<=
      (implies (and (o-p x)
                    (o-p y))
               (or (o<= x y)
                   (o<= y x)))
      :rule-classes nil
      :hints ((\"Goal\" :use trichotomy-of-o<)))

  Crucially important to the proof of the well-foundedness of [o<] on
  [o-p]s is the concept of ordinal-depth, abbreviated od:

    (defun od (l)
      (if (o-finp l)
          0
        (1+ (od (o-first-expt l)))))

  If the od of an [o-p] x is smaller than that of an [o-p] y, then x is
  [o<] y:

    (defun od-1 (x y)
      (if (o-finp x)
          (list x y)
        (od-1 (o-first-expt x) (o-first-expt y))))

    (defthm od-implies-ordlessp
      (implies (and (o-p x)
                    (< (od x) (od y)))
               (o< x y))
      :hints ((\"Goal\"
               :induct (od-1 x y))))

  Remark. A consequence of this lemma is the fact that if s = s(1),
  s(2), ... is an infinite, [o<] descending sequence of [o-p]s, then
  od(s(1)), od(s(2)), ... is a ``weakly'' descending sequence of
  non-negative integers: od(s(i)) is greater than or equal to
  od(s(i+1)).

  Lemma Main. For each non-negative integer n, [o<] well-orders the set
  of [o-p]s with od less than or equal to n .

    Base Case.  n = 0.  The o-ps with 0 od are the non-negative
    integers.  On the non-negative integers, o< is the same as <.

    Induction Step.  n > 0.  We assume that o< well-orders the
    o-ps with od less than n.

      If o< does not well-order the o-ps with od less than or equal to n,
      consider, D, the set of infinite, o< descending sequences of o-ps of od
      less than or equal to n.  The first element of a sequence in D has od n.
      Therefore, the o-first-expt of the first element of a sequence in D has od
      n-1.  Since o<, by IH, well-orders the o-ps with od less than n, the set
      of o-first-expts of first elements of the sequences in D has a minimal
      element, which we denote by B and which has od of n-1.

      Let k be the minimum integer such that for some infinite, o< descending
      sequence s of o-ps with od less than or equal to n, the first element of s
      has an o-first-expt of B and an o-first-coeff of k.  Notice that k is
      positive.

      Having fixed B and k, let s = s(1), s(2), ... be an infinite, o<
      descending sequence of o-ps with od less than or equal to n such that s(1)
      has a o-first-expt of B and an o-first-coeff of k.

      We show that each s(i) has a o-first-expt of B and an o-first-coeff of
      k. For suppose that s(j) is the first member of s either with o-first-expt
      B and o-first-coeff m (m neq k) or with o-first-expt B' and o-first-coeff
      B' (B' neq B). If (o-first-expt s(j)) = B', then B' has od n-1 (otherwise,
      by IH, s would not be infinite) and B' is o< B, contradicting the
      minimality of B. If 0 < m < k, then the fact that the sequence beginning
      at s(j) is infinitely descending contradicts the minimality of k. If m >
      k, then s(j) is greater than its predecessor; but this contradicts the
      fact that s is descending.

      Thus, by the definition of o<, for s to be a decreasing sequence of o-ps,
      (o-rst s(1)), (o-rst s(2)), ... must be a decreasing sequence. We end by
      showing this cannot be the case. Let t = t(1), t(2), ... be an infinite
      sequence of o-ps such that t(i) = (o-rst s(i)). Then t is infinitely
      descending. Furthermore, t(1) begins with an o-p B' that is o< B. Since t
      is in D, t(1) has od n, therefore, B' has od n-1. But this contradicts the
      minimality of B. Q.E.D.

  Theorem. [o<] well-orders the [o-p]s. Proof. Every infinite, o<
  descending sequence of [o-p]s has the property that each member has
  od less than or equal to the od, n, of the first member of the
  sequence. This contradicts Lemma Main. Q.E.D.")
 (PROOF-SUPPORTERS-ALIST (POINTERS)
                         "See [dead-events].")
 (PROOF-TREE
  (DEBUGGING)
  "Proof tree displays

  A view of ACL2 proofs may be obtained by way of ``proof tree
  displays,'' which appear in proof output (see [proofs-co]) when
  proof-tree output is enabled (see below) When ACL2 starts a proof
  and proof-tree output is enabled, the proof output begins with the
  following string.

    << Starting proof tree logging >>

  Then for each goal encountered during the proof, a corresponding
  proof tree display (as described below) is printed into the proof
  output: first the characters in the constant string
  *proof-tree-start-delimiter* are printed, then the proof tree
  display, and finally the characters in the constant string
  *proof-tree-end-delimiter*.

  External tools may present proof tree displays in a separate window.
  In particular, a tool distributed with the ACL2 community books
  customizes the emacs environment to provide window-based proof tree
  displays together with commands for traversing the proof
  transcript; see the discussion of ``ACL2 proof-tree support'' in
  file emacs/emacs-acl2.el distributed with ACL2.

  The command :start-proof-tree enables proof-tree output, while
  :stop-proof-tree disables proof-tree output; see [start-proof-tree]
  and see [stop-proof-tree].

  Here is an example of a proof tree display, with comments. Lines
  marked with ``c'' are considered ``checkpoints,'' i.e., goals whose
  scrutiny may be of particular value.

    ( DEFTHM PLUS-TREE-DEL ...)    ;currently proving PLUS-TREE-DEL
       1 Goal preprocess   ;\"Goal\" creates 1 subgoal by preprocessing
       2 |  Goal' simp     ;\"Goal'\" creates 2 subgoals by simplification
    c  0 |  |  Subgoal 2 PUSH *1   ;\"Subgoal 2\" pushes \"*1\" for INDUCT
    ++++++++++++++++++++++++++++++ ;first pass thru waterfall completed
    c  6 *1 INDUCT                 ;Proof by induction of \"*1\" has
         |  <5 more subgoals>      ; created 6 top-level subgoals.  At
                                   ; this point, one of those 6 has been
                                   ; proved, and 5 remain to be proved.
                                   ; We are currently working on the
                                   ; first of those 5 remaining goals.

  See [proof-tree-examples] for many examples that contain proof tree
  displays. But first, we summarize the kinds of lines that may
  appear in a proof tree display. The simplest form of a proof tree
  display is a header showing the current event, followed by list of
  lines, each having one of the following forms.

    n   ...

  Says that the indicated goal created n subgoals using the indicated
  process. Here ``...'' refers to possible additional information.

    c   n   ...

  As above, but calls attention to the fact that this goal is a
  ``checkpoint'' in the sense that it may be of particular interest.
  Some displays may overwrite ``c'' with ``>'' to indicate the
  current checkpoint being shown in the proof transcript.

    |   ...
    |  |  

  Indicates that the goal just above this line, which is pointed to by
  the rightmost vertical bar (``|''), has k subgoals, none of which
  have yet been processed.

    |   ...
    |  |  

  As above, except that some subgoals have already been processed.

    ++++++++++++++++++++++++++++++

  Separates successive passes through the ``waterfall''. Thus, this
  ``fencepost'' mark indicates the start of a new proof by induction
  or of a new forcing round.

  See [proof-tree-examples] for detailed examples. See
  [checkpoint-forced-goals] to learn how to mark goals as checkpoints
  that [force] the creation of goals in forcing rounds. Finally, see
  [proof-tree-details] for some points not covered elsewhere.


Subtopics

  [Checkpoint-forced-goals]
      Cause forcing goals to be checkpointed in proof trees

  [Proof-tree-details]
      Proof tree details not covered elsewhere

  [Proof-tree-examples]
      Proof tree example

  [Start-proof-tree]
      Start displaying proof trees during proofs

  [Stop-proof-tree]
      Stop displaying proof trees during proofs")
 (PROOF-TREE-DETAILS
  (PROOF-TREE)
  "Proof tree details not covered elsewhere

  See [proof-tree] for an introduction to proof trees, and for a list
  of related topics. Here we present some details not covered
  elsewhere.

  1. When proof tree display is enabled (because the command
  :[stop-proof-tree] has not been executed, or has been superseded by
  a later :[start-proof-tree] command), then time summaries will
  include the time for proof tree display. This time includes the
  time spent computing with proof trees, such as the pruning process
  described briefly above. Even when proof trees are not displayed,
  such as when their display is turned off in the middle of a proof,
  this time will be printed if it is not 0.

  2. When a goal is given a :bye in a proof (see [hints]), it is
  treated for the purpose of proof tree display just as though it had
  been proved.

  3. Several [state] global variables affect proof tree display. (@
  proof-tree-indent) is initially the string \"| \": it is the string
  that is laid down the appropriate number of times to effect
  indentation. (@ proof-tree-buffer-width) is initially the value of
  (fmt-soft-right-margin state), and is used to prevent printing of
  the annotation ``([force]d ...)'' in any greater column than this
  value. However, (assign proof-tree-buffer-width nil) to avoid any
  such suppression. Finally, (@ checkpoint-processors) is a list of
  processors from the constant list *preprocess-clause-ledge*,
  together with :induct. You may remove elements of (@
  checkpoint-processors) to limit which processes are considered
  checkpoints, but note that this can affect what is printed by
  gag-mode (see [set-gag-mode]).

  4. When :[otf-flg] is not set to t in a proof, and the prover then
  decides to revert to the original goal and prove it by induction,
  the proof tree display will reflect this fact as shown here:

    c  0 |  |  Subgoal 2 PUSH (reverting)

  5. The usual [failure] message is printed as part of the prooftree
  display when a proof has failed.")
 (PROOF-TREE-EXAMPLES
  (PROOF-TREE)
  "Proof tree example

  See [proof-tree] for an introduction to proof trees, and for a list
  of related topics. Here we present a detailed example followed by a
  shorter example that illustrates proof by induction.

  Consider the [guard] proof for the definition of a function
  cancel_equal_plus; the body of this definition is of no importance
  here. The first proof tree display is:

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
         |  <18 subgoals>

  This is to be read as follows.

      At this stage of the proof we have encountered the top-level goal,
      named \"Goal\", which generated 18 subgoals using the
      ``preprocess'' process. We have not yet begun to work on those
      subgoals.

  The corresponding message from the ordinary prover output is:

      By case analysis we reduce the conjecture to the following 18
      conjectures.

  Note that the field just before the name of the goal (\"Goal\"), which
  here contains the number 18, indicates the number of cases
  (children) created by the goal using the indicated process. This
  number will remain unchanged as long as this goal is displayed.

  The next proof tree display is:

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
       1 |  Subgoal 18 simp
         |  |  <1 subgoal>
         |  <17 more subgoals>

  which indicates that at this point, the prover has used the
  simplification (``simp'') process on Subgoal 18 to create one
  subgoal (``<1 subgoal>''). The vertical bar (``|'') below ``Subgoal
  18'', accompanied by the line below it, signifies that there are 17
  siblings of Subgoal 18 that remain to be processed.

  The next proof tree displayed is:

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
       1 |  Subgoal 18 simp
    c  2 |  |  Subgoal 18' ELIM
         |  |  |  <2 subgoals>
         |  <17 more subgoals>

  Let us focus on the fourth line of this display:

    c  2 |  |  Subgoal 18' ELIM

  The ``c'' field marks this goal as a ``checkpoint'', i.e., a goal
  worthy of careful scrutiny. In fact, any goal that creates children
  by a process other than ``preprocess'' or ``simp'' is marked as a
  checkpoint. In this case, the destructor-elimination (``[elim]'')
  process has been used to create subgoals of this goal. The
  indentation shows that this goal, Subgoal 18', is a child of
  Subgoal 18. The number ``2'' indicates that 2 subgoals have been
  created (by [elim]). Note that this information is consistent with
  the line just below it, which says ``<2 subgoals>''.

  Finally, the last line of this proof tree display,

    |  <17 more subgoals>

  is connected by vertical bars (``|'') up to the string \"Subgoal 18\",
  which suggests that there are 17 immediate subgoals of Goal
  remaining to process after Subgoal 18. Note that this line is
  indented one level from the second line, which is the line for the
  goal named \"Goal\". The display is intended to suggest that the
  subgoals of Goal that remain to be proved consist of Subgoal 18
  together with 17 more subgoals.

  The next proof tree display differs from the previous one only in
  that now, Subgoal 18' has only one more subgoal to be processed.

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
       1 |  Subgoal 18 simp
    c  2 |  |  Subgoal 18' ELIM
         |  |  |  <1 more subgoal>
         |  <17 more subgoals>

  Note that the word ``more'' in ``<1 more subgoal>'' tells us that
  there was originally more than one subgoal of Subgoal 18. In fact
  that information already follows from the line above, which (as
  previously explained) says that Subgoal 18' originally created 2
  subgoals.

  The next proof tree display occurs when the prover completes the
  proof of that ``1 more subgoal'' referred to above.

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
         |  <17 more subgoals>

  Then, Subgoal 17 is processed and creates one subgoal, by
  simplification:

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
       1 |  Subgoal 17 simp
         |  |  <1 subgoal>
         |  <16 more subgoals>

  ... and so on.

  Later in the proof one might find the following successive proof tree
  displays.

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
         |  <9 more subgoals>

    ( DEFUN CANCEL_EQUAL_PLUS ...)

      18 Goal preprocess
       0 |  Subgoal 9 simp (FORCED)
         |  <8 more subgoals>

  These displays tell us that Subgoal 9 simplified to t (note that the
  ``0'' shows clearly that no subgoals were created), but that some
  rule's hypotheses were [force]d. Although this goal is not
  checkpointed (i.e., no ``c'' appears on the left margin), one can
  cause such goals to be checkpointed; see [checkpoint-forced-goals].

  In fact, the proof tree displayed at the end of the ``main
  proof''(the 0-th forcing round) is as follows.

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
       0 |  Subgoal 9 simp (FORCED)
       0 |  Subgoal 8 simp (FORCED)
       0 |  Subgoal 7 simp (FORCED)
       0 |  Subgoal 6 simp (FORCED)
       0 |  Subgoal 4 simp (FORCED)
       0 |  Subgoal 3 simp (FORCED)

  This is followed by the following proof tree display at the start of
  the forcing round.

      18 Goal preprocess
       0 |  Subgoal 9 simp (FORCED [1]Subgoal 4)
       0 |  Subgoal 8 simp (FORCED [1]Subgoal 6)
       0 |  Subgoal 7 simp (FORCED [1]Subgoal 1)
       0 |  Subgoal 6 simp (FORCED [1]Subgoal 3)
       0 |  Subgoal 4 simp (FORCED [1]Subgoal 5)
       0 |  Subgoal 3 simp (FORCED [1]Subgoal 2)
    ++++++++++++++++++++++++++++++
       6 [1]Goal FORCING-ROUND
       2 |  [1]Subgoal 6 preprocess
         |  |  <2 subgoals>
         |  <5 more subgoals>

  This display shows which goals to ``blame'' for the existence of each
  goal in the forcing round. For example, Subgoal 9 is to blame for
  the creation of [1]Subgoal 4.

  Actually, there is no real goal named \"[1]Goal\". However, the line

    6 [1]Goal FORCING-ROUND

  appears in the proof tree display to suggest a ``parent'' of the six
  top-level goals in that forcing round. As usual, the numeric field
  before the goal name contains the original number of children of
  that (virtual, in this case) goal --- in this case, 6.

  In our example proof, Subgoal 6 eventually gets proved, without doing
  any further forcing. At that point, the proof tree display looks as
  follows.

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
       0 |  Subgoal 9 simp (FORCED [1]Subgoal 4)
       0 |  Subgoal 7 simp (FORCED [1]Subgoal 1)
       0 |  Subgoal 6 simp (FORCED [1]Subgoal 3)
       0 |  Subgoal 4 simp (FORCED [1]Subgoal 5)
       0 |  Subgoal 3 simp (FORCED [1]Subgoal 2)
    ++++++++++++++++++++++++++++++
       6 [1]Goal FORCING-ROUND
         |  <5 more subgoals>

  Notice that the line for Subgoal 8,

    0 |  Subgoal 8 simp (FORCED [1]Subgoal 6)

  no longer appears. That is because the goal [1]Subgoal 6 has been
  proved, along with all its children; and hence, the proof of
  Subgoal 8 no longer depends on any further reasoning.

  The final two proof tree displays in our example are as follows.

    ( DEFUN CANCEL_EQUAL_PLUS ...)
      18 Goal preprocess
       0 |  Subgoal 7 simp (FORCED [1]Subgoal 1)
    ++++++++++++++++++++++++++++++
       6 [1]Goal FORCING-ROUND
       2 |  [1]Subgoal 1 preprocess
       1 |  |  [1]Subgoal 1.1 preprocess
       1 |  |  |  [1]Subgoal 1.1' simp
    c  3 |  |  |  |  [1]Subgoal 1.1'' ELIM
         |  |  |  |  |  <1 more subgoal>

    ( DEFUN CANCEL_EQUAL_PLUS ...)
    <>

  The explanation for the empty proof tree is simple: once [1]Subgoal
  1.1.1 was proved, nothing further remained to be proved. In fact,
  the much sought-after ``Q.E.D.'' appeared shortly after the final
  proof tree was displayed.

  Let us conclude with a final, brief example that illustrates proof by
  induction. Partway through the proof one might come across the
  following proof tree display.

    ( DEFTHM PLUS-TREE-DEL ...)
       1 Goal preprocess
       2 |  Goal' simp
    c  0 |  |  Subgoal 2 PUSH *1
         |  |  <1 more subgoal>

  This display says that in the attempt to prove a theorem called
  plus-tree-del, preprocessing created the only child Goal' from
  Goal, and Goal' simplified to two subgoals. Subgoal 2 is
  immediately pushed for proof by induction, under the name ``*1''.
  In fact if Subgoal 1 simplifies to t, then we see the following
  successive proof tree displays after the one shown above.

    ( DEFTHM PLUS-TREE-DEL ...)
       1 Goal preprocess
       2 |  Goal' simp
    c  0 |  |  Subgoal 2 PUSH *1

    ( DEFTHM PLUS-TREE-DEL ...)
       1 Goal preprocess
       2 |  Goal' simp
    c  0 |  |  Subgoal 2 PUSH *1
    ++++++++++++++++++++++++++++++
    c  6 *1 INDUCT
         |  <5 more subgoals>

  The separator ``+++++...'' says that we are beginning another trip
  through the waterfall. In fact this trip is for a proof by
  induction (as opposed to a forcing round), as indicated by the word
  ``INDUCT''. Apparently *1.6 was proved immediately, because it was
  not even displayed; a goal is only displayed when there is some
  work left to do either on it or on some goal that it brought
  (perhaps indirectly) into existence.

  Once a proof by induction is completed, the ``PUSH'' line that refers
  to that proof is eliminated (``pruned''). So for example, when the
  present proof by induction is completed, the line

    c  0 |  |  Subgoal 2 PUSH *1

  is eliminated, which in fact causes the lines above it to be
  eliminated (since they no longer refer to unproved children).
  Hence, at that point one might expect to see:

    ( DEFTHM PLUS-TREE-DEL ...)
    <>

  However, if the proof by induction of *1 necessitates further proofs
  by induction or a forcing round, then this ``pruning'' will not yet
  be done.")
 (PROOFS-CO
  (IO ACL2-BUILT-INS)
  "The proofs character output channel

  Proofs-co is an [ld] special (see [ld]). The accessor is (proofs-co
  state) and the updater is (set-proofs-co val state). Proofs-co must
  be an open character output channel. It is to this channel that
  [defun], [defthm], and the other event [command]s print their
  commentary.

  ``Proofs-co'' stands for ``proofs character output.'' The initial
  value of proofs-co is the same as the value of [*standard-co*] (see
  [*standard-co*]).")
 (PROPER-CONSP
  (LISTS ACL2-BUILT-INS)
  "Recognizer for proper (null-terminated) non-empty lists

  Proper-consp is the function that checks whether its argument is a
  non-empty list that ends in nil. Also see [true-listp].

  Function: 

    (defun proper-consp (x)
           (declare (xargs :guard t))
           (and (consp x) (true-listp x)))")
 (PROPS
  (WORLD)
  "Print the ACL2 properties on a symbol

    Example:
    :props assoc-eq

  Props takes one argument, a symbol, and prints all of the properties
  that are on that symbol in the ACL2 [world].")
 (PROVER-OUTPUT
  (ACL2)
  "Methods for controlling the output produced by ACL2 during proofs and
  in other situations.


Subtopics

  [Finalize-event-user]
      User-supplied code to complete [events], e.g., with extra summary
      output

  [Gag-mode]
      Verbosity of proof output

  [Initialize-event-user]
      User-supplied code to initiate [events]

  [Pso]
      Show the most recently saved output

  [Pso!]
      Show the most recently saved output, including [proof-tree] output

  [Psof]
      Show the most recently saved output

  [Psog]
      Show the most recently saved output in [gag-mode]

  [Set-gag-mode]
      Modify the nature of proof output

  [Set-inhibit-output-lst]
      Control output

  [Set-inhibit-warnings]
      Control warnings

  [Set-inhibit-warnings!]
      Control warnings non-[local]ly

  [Set-inhibited-summary-types]
      Control which parts of the summary are printed

  [Set-let*-abstractionp]
      To shorten many prettyprinted clauses

  [Set-print-clause-ids]
      Cause subgoal numbers to be printed when 'prove output is inhibited

  [Set-raw-proof-format]
      Print runes as lists in proof output from simplification

  [Warnings]
      Warnings emitted by the ACL2 proof process

  [With-output]
      Suppressing or turning on specified output for an event")
 (PROVING_THEOREMS_ABOUT_MODELS
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Proving Theorems about Models

  [{IMAGE}]

  But ACL2 is a logic. We can prove theorems about the model.

  {IMAGE}

    Theorem.  MC 'mult is a multiplier
    (implies (and (natp x)
                  (natp y))
             (equal (lookup 'z (mc (s 'mult x y) (mclk x)))
                    (* x y))).

  This theorem says that a certain program running on the mc machine
  will correctly multiply any two natural numbers.

  It is a statement about an infinite number of test cases!

  We know it is true about the model because we proved it.

  Of course, models of actual machines usually only accept a finite
  number of different inputs. For example, engineers at Advanced
  Micro Devices (AMD), Centaur, and IBM have ACL2 models of floating
  point units that operate on double precision IEEE floating point
  numbers. These are finite models. But the size of their inputs is
  sufficiently large that they are verified by the same mathematical
  methods used to prove theorems about infinite state systems like
  our little mc.

  [{IMAGE}]")
 (PROVISIONAL-CERTIFICATION
  (BOOKS-CERTIFICATION)
  "Certify a book in stages for improved book-level parallelism

  Provisional certification is a process that can increase parallelism
  when certifying books in parallel, typically using `make', when
  certifying a collection of [books]. We got this idea from Jared
  Davis, who developed rudimentary provisional certification schemes
  first at Rockwell Collins and later for his `Milawa' project. Our
  design has also benefited from conversations with Sol Swords.

  Warning: as of November 2014, enabling provision certification via
  the ACL2_PCERT flag can not be reliably enabled at the Makefile
  level (as is shown below). See {Github Issue 255 |
  https://github.com/acl2/acl2/issues/255} for more information.

  To invoke provisional certification, see [books-certification]. For
  example, you could issue the following command.

    ACL2_PCERT=t cert.pl -j 4 `find . -name '*.lisp'`

  Alternatively, see [books-certification-classic] for a discussion of
  classic ACL2 `make'-based certification (which may disappear in a
  future ACL2 release); here we extend those instructions to show how
  to use provisional certification. (Also, you may wish to look at
  community books file books/system/pcert/Makefile for an example.)
  We begin by describing a few ways to do that. A simple way is to
  add the line `ACL2_PCERT=t' to a `make' command that you use for
  book certification, for example as follows.

    make -j 4 ACL2_PCERT=t

  The following works too, in a bash shell.

    (export ACL2_PCERT=t ; time make -j 4)

  Alternatively, add the line

    ACL2_PCERT ?= t

  to the Makefile residing in the directory, placed above the line that
  specifies the `include' of file Makefile-generic. A successful
  `make' will result in creating the desired [certificate] (.cert)
  files.

  Warning: If you put the line ``ACL2_PCERT ?= t'' below the include of
  Makefile-generic, it might have no effect. For example, try editing
  community books file books/system/pcert/Makefile by moving the line
  ``ACL2_PCERT ?= t'' to the bottom of the file, and watch ``make
  top.cert'' fail to invoke provisional certification.

  The description above may be sufficient for you to use provisional
  certification. We provide additional documentation below for the
  reader who wants to understand more about this process, for example
  when not using `make'. Below we assume prior familiarity with
  [books], in particular [certify-book] and [include-book]. The
  remainder of this [documentation] topic is divided into sections:
  Summary, Correctness Claim and Issues, Combining Pcertify and
  Convert into Pcertify+, and Further Information.

  Summary

  Recall that certification of a book, bk, produces a [certificate]
  file bk.cert. The provisional certification process produces this
  file as well, but as the last of the following three steps. All of
  these steps are carried out by calls of [certify-book] using its
  :pcert keyword argument. We typically call these steps
  ``procedures'', to distinguish them from the steps of an individual
  call of [certify-book].

    * The ``Pcertify'' procedure (sometimes called the ``Create''
      procedure) is invoked by calling [certify-book] with keyword
      argument :pcert :create. It produces a file bk.pcert0,
      sometimes called the ``.pcert0'' file (pronounced ``dot pee
      cert zero''). Proofs are skipped during this procedure, which
      can be viewed as an elaborate syntax check, augmented by
      compilation if specified (as it is by default).
    * The ``Convert'' procedure is invoked by calling [certify-book] with
      keyword argument :pcert :convert. It creates file bk.pcert1
      from bk.pcert0, by doing proofs for all events in bk.lisp. Note
      that the third argument (the `compile-flg' argument) is ignored
      by such a call of certify-book unless its value is :all (either
      explicitly or by way of environment variable ACL2_COMPILE_FLG).
      A subtlety is that if there is a compiled file at least as
      recent as the corresponding .pcert0 file, then that compiled
      file's write date will be updated to the current time at the
      end of this procedure. The usual [local-incompatibility] check
      at the end of [certify-book] is omitted for the Convert
      procedure, since it was performed towards the end of the Create
      procedure.
    * The ``Complete'' procedure is invoked by calling [certify-book] with
      keyword argument :pcert :complete. It checks that every
      included book (including every one that is [local]ly included)
      has a .cert file that is at least as recent as the
      corresponding book. The effect is to move bk.pcert1 to bk.cert.
      Note that all arguments of certify-book other than the :pcert
      argument are ignored for this procedure, other than for some
      trivial argument checking.

  You can combine the Pcertify and Convert procedures into a single
  procedure, Pcertify+, which may be useful for books that contain
  expensive [include-book] [events] but do few proofs. We defer
  discussion of that feature to the section below, ``Combining
  Pcertify and Convert into Pcertify+''.

  The main idea of provisional certification is to break sequential
  dependencies caused by [include-book], that is, so that a book's
  proofs are carried out even when it includes books (sometimes
  called ``sub-books'') that have not themselves been fully
  certified. For example, suppose that a proof development consists
  of books A.lisp, B.lisp, and C.lisp, where file A.lisp contains the
  form (include-book \"B\") and file B.lisp contains the form
  (include-book \"C\"). Normally one would first certify C, then B, and
  finally, A. However, the provisional certification process can
  speed up the process on a multi-core machine, as follows: the
  Pcertify (pronounced ``pee certify'') procedure respects this order
  but (one hopes) is fast since proofs are skipped; the Convert
  procedure essentially completes the certification in parallel by
  doing proofs and creating .pcert1 files based on .pcert0 files; and
  the Complete procedure respects book order when quickly renaming
  .pcert1 files to .cert files. In our example, the steps would be as
  follows, but note that we need not finish all Pcertify steps before
  starting some Convert steps, nor need we finish all Convert steps
  before starting some Complete steps, as explained further below.

    * Pcertify books \"C\", \"B\",and then \"A\", sequentially, skipping proofs
      but doing compilation.
    * Do proofs in parallel for the books using the Convert procedure,
      where each book relies on the existence of its own .pcert0 file
      as well as a .cert, .pcert0, or .pcert1 file for each of its
      included sub-books. Write out a .pcert1 file for the book when
      the proof succeeds.
    * Rename the .pcert1 file to a corresponding .cert file when a .cert
      file exists and is up-to-date for each included book.

  The Convert step can begin for bk.lisp any time after bk.pcert0 is
  built. The Complete step can begin for this book any time after
  bk.pcert1 and every sub-bk.cert are built, for sub-bk a sub-book of
  bk.

  The new procedures --- Pcertify, Convert, and Complete --- are
  invoked by supplying a value for the keyword argument :pcert of
  [certify-book], namely :create, :convert, or :complete,
  respectively. Typically, and by default, the compile-flg argument
  of [certify-book] is t for the Pcertify procedure, so that
  [compilation] can take full advantage of parallelism. This argument
  is treated as nil for the other procedures except when its value is
  :all in the Convert procedure, as mentioned above.

  For those who use [make-event], we note that expansion is done in the
  Pcertify procedure; the later steps use the expansion resulting
  from that procedure. The reason is that although a call of
  [make-event] is similar to a macro call, a difference is that the
  expansion of a make-event form can depend on the [state].
  Therefore, we insist on doing such an expansion only once, so that
  all books involved agree on the expansion. We say more about
  make-event below.

  Correctness Claim and Issues

  The Basic Claim for certification is the same whether or not the
  provisional certification process is employed: all books should be
  certified from scratch, with no files written to the directories of
  the books except by ACL2. Moreover, no trust tags should be used
  (see [defttag]), or else it is the responsibility of the user to
  investigate every occurrence of ``TTAG NOTE'' that is printed to
  standard output.

  But common practice is to certify a set of books in stages: certify a
  few books, fix some books, re-certify changed books, certify some
  more books, and so on. In practice, we expect this process to be
  sound even though it does not meet the preconditions for the Basic
  Claim above. In particular, we expect that the use of checksums in
  [certificate]s will make it exceedingly unlikely that a book is
  still treated as certified after any events in the book or any
  sub-book, or any [portcullis] [command]s of the book or any
  sub-book, have been modified.

  Provisional certification makes it a bit easier for a determined user
  to subvert correctness. For example, the Complete procedure only
  checks write dates to ensure that each sub-book's .cert file is no
  older than the corresponding .lisp file, but it does not look
  inside .cert files of sub-books; in particular it does not look at
  their checksum information. Of course, the automatic dependency
  analysis provided by classic ACL2 `make'-based certification avoids
  accidental problems of this sort. And, checksum information will
  indeed be applied at [include-book] time, at least for sub-books
  included non-[local]ly.

  In short: while we believe that the provisional certification process
  can be trusted, we suggest that for maximum trust, it is best for
  all books in a project to be certified from scratch without the
  provisional certification process.

  Combining Pcertify and Convert into Pcertify+

  You can combine the Pcertify and Convert procedure into a single
  procedure, Pcertify+, which may be useful for books that contain
  expensive [include-book] [events] but do few proofs. If you are
  using `make' to do provisional certification as described above,
  just set `make' variable ACL2_BOOKS_PCERT_ARG_T to the list of
  books for which you want the Pcertify+ procedure performed instead
  of separate Pcertify and Convert procedures. Either of two common
  methods may be used to set this variable, as illustrated below for
  the case that books sub.lisp and mid.lisp are the ones on which you
  want Pcertify+ performed. One method is to add the following to
  your directory's Makefile, above the include of Makefile-generic.

    ACL2_BOOKS_PCERT_ARG_T = sub mid

  Alternatively, you can specify the desired books on the command line,
  for example as follows.

    make -j 4 ACL2_BOOKS_PCERT_ARG_T='sub mid'

  Note that the books are given without their .lisp extensions.

  At the ACL2 level, the Pcertify+ procedure is performed when the
  value t is supplied to the :pcert keyword argument of
  [certify-book]. Thus, :pcert t can be thought of as a combination
  of :pcert :create and :pcert :convert. However, what ACL2 actually
  does is to perform the Pcertify step without skipping proofs, and
  at the end of the certify-book run, it writes out both the .pcert0
  and .pcert1 file, with essentially the same contents. (We say
  ``essentially'' because the implementation writes :PCERT-INFO
  :PROVED to the end of the .pcert0 file, but not to the .pcert1
  file.)

  Further Information

  Some errors during provisional certification cannot be readily
  solved. For example, if there are circular directory dependencies
  (for example, some book in directory D1 includes some book in
  directory D2 and vice-versa), then classic ACL2 `make'-based
  certification will quite possibly fail. For another example,
  perhaps your directory's Makefile is awkward to convert to one with
  suitable dependencies. When no fix is at hand, it might be best
  simply to avoid provisional certification. If you are using classic
  ACL2 `make'-based certification, you can simply add the following
  line to your directory's Makefile, or use ``ACL2_PCERT= '' on the
  `make' command line, to avoid provisional certification.

    override ACL2_PCERT =

  We invite anyone who has troubleshooting tips to contact the ACL2
  developers with suggestions for adding such tips to this section.

  Our next remark is relevant only to users of [make-event], and
  concerns the interaction of that utility with state global
  [ld-skip-proofsp]. Normally, the global value of [ld-skip-proofsp]
  is unchanged during make-event expansion, except that it is bound
  to nil when the make-event form has a non-nil :check-expansion
  argument. But during the Pcertify procedure (not the Pcertify+
  procedure), [ld-skip-proofsp] is always bound to nil at the start
  of make-event expansion. To see why, consider for example the
  community book books/make-event/proof-by-arith.lisp. This book
  introduces a macro, proof-by-arith, that expands to a call of
  [make-event]. This make-event form expands by trying to prove a
  given theorem using a succession of included arithmetic books,
  until the proof succeeds. Now proofs are skipped during the
  Pcertify procedure, and if proofs were also skipped during
  make-event expansion within that procedure, the first arithmetic
  book's [include-book] form would always be saved because the
  theorem's proof ``succeeded'' (as it was skipped!). Of course, the
  theorem's proof could then easily fail during the Convert step. If
  you really want to inhibit proofs during make-event expansion in
  the Pcertify step, consider using a form such as the following:
  (state-global-let* ((ld-skip-proofsp nil)) ...).

  Finally, we describe what it means for there to be a valid
  [certificate] file for including a certified book. Normally, this
  is a file with extension .cert. However, if that .cert file does
  not exist, then ACL2 looks for a .pcert0 file instead; and if that
  also does not exist, it looks for a .pcert1 file. (To see why does
  the .pcert0 file take priority over the .pcert1 file, note that the
  Convert procedure copies a .pcert0 file to a .pcert1 file, so both
  might exist --- but the .pcert1 file might be incomplete if copying
  is in progress.) Once the candidate certificate file is thus
  selected, it must be valid in order for the book to be considered
  certified (see [certificate]). For the certificate file as chosen
  above, then in order for a compiled file to be loaded, it must be
  at least as recent as that certificate file.

  Again, as discussed above, a .pcert0 or .pcert1 file may serve as a
  valid certificate file when the .cert file is missing. But when
  that happens, a warning may be printed that a ``provisionally
  certified'' book has been included. No such warning occurs if
  environment variable ACL2_PCERT has a non-empty value, or if that
  warning is explicitly inhibited (see [set-inhibit-warnings] and see
  [set-inhibit-output-lst]).")
 (PSEUDO-TERMP
  (TERM ACL2-BUILT-INS)
  "A predicate for recognizing term-like s-expressions

    Example Forms:
    (pseudo-termp '(car (cons x 'nil)))      ; has value t
    (pseudo-termp '(car x y z))              ; also has value t!
    (pseudo-termp '(delta (h x)))            ; has value t
    (pseudo-termp '(delta (h x) . 7))        ; has value nil (not a true-listp)
    (pseudo-termp '((lambda (x) (car x)) b)) ; has value t
    (pseudo-termp '(if x y 123))             ; has value nil (123 is not quoted)
    (pseudo-termp '(if x y '123))            ; has value t

  If x is the quotation of a term, then (pseudo-termp x) is t. However,
  if x is not the quotation of a term it is not necessarily the case
  that (pseudo-termp x) is nil.

  See [term] for a discussion of the various meanings of the word
  ``term'' in ACL2. In its most strict sense, a term is either a
  legal variable symbol, a quoted constant, or the application of an
  n-ary function symbol or closed lambda-expression to n terms. By
  ``legal variable symbol'' we exclude constant symbols, such as t,
  nil, and *ts-rational*. By ``quoted constants'' we include 't (aka
  (quote t)), 'nil, '31, etc., and exclude constant names such as t,
  nil and *ts-rational*, unquoted constants such as 31 or 1/2, and
  ill-formed quote expressions such as (quote 3 4). By ``closed
  lambda expression'' we exclude expressions, such as (lambda (x)
  (cons x y)), containing free variables in their bodies. Terms typed
  by the user are translated into strict terms for internal use in
  ACL2.

  The predicate termp checks this strict sense of ``term'' with respect
  to a given ACL2 logical world; See [world]. Many ACL2 functions,
  such as the rewriter, require certain of their arguments to satisfy
  termp. However, as of this writing, termp is in :[program] mode and
  thus cannot be used effectively in conjectures to be proved.
  Furthermore, if regarded simply from the perspective of an
  effective [guard] for a term-processing function, termp checks many
  irrelevant things. (Does it really matter that the variable symbols
  encountered never start and end with an asterisk?) For these
  reasons, we have introduced the notion of a ``pseudo-term'' and
  embodied it in the predicate pseudo-termp, which is easier to
  check, does not require the logical [world] as input, has :[logic]
  mode, and is often perfectly suitable as a [guard] on
  term-processing functions.

  A pseudo-termp is either a symbol, a true list of length 2 beginning
  with the word quote, the application of an n-ary pseudo-lambda
  expression to a true list of n pseudo-terms, or the application of
  a symbol to a true list of n pseudo-termps. By an ``n-ary
  pseudo-lambda expression'' we mean an expression of the form
  (lambda (v1 ... vn) pterm), where the vi are symbols (but not
  necessarily distinct legal variable symbols) and pterm is a
  pseudo-termp.

  Metafunctions may use pseudo-termp as a [guard].")
 (PSO
  (PROVER-OUTPUT)
  "Show the most recently saved output

  Evaluate :pso in order to print output that was generated in an
  environment where output was being saved; see [set-saved-output]
  for details. However, [proof-tree] output will be suppressed; use
  :[pso!] if you want that output to be printed as well.

  Also see [psog], for printing saved output in [gag-mode].")
 (PSO!
  (PROVER-OUTPUT)
  "Show the most recently saved output, including [proof-tree] output

  Evaluate :pso! in order to print output that was generated in an
  environment where output was being saved; see [set-saved-output]
  for details. Note that [proof-tree] will be included; use :[pso] if
  you want that output to be suppressed.

  Also see [psog], for printing saved output in [gag-mode].")
 (PSOF
  (PROVER-OUTPUT)
  "Show the most recently saved output

  For a similar utility, see [pso]. Like :pso, the :psof command prints
  output that was generated in an environment where output was being
  saved, typically [gag-mode]; also see [set-saved-output]. But
  unlike :pso, :psof takes a filename argument and saves output to
  that file, instead of to the terminal. For large proofs, :[psof]
  may complete more quickly than :[pso]. Note that as with :pso,
  [proof-tree] output will be suppressed.

  The first line of output from :psof directs the Emacs editor to use
  auto-revert mode. You can change the frequency of auto-reverting
  the buffer connected to a file by evaluating a suitable command in
  Emacs. For example, the command (setq auto-revert-interval .1)
  arranges for auto-revert mode to update as needed every 1/10 of a
  second.")
 (PSOG
  (PROVER-OUTPUT)
  "Show the most recently saved output in [gag-mode]

  Evaluate :psog in order to print output in [gag-mode] that was
  generated in an environment where output was being saved; see
  [set-saved-output] for details.

  Also see [pso] and see [pso!] for printing the full output.")
 (PSTACK
  (DEBUGGING)
  "Seeing what the prover is up to

    General Forms:
    (pstack)      ; inspect break
    (pstack t)    ; inspect break, printing all calls in abbreviated form
    (pstack :all) ; as above, but only abbreviating the ACL2 world

  When the form (pstack) is executed during a break from a proof, or at
  the end of a proof that the user has aborted, a ``process stack''
  (or ``prover stack'') will be printed that gives some idea of what
  the theorem prover has been doing. Moreover, by evaluating
  (verbose-pstack t) before starting a proof (see [verbose-pstack])
  one can get trace-like information about prover functions,
  including time summaries, printed to the screen during a proof.
  This feature is currently quite raw and may be refined considerably
  as time goes on, based on user suggestions. For example, the usual
  control of printing given by [set-inhibit-output-lst] is irrelevant
  for printing the pstack.

  The use of (pstack t) or (pstack :all) should only be used by those
  who are comfortable looking at functions in the ACL2 source code.
  Otherwise, simply use (pstack).

  Entries in the pstack include the following (listed here
  alphabetically, except for the first).

  preprocess-clause, simplify-clause, etc. (in general,xxx-clause):
  top-level processes in the prover ``waterfall''

  clausify: splitting a goal into subgoals

  ev-fncall: evaluating a function on explicit arguments

  ev-fncall-meta: evaluating a metafunction

  forward-chain: building a context for the current goal using
  [forward-chaining] rules

  induct: finding an induction scheme

  pop-clause: getting the next goal to prove by induction

  process-assumptions: creating forcing rounds

  remove-built-in-clauses: removing built-in clauses (see
  [built-in-clause])

  process-equational-polys: deducing interesting equations

  remove-trivial-equivalences: removing trivial equalities (and
  equivalences) from the current goal

  rewrite-atm: rewriting a top-level term in the current goal

  setup-simplify-clause-pot-lst: building the linear arithmetic
  database for the current goal

  strip-branches, subsumption-replacement-loop: subroutines of clausify

  waterfall: top-level proof control


Subtopics

  [Verbose-pstack]
      Seeing what the prover is up to (for system hackers)")
 (PUFF
  (HISTORY)
  "Replace a compound [command] by its immediate subevents

    Example Forms:
    ACL2 !>:puff :max
    ACL2 !>:puff :x
    ACL2 !>:puff 15
    ACL2 !>:puff \"book\"

    General Form:
    :puff cd

  where cd is a [command] descriptor (see [command-descriptor]) for a
  ``puffable'' [command] (see below). Puff replaces the [command] at
  cd by the immediate subevents of the [command], executed as
  [command]s. Puff then prints, using [pcs], the puffed region.

  We consider puff to be a sort of hack; it is generally robust and
  sound, but that is not guaranteed. If any existing ACL2 event
  resulted from puff, ACL2 considers proofs to have been skipped, and
  thus [certify-book] is disallowed until such events have been
  undone (see [ubt]).

  A ``puffable'' [command] is an [encapsulate] [command], an
  [include-book] command, or any command other than those consisting
  of a single primitive event. For example, since [defun] is a
  primitive event, a [defun] command is not puffable. But a macro
  form that expands into one or more [events] is puffable. The only
  primitive events that are puffable are calls of [encapsulate] or
  [include-book]. In this sense, [make-event] is not considered
  primitive --- that is, it can be puffed --- and moreover, an
  immediate subevent that is a call of make-event is generally
  replaced by its expansion (see [make-event]). A puffable [command]
  contains (interesting) subevents, namely, the events in the body of
  the [encapsulate], in the file of the book included, or in the
  [command] block.

  The puff [command] ``lifts'' the immediate subevents of the indicated
  [command] so that they become [command]s themselves. The [command]
  [puff*] recursively puffs the newly introduced [command]s. See
  [puff*], which also gives an example illustrating both puff and
  [puff*]. Puff undoes the [command] at cd and replaces it by its
  immediate subevents. Thus, in general the length of the [history]
  grows when a puff [command] is executed. If puff causes an error
  (see below), the logical [world] remains unchanged from its initial
  configuration.

  The intended use of puff is to allow the user access to the [events]
  ``hidden'' inside compound [command]s. For example, while trying to
  prove some theorem, p, about a constrained function, fn, one might
  find that the [encapsulate], cd, that introduced fn failed to
  include an important [constraint], q. Without puff, the only way to
  proceed is to undo back through cd, create a suitable [encapsulate]
  that proves and exports q as well as the old [constraint]s,
  re-execute the new [encapsulate], re-execute the [events] since cd,
  and then try p again. Unfortunately, it may be hard to prove q and
  additional [events] may have to be inserted into the [encapsulate]
  to prove it. It may also be hard to formulate the ``right'' q,
  i.e., one that is provable in the [encapsulate] and provides the
  appropriate facts for use in the proof of p.

  Using puff, the user can erase the [encapsulate] at cd, replacing it
  by the [events] in its body. Now the formerly constrained function,
  fn, is defined as its witness. The user can experiment with
  formulations and proofs of q suitable for p. Of course, to get into
  the ultimately desired [state] --- where fn is constrained rather
  than defined and q is exported by an [encapsulate] at cd --- the
  user must ultimately undo back to cd and carry out the more tedious
  program described above. But by using puff it is easier to
  experiment.

  Similar applications of puff allow the user of a book to expose the
  top-level [events] in the book as though they had all been typed as
  [command]s. The user might then ``partially undo'' the book,
  keeping only some of the events in it.

  Puff operates as follows. First, it determines the list of immediate
  subevents of the [command] indicated by cd. It causes an error if
  there is only one subevent and that subevent is identical to the
  [command] --- i.e., if the [command] at cd is a primitive. Next,
  puff undoes back through the indicated [command]. This not only
  erases the [command] at cd but all the [command]s executed after
  it. Finally, puff re-executes the subevents of (the now erased) cd
  followed by all the [command]s that were executed afterwards.

  Observe that the [command]s executed after cd will generally have
  higher [command] numbers than they did before the puff. For
  example, suppose 100 [command]s have been executed and that :puff
  80 is then executed. Suppose [command] 80 contains 5 immediate
  subevents (i.e., is an encapsulation of five [events]). Then, after
  puffing, [command] 80 is the first event of the puffed [command],
  [command] 81 is the second, and so on; 104 [command]s appear to
  have been executed.

  When puffing an [encapsulate] or [include-book], the [local]
  [command]s are executed. Note that this will replace constrained
  functions by their witnesses.

  Here are some details and small exceptions.

    * An [encapsulate] command generated by the macro
      [define-trusted-clause-processor] is not puffable.
    * An attempt to puff an [include-book] command may fail for a book that
      has been modified, as describe late in this documentation
      topic.
    * The puff of an an [include-book] command for an uncertified book will
      simply expose the contents of the book. However, if the book is
      certified then the puff will replace each event by its
      [make-event] expansion. Moreover, any such expansion that is
      [local] will be ignored; similarly for local make-event
      expansions in [encapsulate] commands. This will result in an
      error if the elided event is necessary to support later events
      in the puff of the command.

  Finally, we note that it is an error to puff in the presence of
  [include-book] [events] for certified books that have been altered
  since they were included. (Note that this restriction only applies
  to [include-book], not to [certify-book].) To be specific, suppose
  \"arith\" is a certified book that has been included in a session.
  Suppose that after \"arith\" was included, the source file is
  modified. (This might happen if the user of \"arith\" is not its
  author and the author happens to be working on a new version of
  \"arith\" during the same time period.) Now suppose the user tries to
  puff the [command] that included \"arith\". The attempt to obtain the
  subevents in \"arith\" will discover that the check sum of \"arith\"
  has changed and an error will be caused. No change is made in the
  logical [world]. A similar error is caused if, in this same
  situation, the user tries to puff any command that occurred before
  the inclusion of \"arith\"! That is, puff may cause an error and
  leave the [world] unchanged even if the [command] puffed is not one
  involving the modified book. This happens because in order to
  reconstruct the [world] after the puffed [command], puff must
  obtain the [events] in the book and if the book's source file has
  changed there is no assurance that the reconstructed [world] is the
  one the user intends.

  Warning: We do not detect changes to uncertified [books] that have
  been included and are then puffed or re-included! The act of
  including an uncertified book leaves no trace of the check sum of
  the book. Furthermore, the act prints a warning message disclaiming
  soundness. In light of this, :puff quietly ``re-''executes the
  current contents of the book.")
 (PUFF*
  (HISTORY)
  "Replace a compound [command] by its subevents

    Example Forms:
    ACL2 !>:puff* :max
    ACL2 !>:puff* :x
    ACL2 !>:puff* 15
    ACL2 !>:puff* \"book\"

    General Form:
    :puff* cd

  where cd is a [command] descriptor (see [command-descriptor]) for a
  ``puffable'' [command]. See [puff] for the definition of
  ``puffable'' and for a description of the basic act of ``puffing''
  a [command]. In particular, see [puff] for a discussion of a sense
  in which puff, and hence puff*, should be viewed as a hack. Puff*
  is just the recursive application of [puff]. Puff* prints the
  region [puff]ed, using [pcs].

  To [puff] a [command] is to replace it by its immediate subevents,
  each of which is executed as a [command]. To puff* a [command] is
  to replace the [command] by each of its immediate subevents and
  then to puff* each of the puffable [command]s among the newly
  introduced ones.

  For example, suppose \"ab\" is a book containing the following

    (in-package \"ACL2\")
    (include-book \"a\")
    (include-book \"b\")

  Suppose that book \"a\" only contained [defun]s for the functions a1
  and a2 and that \"b\" only contained [defun]s for b1 and b2.

  Now consider an ACL2 [state] in which only two [command]s have been
  executed, the first being (include-book \"ab\") and the second being
  (include-book \"c\"). Thus, the relevant part of the display produced
  by :[pbt] 1 would be:

    1 (INCLUDE-BOOK \"ab\")
    2 (INCLUDE-BOOK \"c\")

  Call this [state] the ``starting [state]'' in this example, because
  we will refer to it several times.

  Suppose :puff 1 is executed in the starting [state]. Then the first
  [command] is replaced by its immediate subevents and :pbt 1 would
  show:

    1 (INCLUDE-BOOK \"a\")
    2 (INCLUDE-BOOK \"b\")
    3 (INCLUDE-BOOK \"c\")

  Contrast this with the execution of :puff* 1 in the starting [state].
  Puff* would first [puff] (include-book \"ab\") to get the [state]
  shown above. But then it would recursively puff* the puffable
  [command]s introduced by the first [puff]. This continues
  recursively as long as any [puff] introduced a puffable [command].
  The end result of :puff* 1 in the starting [state] is

    1 (DEFUN A1 ...)
    2 (DEFUN A2 ...)
    3 (DEFUN B1 ...)
    4 (DEFUN B2 ...)
    5 (INCLUDE-BOOK \"c\")

  Observe that when puff* is done, the originally indicated [command],
  (include-book \"ab\"), has been replaced by the corresponding
  sequence of primitive [events]. Observe also that puffable
  [command]s elsewhere in the [history], for example, [command] 2 in
  the starting [state], are not affected (except that their [command]
  numbers grow as a result of the splicing in of earlier [command]s).")
 (PUSH-UNTOUCHABLE
  (DEFTTAG)
  "Add name or list of names to the list of untouchable symbols

    Examples:
    (push-untouchable my-var nil)
    (push-untouchable set-mem t)

    General Form:
    (push-untouchable name{s}  fn-p :doc doc-string)

  where name{s} is a non-nil symbol or a non-nil true list of symbols,
  fn-p is any value (but generally nil or t), and doc-string, if
  non-nil, is an optional string that can provide documentation but
  is essentially ignored by ACL2. If name{s} is a symbol it is
  treated as the singleton list containing that symbol. The effect of
  this event is to union the given symbols into the list of
  ``untouchable variables'' in the current world if fn-p is nil, else
  to union the symbols into the list of ``untouchable functions''.
  This event is redundant if every symbol listed is already a member
  of the appropriate untouchables list (variables or functions).

  When a symbol is on the untouchables list it is syntactically illegal
  for any event to call a function or macro of that name, if fn-p is
  non-nil, or to change the value of a state global variable of that
  name, if fn-p is nil. Thus, the effect of pushing a function
  symbol, name, onto untouchables is to prevent any future event from
  using that symbol as a function or macro, or as a state global
  variable (according to fn-p). This is generally done to ``fence
  off'' some primitive function symbol from ``users'' after the
  developer has used the symbol freely in the development of some
  higher level mechanism.

  Also see [remove-untouchable].")
 (PUT-ASSOC
  (ALISTS ACL2-BUILT-INS)
  "Modify an association list by associating a value with a key

    General Forms:
    (put-assoc name val alist)
    (put-assoc name val alist :test 'eql)   ; same as above (eql as equality test)
    (put-assoc name val alist :test 'eq)    ; same, but eq is equality test
    (put-assoc name val alist :test 'equal) ; same, but equal is equality test

  (Put-assoc name val alist) returns an alist that is the same as the
  list alist, except that the first pair in alist with a [car] of
  name is replaced by (cons name val), if there is one. If there is
  no such pair, then (cons name val) is added at the end. Note that
  the order of the keys occurring in alist is unchanged (though a new
  key may be added).

  The [guard] for a call of put-assoc depends on the test. In all
  cases, the last argument must satisfy [alistp]. If the test is
  [eql], then either the first argument must be suitable for [eql]
  (see [eqlablep]) or the last argument must satisfy
  [eqlable-alistp]. If the test is [eq], then either the first
  argument must be a symbol or the last argument must satisfy
  [symbol-alistp].

  See [equality-variants] for a discussion of the relation between
  put-assoc and its variants:

      (put-assoc-eq name val alist) is equivalent to (put-assoc name val
      alist :test 'eq);

      (put-assoc-equal name val alist) is equivalent to (put-assoc name val
      alist :test 'equal).

  In particular, reasoning about any of these primitives reduces to
  reasoning about the function put-assoc-equal.

  Function: 

    (defun put-assoc-equal (name val alist)
           (declare (xargs :guard (alistp alist)))
           (cond ((endp alist) (list (cons name val)))
                 ((equal name (caar alist))
                  (cons (cons name val) (cdr alist)))
                 (t (cons (car alist)
                          (put-assoc-equal name val (cdr alist))))))")
 (PUT-ASSOC-EQ (POINTERS)
               "See [put-assoc].")
 (PUT-ASSOC-EQL (POINTERS)
                "See [put-assoc].")
 (PUT-ASSOC-EQUAL (POINTERS)
                  "See [put-assoc].")
 (PUTPROP
  (WORLD ACL2-BUILT-INS)
  "Update fast property lists

    General form:
    (putprop symbol key value world-alist)

  See community book books/misc/getprop.lisp for an example that
  illustrates the use of ACL2 utilities [getprop] and putprop to take
  advantage of under-the-hood Lisp (hashed) property lists.

  Function: 

    (defun putprop (symb key value world-alist)
           (declare (xargs :guard (and (symbolp symb)
                                       (symbolp key)
                                       (plist-worldp world-alist))))
           (cons (cons symb (cons key value))
                 world-alist))")
 (Q
  (LP)
  "Quit ACL2 (type :q) --- reenter with (lp)

    Example:
    ACL2 !>:Q

  The keyword command :q typed at the top-level of the ACL2 loop will
  terminate the loop and return control to the Common Lisp top-level
  (or, more precisely, to whatever program invoked [lp]). To reenter
  the ACL2 loop, execute (acl2::lp) in Common Lisp. You will be in
  the same state as you were when you exited with :q, unless during
  your stay in Common Lisp you messed the data structures
  representating the ACL2 [state] (including files, property lists,
  and single-threaded objects).

  Unlike all other keyword commands, typing :q is not equivalent to
  invoking the function q. There is no function q.")
 (QUANTIFIER-TUTORIAL
  (DEFUN-SK)
  "A Beginner's Guide to Reasoning about Quantification in ACL2

  The initial version of this tutorial was written by Sandip Ray.
  Additions and revisions are welcome. Sandip has said:

      ``This is a collection of notes that I wrote to remind myself of how
      to reason about quantifiers when I just started. Most users
      after they have gotten the hang of quantifiers probably will
      not need this and will be able to use their intuitions to guide
      them in the process. But since many ACL2 users are not used to
      quantification, I am hoping that this set of notes might help
      them to think clearly while reasoning about quantifiers in
      ACL2.''

  Many ACL2 papers start with the sentence ``ACL2 is a quantifier-free
  first-order logic of recursive functions.'' It is true that the
  syntax of ACL2 is quantifier-free; every formula is assumed to be
  universally quantified over all free variables in the formula. But
  the logic in fact does afford arbitrary first-order quantification.
  This is obtained in ACL2 using a construct called defun-sk. See
  [defun-sk].

  Many ACL2 users do not think in terms of [quantifiers]. The focus is
  almost always on defining recursive functions and reasoning about
  them using induction. That is entirely justified, in fact, since
  proving theorems about recursive functions by induction plays to
  the strengths of the theorem prover. Nevertheless there are
  situations where it is reasonable and often useful to think in
  terms of quantifiers. However, reasoning about quantifiers requires
  that you get into the mindset of thinking about theorems in terms
  of quantification. This note is about how to do this effectively
  given ACL2's implementation of quantification. This does not
  discuss [defun-sk] in detail, but merely shows some examples. A
  detailed explanation of the implementation is in the ACL2
  [documentation] (see [defun-sk]); also see
  [conservativity-of-defchoose].

  [Note: Quantifiers can be used for some pretty cool things in ACL2.
  Perhaps the most interesting example is the way of using
  quantifiers to introduce arbitrary tail-recursive equations; see
  the paper ``Partial Functions in ACL2'' by Panagiotis Manolios and
  J Strother Moore. This note does not address applications of
  quantifiers, but merely how you would reason about them once you
  think you want to use them.]

  Assume that you have some function P. I have just left P as a unary
  function stub below, since I do not care about what P is.

    (defstub P (*) => *)

  Now suppose you want to specify the concept that ``there exists some
  x such that (P x) holds''. ACL2 allows you to write that directly
  using quantifiers.

    (defun-sk exists-P () (exists x (P x)))

  If you submit the above form in ACL2 you will see that the theorem
  prover specifies two functions exists-p and exists-p-witness, and
  exports the following constraints:

    1.  (defun exists-P () (P (exists-P-witness)))
    2.  (defthm exists-P-suff (implies (p x) (exists-p)))

  Here exists-P-witness is a new function symbol in the current ACL2
  theory. What do the constraints above say? Notice the constraint
  exists-p-suff. It says that if you can provide any x such that (P
  x) holds, then you know that exists-p holds. Think of the other
  constraint (definition of exists-p) as going the other way. That
  is, it says that if exists-p holds, then there is some x, call it
  (exists-p-witness), for which P holds. Notice that nothing else is
  known about exists-p-witness than the two constraints above.

  [Note: exists-p-witness above is actually defined in ACL2 using a
  special form called defchoose. See [defchoose]. This note does not
  talk about defchoose. So far as this note is concerned, think of
  exists-p-witness as a new function symbol that has been generated
  somehow in ACL2, about which nothing other than the two facts above
  is known.]

  Similarly, you can talk about the concept that ``for all x (P x)
  holds.'' This can be specified in ACL2 by the form:

    (defun-sk forall-P () (forall x (P x)))

  This produces the following two constraints:

    1.  (defun forall-P () (P (forall-p-witness)))
    2.  (defthm forall-p-necc (implies (not (P x)) (not (forall-p))))

  To understand these, think of for-all-p-witness as producing some x
  which does not satisfy P, if such a thing exists. The constraint
  forall-p-necc merely says that if forall-p holds then P is
  satisfied for every x. (To see this more clearly, just think of the
  contrapositive of the formula shown.) The other constraint
  (definition of forall-p) implies that if forall-p does not hold
  then there is some x, call it (forall-p-witness), which does not
  satisfy P. To see this, just consider the following formula which
  is immediately derivable from the definition.

    (implies (not (forall-p)) (not (P (forall-witness))))

  The description above suggests that to reason about quantifiers, the
  following Rules of Thumb, familiar to most any student of logic,
  are useful.

      RT1: To prove (exists-p), construct some object A such that P holds
      for A and then use exists-P-suff.

      RT2: If you assume exists-P in your hypothesis, use the definition of
      exists-p to know that P holds for exists-p-witness. To use this
      to prove a theorem, you must be able to derive the theorem
      based on the hypothesis that P holds for something, whatever
      the something is.

      RT3: To prove forall-P, prove the theorem (P x) (that is, that P
      holds for an arbitrary x), and then simply instantiate the
      definition of forall-p, that is, show that P holds for the
      witness.

      RT4: If you assume forall-p in the hypothesis of the theorem, see how
      you can prove your conclusion if indeed you were given (P x) as
      a theorem. Possibly for the conclusion to hold, you needed that
      P holds for some specific set of x values. Then use the theorem
      forall-p-necc by instantiating it for the specific x values you
      care about.

  Perhaps the above is too terse. In the remainder of the note, we will
  consider several examples of how this is done to prove theorems in
  ACL2 that involve quantified notions.

  Let us consider two trivial theorems. Assume that for some unary
  function r, you have proved (r x) as a theorem. Let us see how you
  can prove that (1) there exists some x such that (r x) holds, and
  (2) for all x (r x) holds.

  We first model these things using [defun-sk]. Below, r is simply some
  function for which (r x) is a theorem.

    (encapsulate
     (((r *) => *))
     (local (defun r (x) (declare (ignore x)) t))
     (defthm r-holds (r x)))

    (defun-sk exists-r () (exists x (r x)))
    (defun-sk forall-r () (forall x (r x)))

  ACL2 does not have too much reasoning support for quantifiers. So in
  most cases, one would need :use hints to reason about quantifiers.
  In order to apply :use [hints], it is preferable to keep the
  function definitions and theorems disabled.

    (in-theory (disable exists-r exists-r-suff forall-r forall-r-necc))

  Let us now prove that there is some x such that (r x) holds. Since we
  want to prove exists-r, we must use exists-r-suff by RT1. We do not
  need to construct any instance here since r holds for all x by the
  theorem above.

    (defthm exists-r-holds
      (exists-r)
      :hints ((\"Goal\" :use ((:instance exists-r-suff)))))

  Let us now prove the theorem that for all x, (r x) holds. By RT3, we
  must be able to prove it by definition of forall-r.

    (defthm forall-r-holds
      (forall-r)
      :hints ((\"Goal\" :use ((:instance (:definition forall-r))))))

  [Note: Probably no ACL2 user in his or her right mind would prove the
  theorems exists-r-holds and forall-r-holds above. The theorems
  shown are only for demonstration purposes.]

  For the remainder of this note we will assume that we have two
  stubbed out unary functions M and N, and we will look at proving
  some quantified properties of these functions.

    (defstub M (*) => *)
    (defstub N (*) => *)

  Let us now define the predicates all-M, all-N, ex-M, and ex-N
  specifying the various quantifications.

    (defun-sk all-M () (forall x (M x)))
    (defun-sk all-N () (forall x (N x)))
    (defun-sk some-M () (exists x (M x)))
    (defun-sk some-N () (exists x (N x)))

    (in-theory (disable all-M all-N all-M-necc all-N-necc))
    (in-theory (disable some-M some-N some-M-suff some-N-suff))

  Let us prove the classic distributive properties of quantification:
  the distributivity of universal quantification over conjunction,
  and the distributivity of existential quantification over
  disjunction. We can state these properties informally in ``pseudo
  ACL2'' notation as follows:

    1.  (exists x: (M x)) or (exists x: (N x)) <=> (exists x: (M x) or (N x))
    2.  (forall x: (M x)) and (forall: x (N x)) <=> (forall x: (M x) and (N x))

  To make these notions formal we of course need to define the formulas
  at the right-hand sides of 1 and 2. So we define some-MN and all-MN
  to capture these concepts.

    (defun-sk some-MN () (exists x (or (M x) (N x))))
    (defun-sk all-MN () (forall x (and (M x) (N x))))

    (in-theory (disable all-MN all-MN-necc some-MN some-MN-suff))

  First consider proving property 1. The formal statement of this
  theorem would be: (iff (some-MN) (or (some-M) (some-N))).

  How do we prove this theorem? Looking at RT1-RT4 above, note that
  they suggest how one should reason about quantification when one
  has an ``implication''. But here we have an ``equivalence''. This
  suggests another rule of thumb.

      RT5: Whenever possible, prove an equivalence involving quantifiers by
      proving two implications.

  Let us apply RT5 to prove the theorems above. So we will first prove:
  (implies (some-MN) (or (some-M) (some-N)))

  How can we prove this? This involves assuming a quantified predicate
  (some-MN), so we must use RT2 and apply the definition of some-MN.
  Since the conclusion involves a disjunction of two quantified
  predicates, by RT1 we must be able to construct two objects A and B
  such that either M holds for A or N holds for B, so that we can
  then invoke some-M-suff and some-N-suff to prove the conclusion.
  But now notice that if some-MN is true, then there is already an
  object, in fact some-MN-witness, such that either M holds for it,
  or N holds for it. And we know this is the case from the definition
  of some-MN! So we will simply prove the theorem instantiating
  some-M-suff and some-N-suff with this witness. The conclusion is
  that the following event will go through with ACL2.

    (defthm le1
      (implies (some-MN)
               (or (some-M) (some-N)))
      :rule-classes nil
      :hints ((\"Goal\"
                :use ((:instance (:definition some-MN))
                      (:instance some-M-suff
                                 (x (some-MN-witness)))
                      (:instance some-N-suff
                                 (x (some-MN-witness)))))))

  This also suggests the following rule of thumb:

      RT6: If a conjecture involves assuming an existentially quantified
      predicate in the hypothesis from which you are trying to prove
      an existentially quantified predicate, use the witness of the
      existential quantification in the hypothesis to construct the
      witness for the existential quantification in the conclusion.

  Let us now try to prove the converse of le1, that is: (implies (or
  (some-M) (some-N)) (some-MN))

  Since the hypothesis is a disjunction, we will just prove each case
  individually instead of proving the theorem by a :cases hint. So we
  prove the following two lemmas.

    (defthm le2
      (implies (some-M) (some-MN))
      :rule-classes nil
      :hints ((\"Goal\"
                :use ((:instance (:definition some-M))
                      (:instance some-MN-suff
                                 (x (some-M-witness)))))))

    (defthm le3
      (implies (some-N) (some-MN))
      :rule-classes nil
      :hints ((\"Goal\"
                :use ((:instance (:definition some-N))
                      (:instance some-MN-suff
                                 (x (some-N-witness)))))))

  Note that the hints above are simply applications of RT6 as in le1.
  With these lemmas, of course the main theorem is trivial.

    (defthmd |some disjunction|
      (iff (some-MN) (or (some-M) (some-N)))
      :hints ((\"Goal\"
                :use ((:instance le1)
                      (:instance le2)
                      (:instance le3)))))

  Let us now prove the distributivity of universal quantification over
  conjunction, that is, the formula: (iff (all-MN) (and (all-M)
  (all-N)))

  Applying RT5, we will again decompose this into two implications. So
  consider first the one-way implication: (implies (and (all-M)
  (all-N)) (all-MN)).

  Here we get to assume all-M and all-N. Thus by RT4 we can use
  all-M-necc and all-N-necc to think as if we are given the formulas
  (M x) and (N x) as theorems. The conclusion here is also a
  universal quantification, namely we have to prove all-MN. Then RT3
  tells us to proceed as follows. Take any object y. Try to find an
  instantiation z of the hypothesis that implies (and (M y) (N y)).
  Then instantiate y with all-MN-witness. Note that the hypothesis
  lets us assume (M x) and (N x) to be theorems. Thus to justify we
  need to instantiate x with y, and in this case, therefore, with
  all-MN-witness. To make the long story short, the following event
  goes through with ACL2:

    (defthm lf1
       (implies (and (all-M) (all-N))
                (all-MN))
        :rule-classes nil
        :hints ((\"Goal\"
                  :use ((:instance (:definition all-MN))
                        (:instance all-M-necc (x (all-MN-witness)))
                        (:instance all-N-necc (x (all-MN-witness)))))))

  This suggests the following rule of thumb which is a dual of RT6:

      RT7: If a conjecture assumes some universally quantified predicate in
      the hypothesis and its conclusion asserts a universallly
      quantified predicate, then instantiate the ``necessary
      condition'' (forall-mn-necc) of the hypothesis with the witness
      of the conclusion to prove the conjecture.

  Applying RT7 now we can easily prove the other theorems that we need
  to show that universal quantification distributes over conjunction.
  Let us just go through this motion in ACL2.

    (defthm lf2
      (implies (all-MN)
               (all-M))
      :rule-classes nil
      :hints ((\"Goal\"
                :use ((:instance (:definition all-M))
                      (:instance all-MN-necc
                                 (x (all-M-witness)))))))

    (defthm lf3
      (implies (all-MN)
               (all-N))
      :rule-classes nil
      :hints ((\"Goal\"
                :use ((:instance (:definition all-N))
                      (:instance all-MN-necc
                                 (x (all-N-witness)))))))

    (defthmd |all conjunction|
      (iff (all-MN)
           (and (all-M) (all-N)))
     :hints ((\"Goal\" :use ((:instance lf1)
                           (:instance lf2)
                           (:instance lf3)))))

  The rules of thumb for universal and existential quantification
  should make you realize the duality of their use. Every reasoning
  method about universal quantification can be cast as a way of
  reasoning about existential quantification, and vice versa. Whether
  you reason using universal and existential quantifiers depends on
  what is natural in a particular context. But just for the sake of
  completeness let us prove the duality of universal and existential
  quantifiers. So what we want to prove is the following:

    3.  (forall x (not (M x))) = (not (exists x (M x)))

  We first formalize the notion of (forall x (not (M x))) as a
  quantification.

    (defun-sk none-M () (forall x (not (M x))))
    (in-theory (disable none-M none-M-necc))

  So we now want to prove: (equal (none-M) (not (some-M))).

  As before, we should prove this as a pair of implications. So let us
  prove first: (implies (none-M) (not (some-M))).

  This may seem to assert an existential quantification in the
  conclusion, but rather, it asserts the negation of an existential
  quantification. We are now trying to prove that something does not
  exist. How do we do that? We can show that nothing satisfies M by
  just showing that (some-M-witness) does not satisfy M. This
  suggests the following rule of thumb:

      RT8: When you encounter the negation of an existential quantification
      think in terms of a universal quantification, and vice-versa.

  Ok, so now applying RT8 and RT3 you should be trying to apply the
  definition of some-M. The hypothesis is just a pure (non-negated)
  universal quantification so you should apply RT4. A blind
  application lets us prove the theorem as below.

    (defthm nl1
      (implies (none-M) (not (some-M)))
      :rule-classes nil
      :hints ((\"Goal\"
                :use ((:instance (:definition some-M))
                      (:instance none-M-necc (x (some-M-witness)))))))

  How about the converse implication? I have deliberately written it as
  (implies (not (none-M)) (some-M)) instead of switching the
  left-hand and right-hand sides of nl1, which would have been
  equivalent. Again, RH8 tells us how to reason about it, in this
  case using RH2, and we succeed.

    (defthm nl2
      (implies (not (none-M)) (some-M))
      :rule-classes nil
      :hints ((\"Goal\"
                :use ((:instance (:definition none-M))
                      (:instance some-M-suff (x (none-M-witness)))))))

  So finally we just go through the motions of proving the equality.

    (defthmd |forall not = not exists|
      (equal (none-M) (not (some-M)))
      :hints ((\"Goal\"
                :use ((:instance nl1)
                      (:instance nl2)))))

  Let us now see if we can prove a slightly more advanced theorem which
  can be stated informally as: If there is a natural number x which
  satisfies M, then there is a least natural number y that satisfies
  M.

  [Note: Any time I have had to reason about existential quantification
  I have had to do this particular style of reasoning and state that
  if there is an object satisfying a predicate, then there is also a
  ``minimal'' object satisfying the predicate.]

  Let us formalize this concept. We first define the concept of
  existence of a natural number satisfying x.

    (defun-sk some-nat-M () (exists x (and (natp x) (M x))))
    (in-theory (disable some-nat-M some-nat-M-suff))

  We now talk about what it means to say that x is the least number
  satisfying M.

    (defun-sk none-below (y)
      (forall r (implies (and (natp r) (< r y)) (not (M r))))))
    (in-theory (disable none-below none-below-necc))

    (defun-sk min-M () (exists y (and (M y) (natp y) (none-below y))))
    (in-theory (disable min-M min-M-suff))

  The predicate none-below says that no natural number less than y
  satisfies M. The predicate min-M says that there is some natural
  number y satisfying M such that none-below holds for y.

  So the formula we want to prove is: (implies (some-nat-M) (min-M)).

  Since the formula requires that we prove an existential
  quantification, RT1 tells us to construct some object satisfying
  the predicate over which we are quantifying. We should then be able
  to instantiate min-M-suff with this object. That predicate says
  that the object must be the least natural number that satisfies M.
  Since such an object is uniquely computable if we know that there
  exists some natural number satisfying M, let us just write a
  recursive function to compute it. This function is least-M below.

    (defun least-M-aux (i bound)
      (declare (xargs :measure (nfix (- (1+ bound) i))))
      (cond ((or (not (natp i))
                 (not (natp bound))
                 (> i bound))
             0)
           ((M i) i)
           (t (least-M-aux (+ i 1) bound))))

    (defun least-M (bound) (least-M-aux 0 bound))

  Let us now reason about this function as one does typically. So we
  prove that this object is indeed the least natural number that
  satisfies M, assuming that bound is a natural number that satisfies
  M.

    (defthm least-aux-produces-an-M
      (implies (and (natp i)
                    (natp bound)
                    (<= i bound)
                    (M bound))
               (M (least-M-aux i bound))))

    (defthm least-<=bound
      (implies (<= 0 bound)
               (<= (least-M-aux i bound) bound)))

    (defthm least-aux-produces-least
      (implies (and (natp i)
                    (natp j)
                    (natp bound)
                    (<= i j)
                    (<= j bound)
                    (M j))
                (<= (least-M-aux i bound) j)))

    (defthm least-aux-produces-natp
      (natp (least-M-aux i bound)))

    (defthmd least-is-minimal-satisfying-m
      (implies (and (natp bound)
                    (natp i)
                     (< i (least-M bound)))
               (not (M i)))
      :hints ((\"Goal\"
                :in-theory (disable least-aux-produces-least least-<=bound)
                :use ((:instance least-<=bound
                                 (i 0))
                      (:instance least-aux-produces-least
                                 (i 0)
                                 (j i))))))

    (defthm least-has-m
      (implies (and (natp bound)
                    (m bound))
               (M (least-M bound))))

    (defthm least-is-natp
      (natp (least-M bound)))

  So we have done that, and hopefully this is all that we need about
  least-M. So we disable everything.

    (in-theory (disable least-M natp))

  Now of course we note that the statement of the conjecture we are
  interested in has two quantifiers, an inner forall (from
  none-below) and an outer exists (from min-M). Since ACL2 is not
  very good with quantification, we hold its hands to reason with the
  quantifier part. So we will first prove something about the forall
  and then use it to prove what we need about the exists.

      RT9: When you face nested quantifiers, reason about each nesting
      separately.

  So what do we want to prove about the inner quantifier? Looking
  carefully at the definition of none-below we see that it is saying
  that for all natural numbers r < y, (M r) does not hold. Well, how
  would we want to use this fact when we want to prove our final
  theorem? We expect that we will instantiate min-M-suff with the
  object (least-M bound) where we know (via the outermost existential
  quantifier) that M holds for bound, and we will then want to show
  that none-below holds for (least-M bound). So let us prove that for
  any natural number (call it bound), none-below holds for (least-M
  bound). For the final theorem we only need it for natural numbers
  satisfying M, but note that from the lemma
  least-is-minimal-satisfying-m we really do not need that bound
  satisfies M.

  So we are now proving: (implies (natp bound) (none-below (least-M
  bound))).

  Well since this is a standard case of proving a universally
  quantified predicate, we just apply RT3. We have proved that for
  all naturals i < (least-M bound), i does not satisfy M (lemma
  least-is-minimal-satisfying-M), so we merely need the instantiation
  of that lemma with none-below-witness of the thing we are trying to
  prove, that is, (least-M bound). The theorem below thus goes
  through.

    (defthm least-is-minimal
      (implies (natp bound)
               (none-below (least-M bound)))
      :hints ((\"Goal\"
                :use ((:instance (:definition none-below)
                                 (y (least-M bound)))
                      (:instance least-is-minimal-satisfying-m
                                 (i (none-below-witness (least-M bound))))))))

  Finally we are in the outermost existential quantifier, and are in
  the process of applying min-M-suff. What object should we
  instantiate it with? We must instantiate it with (least-M bound)
  where bound is an object which must satisfy M and is a natural. We
  have such an object, namely (some-nat-M-witness) which we know have
  all these qualities given the hypothesis. So the proof now is just
  RT1 and RT2.

    (defthm |minimal exists|
      (implies (some-nat-M) (min-M))
      :hints ((\"Goal\"
                :use ((:instance min-M-suff
                                 (y (least-M (some-nat-M-witness))))
                      (:instance (:definition some-nat-M))))))

  If you are comfortable with the reasoning above, then you are
  comfortable with quantifiers and probably will not need these notes
  any more. In my opinion, the best way of dealing with ACL2 is to
  ask yourself why you think something is a theorem, and the rules of
  thumb above are simply guides to the questions that you need to ask
  when you are dealing with quantification.

  Here are a couple of simple exercises for you to test if you
  understand the reasoning process.

  Exercise 1. Formalize and prove the following theorem. Suppose there
  exists x such that (R x) and suppose that all x satisfy (P x). Then
  prove that there exists x such that (P x) & (R x). (See
  {http://www.cs.utexas.edu/users/moore/acl2/contrib/quantifier-exercise-1-solution.html
  |
  http://www.cs.utexas.edu/users/moore/acl2/contrib/quantifier-exercise-1-solution.html}
  for a solution.)

  Exercise 2. Recall the example just before the preceding exercise,
  where we showed that if there exists a natural number x satisfying
  M then there is another natural number y such that y satisfies M
  and for every natural number z < y, z does not. What would happen
  if we remove the restriction of x, y, and z being naturals? Of
  course, we will not talk about < any more, but suppose you use a
  total order on all ACL2 objects such as [<<]. More concretely,
  consider the definition of some-M above. Let us now define two
  other functions:

    (include-book \"misc/total-order\" :dir :system)

    (defun-sk none-below-2 (y)
      (forall r (implies (<< r y) (not (M r)))))

    (defun-sk min-M2 () (exists y (and (M y) (none-below-2 y))))

  The question is whether (implies (some-M) (min-M2)) is a theorem. Can
  you prove it? Can you disprove it?")
 (QUANTIFIERS
  (DEFUN-SK)
  "Issues about quantification in ACL2

  ACL2 supports first-order quantifiers [exists] and [forall] by way of
  the [defun-sk] event. However, proof support for quantification is
  quite limited. Therefore, you may prefer using recursion in place
  of defun-sk when possible (following common ACL2 practice).

  For example, the notion ``every member of x has property p'' can be
  defined either with recursion or explicit quantification, but
  proofs may be simpler when recursion is used. We illustrate this
  point with two proofs of the same informal claim, one of which uses
  recursion which the other uses explicit quantification. Notice that
  with recursion, the proof goes through fully automatically; but
  this is far from true with explicit quantification (especially
  notable is the ugly hint).

  The informal claim for our examples is: If every member a of each of
  two lists satisfies the predicate (p a), then this holds of their
  [append]; and, conversely.

  See [quantifiers-using-recursion] for a solution to this example
  using recursion.

  See [quantifiers-using-defun-sk] for a solution to this example using
  [defun-sk]. Also See [quantifiers-using-defun-sk-extended] for an
  elaboration on that solution.

  But perhaps first, see [defun-sk] for an ACL2 utility to introduce
  first-order quantification in a direct way. Examples of the use of
  defun-sk are also available: see [defun-sk-example] and see
  [Tutorial4-Defun-Sk-Example] for basic examples, and see
  [quantifier-tutorial] for a more complete, careful beginner's
  introduction that takes you through typical kinds of
  quantifier-based reasoning in ACL2.


Subtopics

  [Quantifiers-using-defun-sk]
      Quantification example

  [Quantifiers-using-defun-sk-extended]
      Quantification example with details

  [Quantifiers-using-recursion]
      Recursion for implementing quantification")
 (QUANTIFIERS-USING-DEFUN-SK
  (QUANTIFIERS)
  "Quantification example

  See [quantifiers] for the context of this example. It should be
  compared to a corresponding example in which a simpler proof is
  attained by using recursion in place of explicit quantification;
  see [quantifiers-using-recursion].

    (in-package \"ACL2\")

    ; We prove that if every member A of each of two lists satisfies the
    ; predicate (P A), then this holds of their append; and, conversely.

    ; Here is a solution using explicit quantification.

    (defstub p (x) t)

    (defun-sk forall-p (x)
      (forall a (implies (member a x)
                         (p a))))

    (defthm member-append
      (iff (member a (append x1 x2))
           (or (member a x1) (member a x2))))

    (defthm forall-p-append
      (equal (forall-p (append x1 x2))
             (and (forall-p x1) (forall-p x2)))
      :hints ((\"Goal\" ; ``should'' disable forall-p-necc, but no need
               :use
               ((:instance forall-p-necc
                           (x (append x1 x2))
                           (a (forall-p-witness x1)))
                (:instance forall-p-necc
                           (x (append x1 x2))
                           (a (forall-p-witness x2)))
                (:instance forall-p-necc
                           (x x1)
                           (a (forall-p-witness (append x1 x2))))
                (:instance forall-p-necc
                           (x x2)
                           (a (forall-p-witness (append x1 x2))))))))

  Also see [quantifiers-using-defun-sk-extended] for an elaboration on
  this example.")
 (QUANTIFIERS-USING-DEFUN-SK-EXTENDED
  (QUANTIFIERS)
  "Quantification example with details

  See [quantifiers-using-defun-sk] for the context of this example.

    (in-package \"ACL2\")

    ; We prove that if every member A of each of two lists satisfies the
    ; predicate (P A), then this holds of their append; and, conversely.

    ; Here is a solution using explicit quantification.

    (defstub p (x) t)

    (defun-sk forall-p (x)
      (forall a (implies (member a x)
                         (p a))))

    ; The defun-sk above introduces the following axioms.  The idea is that
    ; (FORALL-P-WITNESS X) picks a counterexample to (forall-p x) if there is one.

    ;   (DEFUN FORALL-P (X)
    ;     (LET ((A (FORALL-P-WITNESS X)))
    ;          (IMPLIES (MEMBER A X) (P A))))
    ;
    ;   (DEFTHM FORALL-P-NECC
    ;     (IMPLIES (NOT (IMPLIES (MEMBER A X) (P A)))
    ;              (NOT (FORALL-P X)))
    ;     :HINTS ((\"Goal\" :USE FORALL-P-WITNESS)))

    ; The following lemma seems critical.

    (defthm member-append
      (iff (member a (append x1 x2))
           (or (member a x1) (member a x2))))

    ; The proof of forall-p-append seems to go out to lunch, so we break into
    ; directions as shown below.

    (defthm forall-p-append-forward
      (implies (forall-p (append x1 x2))
               (and (forall-p x1) (forall-p x2)))
      :hints ((\"Goal\" ; ``should'' disable forall-p-necc, but no need
               :use
               ((:instance forall-p-necc
                           (x (append x1 x2))
                           (a (forall-p-witness x1)))
                (:instance forall-p-necc
                           (x (append x1 x2))
                           (a (forall-p-witness x2)))))))

    (defthm forall-p-append-reverse
      (implies (and (forall-p x1) (forall-p x2))
               (forall-p (append x1 x2)))
      :hints ((\"Goal\"
               :use
               ((:instance forall-p-necc
                           (x x1)
                           (a (forall-p-witness (append x1 x2))))
                (:instance forall-p-necc
                           (x x2)
                           (a (forall-p-witness (append x1 x2))))))))

    (defthm forall-p-append
      (equal (forall-p (append x1 x2))
             (and (forall-p x1) (forall-p x2)))
      :hints ((\"Goal\" :use (forall-p-append-forward
                            forall-p-append-reverse))))")
 (QUANTIFIERS-USING-RECURSION
  (QUANTIFIERS)
  "Recursion for implementing quantification

  The following example illustrates the use of recursion as a means of
  avoiding proof difficulties that can arise from the use of explicit
  quantification (via [defun-sk]). See [quantifiers] for more about
  the context of this example.

    (in-package \"ACL2\")

    ; We prove that if every member A of each of two lists satisfies the
    ; predicate (P A), then this holds of their append; and, conversely.

    ; Here is a solution using recursively-defined functions.

    (defstub p (x) t)

    (defun all-p (x)
      (if (atom x)
          t
        (and (p (car x))
             (all-p (cdr x)))))

    (defthm all-p-append
      (equal (all-p (append x1 x2))
             (and (all-p x1) (all-p x2))))")
 (QUICK-AND-DIRTY-SUBSUMPTION-REPLACEMENT-STEP
  (MISCELLANEOUS)
  "(advanced topic) controlling a heuristic in the prover's clausifier

  This topic is probably only of interest to those who are undertaking
  particularly complex proof developments.

  The ACL2 prover's handling of propositional logic uses a heuristic
  that we believe might cause the prover to slow down significantly
  or even to trigger a stack overflow. However, we believe these
  negative effects are only felt on very large formulas --- formulas
  that are likely to cause similar degradation of many other parts of
  ACL2.

  The following two events turn off that heuristic (by eliminating
  calls to source function
  quick-and-dirty-subsumption-replacement-step, after which this
  [documentation] topic is named).

    (defun quick-and-dirty-srs-off (cl1 ac)
      (declare (ignore cl1 ac)
               (xargs :mode :logic :guard t))
      nil)

    (defattach quick-and-dirty-srs quick-and-dirty-srs-off)

  However, if you feel the need to try this out, please remember that
  the proof is likely to fail anyway since other parts of ACL2 will
  probably be stressed. A more basic problem with your proof strategy
  may exist: the formulas are getting extraordinarily large. A common
  approach for avoiding such problem include disabling functions (see
  [in-theory]). Other less common approaches might help if you are
  sufficiently desperate, such as defining your own IF function to
  use in place of the built-in IF.

  If you do find an example for which the above two events provide
  significant benefit, we (the ACL2 implementors) would be interested
  in hearing about it.

  To turn the heuristic back on:

    (defattach quick-and-dirty-srs quick-and-dirty-srs-builtin)")
 (QUIT (GOOD-BYE)
       "Quit entirely out of Lisp

  Same as [good-bye].")
 (QUOTE
  (BASICS ACL2-BUILT-INS)
  "Create a constant

  The form (quote x) evaluates to x. See any Common Lisp documentation.
  Also see [unquote].


Subtopics

  [Unquote]
      Obtain the object being quoted")
 (R-EQLABLE-ALISTP
  (ALISTS ACL2-BUILT-INS)
  "Recognizer for a true list of pairs whose [cdr]s are suitable for
  [eql]

  The predicate r-eqlable-alistp tests whether its argument is a
  [true-listp] of [consp] objects whose [cdr]s all satisfy
  [eqlablep].

  Function: 

    (defun r-eqlable-alistp (x)
           (declare (xargs :guard t))
           (cond ((atom x) (equal x nil))
                 (t (and (consp (car x))
                         (eqlablep (cdr (car x)))
                         (r-eqlable-alistp (cdr x))))))")
 (R-SYMBOL-ALISTP
  (ALISTS ACL2-BUILT-INS)
  "Recognizer for association lists with symbols as values

  (R-symbol-alistp x) is true if and only if x is a list of pairs of
  the form (cons key val) where val is a [symbolp].

  Function: 

    (defun r-symbol-alistp (x)
           (declare (xargs :guard t))
           (cond ((atom x) (equal x nil))
                 (t (and (consp (car x))
                         (symbolp (cdr (car x)))
                         (r-symbol-alistp (cdr x))))))")
 (RANDOM$
  (STATE NUMBERS ACL2-BUILT-INS)
  "Obtain a random value

    Example:
    (random$ 10 state) ==> (mv 7 )

  (Random$ limit state), where limit is a positive integer, returns a
  random non-negative integer together with a new [state]. Logically,
  it simply returns the first element of a list that is a field of
  the ACL2 [state], called the acl2-oracle (see [read-ACL2-oracle]),
  together with the new state resulting from removing that element
  from that list. (Except, if that element is not in range as
  specified above, then 0 is returned.) However, random$ actually
  invokes a Common Lisp function to choose the integer returned.
  Quoting from the Common Lisp HyperSpec(TM),
  {http://www.lispworks.com/documentation/HyperSpec/Front |
  http://www.lispworks.com/documentation/HyperSpec/Front}: ``An
  approximately uniform choice distribution is used... each of the
  possible results occurs with (approximate) probability 1/limit.''

  Consider enabling rules natp-random$ and random$-linear if you want
  to reason about random$.

  Function: 

    (defun random$ (limit state)
           (declare (type (integer 1 *) limit)
                    (xargs :stobjs state))
           (mv-let (erp val state)
                   (read-acl2-oracle state)
                   (mv (cond ((and (null erp)
                                   (natp val)
                                   (< val limit))
                              val)
                             (t 0))
                       state)))")
 (RASSOC
  (ALISTS ACL2-BUILT-INS)
  "Look up value in association list

    General Forms:
    (rassoc x alist)
    (rassoc x alist :test 'eql)   ; same as above (eql as equality test)
    (rassoc x alist :test 'eq)    ; same, but eq is equality test
    (rassoc x alist :test 'equal) ; same, but equal is equality test

  (Rassoc x alist) is the first member of alist whose [cdr] is x, or
  nil if no such member exists. (rassoc x alist) is thus similar to
  (assoc x alist), the difference being that it looks for the first
  pair in the given alist whose [cdr], rather than [car], is [eql] to
  x. See [assoc]. The optional keyword, :TEST, has no effect
  logically, but provides the test (default [eql]) used for comparing
  x with the [cdr]s of successive elements of lst.

  The [guard] for a call of rassoc depends on the test. In all cases,
  the second argument must satisfy [alistp]. If the test is [eql],
  then either the first argument must be suitable for [eql] (see
  [eqlablep]) or the second argument must satisfy [r-eqlable-alistp].
  If the test is [eq], then either the first argument must be a
  symbol or the second argument must satisfy [r-symbol-alistp].

  See [equality-variants] for a discussion of the relation between
  rassoc and its variants:

      (rassoc-eq x lst) is equivalent to (rassoc x lst :test 'eq);

      (rassoc-equal x lst) is equivalent to (rassoc x lst :test 'equal).

  In particular, reasoning about any of these primitives reduces to
  reasoning about the function rassoc-equal.

  Function: 

    (defun rassoc-equal (x alist)
           (declare (xargs :guard (alistp alist)))
           (cond ((endp alist) nil)
                 ((equal x (cdr (car alist)))
                  (car alist))
                 (t (rassoc-equal x (cdr alist)))))

  Rassoc is defined by Common Lisp. See any Common Lisp documentation
  for more information.")
 (RASSOC-EQ (POINTERS) "See [rassoc].")
 (RASSOC-EQUAL (POINTERS)
               "See [rassoc].")
 (RATIONAL-LISTP
  (NUMBERS LISTS ACL2-BUILT-INS)
  "Recognizer for a true list of rational numbers

  The predicate rational-listp tests whether its argument is a true
  list of rational numbers.

  Function: 

    (defun rational-listp (l)
           (declare (xargs :guard t))
           (cond ((atom l) (eq l nil))
                 (t (and (rationalp (car l))
                         (rational-listp (cdr l))))))")
 (RATIONALP
  (NUMBERS ACL2-BUILT-INS)
  "Recognizer for rational numbers (ratios and integers)

  (rationalp x) is true if and only if x is an rational number.")
 (READ-ACL2-ORACLE
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Pop the oracle field of the state

  ACL2 has a mutable `state' that contains a number of fields; see
  [state]. One of these fields is a list, called the acl2-oracle
  field. There are no constraints on the elements of this list; thus,
  you will not be able to prove anything about those elements.
  However, as a convenience, ACL2 permits you to evaluate the form
  (read-acl2-oracle state), which returns the multiple value (mv nil
  nil state).

  The ACL2 implementation uses read-acl2-oracle, but you will likely
  find this function to be useless unless you do advanced, scurrilous
  things using trust tags (see [defttag]).

  The following definition is the logical definition of
  read-acl2-oracle, but as explained above does not really
  characterize its behavior under the hood.

  Function: 

    (defun read-acl2-oracle (state-state)
           (declare (xargs :guard (state-p1 state-state)))
           (mv (null (acl2-oracle state-state))
               (car (acl2-oracle state-state))
               (update-acl2-oracle (cdr (acl2-oracle state-state))
                                   state-state)))")
 (READ-BYTE$ (POINTERS) "See [io].")
 (READ-CHAR$ (POINTERS) "See [io].")
 (READ-OBJECT (POINTERS) "See [io].")
 (READ-RUN-TIME
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Read elapsed runtime

  By default, (read-run-time state) returns (mv runtime state), where
  runtime is the elapsed runtime in seconds since the start of the
  current ACL2 session and state is the resulting ACL2 [state]. But
  read-run-time can be made to return elapsed realtime (wall clock
  time) instead; see [get-internal-time].

  The logical definition probably won't concern many users, but for
  completeness, we say a word about it here. That definition uses the
  function [read-ACL2-oracle], which modifies state by popping the
  value to return from its acl2-oracle field.

  Function: 

    (defun
       read-run-time (state-state)
       (declare (xargs :guard (state-p1 state-state)))
       (mv (cond ((or (null (acl2-oracle state-state))
                      (not (rationalp (car (acl2-oracle state-state)))))
                  0)
                 (t (car (acl2-oracle state-state))))
           (update-acl2-oracle (cdr (acl2-oracle state-state))
                               state-state)))")
 (READER
  (MISCELLANEOUS)
  "Reading expressions in the ACL2 read-eval-print loop

  The ACL2 read-eval-print loop reads expressions much like they are
  read in any Common Lisp read-eval-print loop. For example, you may
  use the single tick symbol (') for quote and also the backquote
  symbol (`) with its escapes, comma (,) and comma-atsign (,@). See
  any Common Lisp reference or tutorial.

  ACL2-specific reader macros include its reading of expressions in a
  specified package (using #! --- see [sharp-bang-reader]), its
  restriction of read-time evaluation to constants introduced by
  [defconst] (using #. --- see [sharp-dot-reader]), and the ability
  to put underscores in numeric constants (using #u --- see
  [sharp-u-reader]).

  See [set-iprint] for how to make ACL2 print expressions like #@2#
  that can be read back in.

  Strictly speaking, there is nothing special about how the reader
  handles [keyword]s in the input. But see [keyword-commands] for how
  ACL2 may interpret a top-level keyword command.

  We conclude this topic with a log that illustrates features discussed
  above. Comments of the form {{..}} have been inserted manually.

    ACL2 !>(defconst *c* (+ 3 4))

    Summary
    Form:  ( DEFCONST *C* ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     *C*
    ACL2 !>'(a #.*c* 17)
    ;{{See :doc sharp-dot-reader.
    ;  Notice that #.*c* is read as the value of *c*, thus,
    ;  as 7 rather than as (+ 3 4).}}
    (A 7 17)
    ACL2 !>'(a #.(+ 5 6) 17)
    ;{{But this is not legal in ACL2, as #. must be followed by
    ;  a known constant symbol.}}

    ***********************************************
    ************ ABORTING from raw Lisp ***********
    Error:  ACL2 supports #. syntax only for #.*a*, where *a* has been
    defined by DEFCONST.  Thus the form #.(+ 5 6) is illegal.
    ***********************************************

    ;{{Additional output here has been omitted in this log.}}
    ACL2 !>(defpkg \"FOO\" nil)

    Summary
    Form:  ( DEFPKG \"FOO\" ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     \"FOO\"
    ACL2 !>#!foo'(a b c)
    ;{{See :doc sharp-bang-reader.  The prefix \"#!foo\" causes
    ;  the s-expression after it to be read into the \"FOO\" package.}}
    (FOO::A FOO::B FOO::C)
    ACL2 !>#x100a
    ;{{As in Common Lisp, \"#x\" causes the digits after it to be read in hex.}}
    4106
    ACL2 !>#ux10_0a
    ;{{The \"#u\" prefix allows underscores in the numeral after it.  Those
    ;  underscores are ignored, but can improve readability.}}
    4106
    ACL2 !>(set-iprint t)
    ;{{See :DOC set-print.  This causes \"#@1#\" below to be printed.}}

    ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
    ACL2 !>(set-evisc-tuple (evisc-tuple 3   ; print-level
                                         4   ; print-length
                                         nil ; alist
                                         nil ; hiding-cars
                                         )
                            :sites :ld)
    ;{{Abbreviate the printing of top-level evaluation results.
    ;  See :doc set-evisc-tuple.}}
     (:LD)
    ACL2 !>(make-list 10)
    (NIL NIL NIL NIL . #@1#)
    ACL2 !>'#@1#
    ;{{Note that the reader replaces #@1# with the value that was stored there.}}
    (NIL NIL NIL NIL . #@2#)
    ACL2 !>(without-evisc '(NIL NIL NIL NIL . #@1#))
    ;{{See :doc without-evisc.}}
    (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)
    ACL2 !>(set-evisc-tuple nil :sites :ld)
     (:LD)
    ACL2 !>(let ((x '(3 4)))
             `(a b ,x c))
    ;{{As in Common Lisp, backquote can be escaped by comma.}}
    (A B (3 4) C)
    ACL2 !>(let ((x '(3 4)))
             `(a b ,@x c))
    ;{{As in Common Lisp, backquote can be escaped by comma-atsign, which
    ;  splices its value into the list.}}
    (A B 3 4 C)
    ACL2 !>


Subtopics

  [Fancy-string-reader]
      A friendly syntax for strings literals that have backslashes and
      quotes.

  [Sharp-bang-reader]
      Package prefix that is not restricted to symbols

  [Sharp-dot-reader]
      Read-time evaluation of constants

  [Sharp-u-reader]
      Allow underscore characters in numbers")
 (REAL
  (ACL2)
  "ACL2(r) support for real numbers

  ACL2 supports rational numbers but not real numbers. However,
  starting with Version 2.5, a variant of ACL2 called ``ACL2(r)''
  supports the real numbers by way of non-standard analysis. ACL2(r)
  was conceived and first implemented by Ruben Gamboa in his Ph.D.
  dissertation work, supervised by Bob Boyer with active
  participation by Matt Kaufmann.

  ACL2(r) has the same source files as ACL2. After you download ACL2,
  you can build ACL2(r) by executing the following command on the
  command line in your acl2-sources directory, replacing 
  with a path to your Lisp executable:

    make large-acl2r LISP=

  This will create an executable in your acl2-sources directory named
  saved_acl2r.

  Note that if you download [community-books] as tarfiles, then you
  will automatically be obtaining the books to be certified with
  ACL2(r). They can be certified from your acl2-sources directory,
  shown here as :

    make regression ACL2=/saved_acl2r

  To check that you are running ACL2(r), see if the prompt includes the
  string ``(r)'', e.g.:

    ACL2(r) !>

  Or, look at (@ acl2-version) and see if ``(r)'' is a substring.

  In ACL2 (as opposed to ACL2(r)), when we say ``real'' we mean
  ``rational.''

  Caution: ACL2(r) should be considered experimental: although we
  (Kaufmann and Moore) have carefully completed Gamboa's integration
  of the reals into the ACL2 source code, our primary concern has
  been to ensure unchanged behavior when ACL2 is compiled in the
  default manner, i.e., without the non-standard extensions. As for
  every release of ACL2, at the time of a release we are unaware of
  soundness bugs in ACL2 or ACL2(r).

  There is only limited documentation on the non-standard features of
  ACL2(r). We hope to provide more documentation for such features in
  future releases. Please feel free to query the authors if you are
  interested in learning more about ACL2(r). Gamboa's dissertation
  may also be helpful.


Subtopics

  [I-close]
      ACL2(r) test for whether two numbers are infinitesimally close

  [I-large]
      ACL2(r) recognizer for infinitely large numbers

  [I-limited]
      ACL2(r) recognizer for limited numbers

  [I-small]
      ACL2(r) recognizer for infinitesimal numbers

  [Real-listp]
      ACL2(r) recognizer for a true list of real numbers

  [Standard-part]
      ACL2(r) function mapping limited numbers to standard numbers

  [Standardp]
      ACL2(r) recognizer for standard objects")
 (REAL-LISTP
  (REAL LISTS ACL2-BUILT-INS)
  "ACL2(r) recognizer for a true list of real numbers

  The predicate real-listp tests whether its argument is a true list of
  real numbers. This predicate is only defined in ACL2(r) (see
  [real]).")
 (REAL/RATIONALP
  (NUMBERS ACL2-BUILT-INS)
  "Recognizer for rational numbers (including real number in ACL2(r))

  For most ACL2 users, this is a macro abbreviating [rationalp]. In
  ACL2(r) (see [real]), this macro abbreviates the predicate realp,
  which holds for real numbers as well (including rationals). Most
  ACL2 users can ignore this macro and use [rationalp] instead, but
  many community books use real/rationalp so that these books will be
  suitable for ACL2(r) as well.")
 (REALFIX
  (NUMBERS ACL2-BUILT-INS)
  "Coerce to a real number

  Realfix simply returns any real number argument unchanged, returning
  0 on a non-real argument. Also see [nfix], see [ifix], see [rfix],
  and see [fix] for analogous functions that coerce to a natural
  number, an integer, a rational, and a number, respectively.

  Realfix has a [guard] of t.

  Function: 

    (defun realfix (x)
           (declare (xargs :guard t))
           (if (real/rationalp x) x 0))")
 (REALPART
  (NUMBERS ACL2-BUILT-INS)
  "Real part of a complex number

  Completion Axiom (completion-of-realpart):

    (equal (realpart x)
           (if (acl2-numberp x)
               (realpart x)
             0))

  [Guard] for (realpart x):

    (acl2-numberp x)")
 (REBUILD
  (LD)
  "A convenient way to reconstruct your old [state]

    Examples:
    ACL2 !>(rebuild \"project.lisp\")
    ACL2 !>(rebuild \"project.lisp\" t)
    ACL2 !>(rebuild \"project.lisp\" t :dir :system)
    ACL2 !>(rebuild \"project.lisp\" :all)
    ACL2 !>(rebuild \"project.lisp\" :query)
    ACL2 !>(rebuild \"project.lisp\" 'lemma-22)

  Rebuild allows you to assume all the [command]s in a given file or
  list, supplied in the first argument. Because rebuild processes an
  arbitrary sequence of [command]s with [ld-skip-proofsp] t, it is
  unsound! However, if each of these [command]s is in fact
  admissible, then processing them with rebuild will construct the
  same logical [state] that you would be in if you typed each
  [command] and waited through the proofs again. Thus, rebuild is a
  way to reconstruct a [state] previously obtained by proving your
  way through the [command]s.

  The second, optional argument to rebuild is a ``filter'' (see
  [ld-pre-eval-filter]) that lets you specify which [command]s to
  process. You may specify t, :all, :query, or a new logical name. t
  and :all both mean that you expect the entire file or list to be
  processed. :query means that you will be asked about each [command]
  in turn. A new name means that all [command]s will be processed as
  long as the name is new, i.e., rebuild will stop processing
  [command]s immediately after executing a [command] that introduces
  name. Rebuild will also stop if any [command] causes an error. You
  may therefore wish to plant an erroneous form in the file, e.g.,
  (mv t nil state), (see [ld-error-triples]), to cause rebuild to
  stop there. The form (i-am-here) is such a pre-defined form. If you
  do not specify a filter, rebuild will query you for one.

  Inspection of the definition of rebuild, e.g., via :[pc] rebuild-fn,
  will reveal that it is just a glorified call to the function [ld].
  See [ld] if you find yourself wishing that rebuild had additional
  functionality.

  If you supply the above ``filter'' argument, then you may also supply
  the keyword argument :dir, which is then passed to ld; see [ld].")
 (REDEF
  (LD)
  "A common way to set [ld-redefinition-action]

    Example and General Form:
    ACL2 !>:redef

  This command sets [ld-redefinition-action] to '(:query . :overwrite).

  This command allows redefinition of functions and other [events]
  without undoing, but with a query that requires the user to
  acknowledge that the redefinition is intentional. To avoid that
  query, see [redef!] or for more options, see
  [ld-redefinition-action].")
 (REDEF!
  (LD)
  "A common way to set [ld-redefinition-action]

    Example and General Form:
    ACL2 !>:redef!

  This command sets [ld-redefinition-action] to '(:warn! . :overwrite).

  This command allows redefinition of functions and other [events]
  without undoing, but with a warning. The command :[redef] is
  similar, but queries the user first before doing the redefinition.
  For more related options, see [ld-redefinition-action].")
 (REDEF+
  (LD)
  "System hacker's redefinition [command]

    Example and General Form:
    ACL2 !>:redef+
    ACL2 p!>

  This [command] is intended only for system hackers, not typical
  users. It sets [ld-redefinition-action] to '(:warn! . :overwrite),
  sets the default [defun-mode] to :[program], and invokes
  [set-state-ok] with value t. It also introduces (defttag :redef+),
  so that redefinition of system functions will be permitted; see
  [defttag]. Finally, it removes as untouchable (see
  [push-untouchable]) all variables and functions.

  WARNING: If the form (redef+) is used in a book, then including the
  book can leave you in a state in which dangerous actions are
  allowed, specifically: redefinition, and access to functions and
  variables normally prohibited because they are untouchable. To
  avoid this problem, insert the form ([redef-]) into your book after
  (redef+).

  To see the code for redef+, evaluate :trans1 (redef+). This [command]
  is intended for those who are modifying ACL2 source code
  definitions. Thus, note that even system functions can be redefined
  with a mere warning. Be careful!")
 (REDEF-
  (LD)
  "Turn off system hacker's redefinition [command]

    Example and General Form:
    ACL2 !>:redef-
    ACL2 p!>

  This macro, for system hackers only, is a convenient way to reverse
  the effects of :redef+. See [redef+]. We do not guarantee that
  :redef- will restore everything one might expect to its state
  before the earlier :redef+. To see exactly what :redef- does, look
  at its code, for example by evaluating :trans1 (redef-)")
 (REDEFINED-NAMES
  (WORLD)
  "To collect the names that have been redefined

    Example and General Forms:
    (redefined-names state)

  This function collects names that have been redefined in the current
  ACL2 [state]. :[Program] mode functions that were reclassified to
  :[logic] functions are not collected, since such reclassification
  cannot imperil soundness because it is allowed only when the new
  and old definitions are identical.

  Thus, if (redefined-names state) returns nil then no unsafe
  definitions have been made, regardless of [ld-redefinition-action].
  See [ld-redefinition-action].

  WARNING: This function does not report names that are not explicitly
  redefined in the current logical [world]. Consider for example:

    (encapsulate
     ()
     (defun foo () t)
     (local (defun foo () nil))
     (defthm foo-prop
       (equal (foo) nil)
       :rule-classes nil))

  If you attempt to call [certify-book] in the resulting world, ACL2
  will appropriately refuse to do the certification:

    ACL2 Error in (CERTIFY-BOOK \"foo\" ...):  At least one command in the
    current ACL2 world was executed while the value of state global variable
    'LD-REDEFINITION-ACTION was not nil:

      (DEFUN FOO NIL T)

    Certification is therefore not allowed in this world.  You can use
    :ubt to undo back through this command; see :DOC ubt.

  However, since the local redefinition of foo is gone in the
  certification world, (redefined-names state) will return nil.
  (Technical aside, to be ignored except for those interested in
  implementation details: ACL2 inhibits certify-book in this example
  because the definition of foo is the value of (global-val
  'redef-seen (w state)).)")
 (REDEFINING-PROGRAMS
  (PROGRAMMING)
  "An explanation of why we restrict redefinitions

  ACL2 does not in general allow the redefinition of functions because
  logical inconsistency can result: previously stored theorems can be
  rendered invalid if the axioms defining the functions involved are
  changed. However, to permit prototyping of both :[program] and
  :[logic] mode systems, ACL2 permits redefinition if the user has
  accepted logical responsibility for the consequences by setting
  [ld-redefinition-action] to an appropriate non-nil value. The
  refusal of ACL2 to support the unrestricted redefinition of
  :[program] mode functions may appear somewhat capricious. After
  all, what are the logical consequences of changing a definition if
  no axioms are involved?

  Three important points should be made before we discuss redefinition
  further.

  The first is that ACL2 does support redefinition (of both :[program]
  and :[logic] functions) when [ld-redefinition-action] is non-nil.

  The second is that a ``redefinition'' that does not change the mode,
  formals, guards, type declarations, stobjs, or body of a function
  is considered redundant and is permitted even when
  [ld-redefinition-action] is nil. We recognize and permit redundant
  definitions because it is not uncommon for two distinct [books] to
  share identical function definitions. When determining whether the
  body of a function is changed by a proposed redefinition, we
  actually compare the untranslated versions of the two bodies. See
  [term]. For example, redundancy is not recognized if the old body
  is (list a b) and the new body is (cons a (cons b nil)). We use the
  untranslated bodies because of the difficulty of translating the
  new body in the presence of the old syntactic information, given
  the possibility that the redefinition might attempt to change the
  [signature] of the function, i.e., the number of formals, the
  number of results, or the position of single-threaded objects in
  either.

  The third important point is that a ``redefinition'' that preserves
  the formals, guard, types, stobjs, and body but changes the mode
  from :[program] to :[logic] is permitted even when
  [ld-redefinition-action] is nil. That is what [verify-termination]
  does.

  This note addresses the temptation to allow redefinition of
  :[program] functions in situations other than the three described
  above. Therefore, suppose [ld-redefinition-action] is nil and
  consider the cases.

  Case 1. Suppose the new definition attempts to change the formals or
  more generally the [signature] of the function. Accepting such a
  redefinition would render ill-formed other :[program] functions
  which call the redefined function. Subsequent attempts to evaluate
  those callers could arbitrarily damage the Common Lisp image. Thus,
  redefinition of :[program] functions under these circumstances
  requires the user's active approval, as would be sought with
  [ld-redefinition-action] '(:query . :overwrite).

  Case 2. Suppose the new definition attempts to change the body (even
  though it preserves the [signature]). At one time we believed this
  was acceptable and ACL2 supported the quiet redefinition of
  :[program] mode functions in this circumstance. However, because
  such functions can be used in macros and redundancy checking is
  based on untranslated bodies, this turns out to be unsound! (Aside:
  Perhaps this is not an issue if the function takes [state] or a
  user-defined [stobj] argument; but we do not further consider this
  distinction.) Such redefinition is therefore now prohibited. We
  illustrate such an unsoundness below. Let foo-thm1.lisp be a book
  with the following contents.

    (in-package \"ACL2\")
    (defun p1 (x) (declare (xargs :mode :program)) (list 'if x 't 'nil))
    (defmacro p (x) (p1 x))
    (defun foo (x) (p x))
    (defthm foo-thm1 (iff (foo x) x) :rule-classes nil)

  Note that the macro form (p x) translates to (if x t nil). The
  :[program] function p1 is used to generate this translation. The
  function foo is defined so that (foo x) is (p x) and a theorem
  about foo is proved, namely, that (foo x) is true iff x is true.

  Now let foo-thm2.lisp be a book with the following contents.

    (in-package \"ACL2\")
    (defun p1 (x) (declare (xargs :mode :program)) (list 'if x 'nil 't))
    (defmacro p (x) (p1 x))
    (defun foo (x) (p x))
    (defthm foo-thm2 (iff (foo x) (not x)) :rule-classes nil)

  In this book, the :[program] function p1 is defined so that (p x)
  means just the negation of what it meant in the first book, namely,
  (if x nil t). The function foo is defined identically --- more
  precisely, the untranslated body of foo is identical in the two
  [books], but because of the difference between the two versions of
  the :[program] function p1 the axioms defining the two foos are
  different. In the second book we prove the theorem that (foo x) is
  true iff x is nil.

  Now consider what would happen if the [signature]-preserving
  redefinition of :[program] functions were permitted and these two
  [books] were included. When the second book is included the
  redefinition of p1 would be permitted since the [signature] is
  preserved and p1 is just a :[program]. But then when the
  redefinition of foo is processed it would be considered redundant
  and thus be permitted. The result would be a logic in which it was
  possible to prove that (foo x) is equivalent to both x and (not x).
  In particular, the following sequence leads to a proof of nil:

    (include-book \"foo-thm1\")
    (include-book \"foo-thm2\")
    (thm nil :hints ((\"Goal\" :use (foo-thm1 foo-thm2))))

  It might be possible to loosen the restrictions on the redefinition
  of :[program] functions by allowing [signature]-preserving
  redefinition of :[program] functions not involved in macro
  definitions. Alternatively, we could implement definition
  redundancy checking based on the translated bodies of functions
  (though that is quite problematic). Barring those two changes, we
  believe it is necessary simply to impose the same restrictions on
  the redefinition of :[program] mode functions as we do on :[logic]
  mode functions.")
 (REDO-FLAT
  (DEBUGGING)
  "Redo on failure of a [progn], [encapsulate], or [certify-book]

  When one submits an [encapsulate], [progn], or [certify-book] command
  and there is a failure, ACL2 restores its logical [world] as though
  the command had not been run. But sometimes one would like to debug
  the failure by re-executing all sub-events that succeeded up to the
  point of failure, and then re-executing the failed sub-event. Said
  differently, imagine that the [events] under an encapsulate, progn,
  or certify-book form were flattened into a list of events that were
  then submitted to ACL2 up to the point of failure. This would put
  us in the state in which the original failed event had failed, so
  we could now replay that failed event and try modifying it, or
  first proving additional events, in order to get it admitted.

  Redo-flat is provided for this purpose. Consider the following
  (rather nonsensical) example, in which the [defun] of f3 fails (the
  body is y but the formal parameter list is (x)).

    (encapsulate
     ()
     (defun f1 (x) x)
     (encapsulate ()
                  (local (defthm hack (equal (car (cons x y)) x))))
     (encapsulate ()
                  (local (defthm hack (equal (+ x y) (+ y x)))))
     (encapsulate ()
                  (make-event '(defun f2 (x) x))
                  (progn (defthm foo (equal x x) :rule-classes nil)
                         (defun f3 (x) y)))
     (defun f4 (x) x)
     (defun f5 (x) y))

  After this attempt fails, you can evaluate the following form.

    (redo-flat)

  This will first lay down a [deflabel] event, (deflabel r), so that
  you can eventually remove your debugging work with (:ubt! r). Then
  the successful sub-events that preceded the failure will be
  executed with proofs skipped (so that this execution is fast).
  Then, the failed event will be executed. Finally, a :[pbt] command
  is executed so that you can see a summary of the events that
  executed successfully.

  You can eliminate some of the steps above by supplying keyword
  values, as follows.

    (redo-flat
     :succ  succ ; Skip the successful sub-events if val is nil.
     :fail  fail ; Skip the failed sub-event if val is nil.
     :label lab  ; Skip deflabel if lab or succ is nil, else use (deflabel lab).
     :pbt   val  ; Skip the final :pbt if val, lab, or succ is nil.
     )

  Also, you can avoid skipping proofs for the successful sub-events by
  supplying keyword :succ-ld-skip-proofsp with a valid value for
  ld-skip-proofsp; see [ld-skip-proofsp]. For example, you might want
  to execute (redo-flat :succ-ld-skip-proofsp nil) if you use the
  must-fail utility from community book make-event/eval.lisp, since
  for example (must-fail (thm (equal x y))) normally succeeds but
  would cause an error if proofs are skipped. For another example:
  you may wish to do proofs when re-running certain [make-event]
  forms, for example, when the expansion is (:OR expr1 expr2) and the
  proof initially succeeds for expr2 rather than expr1 (see
  [make-event]).

  If you prefer only to see the successful and failed sub-events,
  without any events being re-executed, you may evaluate the
  following form instead.

    (redo-flat :show t)

  For the example above, this command produces the following output.

    List of events preceding the failure:

    ((DEFUN F1 (X) X)
     (ENCAPSULATE NIL
                  (LOCAL (DEFTHM HACK (EQUAL (CAR (CONS X Y)) X))))
     (ENCAPSULATE NIL
                  (LOCAL (DEFTHM HACK (EQUAL (+ X Y) (+ Y X)))))
     (MAKE-EVENT '(DEFUN F2 (X) X))
     (DEFTHM FOO (EQUAL X X)
             :RULE-CLASSES NIL))

    Failed event:

    (DEFUN F3 (X) Y)
    ACL2 !>

  Redo-flat uses a scheme that should not cause spurious name conflicts
  for [local] events. Above, it is mentioned that events are
  ``flattened''; now we clarify this notion. Each sub-event that
  succeeds and is an [encapsulate] or [progn] is left intact. Only
  such events that fail are replaced by their component events. Thus,
  in the example above, there is no conflict between the two [local]
  sub-events named ``hack,'' because these are contained in
  successful encapsulate sub-events, which are therefore not
  flattened. The [progn] and two [encapsulate] events surrounding the
  definition of f3 are, however, flattened, because that definition
  failed to be admitted.

  Normally, redo-flat will have the desired effect even if you
  interrupted a proof (with control-c). However, redo-flat will not
  produce the desired result after an interrupt if you have enabled
  the debugger using (set-debugger-enable t),")
 (REDUNDANT-ENCAPSULATE
  (ENCAPSULATE)
  "Redundancy of [encapsulate] [events]

  For this [documentation] topic we assume familiarity with encapsulate
  events and the notion of redundancy for [events]; see [encapsulate]
  and see [redundant-events].

  The typical way for an encapsulate event to be redundant is when a
  syntactically identical encapsulate has already been executed under
  the same [default-defun-mode], [default-ruler-extenders], and
  [default-verify-guards-eagerness]. But more generally, the
  encapsulate events need not be syntactically identical; for
  example, it suffices that they agree when the contents of [local]
  sub-events are ignored. The precise criterion for redundancy is
  given below, but let us first look at a consequence of the point
  just made about ignoring the contents of [local] sub-events.
  Consider the following sequence of two events.

    (encapsulate
     ()
     (defun f (x) x)
     (local (defthm f-identity
              (equal (f x) x))))

    (encapsulate
     ()
     (defun f (x) x)
     (local (defthm false-claim
              (equal (f x) (not x)))))

  You might be surprised to learn that the second is actually
  redundant, even though false-claim is clearly not a theorem;
  indeed, its negation is a theorem! The following two points may
  soften the blow. First, this behavior is as specified above (and is
  specified more precisely below): the contents of [local] events are
  ignored when checking redundancy of [encapsulate] events. Second,
  this behavior is sound, because the logical meaning of an
  [encapsulate] event is taken from the events that it exports, which
  do not include events that are [local] to the encapsulate event.

  Some users, however, want to use [encapsulate] events for testing in
  a way that is thwarted by this ignoring of [local] sub-events.
  Consider the following sort of example.

    (encapsulate ()
                 (local (defthm test1 ...)))

    (encapsulate ()
                 (local (defthm test2 ...)))

  Fortunately, in this case both test1 and test2 will be evaluated. The
  reason is that when a completed [encapsulate] event with empty
  [signature] has introduced no sub-[events], then it has no effect
  at all on the logical [world]. Thus, the first encapsulate event is
  not stored in the world; so, the second encapsulate event is not
  redundant, since it is executed in a world that contains no trace
  of the first encapsulate event.

  Also see community books misc/eval.lisp, make-event/eval-check.lisp,
  and make-event/eval-tests.lisp for more ways to test in books.

  The precise criterion for redundancy of [encapsulate] [events] is as
  follows. The two [world]s in which each is evaluated must have the
  same [default-defun-mode]s, the same [default-ruler-extenders], and
  the same [default-verify-guards-eagerness]. Moreover, the existing
  and proposed encapsulate [events] contain the same [signature]s and
  the same number of top-level sub-events, which cannot be zero if
  the signatures are empty (see the discussion above about such
  encapsulate events) --- let k be that number --- and for each i <
  k, the ith top-level events E1 and E2 from the earlier and current
  encapsulates must be related in one of the following ways.

    * E1 and E2 are equal; or
    * E1 is of the form (record-expansion E2 ...); or else
    * E1 and E2 are equal after replacing each [local] sub-event by (local
      (value-triple :elided)), where a sub-event of an event E is
      either E itself, or a sub-event of a constituent event of E in
      the case that E is a call of [with-output],
      [with-prover-time-limit], [with-prover-step-limit],
      record-expansion, [time$], [progn], [progn!], or encapsulate
      itself.")
 (REDUNDANT-EVENTS
  (EVENTS)
  "Allowing a name to be introduced ``twice''

  Sometimes an event will announce that it is ``redundant'', meaning
  that the the form is not evaluated because ACL2 determines that its
  effect is already incorporated into the logical [world]. Thus, when
  this happens, no change to the logical [world] takes place. This
  feature permits two independent [books], each of which defines some
  name, to be included sequentially provided they use exactly the
  same definition.

  Note that by the definition above, a form can have no effect on the
  logical [world] yet not be considered to be redundant. Here is an
  example of such a form.

    (value-triple (cw \"Hello world.~%\"))

  When are two [logical-name] definitions considered ``the same''? It
  depends upon the kind of name being defined. We consider these
  below in alphabetical order. See also the Notes below.

  A [defabsstobj] is redundant if there is already an identical
  defabsstobj event in the logical [world].

  A [defattach] event is never redundant. Note that it doesn't define
  any name.

  A [defaxiom] or [defthm] event is redundant if there is already an
  axiom or theorem of the given name and either the two [events] are
  syntactically identical, or both the formula (after macroexpansion)
  and the resulting [rule-classes] are syntactically identical. Note
  that because of the second of these two criteria, 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 is already defined either with
  a syntactically identical defconst event or one that defines it to
  have the same value.

  A [defdoc] event is never redundant because it doesn't define any
  name.

  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 [defmacro] event is redundant if there is already a macro defined
  with the same name and syntactically identical arguments, [guard],
  and body.

  A [defpkg] event is redundant if a package of the same name with
  exactly the same imports has been defined.

  A [defstobj] event is redundant if there is already a defstobj event
  with the same name that has exactly the same field descriptors (see
  [defstobj]), in the same order, and with the same :renaming value
  if :renaming is supplied for either event.

  A [defthm] event is redundant according to the criteria given above
  in the discussion of defaxiom.

  A [deftheory] is never redundant. The ``natural'' notion of
  equivalent [deftheory] forms 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.

  A [defun], [defuns], or [mutual-recursion] 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], :measure, type declarations, [stobj]s
  declarations and body (before macroexpansion), and an appropriate
  mode (see the ``Note About Appropriate Modes'' below). Moreover,
  the order of the combined :[guard] and type declarations must be
  the same in both cases. Exceptions:
  (1) If either definition is declared :non-executable (see
  [defun-nx]), then the two events must be identical.
  (2) It is permissible for one definition to have a :[guard] of t and
  the other to have no explicit guard (hence, the guard is implicitly
  t).
  (3) The :measure check is avoided if the old definition is
  non-recursive (and not defined within a [mutual-recursion]) or we
  are skipping proofs (for example, during [include-book]).
  Otherwise, the new definition may have a :measure of (:? v1 ...
  vk), where (v1 ... vk) enumerates the variables occurring in the
  measure stored for the old definition.
  (4) If either the old or new event is a [mutual-recursion] event,
  then redundancy requires that both are [mutual-recursion] events
  that define the same set of function symbols.

  An [encapsulate] event is most commonly redundant when a
  syntactically identical [encapsulate] has already been executed
  under the same [default-defun-mode], [default-ruler-extenders], and
  [default-verify-guards-eagerness]. The full criterion for
  redundancy of encapsulate events is more complex, for example
  ignoring contents of [local] [events]; see [redundant-encapsulate].

  An [in-theory] event is never redundant. Note that it doesn't define
  any name.

  An [include-book] event is redundant if the book has already been
  included.

  A call of [make-event] is never redundant, as its argument is always
  evaluated to obtain the make-event expansion. However, that
  expansion may of course be redundant.

  A [mutual-recursion] event is redundant according to the criteria in
  the discussion above for the case of a defun event.

  A [progn] event is never redundant: its subsidiary [events] are
  always considered. Of course, its sub-events may themselves be
  redundant. If all of its sub-events are redundant --- or more
  generally, if none of the sub-events changes the logical [world]
  --- then the progn event also won't change the world.

  A [push-untouchable] event is redundant if every name supplied is
  already a member of the corresponding list of untouchable symbols.

  A [regenerate-tau-database] event is never redundant. Note that it
  doesn't define any name.

  A [remove-untouchable] event is redundant if no name supplied is a
  member of the corresponding list of untouchable symbols.

  A [reset-prehistory] event is redundant if it does not cause any
  change.

  A [set-body] event is redundant if the indicated body is already the
  current body.

  A [table] event not define any name. It is redundant when it sets the
  value already associated with a key of the table, or when it sets
  an entire table (using keyword :clear) to its existing value; see
  [table].

  A [verify-guards] event is redundant if the function has already had
  its [guard]s verified.

  Note About Built-in (Predefined) Functions and Macros:

  Redundancy is restricted for built-in macros and functions that have
  special raw Lisp code. Such redundancy is only legal in the context
  of [local]. This restriction is needed for soundness, for technical
  reasons omitted here (details may be found in a long comment about
  redundant-events in source function
  chk-acceptable-defuns-redundancy).

  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. ACL2 will
  treat the redefinition as redundant, provided the appropriate
  criteria are met (as though it were in :logic mode).

  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].

  Note About Unfortunate Redundancies.

  Notice that our syntactic criterion for redundancy of [defun]
  [events] may not allow redefinition to take effect unless there is
  a syntactic change in the definition. The following example shows
  how an attempt to redefine a function can fail to make any change.

    (set-ld-redefinition-action '(:warn . :overwrite) state)
    (defmacro mac (x) x)
    (defun foo (x) (mac x))
    (defmacro mac (x) (list 'car x))
    (set-ld-redefinition-action nil state)
    (defun foo (x) (mac x)) ; redundant, unfortunately; foo does not change
    (thm (equal (foo 3) 3)) ; succeeds, showing that redef of foo didn't happen

  The call of macro mac was expanded away before storing the first
  definition of foo for the theorem prover. Therefore, the new
  definition of mac does not affect the expansion of foo by the
  theorem prover, because the new definition of foo is ignored.

  One workaround is first to supply a different definition of foo, just
  before the last definition of foo above. Then that final definition
  will no longer be redundant. However, as a courtesy to users, we
  strengthen the redundancy check for function definitions when
  redefinition is active. If in the example above we remove the form
  (set-ld-redefinition-action nil state), then the problem goes away:

    (set-ld-redefinition-action '(:warn . :overwrite) state)
    (defmacro mac (x) x)
    (defun foo (x) (mac x))
    (defmacro mac (x) (list 'car x))
    (defun foo (x) (mac x)) ; no longer redundant
    (thm (equal (foo 3) 3)) ; fails, as we would like

  To summarize: If a [defun] form is submitted that meets the usual
  redundancy criteria, then it may be considered redundant even if a
  macro called in the definition has since been redefined. The
  analogous problem applie to constants, i.e., symbols defined by
  [defconst] that occur in the definition body. However, if
  redefinition is currently active the problem goes away: that is,
  the redundancy check is strengthened to check the ``translated''
  body, in which macro calls and constants defined by [defconst] are
  expanded away.

  The above discussion for [defun] forms applies to [defconst] forms as
  well. However, for [defmacro] forms ACL2 always checks translated
  bodies, so such bogus redundancy does not occur.

  Here is more complex example illustrating the limits of redefinition,
  based on one supplied by Grant Passmore.

    (defun n3 () 0)
    (defun n4 () 1)
    (defun n5 () (> (n3) (n4))) ; body is normalized to nil
    (thm (equal (n5) nil)) ; succeeds, trivially
    (set-ld-redefinition-action '(:warn . :overwrite) state)
    (defun n3 () 2)
    (thm (equal (n5) nil)) ; still succeeds, sadly

  We may expect the final [thm] call to fail because of the following
  reasoning: (n5) = (> (n3) (n4)) = (> 2 1) = t. Unfortunatly, the
  body of n5 was simplified (``normalized'') to nil when n5 was
  admitted, so the redefinition of n3 is ignored during the final thm
  call. (Such normalization can be avoided; see the brief discussion
  of :normalize in the documentation for [defun].) So, given this
  unfortunate situation, one might expect at this point simply to
  redefine n5 using the same definition as before, in order to pick
  up the new definition of n3. Such ``redefinition'' would, however,
  be redundant, for the same reason as in the previous example: no
  syntactic change was made to the definition. Even with redefinition
  active, there is no change in the body of n5, even with macros and
  constants (defined by [defconst]) expanded; there are none such!
  The same workaround applies as before: redefine n5 to be something
  different, and then redefine n5 again to be as desired.

  A related phenomenon can occur for [encapsulate]. As explained above,
  an encapsulate event is redundant if it is identical to one already
  in the database. (But a weaker condition applies in general; see
  [redundant-encapsulate].) Consider then the following contrived
  example.

    (defmacro mac (x) x)
    (encapsulate () (defun foo (x) (mac x)))
    (set-ld-redefinition-action '(:warn . :overwrite) state)
    (defmacro mac (x) (list 'car x))
    (encapsulate () (defun foo (x) (mac x)))

  The last encapsulate event is redundant because it meets the
  criterion for redundancy: it is identical to the earlier
  encapsulate event. Even though redefinition is active, and hence
  ACL2 ``should'' be able to see that the new [defun] of foo is not
  truly redundant, nevertheless the criterion for redundancy of
  [encapsulate] allows the new encapsulate form to be redundant.

  A workaround can be to add something trivial to the encapsulate, for
  example:

    (encapsulate ()
      (deflabel try2) ; ``Increment'' to try3 next time, and so on.
      (defun foo (x) x))


Subtopics

  [Set-enforce-redundancy]
      Require most events to be redundant")
 (REFINEMENT
  (RULE-CLASSES)
  "Record that one equivalence relation refines another

  See [rule-classes] for a general discussion of rule classes,
  including how they are used to build rules from formulas and a
  discussion of the various keywords in a rule class description.

    Example:
    (defthm bag-equal-refines-set-equal
      (implies (bag-equal x y)
               (set-equal y x))
      :rule-classes :refinement)

  Also see [defrefinement].

    General Form:
    (implies (equiv1 x y) (equiv2 x y))

  Equiv1 and equiv2 must be known equivalence relations. The effect of
  such a rule is to record that equiv1 is a refinement of equiv2.
  This means that equiv1 :[rewrite] rules may be used while trying to
  maintain equiv2. See [equivalence] for a general discussion of the
  issues.

  The macro form (defrefinement equiv1 equiv2) is an abbreviation for a
  [defthm] of rule-class :refinement that establishes that equiv1 is
  a refinement of equiv2. See [defrefinement].

  Suppose we have the :[rewrite] rule

    (bag-equal (append a b) (append b a))

  which states that [append] is commutative modulo bag-equality.
  Suppose further we have established that bag-equality refines
  set-equality. Then when we are simplifying [append] expressions
  while maintaining set-equality we use [append]'s commutativity
  property, even though it was proved for bag-equality.

  Equality is known to be a refinement of all equivalence relations.
  The transitive closure of the refinement relation is maintained, so
  if set-equality, say, is shown to be a refinement of some third
  sense of equivalence, then bag-equality will automatially be known
  as a refinement of that third equivalence.

  :refinement lemmas cannot be disabled. That is, once one equivalence
  relation has been shown to be a refinement of another, there is no
  way to prevent the system from using that information. Of course,
  individual :[rewrite] rules can be disabled.

  More will be written about this as we develop the techniques.")
 (REGENERATE-TAU-DATABASE
  (EVENTS INTRODUCTION-TO-THE-TAU-SYSTEM)
  "Regenerate the tau database relative to the current enabled theory

    Example:
    (regenerate-tau-database)

    General Form:
    (regenerate-tau-database :doc doc-string)

  where doc-string, if non-nil, is an optional string that can provide
  documentation but is essentially ignored by ACL2.

  The tau database is regenerated by scanning the current logical world
  and re-processing every rule-generating event in it relative to the
  current enabled theory and current tau auto mode settings. See
  [introduction-to-the-tau-system] for background details.

  This command was intended to allow the user to remove a fact from the
  tau database, by regenerating the database without the fact. But as
  the following discussion highlights, regenerate-tau-database does
  not really solve the problem. We regard it as a placeholder for a
  more sophisticated mechanism. However, we have trouble
  understanding why a user might wish to remove a fact from the
  database and are awaiting further user experiences before designing
  the more sophisticated mechanism.

  Suppose, for example, that you wanted to remove a signature rule
  provided by some rule with name rune. You could disable rune and
  regenerate the database. We discuss why you might --- or might not
  --- want to do this later. But suppose you did it. Unfortunately,
  the database you get will not be just like the one you started with
  minus the signature rule. The reason is that the database you
  started with was generated incrementally and the current theory
  might have evolved. To take a simple example, your starting
  database might have included a rule that has been disabled since it
  was first added. Thus, the part of your starting database built
  before the disabling was constructed with the rule enabled and the
  part built afterwards has the rule disabled. You are unlikely to
  get the same database whether you enable or disable that rule now.

  You might hope that the avoidance of in-theory events would eliminate
  the problem but it does not because even the [ground-zero] theory
  is constructed incrementally from the ``pre-history'' commands used
  to boot up ACL2. Those pre-history commands include some global
  in-theory commands. Since every session starts from the ground-zero
  state, the starting database is already ``infected'' with global
  in-theory commands.

  The reason we hope that it will not be necessary to remove tau facts
  is that the tau system is designed merely to be fast and benign
  (see Design Philosophy in [introduction-to-the-tau-system]). The
  tau system's coverage should grows monotonically with the addition
  of rules. According to this understanding of tau, adding a
  signature rule, for example, may allow tau to prove some additional
  goals but will not prevent it from proving goals it could prove
  previously. If this is understanding of tau is accurate, we see no
  fundamental reason to support the removal of a fact. This, of
  course, ignores the possibility that the user wishes to explore
  alternative proof strategies or measure performance.

  We welcome user observations and experience on this issue.")
 (REGRESSION (POINTERS)
             "See [books-certification].")
 (RELEASE-NOTES
  (ABOUT-ACL2)
  "Pointers to what has changed

  This section of the online [documentation] contains notes on the
  changes that distinguish successive released versions of ACL2.

  The current version of ACL2 is the value of the constant (@
  acl2-version).


Subtopics

  [Note-2-0]
      ACL2 Version 2.0 (July, 1997) Notes

  [Note-2-1]
      ACL2 Version 2.1 (December, 1997) Notes

  [Note-2-2]
      ACL2 Version 2.2 (August, 1998) Notes

  [Note-2-3]
      ACL2 Version 2.3 (October, 1998) Notes

  [Note-2-4]
      ACL2 Version 2.4 (August, 1999) Notes

  [Note-2-5]
      ACL2 Version 2.5 (June, 2000) Notes

  [Note-2-5{r}]
      ACL2 Version 2.5(r) (June, 2000) Notes

  [Note-2-6]
      ACL2 Version 2.6 (November, 2001) Notes

  [Note-2-6{r}]
      ACL2 Version 2.6(r) (November, 2001) Notes

  [Note-2-7]
      ACL2 Version 2.7 (November, 2002) Notes

  [Note-2-7{r}]
      ACL2 Version 2.7(r) (November, 2002) Notes

  [Note-2-8]
      ACL2 Version 2.8 (March, 2004) Notes

  [Note-2-8{r}]
      ACL2 Version 2.8(r) (March, 2003) Notes

  [Note-2-9]
      ACL2 Version 2.9 (October, 2004) Notes

  [Note-2-9{r}]
      ACL2 Version 2.9(r) (October, 2004) Notes

  [Note-2-9-1]
      ACL2 Version 2.9.1 (December, 2004) Notes

  [Note-2-9-2]
      ACL2 Version 2.9.2 (April, 2005) Notes

  [Note-2-9-3]
      ACL2 Version 2.9.3 (August, 2005) Notes

  [Note-2-9-4]
      ACL2 Version 2.9.4 (February, 2006) Notes

  [Note-2-9-5]
      Changes in Version 3.0 since Version 2.9.4

  [Note-3-0]
      ACL2 Version 3.0 (June, 2006) Notes

  [Note-3-0{r}]
      ACL2 Version 3.0(r) (June, 2006) Notes

  [Note-3-0-1]
      ACL2 Version 3.0.1 (August, 2006) Notes

  [Note-3-0-1{r}]
      ACL2 Version 3.0.1(r) (August, 2006) Notes

  [Note-3-0-2]
      ACL2 Version 3.0.2 (December, 2006) Notes

  [Note-3-1]
      ACL2 Version 3.1 (December, 2006) Notes

  [Note-3-1{r}]
      ACL2 Version 3.1(r) (December, 2006) Notes

  [Note-3-2]
      ACL2 Version 3.2 (April, 2007) Notes

  [Note-3-2{r}]
      ACL2 Version 3.2(r) (April, 2007) Notes

  [Note-3-2-1]
      ACL2 Version 3.2.1 (June, 2007) Notes

  [Note-3-2-1{r}]
      ACL2 Version 3.2.1(r) (June, 2007) Notes

  [Note-3-3]
      ACL2 Version 3.3 (November, 2007) Notes

  [Note-3-3{r}]
      ACL2 Version 3.3(r) (November, 2007) Notes

  [Note-3-4]
      ACL2 Version 3.4 (August, 2008) Notes

  [Note-3-4{r}]
      ACL2 Version 3.4(r) (August, 2008) Notes

  [Note-3-5]
      ACL2 Version 3.5 (May, 2009) Notes

  [Note-3-5{r}]
      ACL2 Version 3.5(r) (May, 2009) Notes

  [Note-3-6]
      ACL2 Version 3.6 (August, 2009) Notes

  [Note-3-6{r}]
      ACL2 Version 3.6(r) (August, 2009) Notes

  [Note-3-6-1]
      ACL2 Version 3.6.1 (September, 2009) Notes

  [Note-4-0]
      ACL2 Version 4.0 (July, 2010) Notes

  [Note-4-0{r}]
      ACL2 Version 4.0(r) (July, 2010) Notes

  [Note-4-1]
      ACL2 Version 4.1 (September, 2010) Notes

  [Note-4-1{r}]
      ACL2 Version 4.1(r) (September, 2010) Notes

  [Note-4-2]
      ACL2 Version 4.2 (January, 2011) Notes

  [Note-4-2{r}]
      ACL2 Version 4.2(r) (January, 2011) Notes

  [Note-4-3]
      ACL2 Version 4.3 (July, 2011) Notes

  [Note-4-3{r}]
      ACL2 Version 4.3(r) (July, 2011) Notes

  [Note-5-0]
      ACL2 Version 5.0 (August, 2012) Notes

  [Note-6-0]
      ACL2 Version 6.0 (December, 2012) Notes

  [Note-6-1]
      ACL2 Version 6.1 (February, 2013) Notes

  [Note-6-2]
      ACL2 Version 6.2 (June, 2013) Notes

  [Note-6-3]
      ACL2 Version 6.3 (October, 2013) Notes

  [Note-6-4]
      ACL2 Version 6.4 (January, 2014) Notes

  [Note-6-5]
      ACL2 Version 6.5 (August, 2014) Notes

  [Note-7-0]
      ACL2 Version 7.0 (January, 2015) Notes

  [Note-7-1]
      ACL2 Version 7.1 (May, 2015) Notes

  [Note1]
      Acl2 Version 1.1 Notes

  [Note2]
      Acl2 Version 1.2 Notes

  [Note3]
      Acl2 Version 1.3 Notes

  [Note4]
      Acl2 Version 1.4 Notes

  [Note5]
      Acl2 Version 1.5 Notes

  [Note6]
      Acl2 Version 1.6 Notes

  [Note7]
      ACL2 Version 1.7 (released October 1994) Notes

  [Note8]
      ACL2 Version 1.8 (May, 1995) Notes

  [Note8-update]
      ACL2 Version 1.8 (Summer, 1995) Notes

  [Note9]
      ACL2 Version 1.9 (Fall, 1996) Notes")
 (REM
  (NUMBERS ACL2-BUILT-INS)
  "Remainder using [truncate]

    ACL2 !>(rem 14 3)
    2
    ACL2 !>(rem -14 3)
    -2
    ACL2 !>(rem 14 -3)
    2
    ACL2 !>(rem -14 -3)
    -2
    ACL2 !>(rem -15 -3)
    0
    ACL2 !>

  (Rem i j) is that number k for which (* j (truncate i j)) added to k
  equals i.

  The [guard] for (rem i j) requires that i and j are rational ([real],
  in ACL2(r)) numbers and j is non-zero.

  Rem is a Common Lisp function. See any Common Lisp documentation for
  more information.

  Function: 

    (defun rem (x y)
           (declare (xargs :guard (and (real/rationalp x)
                                       (real/rationalp y)
                                       (not (eql y 0)))))
           (- x (* (truncate x y) y)))")
 (REMOVE
  (LISTS ACL2-BUILT-INS)
  "Remove all occurrences

    General Forms:
    (remove x lst)
    (remove x lst :test 'eql)   ; same as above (eql as equality test)
    (remove x lst :test 'eq)    ; same, but eq is equality test
    (remove x lst :test 'equal) ; same, but equal is equality test

  (Remove x lst) is equal to lst if x is not a member of lst, else is
  the result of removing all occurrences of x from lst. The optional
  keyword, :TEST, has no effect logically, but provides the test
  (default [eql]) used for comparing x with successive elements of
  lst.

  Also see [remove1].

  The [guard] for a call of remove depends on the test. In all cases,
  the second argument must satisfy [true-listp]. If the test is
  [eql], then either the first argument must be suitable for [eql]
  (see [eqlablep]) or the second argument must satisfy
  [eqlable-listp]. If the test is [eq], then either the first
  argument must be a symbol or the second argument must satisfy
  [symbol-listp].

  See [equality-variants] for a discussion of the relation between
  remove and its variants:

      (remove-eq x lst) is equivalent to (remove x lst :test 'eq);

      (remove-equal x lst) is equivalent to (remove x lst :test 'equal).

  In particular, reasoning about any of these primitives reduces to
  reasoning about the function remove-equal.

  Function: 

    (defun remove-equal (x l)
           (declare (xargs :guard (true-listp l)))
           (cond ((endp l) nil)
                 ((equal x (car l))
                  (remove-equal x (cdr l)))
                 (t (cons (car l)
                          (remove-equal x (cdr l))))))

  Remove is defined by Common Lisp. See any Common Lisp documentation
  for more information.")
 (REMOVE-BINOP
  (MACROS)
  "Remove the association of a function name with a macro name

  The form (remove-binop macro-fn) is an abbreviation for the form
  (remove-macro-fn macro-fn). See [remove-macro-fn].")
 (REMOVE-CUSTOM-KEYWORD-HINT
  (EVENTS)
  "Remove a custom keyword hint

    Example Forms:
    (remove-custom-keyword-hint :my-hint)

    General Form:
    (remove-custom-keyword-hint keyword)

  where keyword is a [keywordp].

  For an explanation of how custom keyword hints are processed, see
  [custom-keyword-hints]; also see [add-custom-keyword-hint].

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.")
 (REMOVE-DEFAULT-HINTS
  (DEFAULT-HINTS)
  "Remove from the default hints

    Examples:
    (remove-default-hints '((computed-hint-1 clause)
                            (computed-hint-2 clause
                                             stable-under-simplificationp)))

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  It is [local] to the book or [encapsulate] form in which it occurs
  (see [remove-default-hints!] for a corresponding non-[local]
  event).

    General Form:
    (remove-default-hints lst)

  where lst is a list. Generally speaking, the elements of lst should
  be suitable for use as [computed-hints]. Also see
  [add-default-hints].

  If some elements of the given list do not belong to the existing
  default hints, they will simply be ignored by this event.

  Also See [set-default-hints], see [add-default-hints], and see
  [default-hints].

  Finally, note that the effects of set-default-hints,
  [add-default-hints], and [remove-default-hints] are [local] to the
  book in which they appear. Thus, users who include a book with such
  forms will not have their default hints affected by such forms. In
  order to export the effect of setting the default hints, use
  [set-default-hints!], [add-default-hints!], or
  [remove-default-hints!].")
 (REMOVE-DEFAULT-HINTS!
  (DEFAULT-HINTS)
  "Remove from the default hints non-[local]ly

  Please see [remove-default-hints], which is the same as
  remove-default-hints! except that the latter is not [local] to the
  [encapsulate] or the book in which it occurs. Probably
  [remove-default-hints] is to be preferred unless you have a good
  reason for wanting to export the effect of this event outside the
  enclosing [encapsulate] or book.")
 (REMOVE-DIVE-INTO-MACRO
  (DIVE-INTO-MACROS-TABLE)
  "Removes association of [proof-checker] diving function with macro
  name

    Example:
    (remove-dive-into-macro logand)

  This feature undoes the effect of [add-dive-into-macro], which is
  used so that the [proof-checker]'s DV command and numeric diving
  commands (e.g., 3) will dive properly into subterms. Please see
  [add-dive-into-macro] and especially see [dive-into-macros-table].")
 (REMOVE-DUPLICATES
  (LISTS STRINGS ACL2-BUILT-INS)
  "Remove duplicates from a string or a list

    General Forms:
    (remove-duplicates x)
    (remove-duplicates x :test 'eql)   ; same as above (eql as equality test)
    (remove-duplicates x :test 'eq)    ; same, but eq is equality test
    (remove-duplicates x :test 'equal) ; same, but equal is equality test

  (Remove-duplicates x) returns the result of deleting duplicate
  elements from the beginning of the list or string x. For example,
  (remove-duplicates '(1 2 3 2 4)) is equal to '(1 3 2 4). The
  optional keyword, :TEST, has no effect logically, but provides the
  test (default [eql]) used for comparing x with successive elements
  of lst.

  The [guard] for a call of remove-duplicates depends on the test. In
  all cases, the argument must satisfy [stringp] or [true-listp]. If
  the test is [eql], then the argument must satisfy either [stringp]
  or [eqlable-listp]. If the test is [eq], then the argument must
  satisfy [symbol-listp].

  The relation between remove-duplicates and its variants is related to
  the usual pattern for equality variants; see [equality-variants].
  However, the possibility of a string argument changes the usual
  pattern a bit. As one might expect:

      (remove-duplicates-eq lst) is equivalent to (remove-duplicates lst
      :test 'eq).

  However, remove-duplicates-equal is defined without consideration of
  strings, for backward compatibility with versions of ACL2 through
  Version_4.2. The macro remove-duplicates-logic has been introduced
  to model the behavior of remove-duplicates even on strings; use
  :[pe] if you wish to see its definition. So we can say the
  following.

      (remove-duplicates-logic lst) is equivalent to (remove-duplicates lst
      :test 'equal); and

      (remove-duplicates-logic lst) is equal to (remove-duplicates-equal
      lst) when lst is not a string.

  In particular, when the argument is not a string, reasoning about any
  of these primitives reduces to reasoning about the function
  remove-duplicates-equal.

  Function: 

    (defun remove-duplicates-equal (l)
           (declare (xargs :guard (true-listp l)))
           (cond ((endp l) nil)
                 ((member-equal (car l) (cdr l))
                  (remove-duplicates-equal (cdr l)))
                 (t (cons (car l)
                          (remove-duplicates-equal (cdr l))))))

  Remove-duplicates is defined by Common Lisp. See any Common Lisp
  documentation for more information.")
 (REMOVE-DUPLICATES-EQ (POINTERS)
                       "See [remove-duplicates].")
 (REMOVE-DUPLICATES-EQUAL (POINTERS)
                          "See [remove-duplicates].")
 (REMOVE-EQ (POINTERS) "See [remove].")
 (REMOVE-EQUAL (POINTERS)
               "See [remove].")
 (REMOVE-INVISIBLE-FNS
  (LOOP-STOPPER)
  "Make some unary functions no longer invisible

    Examples:
    (remove-invisible-fns (binary-+ unary-- foo)
    (remove-invisible-fns (+ unary-- foo)

  The setting above has makes unary functions [unary--] and foo no
  longer ``invisible'' for the purposes of applying permutative
  :[rewrite] rules to [binary-+] trees.

    General Form:
    (remove-invisible-fns top-fn unary-fn1 ... unary-fnk)

  where top-fn is a function symbol and the unary-fni are unary
  function symbols, or more generally, these are all macro aliases
  for function symbols (see [macro-aliases-table]).

  See [add-invisible-fns] and also see [invisible-fns-table] and see
  [set-invisible-fns-table].")
 (REMOVE-MACRO-ALIAS
  (MACROS)
  "Remove the association of a function name with a macro name

    Example:
    (remove-macro-alias append)

    General Form:
    (remove-macro-alias macro-name)

  See [macro-aliases-table] for a discussion of macro aliases; also see
  [add-macro-alias]. This form sets [macro-aliases-table] to the
  result of deleting the key macro-name from that [table]. If the
  name does not occur in the [table], then this form still generates
  an event, but the event has no real effect.")
 (REMOVE-MACRO-FN
  (MACROS)
  "Remove the association of a function name with a macro name

    Example:
    (remove-macro-fn binary-append)

    General Form:
    (remove-macro-fn macro-fn)

  See [add-macro-fn] for a discussion of how to associate a macro name
  with a function name. This form sets [untrans-table] to the result
  of deleting the association of a macro name with the given binary
  function name. If the function name has no such association, then
  this form still generates an event, but the event has no real
  effect.")
 (REMOVE-NTH-ALIAS
  (NTH-ALIASES-TABLE)
  "Remove a symbol alias for printing of [nth]/[update-nth] terms

    Example:
    (remove-nth-alias append)

    General Form:
    (remove-nth-alias alias-name)

  See [nth-aliases-table] for further discussion; also see
  [add-nth-alias]. This form sets [nth-aliases-table] to the result
  of deleting the key alias-name from that [table]. If the name does
  not occur in the [table], then this form still generates an event,
  but the event has no real effect.")
 (REMOVE-OVERRIDE-HINTS
  (OVERRIDE-HINTS)
  "Delete from the list of [override-hints]

  See [override-hints] for a discussion of override-hints. Here we
  describe how to delete from the list of override-hints. Note that
  the effects of remove-override-hints [events] are [local] to the
  [books] or encapsulate [events] in which they reside; see
  [remove-override-hints!] to avoid that restriction. Also see
  [add-override-hints] and see [set-override-hints].

    General Form:
    (remove-override-hints form)

  where form should evaluate to a list of computed hint forms. The
  effect of this event is to set the list of [override-hints] to the
  result of deleting each element of the evaluation result from the
  [override-hints], if that element indeed belongs to the
  override-hints; no check is made that these elements are actually
  elements of the existing override-hints.")
 (REMOVE-OVERRIDE-HINTS!
  (OVERRIDE-HINTS)
  "Delete non-[local]ly from the list of [override-hints]

  Remove-override-hints! is the same as [remove-override-hints], except
  that the former is not [local] to [books] or [encapsulate] [events]
  in which it occurs. See [remove-override-hints]; also see
  [add-override-hints] and see [set-override-hints].")
 (REMOVE-RAW-ARITY
  (SET-RAW-MODE)
  "Remove arity information for raw mode

  Technical note: This macro is a no-op, and is not necessary, when
  ACL2 is built with #-acl2-mv-as-values.

  The form (remove-raw-arity fn) undoes the effect of an earlier
  (remove-raw-arity fn val). See [add-raw-arity].")
 (REMOVE-UNTOUCHABLE
  (DEFTTAG)
  "Remove names from lists of untouchable symbols

    Example Forms:
    (remove-untouchable my-var nil) ; then state global my-var is not untouchable
    (remove-untouchable set-mem t)  ; then function set-mem is not untouchable

  Also see [push-untouchable].

  This documentation topic is directed at those who build systems on
  top of ACL2. We first describe a means for removing restrictions
  related to so-called ``untouchables'': functions (or macros) that
  cannot be called, or state global variables that cannot be modified
  or unbound, without intervention that requires an active trust tag
  (see [defttag]). Then we describe the remove-untouchable event.

  We begin by discussing untouchable state global variables
  temp-touchable-vars and temp-touchable-fns, which initially have
  value nil. These can often be used in place of remove-untouchable.
  When the value is t, no variable (respectively, no function or
  macro) is treated as untouchable, regardless of the set of initial
  untouchables or the remove-untouchable or [push-untouchable]
  [events] that have been admitted. Otherwise the value of each of
  these two variables is a [symbol-listp], and no member of this list
  is treated as an untouchable variable (in the case of
  temp-touchable-vars) or as an untouchable function or macro (in the
  case of temp-touchable-fns). These two state global variables can
  be set by set-temp-touchable-vars and set-temp-touchable-fns,
  respectively, provided there is an active trust tag (see
  [defttag]). Here is an illustrative example. This macro executes
  the indicated forms in a context where there are no untouchable
  variables, but requires an active trust tag when invoked.

    (defmacro with-all-touchable (&rest forms)
      `(progn!
        :state-global-bindings
        ((temp-touchable-vars t set-temp-touchable-vars))
        (progn! ,@forms)))

  An equivalent version, which however is not recommended since
  [state-global-let*] may have surprising behavior in raw Lisp, is as
  follows.

    (defmacro with-all-touchable (&rest forms)
      `(progn!
        (state-global-let*
         ((temp-touchable-vars t set-temp-touchable-vars))
         (progn! ,@forms))))

  Finally, the value t for temp-touchable-vars removes the requirement
  that built-in state globals cannot be made unbound (with
  makunbound-global).

  We now turn to the remove-untouchable event, in case the approach
  above is for some reason not adequate. This event is illegal by
  default, since it can be used to provide access to ACL2 internal
  functions and data structures that are intentionally made
  untouchable for the user. If you want to call it, you must first
  create an active trust tag; see [defttag].

    General Form:
    (remove-untouchable name{s}  fn-p :doc doc-string)

  where name{s} is a non-nil symbol or a non-nil true list of symbols,
  fn-p is any value (but generally nil or t), and doc-string, if
  non-nil, is an optional string that can provide documentation but
  is essentially ignored by ACL2. If name{s} is a symbol it is
  treated as the singleton list containing that symbol. The effect of
  this event is to remove the given symbols from the list of
  ``untouchable variables'' in the current world if fn-p is nil, else
  to remove the symbols into the list of ``untouchable functions''.
  This event is redundant if no symbol listed is a member of the
  appropriate untouchables list (variables or functions).")
 (REMOVE1
  (LISTS ACL2-BUILT-INS)
  "Remove first occurrences, testing using [eql]

    General Forms:
    (remove1 x lst)
    (remove1 x lst :test 'eql)   ; same as above (eql as equality test)
    (remove1 x lst :test 'eq)    ; same, but eq is equality test
    (remove1 x lst :test 'equal) ; same, but equal is equality test

  (Remove1 x lst) is equal to lst if x is not a member of lst, else is
  the result of removing the first occurrences of x from lst. The
  optional keyword, :TEST, has no effect logically, but provides the
  test (default [eql]) used for comparing x with successive elements
  of lst.

  Also see [remove].

  The [guard] for a call of remove1 depends on the test. In all cases,
  the second argument must satisfy [true-listp]. If the test is
  [eql], then either the first argument must be suitable for [eql]
  (see [eqlablep]) or the second argument must satisfy
  [eqlable-listp]. If the test is [eq], then either the first
  argument must be a symbol or the second argument must satisfy
  [symbol-listp].

  See [equality-variants] for a discussion of the relation between
  remove1 and its variants:

      (remove1-eq x lst) is equivalent to (remove1 x lst :test 'eq);

      (remove1-equal x lst) is equivalent to (remove1 x lst :test 'equal).

  Function: 

    (defun remove1-equal (x l)
           (declare (xargs :guard (true-listp l)))
           (cond ((endp l) nil)
                 ((equal x (car l)) (cdr l))
                 (t (cons (car l)
                          (remove1-equal x (cdr l))))))

  In particular, reasoning about any of these primitives reduces to
  reasoning about the function remove1-equal.")
 (REMOVE1-EQ (POINTERS) "See [remove1].")
 (REMOVE1-EQUAL (POINTERS)
                "See [remove1].")
 (REORDER (POINTERS)
          "See [hints] for keyword :reorder.")
 (RESET-FC-REPORTING
  (FORWARD-CHAINING-REPORTS)
  "Reset the forward-chaining tracking state to its initial
  configuration

    Example:  (reset-fc-reporting)

  This function erases all forward chaining tracking criteria and sets
  the on-the-fly reporting flag to nil. The next time you set the
  criteria (see [set-fc-criteria]) the short form of reports, in
  which only the caller and the fc-report number is printed, will
  appear in your proof logs.

  See [forward-chaining-reports] for details.")
 (RESET-KILL-RING
  (HISTORY)
  "Save memory by resetting and perhaps resizing the kill ring used by
  [oops]

  By default, ACL2 holds on to old logical [world]s when you undo
  [command]s (see [ubt]), as documented elswhere; see [oops]. You can
  free up memory by deleting those old worlds using reset-kill-ring.

    Examples:
    (reset-kill-ring t state)   ; replace each element of the kill ring by nil
    (reset-kill-ring 2 state)   ; create a new kill ring of '(nil nil)
    (reset-kill-ring 0 state)   ; create a new kill ring that is empty
    (reset-kill-ring nil state) ; just return the length of the kill ring

    General form:
    (reset-kill-ring n state)

  where n evaluates either to t, to nil, or to a nonnegative integer (a
  [natp]). If n evaluates to t, it is treated as the length of the
  current kill ring. If n is nil, then the length k of the current
  kill ring is returned as a value triple (mv nil k state). If n is a
  [natp], then the kill ring is replaced with a list of n nils.

  In particular, use (reset-kill-ring 0 state) to avoid saving any old
  logical [world]s, at the cost of disabling the effect of the [oops]
  [command].")
 (RESET-LD-SPECIALS
  (LD)
  "Restores initial settings of the [ld] specials

    Examples:
    (reset-ld-specials t)
    (reset-ld-specials nil)

  Roughly speaking, the [ld] specials are certain [state] global
  variables, such as [current-package], [ld-prompt], and
  [ld-pre-eval-filter], which are managed by [ld] as though they were
  local variables. These variables determine the channels on which
  [ld] reads and prints and control many options of [ld]. See [ld]
  for the details on what the [ld] specials are.

  This function, reset-ld-specials, takes one Boolean argument, flg.
  The function resets all of the [ld] specials to their initial,
  top-level values, except for the three channel variables,
  [standard-oi], [standard-co], and [proofs-co], which are reset to
  their initial values only if flg is non-nil. Of course, if you are
  in a recursive call of [ld], then when you exit that call, the [ld]
  specials will be restored to the values they had at the time [ld]
  was called recursively. To see what the initial values are, inspect
  the value of the constant *initial-ld-special-bindings*.")
 (RESET-PREHISTORY
  (HISTORY)
  "Reset the prehistory

    Examples:
    (reset-prehistory)     ; restart command numbering at 0
    (reset-prehistory nil) ; same as above
    (reset-prehistory t)   ; as above except also disable ubt-prehistory

    General Forms:
    (reset-prehistory)
    (reset-prehistory permanent-p)
    (reset-prehistory permanent-p doc-string)

  where permanent-p is t or nil, and doc-string, if non-nil, is an
  optional string that can provide documentation but is essentially
  ignored by ACL2. After execution of this command, ACL2 will change
  the numbering provided by its [history] utilities so that this
  reset-prehistory command (or the top-level compound [command]
  containing it, which for example might be an [include-book]) is
  assigned the number 0. The only way to undo this command is with
  command [ubt-prehistory]. However, even that is disallowed if
  permanent-p is t.

  Note that the second argument of [certify-book], which specifies the
  number of commands in the certification world (i.e., since
  ground-zero), is not sensitive to reset-prehistory; rather, it
  expects the number of commands since ground-zero. To see such
  commands, :[pbt] :start.

  A reset-prehistory event for which parameter permanent-p has the
  default value of nil is always skipped when any of the following
  conditions holds: during [certify-book]; during [include-book] or
  the second pass of [encapsulate] (indeed, whenever [ld] special
  '[ld-skip-proofsp] has value 'include-book); or when state global
  'skip-reset-prehistory has a non-nil value. Thus, we avoid
  resetting the history numbering to 0 when including or certifying a
  book, since that would probably not be what was intended.

  See [ubt-prehistory] for how to undo a reset-prehistory command that
  does not have a permanent-p of t.")
 (RESET-PRINT-CONTROL (POINTERS)
                      "See [print-control].")
 (RESIZE-LIST
  (STOBJ ACL2-BUILT-INS)
  "List resizer in support of stobjs

  (Resize-list lst n default-value) takes a list, lst, and a desired
  length, n, for the result list, as well as a default-value to use
  for the extra elements if n is greater than the length of lst.

  Resize-list has a guard of t. This function is called in the body of
  function, resize- where  is an array field of a [stobj]. See
  [stobj] and see [defstobj].

  Function: 

    (defun resize-list (lst n default-value)
           (declare (xargs :guard t))
           (if (and (integerp n) (> n 0))
               (cons (if (atom lst) default-value (car lst))
                     (resize-list (if (atom lst) lst (cdr lst))
                                  (1- n)
                                  default-value))
               nil))")
 (REST
  (NTH ACL2-BUILT-INS)
  "Rest ([cdr]) of the list

  In the logic, rest is just a macro for [cdr].

  Rest is a Common Lisp function. See any Common Lisp documentation for
  more information.

  Macro: 

    (defmacro rest (x) (list 'cdr x))")
 (RESTORE-MEMOIZATION-SETTINGS
  (MEMOIZE)
  "Restore the saved memoization settings

  For background on memoization, see [memoize].

    General Form:
    (restore-memoization-settings)

  Calls of this macro restore the memoization settings saved by
  [save-and-clear-memoization-settings].")
 (RESTRICT (POINTERS)
           "See [hints] for keyword :restrict.")
 (RETRIEVE
  (PROOF-CHECKER)
  "Re-enter a (specified) [proof-checker] state

    Examples:
    (retrieve associativity-of-permutationp)
    retrieve

    General Form:
    (retrieve &optional name)

  See [ACL2-pc::retrieve], or use (help retrieve) inside the
  interactive [proof-checker] loop. Also see [unsave].")
 (RETURN-LAST
  (BASICS ACL2-BUILT-INS)
  "Return the last argument, perhaps with side effects

  Return-last is an ACL2 function that returns its last argument. It is
  used to implement common utilities such as [prog2$] and [time$].
  For most users, this may already be more than one needs to know
  about return-last; for example, ACL2 tends to avoid printing calls
  of return-last in its output, printing calls of [prog2$] or [time$]
  (or other such utilities) instead.

  If you encounter a call of return-last during a proof, then you may
  find it most useful to consider return-last simply as a function
  defined by the following equation.

    (equal (return-last x y z) z)

  It may also be useful to know that unlike other ACL2 functions,
  return-last can take a multiple value as its last argument, in
  which case this multiple value is returned. The following contrived
  definition illustrates this point.

    ACL2 !>(defun foo (fn x y z)
             (return-last fn x (mv y z)))

    Since FOO is non-recursive, its admission is trivial.  We observe that
    the type of FOO is described by the theorem
    (AND (CONSP (FOO FN X Y Z)) (TRUE-LISTP (FOO FN X Y Z))).  We used
    primitive type reasoning.

    (FOO * * * *) => (MV * *).

    Summary
    Form:  ( DEFUN FOO ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     FOO
    ACL2 !>(foo 'bar 3 4 5)
    (4 5)
    ACL2 !>(mv-let (a b)
                   (foo 'bar 3 4 5)
                   (cons b a))
    (5 . 4)
    ACL2 !>

  Most readers would be well served to avoid reading the rest of this
  documentation of return-last. For reference, however, below we
  document it in some detail. We include some discussion of its
  evaluation, in particular its behavior in raw Lisp, because we
  expect that most who read further are working with raw Lisp code
  (and trust tags).

  Return-last is an ACL2 function that can arise from macroexpansion of
  certain utilities that return their last argument, which may be a
  multiple value. Consider for example the simplest of these,
  [prog2$]:

    ACL2 !>:trans1 (prog2$ (cw \"Some CW printing...~%\") (+ 3 4))
     (RETURN-LAST 'PROGN
                  (CW \"Some CW printing...~%\")
                  (+ 3 4))
    ACL2 !>

  Notice that a call of prog2$ macroexpands to a call of return-last in
  which the first argument is (quote progn). Although return-last is
  a function in the ACL2 world, it is implemented ``under the hood''
  as a macro in raw Lisp, as the following log (continuing the
  example above) illustrates.

    ACL2 !>:q

    Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
    ? [RAW LISP] (macroexpand-1 '(RETURN-LAST 'PROGN
                                               (CW \"Some CW printing...~%\")
                                               (+ 3 4)))
    (PROGN (LET ((*AOKP* T)) (CW \"Some CW printing...~%\")) (+ 3 4))
    T
    ? [RAW LISP]

  Thus, the original prog2$ call generates a corresponding call of
  progn in raw Lisp, which in turn causes evaluation of each argument
  and returns whatever is returned by evaluation of the last (second)
  argument.

  (Remark for those who use [defattach]. The binding of *aokp* to t is
  always included for the second argument as shown except when the
  first argument is of the form (QUOTE M) where M is a macro, or
  (less important) when the first argument is a symbol or a cons
  whose car is QUOTE. This binding allows ACL2 to use attachments in
  the second argument of return-last (hence, in the first argument of
  [prog2$]), even in contexts such as proofs in which attachments are
  normally not allowed. Those who use [hons-enabled] ACL2 executables
  will see an additional binding in the above single-step
  macroexpansion, which allows the storing of [memoize]d results even
  when that would otherwise be prevented because of the use of
  attachments.)

  In general, a form (return-last (quote F) X Y) macroexpands to (F X
  Y), where F is defined in raw Lisp to return its last argument. The
  case that F is progn is a bit misleading, because it is so simple.
  More commonly, macroexpansion produces a call of a macro defined in
  raw Lisp that may produce side effects. Consider for example the
  ACL2 utility [with-guard-checking], which is intended to change the
  [guard]-checking mode to the indicated value (see
  [with-guard-checking]).

    ACL2 !>(with-guard-checking :none (car 3)) ; no guard violation
    NIL
    ACL2 !>:trans1 (with-guard-checking :none (car 3))
     (WITH-GUARD-CHECKING1 (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                           (CAR 3))
    ACL2 !>:trans1 (WITH-GUARD-CHECKING1 (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                                         (CAR 3))
     (RETURN-LAST 'WITH-GUARD-CHECKING1-RAW
                  (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                  (CAR 3))
    ACL2 !>:q

    Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
    ? [RAW LISP] (macroexpand-1
                  '(RETURN-LAST 'WITH-GUARD-CHECKING1-RAW
                                 (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                                 (CAR 3)))
    (WITH-GUARD-CHECKING1-RAW (CHK-WITH-GUARD-CHECKING-ARG :NONE) (CAR 3))
    T
    ? [RAW LISP] (pprint
                  (macroexpand-1
                   '(WITH-GUARD-CHECKING1-RAW
                     (CHK-WITH-GUARD-CHECKING-ARG :NONE)
                     (CAR 3))))

    (LET ((ACL2_GLOBAL_ACL2::GUARD-CHECKING-ON
           (CHK-WITH-GUARD-CHECKING-ARG :NONE)))
      (DECLARE (SPECIAL ACL2_GLOBAL_ACL2::GUARD-CHECKING-ON))
      (CAR 3))
    ? [RAW LISP]

  The above raw Lisp code binds the state global variable
  guard-checking-on to :none, as chk-with-guard-checking-arg is just
  the identity function except for causing a hard error for an
  illegal input.

  The intended use of return-last is that the second argument is
  evaluated first in a normal manner, and then the third argument is
  evaluated in an environment that may depend on the value of the
  second argument. (For example, the macro [with-prover-time-limit]
  macroexpands to a call of return-last with a first argument of
  'WITH-PROVER-TIME-LIMIT1-RAW, a second argument that evaluates to a
  numeric time limit, and a third argument that is evaluated in an
  environment where the theorem prover is restricted to avoid running
  longer than that time limit.) Although this intended usage model is
  not strictly enforced, it is useful to keep in mind in the
  following description of how calls of return-last are handled by
  the ACL2 evaluator.

  When a form is submitted in the top-level loop, it is handled by
  ACL2's custom evaluator. That evaluator is specified to respect the
  semantics of the expression supplied to it: briefly put, if an
  expression E evaluates to a value V, then the equality (equal E
  (quote V)) should be a theorem. Notice that this specification does
  not discuss the side-effects that may occur when evaluating a call
  of return-last, so we discuss that now. Suppose that the ACL2
  evaluator encounters the call (return-last 'fn expr1 expr2). First
  it evaluates expr1. If this evaluation succeeds without error, then
  it constructs an expression of the form (fn *x* ev-form), where *x*
  is a Lisp variable bound to the result of evaluating expr1 and
  ev-form is a call of the evaluator for expr2. (Those who want
  implementation details are invited to look at function
  ev-rec-return-last in ACL2 source file translate.lisp.) There are
  exceptions if fn is progn, ec-call1-raw, with-guard-checking1-raw,
  or mbe1-raw, but the main idea is the same: do a reasonable job
  emulating the behavior of a raw-Lisp call of return-last.

  The following log shows how a [time$] call can generate a call of the
  evaluator for the last argument of return-last (arguent expr2,
  above). We use :[trans1] to show single-step macroexpansions, which
  indicate how a call of [time$] expands to a call of return-last.
  The implementation actually binds the Lisp variable
  *RETURN-LAST-ARG3* to expr2 before calling the ACL2 evaluator,
  ev-rec.

    ACL2 !>:trans1 (time$ (+ 3 4))
     (TIME$1 (LIST 0 NIL NIL NIL NIL)
             (+ 3 4))
    ACL2 !>:trans1 (TIME$1 (LIST 0 NIL NIL NIL NIL)
                           (+ 3 4))
     (RETURN-LAST 'TIME$1-RAW
                  (LIST 0 NIL NIL NIL NIL)
                  (+ 3 4))
    ACL2 !>(time$ (+ 3 4))
    ; (EV-REC *RETURN-LAST-ARG3* ...) took
    ; 0.00 seconds realtime, 0.00 seconds runtime
    ; (1,120 bytes allocated).
    7
    ACL2 !>

  We now show how things can go wrong in other than the ``intended
  use'' case described above. In the example below, the macro mac-raw
  is operating directly on the syntactic representation of its first
  argument, which it obtains of course as the second argument of a
  return-last call. Again this ``intended use'' of return-last
  requires that argument to be evaluated and then only its result is
  relevant; its syntax is not supposed to matter. We emphasize that
  only top-level evaluation depends on this ``intended use''; once
  evaluation is passed to Lisp, the issue disappears. We illustrate
  below how to use the [top-level] utility to avoid this issue; see
  [top-level]. The example uses the utility defmacro-last to
  ``install'' special handling of the raw-Lisp macro mac-raw by
  return-last; later below we discuss defmacro-last.

    ACL2 !>(defttag t)

    TTAG NOTE: Adding ttag :T from the top level loop.
     T
    ACL2 !>(progn!
             (set-raw-mode t)
             (defmacro mac-raw (x y)
               `(progn (print (quote ,(cadr x)))
                       (terpri) ; newline
                       ,y)))

    Summary
    Form:  ( PROGN! (SET-RAW-MODE T) ...)
    Rules: NIL
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     NIL
    ACL2 !>(defmacro-last mac)
    [[ ... output omitted ... ]]
     RETURN-LAST-TABLE
    ACL2 !>(return-last 'mac-raw '3 nil)

    ***********************************************
    ************ ABORTING from raw Lisp ***********
    Error:  Fault during read of memory address #x120000300006
    ***********************************************

    If you didn't cause an explicit interrupt (Control-C),
    then the root cause may be call of a :program mode
    function that has the wrong guard specified, or even no
    guard specified (i.e., an implicit guard of t).
    See :DOC guards.

    To enable breaks into the debugger (also see :DOC acl2-customization):
    (SET-DEBUGGER-ENABLE T)
    ACL2 !>(top-level (return-last 'mac-raw '3 nil))

    3
    NIL
    ACL2 !>

  We next describe how to extend the behavior of return-last. This
  requires an active trust tag (see [defttag]), and is accomplished
  by extending a [table] provided by ACL2, see [return-last-table].
  Rather than using [table] [events] directly for this purpose, it is
  probably more convenient to use a macro, defmacro-last. We describe
  the community book books/misc/profiling.lisp in order to illustrate
  how this works. The events in that book include the following,
  which are described below.

    (defttag :profiling)

    (progn!
     (set-raw-mode t)
     (load (concatenate 'string (cbd) \"profiling-raw.lsp\")))

    (defmacro-last with-profiling)

  The first event introduces a trust tag. The second loads a file into
  raw Lisp that defines a macro, with-profiling-raw, which can do
  profiling for the form to be evaluated. The third introduces an
  ACL2 macro with-profiling, whose calls expand into calls of the
  form (return-last (quote with-profiling-raw) & &). The third event
  also extends [return-last-table] so that these calls will expand in
  raw Lisp to calls of with-profiling-raw.

  The example above illustrates the following methodology for
  introducing a macro that returns its last argument but produces
  useful side-effects with raw Lisp code.

      (1) Introduce a trust tag (see [defttag]).

      (2) Using [progn!], load into raw Lisp a file defining a macro,
      RAW-NAME, that takes two arguments, returning its last (second)
      argument but using the first argument to produce desired side
      effects during evaluation of that last argument.

      (3) Evaluate the form (defmacro-last NAME :raw RAW-NAME). This will
      introduce NAME as an ACL2 macro that expands to a corresponding
      call of RAW-NAME (see (2) above) in raw Lisp. The specification
      of keyword value of :raw as RAW-NAME may be omitted if RAW-NAME
      is the result of modifying the symbol NAME by suffixing the
      string \"-RAW\" to the [symbol-name] of NAME.

  WARNING: Not every use of return-last can be soundly evaluated
  outside a function body. The reason is that ACL2's evaluator,
  ev-rec, recurs through terms that are presented in the top-level
  loop, and handles return-last calls in a special manner: basically,
  the call of ev-rec on the form (return-last 'mac-raw x y) leads to
  evaluation of a macro call of the form (mac-raw *return-last-arg2*
  (ev-rec ...)), where *return-last-arg2* is a global variable bound
  to the result of evaluating x with ev-rec. Consider the following
  example.

    (defttag t)
    (set-raw-mode-on state)
    (defmacro mac-raw (str y) ; print message is an atom
     `(let ((result (consp ,y))
            (str ,str))
        (or result
            (prog2$ (fmx ,str ',y)
                    nil))))
    (set-raw-mode-off state)
    (defmacro-last mac)
    ; Horrible error:
    (mac \"Not a cons: ~x0~%\" 17)
    ; Works, but probably many would consider it awkward to use top-level:
    (top-level (mac \"Not a cons: ~x0~%\" 17))

  In such cases we suggest supplying keyword :top-level-ok nil to the
  call of defmacro-last, for example:

    (defmacro-last mac :top-level-ok nil)

  Then any attempt to call mac at the top level, as opposed to inside a
  function body, will cause a clean error before evaluation begins.

  It is useful to explore what is done by defmacro-last.

    ACL2 !>:trans1 (defmacro-last with-profiling)
     (PROGN (DEFMACRO WITH-PROFILING (X Y)
                      (LIST 'RETURN-LAST
                            (LIST 'QUOTE 'WITH-PROFILING-RAW)
                            X Y))
            (TABLE RETURN-LAST-TABLE 'WITH-PROFILING-RAW
                   'WITH-PROFILING))
    ACL2 !>:trans1 (with-profiling '(assoc-eq fgetprop rewrite) (mini-proveall))
     (RETURN-LAST 'WITH-PROFILING-RAW
                  '(ASSOC-EQ FGETPROP REWRITE)
                  (MINI-PROVEALL))
    ACL2 !>:q

    Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
    ? [RAW LISP] (macroexpand-1
                  '(RETURN-LAST 'WITH-PROFILING-RAW
                                 '(ASSOC-EQ FGETPROP REWRITE)
                                 (MINI-PROVEALL)))
    (WITH-PROFILING-RAW '(ASSOC-EQ FGETPROP REWRITE) (MINI-PROVEALL))
    T
    ? [RAW LISP]

  To understand the macro with-profiling-raw you could look at the
  community book loaded above: books/misc/profiling-raw.lsp.

  We mentioned above that ACL2 tends to print calls of [prog2$] or
  [time$] (or other such utilities) instead of calls of return-last.
  Here we elaborate that point. ACL2's `untranslate' utility treats
  (return-last (quote F) X Y) as (G X Y) if F corresponds to the
  symbol G in return-last-table. However, it is generally rare to
  encounter such a term during a proof, since calls of return-last
  are generally expanded away early during a proof.

  Calls of return-last that occur in code --- forms submitted in the
  top-level ACL2 loop, and definition bodies other than those marked
  as [non-executable] (see [defun-nx]) --- have the following
  restriction: if the first argument is of the form (quote F), then F
  must be an entry in return-last-table. There are however four
  exceptions: the following symbols are considered to be keys of
  return-last-table even if they are no longer associated with
  non-nil values, say because of a [table] event with keyword :clear.

      * progn, associated with [prog2$]
      * mbe1-raw, associated with mbe1, a version of mbe
      * ec-call1-raw, associated with ec-call1 (a variant of [ec-call])
      * with-guard-checking1-raw, associated with with-guard-checking1 (a
      variant of [with-guard-checking])

  Note that because of its special status, it is illegal to trace
  return-last.

  We conclude by warning that as a user, you take responsibility for
  not compromising the soundness or error handling of ACL2 when you
  define a macro in raw Lisp and especially when you install it as a
  key of [return-last-table], either directly or (more likely) using
  defmacro-last. In particular, be sure that you are defining a macro
  of two arguments that always returns the value of its last
  argument, returning the complete multiple value if that last
  argument evaluates to a multiple value.

  The following is correct, and illustrates care taken to return
  multiple values.

    :q
    (defmacro my-time1-raw (val form)
      (declare (ignore val))
      `(let  ((start-time (get-internal-run-time))
              (result (multiple-value-list ,form))
              (end-time (get-internal-run-time)))
         (format t \"Total time: ~s~%\"
                 (float (/ (- end-time start-time)
                           internal-time-units-per-second)))
         (values-list result)))
    (lp)
    (defttag t)
    (defmacro-last my-time1)
    (defmacro my-time (form)
      `(my-time1 nil ,form))

  Then for example:

    ACL2 !>(my-time (equal (make-list 1000000) (make-list 1000000)))
    Total time: 0.12
    T
    ACL2 !>

  But if instead we provide the following more naive implementation, of
  the above raw Lisp macro, the above evaluation can produce an
  error, for example if the host Lisp is CCL.

    (defmacro my-time1-raw (val form)
        (declare (ignore val))
        `(let  ((start-time (get-internal-run-time))
                (result ,form)
                (end-time (get-internal-run-time)))
           (format t \"Total time: ~s~%\"
                   (float (/ (- end-time start-time)
                             internal-time-units-per-second)))
           result)) ; WRONG -- need multiple values returned!

  Here is a second, similar example. This time we'll start with the
  error; can you spot it?

    (defttag t)
    (progn!
     (set-raw-mode t)
     (defmacro foo-raw (x y)
       `(prog1
            ,y
          (cw \"Message showing argument 1: ~x0~%\" ,x))))
    (defmacro-last foo)

  We then can wind up with a hard Lisp error:

    ACL2 !>(foo 3 (mv 4 5))
    Message showing argument 1: 3

    ***********************************************
    ************ ABORTING from raw Lisp ***********
    Error:  value NIL is not of the expected type REAL.
    ***********************************************

    If you didn't cause an explicit interrupt (Control-C),
    then the root cause may be call of a :program mode
    function that has the wrong guard specified, or even no
    guard specified (i.e., an implicit guard of t).
    See :DOC guards.

    To enable breaks into the debugger (also see :DOC acl2-customization):
    (SET-DEBUGGER-ENABLE T)
    ACL2 !>

  Here is a corrected version of the above macro. The point here is
  that prog1 returns a single value, while our-multiple-value-prog1
  returns all the values that are returned by its first argument.

    (progn!
     (set-raw-mode t)
     (defmacro foo-raw (x y)
       `(our-multiple-value-prog1 ;; better
         ,y
         (cw \"Message showing argument 1: ~x0~%\" ,x))))

  Function: 

    (defun return-last (fn eager-arg last-arg)
           (declare (ignore fn eager-arg)
                    (xargs :guard (if (equal fn 'mbe1-raw)
                                      (equal last-arg eager-arg)
                                      t)))
           last-arg)


Subtopics

  [Return-last-table]
      Install special raw Lisp behavior")
 (RETURN-LAST-TABLE
  (RETURN-LAST)
  "Install special raw Lisp behavior

  Please first see [return-last] for relevant background.

  This [table] is for advanced users only, and requires an active trust
  tag (see [defttag]). We recommend that you do not modify this table
  directly, but instead use the macro defmacro-last. Here we augment
  that discussion with some highly technical observations that can
  probably be ignored if you use defmacro-last.

  This [table] has a :guard requiring that each key be a symbol defined
  in raw Lisp, generally as a macro, and requiring that each non-nil
  value be associated either with a symbol that names a macro defined
  in ACL2, or else with a list of one element containing such a
  symbol. The table can only be modified when there is an active
  trust tag; see [defttag]. If a key is associated with the value
  nil, then that key is treated as though it were not in the table.

  Note that keys of this table are not eligible to be bound by [flet].
  The current value of this table may be obtained by evaluating the
  form (table-alist 'return-last-table (w state)). The built-in
  constant *initial-return-last-table* holds the initial value of
  this table.")
 (REVAPPEND
  (LISTS ACL2-BUILT-INS)
  "Concatentate the [reverse] of one list to another

  (Revappend x y) [concatenate]s the [reverse] of the list x to y,
  which is also typically a list.

  The following theorem characterizes this English description.

    (equal (revappend x y)
           (append (reverse x) y))

  Hint: This lemma follows immediately from the definition of [reverse]
  and the following lemma.

    (defthm revappend-append
      (equal (append (revappend x y) z)
             (revappend x (append y z))))

  The [guard] for (revappend x y) requires that x is a true list.

  Revappend is defined in Common Lisp. See any Common Lisp
  documentation for more information.

  Function: 

    (defun revappend (x y)
           (declare (xargs :guard (true-listp x)))
           (if (endp x)
               y (revappend (cdr x) (cons (car x) y))))")
 (REVERSE
  (LISTS STRINGS ACL2-BUILT-INS)
  "Reverse a list or string

  (Reverse x) is the result of reversing the order of the elements of
  the list or string x.

  The [guard] for reverse requires that its argument is a true list or
  a string.

  Reverse is defined in Common Lisp. See any Common Lisp documentation
  for more information.

  Function: 

    (defun reverse (x)
           (declare (xargs :guard (or (true-listp x) (stringp x))))
           (cond ((stringp x)
                  (coerce (revappend (coerce x 'list) nil)
                          'string))
                 (t (revappend x nil))))")
 (REVISITING_THE_ADMISSION_OF_APP
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Revisiting the Admission of App

  [{IMAGE}]

  Here is the definition of app again with certain parts highlighted.
  If you are taking the Walking Tour, please read the text carefully
  and click on each of the links below, except those marked [{ICON}].
  Then come back here.

  {IMAGE}

    [ACL2 !>](defun app (x y)
      (cond ((endp x) y)
            (t (cons (car x)
                     (app (cdr x) y)))))

    The [admission] of APP is trivial, using the
    relation [o<] [{ICON}] (which is known to be well-founded on
    the domain recognized by [o-p] [{ICON}]) and the measure
    ([ACL2-count] [{ICON}] X).  We [observe] that the
    [type] of APP is described by the theorem (OR
    (CONSP (APP X Y)) (EQUAL (APP X Y) Y)).  We used primitive type
    reasoning.

    [Summary]
    Form:  ( DEFUN APP ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  None
    Time:  0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
     APP

  {IMAGE}

  [{IMAGE}]")
 (REWRITE
  (RULE-CLASSES)
  "Make some :rewrite rules (possibly conditional ones)

  See [rule-classes] for a general discussion of rule classes,
  including how they are used to build rules from formulas and a
  discussion of the various keywords in a rule class description.

  This doc topic discusses the rule-class :rewrite. If you want a
  general discussion of how rewriting works in ACL2 and some guidance
  on how to construct effective rewrite rules, see
  [introduction-to-rewrite-rules-part-1] and then see
  [introduction-to-rewrite-rules-part-2].

    Examples:

    (defthm plus-commutes                 ; Replace (+ a b) by (+ b a) provided
      (equal (+ x y) (+ y x)))            ; certain heuristics approve the
                                          ; permutation.

    (defthm plus-commutes                 ; equivalent to the above
      (equal (+ x y) (+ y x))
      :rule-classes ((:rewrite :corollary (equal (+ x y) (+ y x))
                               :loop-stopper ((x y binary-+))
                               :match-free :all)))

    (defthm append-nil                    ; Replace (append a nil) by a, if
      (implies (true-listp x)             ; (true-listp a) rewrites to t.
               (equal (append x nil) x)))

    (defthm append-nil                    ; as above, but with defaults and
      (implies (true-listp x)             ; a backchain limit
               (equal (append x nil) x))
      :rule-classes ((:rewrite :corollary (implies (true-listp x)
                                                   (equal (append x nil) x))
                               :backchain-limit-lst (3) ; or equivalently, 3
                               :match-free :all)))

    (defthm member-append                 ; Replace (member e (append b c)) by
      (implies                            ; (or (member e b) (member e c) in
       (and                               ; contexts in which propositional
        (true-listp x)                    ; equivalence is sufficient, provided
        (true-listp y))                   ; b and c are true-lists.
       (iff (member e (append x y))
            (or (member e x) (member e y)))))

    General Form:
    (and ...
         (implies (and ...hi...)
                  (implies (and ...hk...)
                           (and ...
                                (equiv lhs rhs)
                                ...)))
         ...)

  Note: One :rewrite rule class object might create many rewrite rules
  from the :[corollary] formula. To create the rules, we first
  translate the formula, expanding all macros (see [trans]) and also
  removing [guard-holders]. Next, we eliminate all lambdas; one may
  think of this step as simply substituting away every [let], [let*],
  and [mv-let] in the formula. We then flatten the [and] and
  [implies] structure of the formula; for example, if the hypothesis
  or conclusion is of the form (and (and term1 term2) term3), then we
  replace that by the ``flat'' term (and term1 term2 term3). (The
  latter is actually an abbreviation for the right-associated term
  (and term1 (and term2 term3)).) The result is a conjunction of
  formulas, each of the form

    (implies (and h1 ... hn) concl)

  where no hypothesis is a conjunction and concl is neither a
  conjunction nor an implication. If necessary, the hypothesis of
  such a conjunct may be vacuous. We then further coerce each concl
  into the form (equiv lhs rhs), where equiv is a known [equivalence]
  relation, by replacing any concl not of that form by (iff concl t).
  A concl of the form (not term) is considered to be of the form (iff
  term nil). By these steps we reduce the given :[corollary] to a
  sequence of conjuncts, each of which is of the form

    (implies (and h1 ... hn)
             (equiv lhs rhs))

  where equiv is a known [equivalence] relation. See [equivalence] for
  a general discussion of the introduction of new [equivalence]
  relations. At this point, we check whether lhs and rhs are the same
  term; if so, we cause an error, since this rule will loop. (But
  this is just a basic check; the rule could loop in other cases, for
  example if rhs is an instance of lhs; see [loop-stopper].)

  We create a :rewrite rule for each such conjunct, if possible, and
  otherwise cause an error. It is possible to create a rewrite rule
  from such a conjunct provided lhs is not a variable, a quoted
  constant, a [let]-expression, a lambda application, or an
  [if]-expression.

  A :rewrite rule is used when any instance of the lhs occurs in a
  context in which the [equivalence] relation is an admissible
  [congruence] relation. First, we find a substitution that makes lhs
  equal to the target term. Then we attempt to relieve the
  instantiated hypotheses of the rule. Hypotheses that are fully
  instantiated are relieved by recursive rewriting. Hypotheses that
  contain ``free variables'' (variables not assigned by the unifying
  substitution) are relieved by attempting to guess a suitable
  instance so as to make the hypothesis equal to some known
  assumption in the context of the target. If the hypotheses are
  relieved, and certain restrictions that prevent some forms of
  infinite regress are met (see [loop-stopper]), the target is
  replaced by the instantiated rhs, which is then recursively
  rewritten.

  ACL2's rewriting process has undergone some optimization. In
  particular, when a term t1 is rewritten to a new term t2, the
  rewriter is then immediately applied to t2. On rare occasions you
  may find that you do not want this behavior, in which case you may
  wish to use a trick involving [hide]; see [meta], near the end of
  that documentation.

  In another optimization, when the hypotheses and right-hand side are
  rewritten, ACL2 does not really first apply the substitution and
  then rewrite; instead, it as it rewrites those terms it looks up
  the already rewritten values of the bound variables. Sometimes you
  may want those bindings rewritten again, e.g., because the
  variables occur in slots that admit additional equivalence
  relations. See double-rewrite.

  See [introduction-to-rewrite-rules-part-1] and see
  [introduction-to-rewrite-rules-part-2] for an extended discussion
  of how to create effective rewrite rules.


Subtopics

  [Backchain-limit]
      Limiting the effort expended on relieving hypotheses

  [Bind-free]
      To bind free variables of a rewrite, definition, or linear rule

  [Case-split]
      Like force but immediately splits the top-level goal on the
      hypothesis

  [Double-rewrite]
      Cause a term to be rewritten twice

  [Force]
      Identity function used to force a hypothesis

  [Free-variables]
      Free variables in rules

  [Hide]
      Hide a term from the rewriter

  [Loop-stopper]
      Limit application of permutative rewrite rules

  [Rewrite-stack-limit]
      Limiting the stack depth of the ACL2 rewriter

  [Set-rw-cache-state]
      Set the default rw-cache-state

  [Set-rw-cache-state!]
      Set the default rw-cache-state non-[local]ly

  [Simple]
      :[definition] and :[rewrite] rules used in preprocessing

  [Syntaxp]
      Attach a heuristic filter on a rule")
 (REWRITE-STACK-LIMIT
  (REWRITE)
  "Limiting the stack depth of the ACL2 rewriter

  ACL2 users can create rules of class :[rewrite] (see [rule-classes])
  that have the potential of causing an infinite loop in the ACL2
  rewriter. This could lead to Lisp stack overflows and even
  segmentation faults. For this reason, the depth of certain calls of
  functions in the ACL2 rewriter is limited by default using the
  value of the form (rewrite-stack-limit (w state)). To see the limit
  in action, execute the following forms.

    (defthm app-assoc-1
      (equal (append (append x y) z)
             (append x y z)))
    (defthm app-assoc-2
      (equal (append x y z)
             (append (append x y) z)))
    (thm (equal (append a b c) xxx)
         ; try without these hints to see a slightly different error message
         :hints ((\"Goal\" :do-not '(preprocess))))

  The ensuing error message shows a stack of one greater than the value
  of (rewrite-stack-limit (w state)), which by default is the value
  of the constant *default-rewrite-stack-limit*. The error message
  also explains how to use :[brr] t and ([cw-gstack]) to find looping
  rewrite rules.

  This limit can be changed; see [set-rewrite-stack-limit].

  For a related limit, see [backchain-limit].


Subtopics

  [Set-rewrite-stack-limit]
      Sets the rewrite stack depth used by the rewriter")
 (REWRITE_RULES_ARE_GENERATED_FROM_DEFTHM_EVENTS
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Rewrite Rules are Generated from DEFTHM Events

  [{IMAGE}]

  By reading the documentation of [defthm] [{ICON}] (and especially of
  its :[rule-classes] [{ICON}] argument) you would learn that when we
  submitted the command

    (defthm associativity-of-app
      (equal (app (app a b) c)
             (app a (app b c))))

  we not only command the system to prove that app is an associative
  function but

    * we commanded it to use that fact as a rewrite rule.

  That means that every time the system encounters a term of the form

    (app (app x y) z)

  it will replace it with

    (app x (app y z))!

  [{IMAGE}]")
 (RFIX
  (NUMBERS ACL2-BUILT-INS)
  "Coerce to a rational number

  Rfix simply returns any rational number argument unchanged, returning
  0 on a non-rational argument. Also see [nfix], see [ifix], see
  [realfix], and see [fix] for analogous functions that coerce to a
  natural number, an integer, a real, and a number, respectively.

  Rfix has a [guard] of t.

  Function: 

    (defun rfix (x)
           (declare (xargs :guard t))
           (if (rationalp x) x 0))")
 (ROUND
  (NUMBERS ACL2-BUILT-INS)
  "Division returning an integer by rounding off

    Example Forms:
    ACL2 !>(round 14 3)
    5
    ACL2 !>(round -14 3)
    -5
    ACL2 !>(round 14 -3)
    -5
    ACL2 !>(round -14 -3)
    5
    ACL2 !>(round 13 3)
    4
    ACL2 !>(round -13 3)
    -4
    ACL2 !>(round 13 -3)
    -4
    ACL2 !>(round -13 -3)
    4
    ACL2 !>(round -15 -3)
    5
    ACL2 !>(round 15 -2)
    -8

  (Round i j) is the result of taking the quotient of i and j and
  rounding off to the nearest integer. When the quotient is exactly
  halfway between consecutive integers, it rounds to the even one.

  The [guard] for (round i j) requires that i and j are rational
  ([real], in ACL2(r)) numbers and j is non-zero.

  Round is a Common Lisp function. See any Common Lisp documentation
  for more information. However, note that unlike Common Lisp, the
  ACL2 round function returns only a single value,

  Function: 

    (defun
         round (i j)
         (declare (xargs :guard (and (real/rationalp i)
                                     (real/rationalp j)
                                     (not (eql j 0)))))
         (let ((q (* i (/ j))))
              (cond ((integerp q) q)
                    ((>= q 0)
                     (let* ((fl (floor q 1)) (remainder (- q fl)))
                           (cond ((> remainder 1/2) (+ fl 1))
                                 ((< remainder 1/2) fl)
                                 (t (cond ((integerp (* fl (/ 2))) fl)
                                          (t (+ fl 1)))))))
                    (t (let* ((cl (ceiling q 1))
                              (remainder (- q cl)))
                             (cond ((< (- 1/2) remainder) cl)
                                   ((> (- 1/2) remainder) (+ cl -1))
                                   (t (cond ((integerp (* cl (/ 2))) cl)
                                            (t (+ cl -1))))))))))")
 (RULE-CLASSES
  (ACL2)
  "Adding rules to the database

    Example Form (from community book finite-set-theory/total-ordering.lisp):
    (defthm <<-trichotomy
      (implies (and (ordinaryp x)
                    (ordinaryp y))
               (or (<< x y)
                   (equal x y)
                   (<< y x)))
      :rule-classes
      ((:rewrite :corollary
                 (implies (and (ordinaryp x)
                               (ordinaryp y)
                               (not (<< x y))
                               (not (equal x y)))
                          (<< y x)))))

    General Form:
    a true list of rule class objects as defined below

    Special Cases:
    a symbol abbreviating a single rule class object

  When [defthm] is used to prove a named theorem, rules may be derived
  from the proved formula and stored in the database. The user
  specifies which kinds of rules are to be built, by providing a list
  of rule class names or, more generally, rule class objects, which
  name the kind of rule to build and optionally specify various
  attributes of the desired rule. The rule class names are
  :[rewrite], :[built-in-clause], :[clause-processor],
  :[compound-recognizer], :[congruence], :[definition], :[elim],
  :[equivalence], :[forward-chaining], :[generalize], :[induction],
  :[linear], :[meta], :[refinement], :[tau-system],
  :[type-prescription], :[type-set-inverter], and
  :[well-founded-relation]. Some classes require the
  user-specification of certain class-specific attributes. Each class
  of rule affects the theorem prover's behavior in a different way,
  as discussed in the corresponding documentation topic. In this
  topic we discuss the various attributes that may be attached to
  rule classes.

  Note that not all [events] generate rules. For example, a [defthm]
  event that specifies :rule-classes nil does not generate a rule.
  Similarly, a [defchoose] event generates an axiom that can be
  referenced by name in :use [hints], but it does not generate a
  rule.

  A rule class object is either one of the :class keywords or else is a
  list of the form shown below. Those fields marked with ``(!)'' are
  required when the :class is as indicated.

    (:class
      :COROLLARY term
      :TRIGGER-FNS (fn1 ... fnk) ; provided :class = :META (!)
      :TRIGGER-TERMS (t1 ... tk) ; provided :class = :FORWARD-CHAINING
                                 ;       or :class = :LINEAR
      :TYPE-SET n                ; provided :class = :TYPE-SET-INVERTER
      :TYPED-TERM term           ; provided :class = :TYPE-PRESCRIPTION
      :CLIQUE (fn1 ... fnk)      ; provided :class = :DEFINITION
      :CONTROLLER-ALIST alist    ; provided :class = :DEFINITION
      :INSTALL-BODY directive    ; provided :class = :DEFINITION
      :LOOP-STOPPER alist        ; provided :class = :REWRITE
      :PATTERN term              ; provided :class = :INDUCTION (!)
      :CONDITION term            ; provided :class = :INDUCTION
      :SCHEME term               ; provided :class = :INDUCTION (!)
      :MATCH-FREE all-or-once    ; provided :class = :REWRITE
                                         or :class = :LINEAR
                                         or :class = :FORWARD-CHAINING
      :BACKCHAIN-LIMIT-LST limit ; provided :class = :REWRITE
                                         or :class = :META
                                         or :class = :LINEAR
                                         or :class = :TYPE-PRESCRIPTION
      :HINTS hints               ; provided instrs = nil
      :INSTRUCTIONS instrs       ; provided  hints = nil
      :OTF-FLG flg)

  When rule class objects are provided by the user, most of the fields
  are optional and their values are computed in a context sensitive
  way. When a :class keyword is used as a rule class object, all
  relevant fields are determined contextually. Each rule class object
  in :rule-classes causes one or more rules to be added to the
  database. The :class keywords are documented individually under the
  following names. Note that when one of these names is used as a
  :class, it is expected to be in the keyword package (i.e., the
  names below should be preceded by a colon but the ACL2
  [documentation] facilities do not permit us to use keywords below).

  See also [force], [case-split], [syntaxp], and [bind-free] for
  ``pragmas'' one can wrap around individual hypotheses of certain
  classes of rules to affect how the hypothesis is relieved.

  Before we get into the discussion of rule classes, let us return to
  an important point. In spite of the large variety of rule classes
  available, at present we recommend that new ACL2 users rely almost
  exclusively on (conditional) rewrite rules. A reasonable but
  slightly bolder approach is to use :[type-prescription] and
  :[forward-chaining] rules for ``type-theoretic'' rules, especially
  ones whose top-level function symbol is a common one like
  [true-listp] or [consp]; see [type-prescription] and see
  [forward-chaining]. However, the rest of the rule classes are
  really not intended for widespread use, but rather are mainly for
  experts.

  We expect that we will write more about the question of which kind of
  rule to use. For now: when in doubt, use a :[rewrite] rule.

  :Rule-classes is an optional keyword argument of the [defthm] (and
  [defaxiom]) event. In the following, let name be the name of the
  event and let thm be the formula to be proved or added as an axiom.

  If :rule-classes is not specified in a [defthm] (or [defaxiom])
  event, it is as though what was specified was to make one or more
  :[rewrite] rules, i.e., as though :rule-classes ((:rewrite)) had
  been used. Use :rule-classes nil to specify that no rules are to be
  generated.

  If :rule-classes class is specified, where class is a non-nil symbol,
  it is as though :rule-classes ((class)) had been used. Thus,
  :rule-classes :[forward-chaining] is equivalent to :rule-classes
  ((:forward-chaining)).

  We therefore now consider :rule-classes as a true list. If any
  element of that list is a keyword, replace it by the singleton list
  containing that keyword. Thus, :rule-classes (:rewrite :elim) is
  the same as :rule-classes ((:rewrite) (:elim)).

  Each element of the expanded value of :rule-classes must be a true
  list whose [car] is one of the rule class keyword tokens listed
  above, e.g., :[rewrite], :[elim], etc., and whose [cdr] is a
  ``keyword alist'' alternately listing keywords and values. The
  keywords in this alist must be taken from those shown below. They
  may be listed in any order and most may be omitted, as specified
  below.

      :[Corollary] --- its value, term, must be a term. If omitted, this
      field defaults to thm. The :[corollary] of a rule class object
      is the formula actually used to justify the rule created and
      thus determines the form of the rule. Nqthm provided no similar
      capability: each rule was determined by thm, the theorem or
      axiom added. ACL2 permits thm to be stated ``elegantly'' and
      then allows the :[corollary] of a rule class object to specify
      how that elegant statement is to be interpreted as a rule. For
      the rule class object to be well-formed, its (defaulted)
      :[corollary], term, must follow from thm. Unless term follows
      trivially from thm using little more than propositional logic,
      the formula (implies thm term) is submitted to the theorem
      prover and the proof attempt must be successful. During that
      proof attempt the values of :[hints], :[instructions], and
      :[otf-flg], as provided in the rule class object, are provided
      as arguments to the prover. Such auxiliary proofs give the sort
      of output that one expects from the prover. However, as noted
      above, corollaries that follow trivially are not submitted to
      the prover; thus, such corollaries cause no prover output.

      Note that before term is stored, all calls of macros in it are
      expanded away. See [trans].

      :[Hints], :[instructions], :[otf-flg] --- the values of these fields
      must satisfy the same restrictions placed on the fields of the
      same names in [defthm]. These values are passed to the
      recursive call of the prover used to establish that the
      :[corollary] of the rule class object follows from the theorem
      or axiom thm.

      :[Type-set] --- this field may be supplied only if the :class is
      :[type-set-inverter]. When provided, the value must be a
      type-set, an integer in a certain range. If not provided, an
      attempt is made to compute it from the corollary. See
      [type-set-inverter].

      :Typed-term --- this field may be supplied only if the :class is
      :[type-prescription]. When provided, the value is the term for
      which the :[corollary] is a type-prescription lemma. If no
      :typed-term is provided in a :[type-prescription] rule class
      object, we try to compute heuristically an acceptable term. See
      [type-prescription].

      :Trigger-terms --- this field may be supplied only if the :class is
      :[forward-chaining] or :[linear]. When provided, the value is a
      list of terms, each of which is to trigger the attempted
      application of the rule. If no :trigger-terms is provided, we
      attempt to compute heuristically an appropriate set of
      triggers. See [forward-chaining] or see [linear].

      :Trigger-fns --- this field must (and may only) be supplied if the
      :class is :[meta]. Its value must be a list of function symbols
      (except that a macro alias can stand in for a function symbol;
      see [add-macro-alias]). Terms with these symbols trigger the
      application of the rule. See [meta].

      :Clique and :controller-alist --- these two fields may only be
      supplied if the :class is :[definition]. If they are omitted,
      then ACL2 will attempt to guess them. Suppose the :[corollary]
      of the rule is (implies hyp (equiv (fn a1 ... an) body)). The
      value of the :clique field should be a true list of function
      symbols, and if non-nil must include fn. These symbols are all
      the members of the mutually recursive clique containing this
      definition of fn. That is, a call of any function in :clique is
      considered a ``recursive call'' for purposes of the expansion
      heuristics. The value of the :controller-alist field should be
      an alist that maps each function symbol in the :clique to a
      list of t's and nil's of length equal to the arity of the
      function. For example, if :clique consists of just two symbols,
      fn1 and fn2, of arities 2 and 3 respectively, then ((fn1 t nil)
      (fn2 nil t t)) is a legal value of :controller-alist. The value
      associated with a function symbol in this alist is a ``mask''
      specifying which argument slots of the function ``control'' the
      recursion for heuristic purposes. Sloppy choice of :clique or
      :controller-alist can result in infinite expansion and stack
      overflow.

      :Install-body --- this field may only be supplied if the :class is
      :[definition]. Its value must be t, nil, or the default,
      :normalize. A value of t or :normalize will cause ACL2 to
      install this rule as the new body of the function being
      ``defined'' (fn in the paragraph just above); hence this
      definition will be installed for future :expand [hints].
      Furthermore, if this field is omitted or the value is
      :normalize, then this definition will be simplified using the
      so-called ``normalization'' procedure that is used when
      processing definitions made with [defun]. You must explicitly
      specify :install-body nil in the following cases: fn (as above)
      is a member of the value of constant
      *definition-minimal-theory*, the arguments are not a list of
      distinct variables, equiv (as above) is not [equal], or there
      are free variables in the hypotheses or right-hand side (see
      [free-variables]). However, supplying :install-body nil will
      not affect the rewriter's application of the :definition rule,
      other than to avoid using the rule to apply :expand hints. If a
      definition rule equates (f a1 ... ak) with body but there are
      hypotheses, hyps, then :expand [hints] will replace terms (f
      term1 ... termk) by corresponding terms (if hyps body (hide (f
      term1 ... termk))).

      :[Loop-stopper] --- this field may only be supplied if the class is
      :[rewrite]. Its value must be a list of entries each consisting
      of two variables followed by a (possibly empty) list of
      function symbols, for example ((x y binary-+) (u v foo bar)).
      It will be used to restrict application of rewrite rules by
      requiring that the list of instances of the second variables
      must be ``smaller'' than the list of instances of the first
      variables in a sense related to the corresponding functions
      listed; see [loop-stopper]. The list as a whole is allowed to
      be nil, indicating that no such restriction shall be made. Note
      that any such entry that contains a variable not being
      instantiated, i.e., not occurring on the left side of the
      rewrite rule, will be ignored. However, for simplicity we
      merely require that every variable mentioned should appear
      somewhere in the corresponding :[corollary] formula.

      :Pattern, :Condition, :Scheme --- the first and last of these fields
      must (and may only) be supplied if the class is :[induction].
      :Condition is optional but may only be supplied if the class is
      :[induction]. The values must all be terms and indicate,
      respectively, the pattern to which a new induction scheme is to
      be attached, the condition under which the suggestion is to be
      made, and a term which suggests the new scheme. See
      [induction].

      :Match-free --- this field must be :all or :once and may be supplied
      only if the :class is either :[rewrite], :[linear], or
      :[forward-chaining]. (This field is not implemented for other
      rule classes, including the :[type-prescription] rule class.)
      See [free-variables] for a description of this field. Note:
      Although this field is intended to be used for controlling
      retries of matching free variables in hypotheses, it is legal
      to supply it even if there are no such free variables. This can
      simplify the automated generation of rules, but note that when
      :match-free is supplied, the warning otherwise provided for the
      presence of free variables in hypotheses will be suppressed.

      :Backchain-limit-lst --- this field may be supplied only if the
      :class is either :[rewrite], :[meta], :[linear], or
      :[type-prescription]. It is further required either only one
      rule is generated from the formula or, at least, every such
      rule has the same list of hypotheses. The value for
      :backchain-limit-lst must be nil; a non-negative integer; or,
      except in the case of :[meta] rules, a true list each element
      of which is either nil or a non-negative integer. If it is a
      list, its length must be equal to the number of hypotheses of
      the rule and each item in the list is the ``backchain limit''
      associated with the corresponding hypothesis. If
      backchain-limit-lst is a non-negative integer, it is defaulted
      to a list of the appropriate number of repetitions of that
      integer. The backchain limit of a hypothesis is used to limit
      the effort that ACL2 will expend when relieving the hypothesis.
      If it is NIL, no new limits are imposed; if it is an integer,
      the hypothesis will be limited to backchaining at most that
      many times. Note that backchaining may be further limited by a
      global backchain-limit; see [backchain-limit] for details. For
      different ways to reign in the rewriter, see
      [rewrite-stack-limit] and see [set-prover-step-limit]. Jared
      Davis has pointed out that you can set the :backchain-limit-lst
      to 0 to avoid any attempt to relieve [force]d hypotheses, which
      can lead to a significant speed-up in some cases.

  Once thm has been proved (in the case of [defthm]) and each rule
  class object has been checked for well-formedness (which might
  require additional proofs), we consider each rule class object in
  turn to generate and add rules. Let :class be the class keyword
  token of the ith class object (counting from left to right).
  Generate the [rune] (:class name . x), where x is nil if there is
  only one class and otherwise x is i. Then, from the :[corollary] of
  that object, generate one or more rules, each of which has the name
  (:class name . x). See the :[doc] entry for each rule class to see
  how formulas determine rules. Note that it is in principle possible
  for several rules to share the same name; it happens whenever a
  :[corollary] determines more than one rule. This in fact only
  occurs for :[rewrite], :[linear], and :[forward-chaining] class
  rules and only then if the :[corollary] is essentially a
  conjunction. (See the documentation for [rewrite], [linear], or
  [forward-chaining] for details.)


Subtopics

  [Backchaining]
      Attempting to relieve the hypotheses of a rule

  [Built-in-clause]
      To build a clause into the simplifier

  [Clause-processor]
      Make or apply a :clause-processor rule (goal-level simplifier)

  [Compound-recognizer]
      Make a rule used by the typing mechanism

  [Congruence]
      The relations to maintain while simplifying arguments

  [Corollary]
      The corollary formula of a [rune]

  [Default-backchain-limit]
      Specifying the backchain limit for a rule

  [Definition]
      Make a rule that acts like a function definition

  [Elim]
      Make a destructor elimination rule

  [Equivalence]
      Mark a relation as an equivalence relation

  [Executable-counterpart]
      A rule for computing the value of a function

  [Forward-chaining]
      Make a rule to forward chain when a certain trigger arises

  [Free-variables]
      Free variables in rules

  [Generalize]
      Make a rule to restrict generalizations

  [Guard-holders]
      Remove trivial calls from a [term]

  [Induction]
      Make a rule that suggests a certain induction

  [Linear]
      Make some arithmetic inequality rules

  [Meta]
      Make a :meta rule (a hand-written simplifier)

  [Patterned-congruence]
      Removing restrictions on classic [congruence] rules

  [Refinement]
      Record that one equivalence relation refines another

  [Rewrite]
      Make some :rewrite rules (possibly conditional ones)

  [Tau-system]
      Make a rule for the ACL2 ``type checker''

  [Type-prescription]
      Make a rule that specifies the type of a term

  [Type-set-inverter]
      Exhibit a new decoding for an ACL2 type-set

  [Well-founded-relation]
      Show that a relation is well-founded on a set")
 (RULE-NAMES
  (THEORIES)
  "How rules are named.

    Examples:
    (:rewrite assoc-of-app)
    (:linear delta-aref . 2)
    (:definition length)
    (:executable-counterpart length)

  See [rune].")
 (RULER-EXTENDERS
  (DEFUN)
  "Control for ACL2's termination and induction analyses

  Introduction

  Consider the following recursive definition, which returns a list of
  threes of length one more than the length of x.

    (defun f (x)
      (cons 3
            (if (consp x)
                (f (cdr x))
              nil)))

  One might expect ACL2's termination analysis to admit this function,
  since we know that (cdr x) is ``smaller'' than x if (consp x) is
  true. (By default, ACL2's notion of ``smaller'' is ordinary
  natural-number <, and the argument x is measured by applying
  function acl2-count to x.) However, that termination analysis does
  not consider [if] tests, like (consp x) above, when they occur
  under calls of functions other than IF, such as CONS in the case
  above.

  One way to overcome this problem is to ``lift'' the IF test to the
  top level, as follows.

    (defun f (x)
      (if (consp x)
          (cons 3 (f (cdr x)))
        (cons 3 nil)))

  But another way to overcome the problem is to tell ACL2 to extend its
  termination (and induction) analysis through calls of cons, as
  follows.

    (defun f (x)
      (declare (xargs :ruler-extenders (cons)))
      (cons 3
            (if (consp x)
                (f (cdr x))
              nil)))

  You may even wish to provide value :all instead of an explicit list
  of ruler-extenders, so that no function call blocks the termination
  analysis:

    (defun f (x)
      (declare (xargs :ruler-extenders :all))
      (cons 3
            (if (consp x)
                (f (cdr x))
              nil)))

  Alternatively, you can omit the XARGS :RULER-EXTENDERS form, instead
  modifying the global default set of ruler-extenders:

    (set-ruler-extenders :all)

    ; or, for example:
    (set-ruler-extenders '(cons return-last))

  You can call the function [default-ruler-extenders] as follows to see
  the current global default set of ruler-extenders:

    (default-ruler-extenders (w state))

  We conclude this introduction by considering the handling of LET
  expressions by termination analysis. Consider the following
  example.

    (defun fact (n)
      (the (integer 1 *)
           (if (posp n)
               (* n (fact (1- n)))
             1)))

  ACL2 treats the call of [the] in the body of this definition as
  follows.

    (let ((var (if (posp n)
                   (* n (fact (1- n)))
                 1)))
      (if (and (integerp var) (<= 1 var))
          var
        ))

  A [let] expression, in turn, is treated as a [lambda] application:

    ((lambda (var)
       (if (if (integerp var)
               (not (< var 1))
             nil)
           var
         ))
     (if (posp n)
         (* n (fact (1- n)))
       1))

  Notice that the [posp] test, which governs the recursive call of
  fact, is inside an argument of a function application, namely the
  application of the LAMBDA expression. So by default, ACL2 will not
  consider this [posp] test in its termination analysis. The keyword
  :LAMBDAS in the list of ruler-extenders denotes all calls of lambda
  expressions, much as the inclusion of CONS in the ruler-extenders
  denotes all calls of CONS. The following definition is thus
  accepted by ACL2.

    (defun fact (n)
      (declare (xargs :ruler-extenders (:lambdas)))
      (the (integer 1 *)
           (if (posp n)
               (* n (fact (1- n)))
             1)))

  As a convenience, ACL2 allows the symbol :lambdas in place of
  (:lambdas), and in fact the former will also include the default
  ruler-extenders: [return-last] (which comes from macroexpansion of
  calls of [prog2$], [ec-call], and others) and [mv-list].

  IMPORTANT REMARKS. (1) Notice that the argument to
  set-ruler-extenders is evaluated, but the argument to
  :RULER-EXTENDERS in XARGS is not evaluated. (2) Do not put macro
  names in your list of ruler-extenders. For example, if you intend
  that + should not block the termination analysis, in analogy to
  cons in the example above, then the list of ruler-extenders should
  include binary-+, not +. Of course, if you use :all then this is
  not an issue, but see the next remark. (3) Also please note that by
  taking advantage of the ruler-extenders, you may be complicating
  the induction scheme stored for the function, whose computation
  takes similar advantage of the additional IF structure that you are
  specifying.

  Below we describe the notion of ruler-extenders in detail, as well as
  how to set its default using set-ruler-extenders.

  Details

  We begin by discussing how to set the ruler-extenders by using the
  macro set-ruler-extenders; below we will discuss the use of keyword
  :ruler-extenders in [xargs] [declare] forms.

    Examples:
    (set-ruler-extenders :basic) ; return to default
    (set-ruler-extenders *basic-ruler-extenders*) ; same as immediately above
    (set-ruler-extenders :all) ; every governing IF test rules a recursive call
    (set-ruler-extenders :lambdas) ; LET does not block termination analysis
    (set-ruler-extenders (cons :lambdas *basic-ruler-extenders*))
                                   ; same as immediately above
    (set-ruler-extenders '(f g)) ; termination analysis goes past calls of f, g

    General Form:
    (set-ruler-extenders val)

  where val evaluates to one of :basic, :all, :lambdas, or a true list
  of symbols containing no keyword other than, optionally, :lambdas.

  When a recursive definition is submitted to ACL2 (in :[logic] mode),
  the recursion must be proved to terminate; see [defun]. More
  precisely, ACL2 explores the [if] structure of the body of the
  definition to accumulate the tests that ``rule'' any given
  recursive call. The following example reviews how this works.
  Suppose that f has already been defined.

    (defun g (x y)
      (declare (xargs :measure (+ (acl2-count x) (acl2-count y))))
      (if (consp x)
          (g (cdr x) y)
        (if (consp y)
            (f (g x (cdr y)))
          (f (list x y)))))

  ACL2 makes the following response to this proposed definition. Notice
  that the :measure proposed above must be proved to be an ACL2
  ordinal --- that is, to satisfy O-P --- and that the arguments to
  each recursive call must be smaller (in the sense of that measure
  and O<, which here reduces to the ordinary < relation) than the
  formals under the assumption of the ruling IF tests. The first
  IMPLIES term below thus corresponds to the recursive call (g (cdr
  x) y), while the second corresponds to the recursive call (g x (cdr
  y)).

    For the admission of G we will use the relation O< (which is known
    to be well-founded on the domain recognized by O-P) and the measure
    (+ (ACL2-COUNT X) (ACL2-COUNT Y)).  The non-trivial part of the measure
    conjecture is

    Goal
    (AND (O-P (+ (ACL2-COUNT X) (ACL2-COUNT Y)))
         (IMPLIES (CONSP X)
                  (O< (+ (ACL2-COUNT (CDR X)) (ACL2-COUNT Y))
                      (+ (ACL2-COUNT X) (ACL2-COUNT Y))))
         (IMPLIES (AND (NOT (CONSP X)) (CONSP Y))
                  (O< (+ (ACL2-COUNT X) (ACL2-COUNT (CDR Y)))
                      (+ (ACL2-COUNT X) (ACL2-COUNT Y))))).

  Now consider the following alternate version of the above definition.

    (defun g (x y)
      (declare (xargs :measure (+ (acl2-count x) (acl2-count y))))
      (if (consp x)
          (g (cdr x) y)
        (f (if (consp y)
               (g x (cdr y))
             (list x y)))))

  The first test, (consp x), still rules the first recursive call, (g
  (cdr x) y). And the negation of that test, namely (not (consp x)),
  still rules the second recursive call (g x (cdr y)). But the call
  of f blocks the top-down exploration of the IF structure of the
  body of g, so (consp y) does not rule that second recursive call,
  which (again) is (g x (cdr y)). As a result, ACL2 fails to admit
  the above definition.

  Set-ruler-extenders is provided to overcome the sort of blocking
  described above. Suppose for example that the following event is
  submitted:

    (set-ruler-extenders '(f))

  Then the alternate definition of g above is admissible, because the
  call of f no longer blocks the top-down exploration of the IF
  structure of the body of g: that is, (consp y) becomes a ruler of
  the recursive call (g x (cdr y)). In this case, we say that f is a
  ``ruler-extender''. The same result obtains if we first submit

    (set-ruler-extenders :all)

  as this removes all function calls as blockers of the top-down
  analysis. In other words, with :all it is the case that for every
  recursive call, every test argument of a superior call of IF
  contributes a ruler of that recursive call.

  ACL2 handles [let] (and [let*]) expressions by translating them to
  LAMBDA expressions (see [term]). The next examples illustrates
  termination analysis involving such expressions. First consider the
  following (admittedly inefficient) definition.

    (defun fact (n)
      (let ((k (if (natp n) n 0)))
        (if (equal k 0)
            1
          (* k (fact (+ -1 k))))))

  ACL2 translates the body of this definition to a LAMBDA application,
  essentially:

    ((lambda (k)
       (if (equal k 0)
           1
         (* k (fact (+ -1 k)))))
     (if (natp n) n 0))

  As with the application of any function other than IF, the top-down
  termination analysis does not dive into arguments: the LAMBDA
  blocks the continuation of the analysis into its argument. But
  here, the argument of the LAMBDA is (if (natp n) n 0), which has no
  recursive calls to consider anyhow. What is more interesting: ACL2
  does continue its termination analysis into the body of the LAMBDA,
  in an environment binding the LAMBDA formals to its actuals. In
  this case, the termination analysis thus continues into the term

    (if (equal k 0)
        1
      (* k (fact (+ -1 k))))

  in the environment that binds k to the term (if (natp n) n 0). Thus,
  the proof obligation is successfully discharged, as reported by
  ACL2:

    For the admission of FACT we will use the relation O< (which is known
    to be well-founded on the domain recognized by O-P) and the measure
    (ACL2-COUNT N).  The non-trivial part of the measure conjecture is

    Goal
    (IMPLIES (NOT (EQUAL (IF (NATP N) N 0) 0))
             (O< (ACL2-COUNT (+ -1 (IF (NATP N) N 0)))
                 (ACL2-COUNT N))).
    .....
    Q.E.D.

    That completes the proof of the measure theorem for FACT.

  But now consider the following definition, in which the recursion
  takes place inside the argument of the LAMBDA rather than inside
  the LAMBDA body.

    (defun app (x y)
      (let ((result (if (endp x)
                        y
                      (cons (car x)
                            (app (cdr x) y)))))
        (if (our-test result)
            result
          0)))

  Writing the body in LAMBDA notation:

    ((lambda (result)
       (if (our-test result)
           result
         0))
     (if (endp x)
         y
       (cons (car x)
             (app (cdr x) y))))

  By default, the LAMBDA call blocks the top-down termination analysis
  from proceeding into the term (if (endp x) ...). To solve this, one
  can submit the event:

    (set-ruler-extenders :lambdas)

  The above definition of app is then admitted by ACL2, because the
  termination analysis is no longer blocked by the LAMBDA call.

  The example just above illustrates that the heuristically-chosen
  measure is suitably sensitive to the ruler-extenders. Specifically:
  that measure is the application of acl2-count to the first formal
  parameter of the function that is tested along every branch of the
  relevant IF structure (as determined by the rulers) and occurs as a
  proper subterm at the same argument position in every recursive
  call. The heuristics for choosing the controller-alist for a
  [definition] rule are similarly sensitive to the ruler-extenders
  (see [definition]).

  The remarks above for [defun] [events] are equally applicable when a
  definition sits inside a [mutual-recursion] event, except of course
  that in this case, a ``recursive call'' is a call of any function
  being defined by that [mutual-recursion] event.

  Rules of class :[definition] are sensitive to set-ruler-extenders in
  analogy to the case of defun [events].

  This macro generates a call (table acl2-defaults-table
  :ruler-extenders val) and hence is [local] to any [books] and
  [encapsulate] [events] in which it occurs. See
  [ACL2-defaults-table]. The current list of ruler-extenders may be
  obtained as

    (cdr (assoc-eq :ruler-extenders
         (table-alist 'acl2-defaults-table (w state))))

  or more conveniently, as:

    (default-ruler-extenders (w state))

  Note that evaluation of (set-ruler-extenders lst), where lst
  evaluates to a list, does not necessarily include the default
  ruler-extenders --- i.e., those included for the argument, :basic
  --- which are the elements of the list constant
  *basic-ruler-extenders*, namely [return-last] and [mv-list]. You
  may, of course, include these explicitly in your list argument.

  We conclude our discussion by noting that the set of ruler-extenders
  can affect the induction scheme that is stored with a recursive
  definition. The community book
  books/misc/misc2/ruler-extenders-tests.lisp explains how induction
  schemes are derived in this case. Consider the following example.

    (defun tree-of-nils-p (x)
      (if (consp x)
          (and (tree-of-nils-p (car x))
               (tree-of-nils-p (cdr x)))
        (null x)))

  The above definition generates the following induction scheme. Note
  that (and u v) expands to (if u v nil), which explains why the term
  (tree-of-nils-p (car x)) rules the recursive call (tree-of-nils-p
  (cdr x)), resulting in the hypothesis (tree-of-nils-p (car x)) in
  the final conjunct below.

    (AND (IMPLIES (NOT (CONSP X)) (:P X))
         (IMPLIES (AND (CONSP X)
                       (NOT (TREE-OF-NILS-P (CAR X)))
                       (:P (CAR X)))
                  (:P X))
         (IMPLIES (AND (CONSP X)
                       (TREE-OF-NILS-P (CAR X))
                       (:P (CAR X))
                       (:P (CDR X)))
                  (:P X)))

  Now consider the following variant of the above definition, in which
  a call of the function identity blocks the termination analysis.

    (defun tree-of-nils-p (x)
      (if (consp x)
          (identity (and (tree-of-nils-p (car x))
                         (tree-of-nils-p (cdr x))))
        (null x)))

  This time the induction scheme is as follows, since only the
  top-level IF test contributes rulers to the termination analysis.

    (AND (IMPLIES (NOT (CONSP X)) (:P X))
         (IMPLIES (AND (CONSP X)
                       (:P (CAR X))
                       (:P (CDR X)))
                  (:P X)))

  But now suppose we first designate identity as a ruler-extender.

    (set-ruler-extenders '(identity))

  Then the induction scheme generated for the both of the above
  variants of tree-of-nils-p is the one shown for the first variant,
  which is reasonable because both definitions now produce
  essentially the same termination analysis.


Subtopics

  [Default-ruler-extenders]
      The default [ruler-extenders] for [defun]'d functions")
 (RUNE
  (THEORIES)
  "A rule name

    Examples:
    (:rewrite assoc-of-app)
    (:linear delta-aref . 2)
    (:definition length)
    (:executable-counterpart length)

  Note: This topic discusses a basic notion of ``rule name'', or
  ``rune'' for short. Users often use abbrevitions for runes; for
  example, a [theory] expression (DISABLE APPEND) abbreviates the
  following set of runes: {(:DEFINITION BINARY-APPEND), (:INDUCTION
  BINARY-APPEND)}. See [theories] for a discussion of so-called
  ``runic designators'', which include expressions like APPEND (as
  above) as well as (APPEND) (for the executable-counterpart of
  BINARY-APPEND. Runic designators can also be ``runic
  abbreviations'' such as (:d APPEND), (:e APPEND), (:i APPEND), and
  (:t APPEND), which designate the definition,
  executable-counterpart, induction, and type-prescription rules for
  BINARY-APPEND. For a complete description of runic designators, see
  [theories]; we return now to the more basic notion of a rune.

  Background: The theorem prover is driven from a database of rules.
  The most common rules are :[rewrite] rules, which cause the
  simplifier to replace one term with another. [Events] introduce
  rules into the database. For example, a [defun] event may introduce
  runes for symbolically replacing a function call by its
  instantiated body, for evaluating the function on constants, for
  determining the type of a call of the function, and for the
  induction scheme introduced upon defining the function. [Defthm]
  may introduce several rules, one for each of the :[rule-classes]
  specified (where one rule class is specified if :[rule-classes] is
  omitted, namely, :rewrite).

  Every rule in the system has a name. Each name is a structured object
  called a ``rune,'' which is short for ``rule name''. Runes are
  always of the form (:token symbol . x), where :token is some
  keyword symbol indicating what kind of rule is named, symbol is the
  event name that created the rule (and is called the ``base symbol''
  of the rune), and x is either nil or a natural number that makes
  the rule name distinct from that of rules generated by other
  [events] or by other :[rule-classes] within the same event.

  For example, an event of the form

    (defthm name thm
      :rule-classes ((:REWRITE :COROLLARY term1)
                     (:REWRITE :COROLLARY term2)
                     (:ELIM    :COROLLARY term3)))

  typically creates three rules, each with a unique rune. The runes are

    (:REWRITE name . 1), (:REWRITE name . 2), and (:ELIM name).

  However, a given formula may create more than one rule, and all rules
  generated by the same :corollary formula will share the same rune.
  Consider the following example.

    (defthm my-thm
      (and (equal (foo (bar x)) x)
           (equal (bar (foo x)) x)))

  This is treated identically to the following.

    (defthm my-thm
      (and (equal (foo (bar x)) x)
           (equal (bar (foo x)) x))
      :rule-classes ((:rewrite
                      :corollary
                      (and (equal (foo (bar x)) x)
                           (equal (bar (foo x)) x)))))

  In either case, two rules are created: one rewriting (foo (bar x)) to
  x, and one rewriting (bar (foo x)) to x. However, only a single
  rune is created, (:REWRITE MY-THM), because there is only one rule
  class. But now consider the following example.

    (defthm my-thm2
      (and (equal (foo (bar x)) x)
           (equal (bar (foo x)) x))
      :rule-classes ((:rewrite
                      :corollary
                      (and (equal (foo (bar x)) x)
                           (equal (bar (foo x)) x)))
                     (:rewrite
                      :corollary
                      (and (equal (foo (bar (foo x))) (foo x))
                           (equal (bar (foo (bar x))) (bar x))))))

  This time there are four rules created. The first two rules are as
  before, and are assigned the rune (:REWRITE MY-THM . 1). The other
  two rules are similarly generated for the second :corollary, and
  are assigned the rune (:REWRITE MY-THM . 2).

  The function [corollary] will return the [corollary] term associated
  with a given rune in a given [world]. Example:

    (corollary '(:TYPE-PRESCRIPTION DIGIT-TO-CHAR) (w state))

  However, the preferred way to see the corollary term associated with
  a rune or a name is to use :pf; see [pf].

  The [defun] event creates as many as four rules. (:definition fn) is
  the rune given to the equality axiom defining the function, fn.
  (:executable-counterpart fn) is the rune given to the rule for
  computing fn on known arguments. A type prescription rule may be
  created under the name (:type-prescription fn), and an [induction]
  rule may be created under the name (:induction fn).

  Runes may be individually [enable]d and [disable]d, according to
  whether they are included in the current theory. See [theories].
  Thus, it is permitted to [disable] (:elim name), say, while
  enabling the other rules derived from name. Similarly, (:definition
  fn) may be [disable]d while (:executable-counterpart fn) and the
  type prescriptions for fn are [enable]d.

  Associated with most runes is the formula justifying the rule named.
  This is called the ``[corollary] formula'' of the rune and may be
  obtained via the function [corollary], which takes as its argument
  a rune and a property list [world]. Also see [pf]. The [corollary]
  formula for (:rewrite name . 1) after the [defthm] event above is
  term1. The corollary formulas for (:definition fn) and
  (:executable-counterpart fn) are always identical: the defining
  axiom. Some runes, e.g., (:definition car), do not have corollary
  formulas. [Corollary] returns nil on such runes. In any case, the
  corollary formula of a rune, when it is non-nil, is a theorem and
  may be used in the :use and :by [hints].

  Note: The system has built-in rules that, for regularity, ought to
  have names but don't because they can never be [disable]d. One such
  rule is that implemented by the [linear] arithmetic package.
  Because many of our subroutines are required by their calling
  conventions to return the justifying rune, we have invented the
  notion of ``fake runes.'' Fake runes always have the base symbol
  nil, use a keyword token that includes the phrase ``fake-rune'',
  and are always [enable]d. Here is the list of fake runes.

      ((:fake-rune-for-linear nil)
       (:fake-rune-for-type-set nil))

  Occasionally the system will print a fake rune where a rune is
  expected. For example, when (:FAKE-RUNE-FOR-LINEAR NIL) is reported
  among the rules used in a proof, it is an indication that the
  linear arithmetic package was used. However, fake runes are not
  allowed in [theories], they cannot be [enable]d or [disable]d, and
  they do not have associated [corollary] formulas. In short, despite
  the fact that the user may sometimes see fake runes printed, they
  should never be typed.


Subtopics

  [Find-rules-of-rune]
      Find the rules named rune")
 (RUNNING_MODELS
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Running Models

  [{IMAGE}]

  Suppose the machine being modeled is some kind of arithmetic unit.
  Suppose the model can be initialized so as to multiply x times y
  and leave the answer in z. Then if we initialize s to multiply with
  x=5 and y=7 and run the machine long enough, we can read the answer
  35 in the final state. {IMAGE}

  Because ACL2 is a programming language, our model can be run or
  executed.

  If you defined the model in ACL2 and then typed

    (lookup 'z (mc (s 'mult 5 7) 29))

  then ACL2 would compute 35. (Here we assume that the function s
  creates a state ready to run a given application on given inputs x
  and y.) You can emulate or test the model of your machine.

  This is obvious because ACL2 is Common Lisp; and Common Lisp is a
  programming language.

  [{IMAGE}]")
 (SAVE-AND-CLEAR-MEMOIZATION-SETTINGS
  (MEMOIZE)
  "Save and remove the current memoization settings

  For background on memoization, see [memoize].

    General Form:
    (save-and-clear-memoization-settings)

  Calls of this macro achieve two changes. The first copies the current
  memoization settings into an ACL2 [table], and the second
  unmemoizes all functions that were memoized by calls of [memoize].
  Also see [restore-memoization-settings].")
 (SAVE-EXEC
  (INTERFACING-TOOLS COMMAND-LINE)
  "Save an executable image and a wrapper script

  Save-exec saves your ACL2 state so that you can immediately re-start
  later in that same state. This utility can be useful for a project
  with [books] to be included every time ACL2 is started, to avoid
  time taken to run [include-book]. Another use of save-exec is to
  save an executable that takes command-line arguments beyond those
  normally passed to the host Lisp executable. All arguments of a
  call of save-exec are evaluated.

    Examples:

    ; Save an executable script named my-saved_acl2, with the indicated message
    ; added to the start-up banner:
    (save-exec \"my-saved_acl2\"
               \"This saved image includes Version 7 of Project Foo.\")

    ; Same as above, but instead with a generic comment in the start-up banner:
    (save-exec \"my-saved_acl2\" nil)

    ; Arrange that the generated script passes the indicated arguments to be
    ; processed by the Lisp (ACL2) executable (where this example is specific to
    ; the case that CCL is the host Lisp):
    (save-exec \"my-saved_acl2\" nil
               :host-lisp-args \"--no-init -Z 256M\")

    ; Arrange that the generated script passes along the indicated arguments
    ; to Lisp (ACL2), but that they are not processed by Lisp other than to
    ; record the additional arguments (see (6) below).
    (save-exec \"my-saved_acl2\" nil
               :inert-args \"abc xyz -i foo\")

    ; Combining the preceding two examples:
    (save-exec \"my-saved_acl2\" nil
               :host-lisp-args \"--no-init -Z 256M\"
               :inert-args \"abc xyz -i foo\")

    ; Arrange that ACL2 evaluates (with LD) the three forms shown.
    ; In this example, the THM form fails, but that does not stop the definition
    ; of BAR from being evaluated: LD continues on, just as the top-level loop
    ; lets you continue after a failure.
    (save-exec \"my-acl2\" \"test\"
               :init-forms
               '((defun foo (x) (reverse x))
                 (thm (equal (foo x) x))
                 (defun bar (x) x)))

    ; Essentially as just above, except that the call of LD returns after the THM
    ; failure, so BAR does not get defined.
    (save-exec \"my-acl2\" \"test\"
               :init-forms
               '((ld '((defun foo (x) (reverse x))
                       (thm (equal (foo x) x))
                       (defun bar (x) x))
                     :ld-pre-eval-print t :ld-verbose nil)))

    ; Immediately exit the ACL2 read-eval-print loop after starting up.
    (save-exec \"my-acl2\" nil
               :return-from-lp t)

    ; Immediately exit the ACL2 read-eval-print loop after starting up and
    ; defining function FOO in the logic.
    (save-exec \"my-acl2\" \"Start with foo defined.\"
               :return-from-lp '(with-output
                                 :off :all
                                 (defun foo (x) x)))

    ; Immediately exit the ACL2 read-eval-print loop after starting up and
    ; defining variable xxx in raw Lisp.
    (save-exec \"my-acl2\" \"Start with xxx defined.\"
               :return-from-lp '(with-output
                                 :off :all
                                 (ld '((set-raw-mode-on!)
                                       (defvar xxx (make-list 10))
                                       (set-raw-mode nil)
                                       (u)))))

  Each example above generates a file named \"my-saved_acl2\". That file
  is quite similar in form to the script generated when building ACL2
  directly from source code; details are below. For example, here are
  the contents of that generated file if the host Lisp is CCL (but
  where dates and pathnames are specific to one's environment). Here,
  we break lines using `\\', but the exec command is actually on a
  single line.

    #!/bin/sh

    # Saved August 16, 2013  23:06:49
    #  then August 17, 2013  11:01:56

    export CCL_DEFAULT_DIRECTORY=\"/projects/acl2/lisps/ccl/15542/ccl\"
    exec \"/projects/ccl/lx86cl64\" -I \"/u/smith/my-saved_acl2.lx86cl64\" \\
         -Z 64M -K ISO-8859-1 -e \"(acl2::acl2-default-restart)\" \\
         --no-init -Z 256M \\
         -- \\
         abc xyz -i foo \\
         \"$@\"

    General Form:
    (save-exec exec-filename extra-startup-string
               :host-lisp-args host-lisp-args
               :inert-args inert-args
               :return-from-lp return-from-lp
               :init-forms init-forms)

  where the keyword arguments are optional, and arguments are as
  follows.

      Exec-filename is the filename of the proposed executable.

      Extra-startup-string is a non-empty string to be printed after the
      normal ACL2 startup message when you start up the saved image.
      However, extra-startup-string is allowed to be nil, in which
      case a generic string will be printed instead.

      Host-lisp-args can be nil (the default), but if it is a non-nil
      value, then it is a string to be inserted into the command line
      in the saved script, specifying additional arguments that are
      to be processed by the host Lisp executable. (Note for SBCL
      only: these are runtime options; for toplevel options, see (8)
      below.)

      Inert-args can be nil (the default), but if it is a non-nil value,
      then it is a string to be inserted into the command line in the
      saved script, specifying additional arguments that are not to
      be processed by the host Lisp executable.

  Return-from-lp and init-forms are nil by default. Regardless of their
  value, ACL2 starts up and enters its read-eval-print loop in the
  usual way; see [lp]. Normally you'll stay inside that loop, but if
  return-from-lp or init-forms is not nil, then the indicated forms
  are evaluated in the ACL2 read-eval-print loop: a single form in
  the case of return-from-lp, and a list of forms in the case of
  init-forms. (Essentially, the [ld] special [standard-oi] is
  provided to a call of [ld] as a list with the indicated forms on
  the front.) Moreover, if the case of return-from-lp, the loop is
  exited after evaluation of the form, leaving you in raw Lisp.
  Evaluation of return-from-lp is done with [ld] options that
  minimize output (also see [with-output] to minimize output).
  Suggestion: let return-from-lp be t if you simply want to exit the
  read-eval-print loop at startup, without evaluating any
  (nontrivial) form.

  NOTE: It is illegal to supply non-nil values for both :return-from-lp
  and :init-forms. But if you add (value :q) to the end of your list
  of :init-forms, and your other forms do not result in an error,
  then you will be left in raw Lisp (as was presumably intended if
  you were planning to use :return-from-lp).

  The remainder of this documentation focuses on the options other than
  return-from-lp and init-forms.

  Details:

  (1) You must first exit the ACL2 read-eval-print loop, typically by
  executing :q, before evaluating a save-exec call; otherwise an
  error occurs.

  (2) The image will be saved so that in the new image, the raw Lisp
  package and the package in the ACL2 read-eval-print loop (see [lp])
  will be the same as their respective values at the time save-exec
  is called.

  (3) Save-exec generates a small script file (e.g., \"my-saved_acl2\" in
  the examples above), similar in form (see (4) below) to the script
  generated when building ACL2 directly from source code, but with a
  comment line indicating the time at which the new script is
  written. Save-exec also saves an associated binary file. The binary
  file's name is obtained by putting a suffix on the script filename;
  for example, if the host Lisp is GCL running on a Linux or Darwin
  (MacOS) system, then that binary file has the name
  my-saved_acl2.gcl in the examples above.

  (4) If inert-args is nil (for example if keyword :inert-args is
  omitted), then when the generated ACL2 script is invoked with
  command line arguments, those arguments will be passed to the host
  Lisp; otherwise they will not. Thus for the example above, suppose
  we invoke the generated script as follows.

    my-saved_acl2 -a bcd -e fgh

  If my-saved_acl2 was generated using a save-exec command with a
  non-nil value specified for keyword :inert-args, then the arguments
  ``-a bcd -e fgh'' will not be passed to the host Lisp; otherwise,
  they will be. Note that for ACL2 executable scripts generated by an
  ordinary ACL2 build from sources, the latter case (i.e., without
  inert-args) takes place.

  (5) The generated script, which specifies execution with /bin/sh,
  will generally contain a line of one of the following forms. (But
  for SBCL, see (8) below.) In the examples that follow, ACL2_options
  is a suitable list of command-line arguments given to the ACL2
  executable. The quoted string \"$@\" is intended to allow the user to
  pass additional command-line arguments to that executable.

      If host-lisp-args and inert-args are omitted (or nil):

        exec   \"$@\"

      More generally, host-lisp-args is inserted immediately after
      , but only if it is non-nil (hence a string). If
      inert-args is nil, we thus get:

        exec   host-lisp-args \"$@\"

      If host-lisp-args redefines a value from , then it is
      up to the host lisp which value to use. For example,
      experiments show that in CCL, if -Z appears twice, each with a
      legal value, then the second value is the one that is used
      (i.e. it does indeed override the original value written out by
      ACL2 in . But experiments also show that in
      LispWorks, where ``-init -'' is included in ,
      then inclusion of ``-init foo.lisp'' in host-lisp-args is
      ignored.

      The remaining cases below are for a non-nil value of inert-args. In
      each case, if host-lisp-args is nil then it should be omitted
      from the displayed command.

      If inert-args is t then an additional argument, `--', indicates that
      when ACL2 is given command line arguments, these should not be
      processed by the host Lisp (other than recording them; see (6)
      below):

        exec   host-lisp-args -- \"$@\"

      If inert-args is a string then the result is similar to the above,
      except that inert-args is added immediately after `--':

        exec   host-lisp-args -- inert-args \"$@\"

  (6) See [oslib::argv] for a utility that returns a list of all
  inert-args from an invocation of ACL2. See also [getopt] for a
  convenient way to parse these arguments.

  (7) Suppose that you invoke an ACL2 script, say \"my-saved_acl2\", that
  was generated by save-exec, and then optionally evaluate some
  forms. Then you may save a new ACL2 script with save-exec. The new
  script will contain comment lines that extend comment lines in
  \"my-saved_acl2\" with a new write date, but otherwise will be
  identical to the script that would have been generated by executing
  the new save-exec call after invoking the original ACL2 executable
  (built directly from ACL2 sources) instead of \"my-saved_acl2\". In
  other words, the options added by the earlier save-exec call that
  created \"my-saved_acl2\" are discarded by the new save-exec call.
  However, the .core file will built on top of the .core file that
  was consulted when \"my-saved_acl2\" was invoked.

  (8) The following note pertains only to the case that the host Lisp
  is SBCL. For SBCL, the scripts written are analogous to, but
  slightly different from, those shown above. Please note that for
  SBCL, the host-lisp-args are what the SBCL manual calls ``runtime
  options''. For SBCL only, an extra keyword argument,
  :toplevel-args, may be used for specifying what the SBCL manual
  calls ``toplevel options. As with :host-lisp-args, this value,
  toplevel-args, should be nil (the default) or a string. Here is an
  example.

    (save-exec \"my-saved_acl2\" nil
               :host-lisp-args \"--dynamic-space-size 12000\"
               :toplevel-args \"--eval '(print \\\"HELLO\\\")'\"
               :inert-args \"--my-option my-value\")

  The script generated by this example call of save-exec contains a
  line such as the following (with the same convention for `\\' as
  before)

    exec \"/projects/sbcl-1.1.7-x86-64-linux/src/runtime/sbcl\" \\
         --dynamic-space-size 2000 --control-stack-size 8 \\
         --core \"/u/smith/my-saved_acl2.core\" --dynamic-space-size 12000 \\
         --end-runtime-options \\
         --no-userinit --eval '(acl2::sbcl-restart)' \\
         --eval '(print \"HELLO\")' \\
         --end-toplevel-options \\
         --my-option my-value \\
         \"$@\"

  In general, the generated script is of one of the following forms
  (with the same convention for `\\' as before).

      For the case that inert-args is nil:

        exec  \\
              host-lisp-args --end-runtime-options \\
              host-lisp-args \\
             \"$@\"

      For the case that inert-args is non-nil:

        exec  \\
              host-lisp-args --end-runtime-options \\
              host-lisp-args --end-toplevel-options \\
             inert-args \"$@\"

  Notice that as before, when the generated script is invoked (for
  example, at the shell), additional command-line arguments provided
  at that time are passed to Lisp if and only if inert-args is nil.
  For SBCL, when they are passed to Lisp they are passed as toplevel
  options, not as runtime options.")
 (SAVING-AND-RESTORING (POINTERS)
                       "See [save-exec].")
 (SEARCH
  (LISTS STRINGS ACL2-BUILT-INS)
  "Search for a string or list in another string or list

    Example Forms:
    (search \"cd\" \"Cdabcdefcde\")                   ; = 4, index of first match
    (search \"cd\" \"Cdabcdefcde\" :test 'equal)      ; same as above
    (search \"cd\" \"Cdabcdefcde\" :from-end t)       ; = 8, index of last match
    (search \"cd\" \"Cdabcdefcde\" :start1 1)         ; = 1
    (search \"cd\" \"Cdabcdefcde\" :start2 5)         ; = 8
    (search \"cd\" \"Cdabcdefcde\" :test 'char-equal) ; = 0 (case-insensitive)
    (search \"ac\" \"Cdabcdefcde\")                   ; = nil
    (search '(a b) '(9 8 a b 7 6))                    ; = 2

    General Form:
    (search seq1 seq2 &key from-end test start1 start2 end1 end2)

  Search indicates whether one string or list occurs as a (contiguous)
  subsequence of another string or list, respectively. It returns nil
  if no such match is found; otherwise it returns the (zero-based)
  index of the first match by default, but a non-nil value of keyword
  argument :from-end causes it to return the last match. The :test is
  equal by default. The other legal value for :test is char-equal,
  which can be given only for two strings, in which case the match is
  case-insensitive. Finally, values of :start1 and :end1 for the
  first sequence, and of :start2 and :end2 for the second sequence,
  bound the portion of the respective sequence used for deciding on a
  match, though the index returned is always an index into the second
  sequence as a whole.

  The [guard] for calls of search is given by a function,
  search-fn-guard, which has the following requirements.

    * The two arguments much both satisfy [true-listp] or else must both be
      strings, which must consist of standard characters (see
      [standard-char-p]) if the :test is [char-equal].
    * The :test must evaluate to one of the symbols [equal] or
      [char-equal], where the latter is only allowed if the (first)
      two arguments are strings.
    * The values of :start1, :start2, :end1, and :end2 must all be natural
      numbers, where if omitted they default to 0, 0, the length len1
      of the first argument, and the length len2 of the second
      argument, respectively.
    * If start1 is the value of :start1, defaulting as described just
      above, and similarly for the other start and end keywords and
      for lengths len1 and len2 as described just above, then: start1
      <= end1 <= len1 and start2 <= end2 <= len2.

  Search is a Common Lisp function (actually, a macro in ACL2). See any
  Common Lisp documentation for more information.


Definition

  Macro: 

    (defmacro
     search
     (seq1 seq2 &key from-end (test ''equal)
           (start1 '0)
           (start2 '0)
           (end1 'nil end1p)
           (end2 'nil end2p))
     (cons
      'search-fn
      (cons
       seq1
       (cons
        seq2
        (cons
         from-end
         (cons
          test
          (cons
              start1
              (cons start2
                    (cons end1
                          (cons end2
                                (cons end1p (cons end2p 'nil))))))))))))

  Function: 

    (defun
     search-fn
     (seq1 seq2 from-end test
           start1 start2 end1 end2 end1p end2p)
     (declare
      (xargs
          :guard (search-fn-guard seq1 seq2 from-end test
                                  start1 start2 end1 end2 end1p end2p)))
     (let*
      ((end1 (if end1p end1 (length seq1)))
       (end2 (if end2p end2 (length seq2)))
       (seq1 (subseq seq1 start1 end1)))
      (mv-let
       (seq1 seq2)
       (cond ((eq test 'char-equal)
              (mv (string-downcase seq1)
                  (string-downcase seq2)))
             (t (mv seq1 seq2)))
       (and (<= (- end1 start1) (- end2 start2))
            (cond (from-end (search-from-end seq1 seq2 start2 end2 nil))
                  (t (search-from-start seq1 seq2 start2 end2)))))))

  Function: 

    (defun
       search-from-end
       (seq1 seq2 start2 end2 acc)
       (declare (xargs :guard (and (or (true-listp seq1) (stringp seq1))
                                   (or (true-listp seq2) (stringp seq2))
                                   (integerp start2)
                                   (<= 0 start2)
                                   (integerp end2)
                                   (<= end2 (length seq2))
                                   (<= (+ start2 (length seq1)) end2))))
       (cond ((or (not (integerp end2))
                  (not (integerp start2)))
              nil)
             (t (let* ((bound2 (+ start2 (length seq1)))
                       (matchp (equal seq1 (subseq seq2 start2 bound2)))
                       (new-acc (if matchp start2 acc)))
                      (cond ((>= bound2 end2) new-acc)
                            (t (search-from-end seq1 seq2 (1+ start2)
                                                end2 new-acc)))))))

  Function: 

    (defun
       search-from-start
       (seq1 seq2 start2 end2)
       (declare (xargs :guard (and (or (true-listp seq1) (stringp seq1))
                                   (or (true-listp seq2) (stringp seq2))
                                   (integerp start2)
                                   (<= 0 start2)
                                   (integerp end2)
                                   (<= end2 (length seq2))
                                   (<= (+ start2 (length seq1)) end2))))
       (let ((bound2 (+ start2 (length seq1))))
            (cond ((or (not (integerp end2))
                       (not (integerp start2)))
                   nil)
                  ((equal seq1 (subseq seq2 start2 bound2))
                   start2)
                  ((>= bound2 end2) nil)
                  (t (search-from-start seq1 seq2 (1+ start2)
                                        end2)))))")
 (SECOND
  (NTH ACL2-BUILT-INS)
  "Second member of the list

  See any Common Lisp documentation for details.")
 (SERIALIZE
  (IO)
  "Routines for saving ACL2 objects to files, and later restoring them

  We thank Jared Davis for contributing the ``serialization'' routines
  for saving ACL2 objects in files for later loading. These are
  available in [hons-enabled] ACL2 executables.

  We implement some routines for writing arbitrary ACL2 objects to
  files, and for loading those files later. We usually call these
  \".sao\" files, which stands for (S)erialized (A)CL2 (O)bject.

  Our serialization scheme uses a compact, binary format that preserves
  structure sharing in the original object. We optimize for read
  performance.


Subtopics

  [Serialize-alternatives]
      Historic alternatives to the [serialize] routines.

  [Serialize-in-books]
      Using serialization efficiently in books

  [Serialize-read]
      Read a serialized ACL2 object from a file

  [Serialize-write]
      Write an ACL2 object into a file

  [With-serialize-character]
      Control output mode for print-object$")
 (SERIALIZE-ALTERNATIVES
  (SERIALIZE)
  "Historic alternatives to the [serialize] routines.

  Users of [hons-enabled] ACL2 executables could previously use the
  routines compact-print-file and compact-read-file, which were once
  built into ACL2. Another option was to use the hons-archive
  library. These tools were deprecated and ultimately removed from
  ACL2. If for some reason you need to use them, see
  [community-books] SVN revisions prior to 1314.")
 (SERIALIZE-IN-BOOKS
  (SERIALIZE)
  "Using serialization efficiently in books

  Our serialize scheme was developed in order to allow very large ACL2
  objects to be loaded into books. Ordinarily this is carried out
  using [serialize-read] within a [make-event], e.g.,

    (make-event (mv-let (obj state)
                        (serialize-read \"my-file\")
                        (value `(defconst *my-file* ',obj))))

  But this scheme is not particularly efficient.

  During [certify-book], the actual call of serialize-read is carried
  out, and this is typically pretty fast. But then a number of
  possibly inefficient things occur.

      - The ACL2 function bad-lisp-object is run on the resulting object.
      This is memoized for efficiency, but may still take
      considerable time when the file is very large.

      - The checksum of the resulting object is computed. This is also
      memoized, but as before may still take some time.

      - The object that was just read is then written into book.cert,
      essentially with [serialize-write]. This can take some time,
      and results in large certifiate files.

  Then, during [include-book], the make-event expansion of is loaded.
  This is now basically just a serialize-read.

  The moral of the story is that using serialize will only help your
  certify-book time, and it only impacts a portion of the overall
  time.

  To avoid this overhead, we have developed an UNSOUND alternative to
  serialize-read, which is available only by loading an additional
  book. So, if the above scheme is not performing well for you, you
  may wish to see [unsound-read].")
 (SERIALIZE-READ
  (SERIALIZE ACL2-BUILT-INS)
  "Read a serialized ACL2 object from a file

  General form:

    (serialize-read filename
                    [:hons-mode {:always, :never, :smart}]   ; :smart by default
                    [:verbosep  {t, nil}])                   ; nil by default
     -->
    (mv obj state)

  In the logic this is an oracle read.

  Under the hood, we try to read and return a serialized object from a
  file that was presumably created by [serialize-write]. On success
  we return the contents of the file. Any failures (e.g., file not
  found, bad file contents, etc.) will result in a hard Lisp error.

  The filename should be a string that gives the path to the file.

  The hons-mode controls how whether to use [hons] or [cons] to restore
  the object. The default mode is :smart, which means that conses
  that were [normed] at the time of the file's creation should be
  restored with hons. But you can override this and insist that hons
  is to :always or :never be used, instead.

  Why would you use :never? If your object previously had a lot of
  honses, but you no longer have any need for them to be normed, then
  using :never may sometimes be a lot faster since it can avoid hons
  calls. On the other hand, if you are going to [hons-copy] some part
  of the file's contents, then it is likely faster to use :smart or
  :always instead of first creating normal conses and then copying
  them to build honses.

  The :verbosep flag just controls whether to print some low-level
  details related to timing and memory usage as the file is being
  read.")
 (SERIALIZE-WRITE
  (SERIALIZE ACL2-BUILT-INS)
  "Write an ACL2 object into a file

  General form:

    (serialize-write filename obj
                     [:verbosep  {t, nil}])    ; nil by default
     -->
    state

  In the logic this carries out an oracle read.

  Under the hood, we try to save obj into the file indicated by
  filename, which must be a string. The object can later be recovered
  with [serialize-read]. We just return state, and any failures
  (e.g., file not openable) will result in a hard Lisp error.

  Writing objects to disk is generally slower than reading them back in
  since some analysis is required to convert an object into our
  [serialize]d object format.

  The verbosep flag just says whether to print some low-level details
  related to timing and memory usage as the file is being read.")
 (SET-ABSSTOBJ-DEBUG
  (DEFABSSTOBJ)
  "Obtain debugging information upon atomicity violation for an abstract
  stobj

  This [documentation] topic assumes familiarity with abstract stobjs.
  See [defabsstobj].

  Below we explain what is meant by an error message such as the
  following.

    ACL2 Error in CHK-ABSSTOBJ-INVARIANTS:  Possible invariance violation
    for an abstract stobj!  See :DOC set-absstobj-debug, and PROCEED AT
    YOUR OWN RISK.

  The use of (set-absstobj-debug t) will make this error message more
  informative, as follows, at the cost of slower execution --- but in
  practice, the slowdown may be negligible (more on that below).

    ACL2 Error in CHK-ABSSTOBJ-INVARIANTS:  Possible invariance violation
    for an abstract stobj!  See :DOC set-absstobj-debug, and PROCEED AT
    YOUR OWN RISK.  Evaluation was aborted under a call of abstract stobj
    export UPDATE-FLD-NIL-BAD.

  You may be best off starting a new ACL2 session if you see one of the
  errors above. But you can continue at your own risk. With a trust
  tag (see [defttag]), you can even fool ACL2 into thinking nothing
  is wrong, and perhaps you can fix up the abstract stobj so that
  indeed, nothing really is wrong. See the community book
  books/misc/defabsstobj-example-4.lisp for how to do that. That book
  also documents the :always keyword and a special value for the
  first argument, :RESET.

    Examples:
    (set-absstobj-debug t)                 ; obtain extra debug info, as above
    (set-absstobj-debug t :event-p t)      ; same as above
    (set-absstobj-debug t
                        :on-skip-proofs t) ; as above, but even in include-book
    (set-absstobj-debug t :event-p nil)    ; returns one value, not error triple
    (set-absstobj-debug nil)               ; avoid extra debug info (default)

    General Form:
    (set-absstobj-debug val
                        :event-p        event-p        ; default t
                        :always         always         ; default nil
                        :on-skip-proofs on-skip-proofs ; default nil
                        )

  where the keyword arguments are optional with defaults as indicated
  above, and all supplied arguments are evaluated except for
  on-skip-proofsp, which must be Boolean (if supplied). Keyword
  arguments are discussed at the end of this topic.

  Recall (see [defabsstobj]) that for any exported function whose :EXEC
  function might (according to ACL2's heuristics) modify the concrete
  stobj non-atomically, one must specify :PROTECT t. This results in
  extra code generated for the exported function, which provides a
  check that atomicity was not actually violated by a call of the
  exported function. The extra code might slow down execution, but
  perhaps only negligibly in typical cases. If you can tolerate a bit
  extra slow-down, then evaluate the form (set-absstobj-debug t).
  Subsequent such errors will provide additional information, as in
  the example displayed earlier in this documentation topic.

  Finally we document the keyword arguments, other than :ALWAYS, which
  is discussed in a book as mentioned above. When the value of
  :EVENT-P is true, which it is by default, the call of
  set-absstobj-debug will expand to an event. That event is a call of
  [value-triple]. In that case, :ON-SKIP-PROOFS is passed to that
  call so that set-absstobj-debug has an effect even when proofs are
  being skipped, as during [include-book]. That behavior is the
  default; that is, :ON-SKIP-PROOFS is nil by default. Also see
  [value-triple]. The value of keyword :ON-SKIP-PROOFS must always be
  either t or nil, but other than that, it is ignored when EVENT-P is
  nil.")
 (SET-ACCUMULATED-PERSISTENCE (POINTERS)
                              "See [accumulated-persistence].")
 (SET-BACKCHAIN-LIMIT
  (BACKCHAIN-LIMIT)
  "Sets the backchain-limit used by the type-set and rewriting
  mechanisms

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  Moreover, its effect is to set the [ACL2-defaults-table], and hence
  its effect is [local] to the book or [encapsulate] form containing
  it; see [ACL2-defaults-table].

  This event sets the global [backchain-limit] used by the ACL2
  type-set and rewriting mechanisms. Its value may be a cons whose
  car and cdr are each either nil or a non-negative integer. Its
  value x may also be nil or a non-negative integer, which is treated
  as a cons whose car and cdr are both x.

  The car is used to limit backchaining used by the ACL2 type-set
  mechanism, while the cdr is used to limit backchaining used by the
  rewriting mechanism. See [backchain-limit] for details about how
  backchain-limits are used. Rewrite backchain limits may also be
  installed at the level of hints; see [hints] for a discussion of
  :backchain-limit-rw.

    :set-backchain-limit nil  ; do not impose any additional limits
    :set-backchain-limit 0    ; allow only type-set reasoning for rewriting
                              ; hypotheses
    :set-backchain-limit 500  ; allow backchaining to a depth of no more
                              ; than 500 for rewriting hypotheses
    (set-backchain-limit 500) ; same as above
    :set-backchain-limit (500 500)
                              ; same as above
    (set-backchain-limit '(500 500))
                              ; same as above
    (set-backchain-limit '(3 500))
                              ; allow type-set backchaining to a depth of no more
                              ; than 3 and rewriter backchaining to a depth of no
                              ; more than 500

  The default limit is (nil nil).")
 (SET-BODY
  (DEFINITION EVENTS)
  "Set the definition body

    Examples:
    (set-body foo (:definition foo)) ; restore original definition of foo
    (set-body foo foo) ; same as just above
    (set-body foo my-foo-def) ; use my-foo-def for the body of foo
    (set-body foo (:definition my-foo-def)) ; same as just above

  Rules of class :[definition] can install a new definition body, used
  for example by :expand [hints]. See [definition] and also see
  [hints] for a detailed discussion of the :install-body fields of
  :[definition] rules and their role in :expand hints.

  There may be several such definitions, but by default, the latest one
  is used by :expand hints. Although the :with keyword may be used in
  :expand hints to override this behavior locally (see [hints]), it
  may be convenient to install a definition for expansion other than
  the latest one --- for example, the original definition. Set-body
  may be used for this purpose.

    General Form:
    (set-body function-symbol rule-name)

  where rule-name is either a :definition [rune] or is a function
  symbol, sym, which represents the rune (:definition sym).

  You can view all definitions available for expansion; see
  [show-bodies].")
 (SET-BOGUS-DEFUN-HINTS-OK
  (DEFUN)
  "Allow unnecessary (xargs :hints ...).

    General Forms:
    (set-bogus-defun-hints-ok t)
    (set-bogus-defun-hints-ok nil)
    (set-bogus-defun-hints-ok :warn)

  By default, ACL2 causes an error when the keyword :[hints] is
  supplied in an [xargs] [declare] form for a non-recursive
  definition (see [defun]). This behavior can be defeated with
  (set-bogus-defun-hints-ok t), or if you still want to see a warning
  in such cases, (set-bogus-defun-hints-ok :warn).")
 (SET-BOGUS-MUTUAL-RECURSION-OK
  (MUTUAL-RECURSION)
  "Allow unnecessary ``mutual recursion''

    Examples:
    (set-bogus-mutual-recursion-ok t)
    (set-bogus-mutual-recursion-ok nil)
    (set-bogus-mutual-recursion-ok :warn)

  By default, ACL2 checks that when a ``clique'' of more than one
  function is defined simultaneously (using [mutual-recursion] or
  [defuns]), then every body calls at least one of the functions in
  the ``clique.'' Below, we refer to definitional events that fail
  this check as ``bogus'' mutual recursions. The check is important
  because ACL2 does not store induction schemes for functions defined
  with other functions in a [mutual-recursion] or [defuns] event.
  Thus, ACL2 may have difficulty proving theorems by induction that
  involve such functions. Moreover, the check can call attention to
  bugs, since users generally intend that their mutual recursions are
  not bogus.

  Nevertheless, there are times when it is advantageous to allow bogus
  mutual recursions, for example when they are generated
  mechanically, even at the expense of losing stored induction
  schemes. The first example above allows bogus mutual recursion. The
  second example disallows bogus mutual recursion; this is the
  default. The third example allows bogus mutual recursion, but
  prints an appropriate warning.

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  Moreover, its effect is to set the [ACL2-defaults-table], and hence
  its effect is [local] to the book or [encapsulate] form containing
  it; see [ACL2-defaults-table].

    General Form:
    (set-bogus-mutual-recursion-ok flg)

  where flg is either t, nil, or :warn.")
 (SET-CASE-SPLIT-LIMITATIONS
  (MISCELLANEOUS)
  "Set the case-split-limitations

    Examples:
    (set-case-split-limitations '(500 100))
    (set-case-split-limitations 'nil)
    (set-case-split-limitations '(500 nil))

  The first of these prevents clausify from trying the
  subsumption/replacement (see below) loop if more than 500 clauses
  are involved. It also discourages the clause simplifier from
  splitting into more than 100 cases at once.

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  Moreover, its effect is to set the [ACL2-defaults-table], and hence
  its effect is [local] to the book or [encapsulate] form containing
  it; see [ACL2-defaults-table].

  See [hints] for discussion of a related hint,
  :case-split-limitations. Also see [splitter] for information about
  reports on rules that may be responsible for case splits.

    General Form:
    (set-case-split-limitations lst)

  where lst is either nil (denoting a list of two nils), or a list of
  length two, each element of which is either nil or a natural
  number. When nil is used as an element, it is treated as positive
  infinity. The default setting is (500 100).

  The first number specifies the maximum number of clauses that may
  participate in the ``subsumption/replacement'' loop. Because of the
  expensive nature of that loop (which compares every clause to every
  other in a way that is quadratic in the number of literals in the
  clauses), when the number of clauses exceeds about 1000, the system
  tends to ``go into a black hole,'' printing nothing and not even
  doing many garbage collections (because the subsumption/replacement
  loop does not create new clauses so much as it just tries to delete
  old ones). The initial setting is lower than the threshold at which
  we see noticeably bad performance, so you probably will not see
  this behavior unless you have raised or disabled the limit.

  Why raise the subsumption/replacement limit? The
  subsumption/replacement loop cleans up the set of subgoals produced
  by the simplifier. For example, if one subgoal is

    (implies (and p q r) s)            [1]

  and another is

    (implies (and p (not q) r) s)      [2]

  then the subsumption/replacement loop would produce the single
  subgoal

    (implies (and p r) s)              [3]

  instead. This cleanup process is simply skipped when the number of
  subgoals exceeds the subsumption/replacement limit. But each
  subgoal must nonetheless be proved. The proofs of [1] and [2] are
  likely to duplicate much work, which is only done once in proving
  [3]. So with a low limit, you may find the system quickly produces
  a set of subgoals but then takes a long time to prove that set.
  With a higher limit, you may find the set of subgoals to be
  ``cleaner'' and faster to prove.

  Why lower the subsumption/replacement limit? If you see the system go
  into a ``black hole'' of the sort described above (no output, and
  few garbage collections), it could due to the
  subsumption/replacement loop working on a large set of large
  subgoals. You might temporarily lower the limit so that it begins
  to print the uncleaned set of subgoals. Perhaps by looking at the
  output you will realize that some function can be disabled so as to
  prevent the case explosion. Then raise or disable the limit again!

  The second number in the case-split-limitations specifies how many
  case splits the simplifier will allow before it begins to shut down
  case splitting. In normal operation, when a literal rewrites to a
  nest of IFs, the system simplifies all subsequent literals in all
  the contexts generated by walking through the nest in all possible
  ways. This can also cause the system to ``go into a black hole''
  printing nothing except garbage collection messages. This ``black
  hole'' behavior is different from than mentioned above because
  space is typically being consumed at a prodigious rate, since the
  system is rewriting the literals over and over in many different
  contexts.

  As the simplifier sweeps across the clause, it keeps track of the
  number of cases that have been generated. When that number exceeds
  the second number in case-split-limitations, the simplifier stops
  rewriting literals. The remaining, unrewritten, literals are copied
  over into the output clauses. IFs in those literals are split out,
  but the literals themselves are not rewritten. Each output clause
  is then attacked again, by subsequent simplification, and
  eventually the unrewritten literals in the tail of the clause will
  be rewritten because the earlier literals will stabilize and stop
  producing case splits.

  The default setting of 100 is fairly low. We have seen successful
  proofs in which thousands of subgoals were created by a
  simplification. By setting the second number to small values, you
  can force the system to case split slowly. For example, a setting
  of 5 will cause it to generate ``about 5'' subgoals per
  simplification.

  You can read about how the simplifier works in the book
  Computer-Aided Reasoning: An Approach (Kaufmann, Manolios, Moore);
  also see [introduction-to-the-theorem-prover] for a detailed
  tutorial on using the ACL2 prover. If you think about it, you will
  see that with a low case limit, the initial literals of a goal are
  repeatedly simplified, because each time a subgoal is simplified we
  start at the left-most subterm. So when case splitting prevents the
  later subterms from being fully split out, we revisit the earlier
  terms before getting to the later ones. This can be good. Perhaps
  it takes several rounds of rewriting before the earlier terms are
  in normal form and then the later terms rewrite quickly. But it
  could happen that the earlier terms are expensive to rewrite and do
  not change, making the strategy of delayed case splits less
  efficient. It is up to you.

  Sometimes the simplifier produces more clauses than you might expect,
  even with case-split-limitations in effect. As noted above, once
  the limit has been exceeded, the simplifier does not rewrite
  subsequent literals. But IFs in those literals are split out
  nonetheless. Furthermore, the enforcement of the limit is -- as
  described above -- all or nothing: if the limit allows us to
  rewrite a literal then we rewrite the literal fully, without regard
  for limitations, and get as many cases as ``naturally'' are
  produced. It quite often happens that a single literal, when
  expanded, may grossly exceed the specified limits.

  If the second ``number'' is nil and the simplifier is going to
  produce more than 1000 clauses, a ``helpful little message'' to
  this effect is printed out. This output is printed to the system's
  ``comment window'' not the standard proofs output.")
 (SET-CBD
  (BOOKS-REFERENCE)
  "To set the connected book directory

    Example Forms:
    ACL2 !>:set-cbd \"/usr/home/smith/\"
    ACL2 !>:set-cbd \"my-acl2/books\"

  See [cbd] for a description of the connected book directory.

    General Form:
    (set-cbd str)

  where str is a nonempty string that represents the desired directory
  (see [pathname]). This command sets the connected book directory
  (see [cbd]) to the string representing the indicated directory.
  Thus, this command may determine which files are processed by
  [include-book] and [certify-book] [command]s typed at the
  top-level. However, the [cbd] is also temporarily set by those two
  book processing [command]s.

  IMPORTANT: Pathnames in ACL2 are in the Unix (trademark of AT&T)
  style. That is, the character ``/'' separates directory components
  of a pathname, and pathnames are absolute when they start with this
  character, and relative otherwise. See [pathname].")
 (SET-CHECKPOINT-SUMMARY-LIMIT
  (SET-GAG-MODE)
  "Control printing of key checkpoints upon a proof's failure

  See [set-gag-mode] for a discussion of key checkpoints.

    Examples:

    ; (Default) When a proof fails, print all key checkpoints before
    ; induction but at most 3 key checkpoints after induction:
    (set-checkpoint-summary-limit (nil . 3))

    ; When a proof fails, print at most 3 key checkpoints before
    ; induction but all 3 key checkpoints after induction:
    (set-checkpoint-summary-limit (3 . nil))

    ; When a proof fails, print at most 3 key checkpoints before
    ; induction and at most 5 key checkpoints after induction:
    (set-checkpoint-summary-limit (3 . 5))

    ; When a proof fails, print at most 3 key checkpoints before
    ; induction and at most 3 key checkpoints after induction:
    (set-checkpoint-summary-limit (3 . 3))
    ; or equivalently,
    (set-checkpoint-summary-limit 3)

    ; When a proof fails, print all key checkpoints:
    (set-checkpoint-summary-limit (nil . nil))
    ; or equivalently,
    (set-checkpoint-summary-limit nil)

    ; When a proof fails, print no information at all about key checkpoints:
    (set-checkpoint-summary-limit t)

    General Forms:
    (set-checkpoint-summary-limit (n1 . n2))
    (set-checkpoint-summary-limit n)
    (set-checkpoint-summary-limit t)

  where each of n1 and n2 is a natural number or nil. For the second
  form, n can be a natural number or nil and is treated as (n . n).
  The value t inhibits all printing of checkpoint summary
  information. The values n1 and n2 determine printing of key
  checkpoints generated before the first induction and generated
  after the first induction, respectively, where at most n1 or n2
  (respectively) such key checkpoints are printed unless the value is
  nil, in which case there is no limitation.

  The argument x for set-checkpoint-summary-limit, as described above,
  may be quoted, i.e. supplied as 'x or (quote x). Thus, you may use
  the keyword form (see [keyword-commands]) if you prefer, for
  example:

    :set-checkpoint-summary-limit (nil . 3)")
 (SET-COMPILE-FNS
  (COMPILATION)
  "Have each function compiled as you go along.

    Example Forms:
    (set-compile-fns t)    ; new functions compiled after DEFUN
    (set-compile-fns nil)  ; new functions not compiled after DEFUN

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.

  Also see [comp], because it may be more efficient in some Common
  Lisps to compile many functions at once rather than to compile each
  one as you go along.

    General Form:
    (set-compile-fns term)

  where term is a variable-free term that evaluates to t or nil. This
  macro is equivalent to

    (table acl2-defaults-table :compile-fns term)

  and hence is [local] to any [books] and [encapsulate] [events] in
  which it occurs; see [ACL2-defaults-table]. However, unlike the
  above simple call of the [table] event function (see [table]), no
  output results from a set-compile-fns event.

  Set-compile-fns may be thought of as an event that merely sets a flag
  to t or nil. The flag's effect is felt when functions are defined,
  as with [defun]. If the flag is t, functions are automatically
  compiled after they are defined, as are their executable
  counterparts (see [executable-counterpart]). Otherwise, functions
  are not automatically compiled. Exception: The flag has no effect
  when explicit compilation is suppressed; see [compilation].

  Because set-compile-fns is an event, the old value of the flag is
  restored when a set-compile-fns event is undone.

  Even when :set-compile-fns t has been executed, functions are not
  individually compiled when processing an [include-book] event. If
  you wish to include a book of compiled functions, we suggest that
  you first certify it with the [compilation] flag set (see
  [certify-book]) or else compile the book by supplying the
  appropriate load-compiled-file argument to [include-book]. More
  generally, [compilation] via set-compile-fns is suppressed when the
  [state] global variable [ld-skip-proofsp] has value
  '[include-book].")
 (SET-COMPILER-ENABLED
  (COMPILATION)
  "Disable [compilation].

  For a thorough discussion of this utility, see [compilation].
  Probably its most common use is the following, in order to prohibit
  [include-book] from attempting to include compiled files:

    (set-compiler-enabled nil state)")
 (SET-DEBUGGER-ENABLE
  (DEBUGGING)
  "Control whether Lisp errors and breaks invoke the Lisp debugger

    Forms (see below for explanations and GCL exceptions):

    (set-debugger-enable t)         ; enable breaks into the raw Lisp debugger
    (set-debugger-enable :break)    ; same as above
    :set-debugger-enable t          ; same as above
    (set-debugger-enable :break-bt) ; as above, but print a backtrace first
    (set-debugger-enable :bt-break) ; as above, but print a backtrace first
    (set-debugger-enable :bt)       ; print a backtrace but do not enter debugger
    (set-debugger-enable :never)    ; disable all breaks into the debugger
    (set-debugger-enable nil)       ; disable debugger except when calling break$

  Introduction. Suppose we define foo in :[program] mode to take the
  [car] of its argument. This can cause a raw Lisp error. ACL2 will
  then return control to its top-level loop unless you enable the
  Lisp debugger, as shown below (except: the error message can take
  quite a different form in non-ANSI GCL).

    ACL2 !>(defun foo (x) (declare (xargs :mode :program)) (car x))

    Summary
    Form:  ( DEFUN FOO ...)
    Rules: NIL
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     FOO
    ACL2 !>(foo 3)
    ***********************************************
    ************ ABORTING from raw Lisp ***********
    Error:  Attempt to take the car of 3 which is not listp.
    ***********************************************

    If you didn't cause an explicit interrupt (Control-C),
    then the root cause may be call of a :program mode
    function that has the wrong guard specified, or even no
    guard specified (i.e., an implicit guard of t).
    See :DOC guards.

    To enable breaks into the debugger (also see :DOC acl2-customization):
    (SET-DEBUGGER-ENABLE T)
    ACL2 !>(SET-DEBUGGER-ENABLE T)
    
    ACL2 !>(foo 3)
    Error: Attempt to take the car of 3 which is not listp.
      [condition type: TYPE-ERROR]

    Restart actions (select using :continue):
     0: Abort entirely from this (lisp) process.
    [Current process: Initial Lisp Listener]
    [1] ACL2(1): [RAW LISP]

  Details. ACL2 usage is intended to take place inside the ACL2
  read-eval-print loop (see [lp]). Indeed, in most Lisp
  implementations ACL2 comes up inside that loop, as evidenced by the
  prompt:

    ACL2 !>

  However, one can occasionally hit a raw Lisp error. Here is the above
  example again, this time for a GCL implementation, which
  unfortunately gives a slightly less aesthetic report.

    ACL2 !>(foo 3)

    Error: 3 is not of type LIST.
    Fast links are on: do (si::use-fast-links nil) for debugging
    Error signalled by CAR.
    Backtrace: funcall > system:top-level > lisp:lambda-closure > lp > acl2_*1*_acl2::foo > foo > car > system:universal-error-handler > system::break-level-for-acl2 > let* > UNLESS
    ACL2 !>

  Here, the user has defined foo in :[program] mode, with an implicit
  [guard] of t. The ACL2 evaluator therefore called the Lisp
  evaluator, which expected nil or a [consp] argument to [car].

  By default, ACL2 will return to its top-level loop (at the same level
  of [ld]) when there is a raw Lisp error, as though a call of [er]
  with flag HARD has been evaluated. If instead you want to enter the
  raw Lisp debugger in such cases, evaluate the following form.

    (set-debugger-enable t)

  You can subsequently return to the default behavior with:

    (set-debugger-enable nil)

  Either way, you can enter the Lisp debugger from within the ACL2 loop
  by evaluating ([break$]). If you want break$ disabled, then
  evaluate the following, which disables entry to the Lisp debugger
  not only for Lisp errors but also when executing (break$).

    (set-debugger-enable :never)

  The discussion above also applies to interrupts (from Control-C) in
  some, but not all, host Common Lisps --- perhaps all except for
  non-ANSI GCL, where interrupts will likely always put you into the
  debugger.

  It remains to discuss options :break, :bt, :break-bt, and :bt-break.
  Option :break is synonymous with option t, while option :bt prints
  a backtrace. Options :break-bt and :bt-break are equivalent, and
  each has the combined effect of :bt and :break: a backtrace is
  printed and then the debugger is entered.

  Note that set-debugger-enable applies not only to raw Lisp errors,
  but also to ACL2 errors: those affected by [break-on-error].
  However, for ACL2 errors, entering the debugger is controlled only
  by break-on-error, not by set-debugger-enable. For ACL2 errors
  encountered after evaluating (break-on-error t), the
  set-debugger-enable values of :bt, :break-bt, and :bt-break will
  result in the same effect: in many host LIsps, this effect will be
  to cause a backtrace to be printed.

  Remark for Common Lisp hackers (except for the case that the host
  Lisp is non-ANSI GCL). You can customize the form of the backtrace
  printed by entering raw Lisp (with :q) and then redefining function
  print-call-history, whose definition immediately precedes that of
  break-on-error in ACL2 source file ld.lisp. Of course, all bets are
  off when defining any function in raw Lisp, but as a practical
  matter you are probably fine as long as your books are ultimately
  certified with an unmodified copy of ACL2. If you come up with
  improvements to print-call-history, please pass them along to the
  ACL2 implementors.")
 (SET-DEFAULT-BACKCHAIN-LIMIT
  (BACKCHAIN-LIMIT)
  "Sets the default backchain-limit used when admitting a rule

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  Moreover, its effect is to set the [ACL2-defaults-table], and hence
  its effect is [local] to the book or [encapsulate] form containing
  it; see [ACL2-defaults-table].

  This event sets the default [backchain-limit] used when a new
  [rewrite], [linear], [meta], or [type-prescription] rule is
  admitted. Its value may be a two-element list whose elements are
  each either nil or a non-negative integer. Its value x may also be
  nil or a non-negative integer, which is treated as the two element
  list (x x).

  The first element of the list is used to limit backchaining for a
  rule of class [type-prescription] while the second element is used
  to limit backchaining for the other three classes of rules
  mentioned above. See [backchain-limit] for details about how
  backchain-limits are used. The examples below assume that a new
  rule doesn't itself specify a value for :backchain-limit-lst.

    :set-default-backchain-limit nil  ; do not impose backchain limits for the
                                      ; rule
    :set-default-backchain-limit 0    ; allow only type-set reasoning for
                                      ; relieving a new rule's hypotheses
    :set-default-backchain-limit 500  ; allow backchaining through a new rewrite,
                                      ; linear, or meta rule's hypotheses to a
                                      ; depth of no more than 500
    (set-default-backchain-limit 500) ; same as above
    :set-default-backchain-limit (nil 500)
                                      ; same as above
    (set-default-backchain-limit '(nil 500))
                                      ; same as above
    (set-default-backchain-limit '(3 500))
                                      ; for a new :type-prescription rule, allow
                                      ; type-set backchaining to a depth
                                      ; of no more than 3; for a new
                                      ; rule of class :rewrite, :linear,
                                      ; or :meta, allow backchaining to
                                      ; a depth of no more than 50
    (set-default-backchain-limit '(nil 500))
                                      ; do not limit backchaining for a
                                      ; new :type-prescription rule; for
                                      ; a new rule of class :rewrite,
                                      ; :linear, or :meta, allow
                                      ; backchaining to a depth of no
                                      ; more than 50

  The initial default backchain-limit is nil.")
 (SET-DEFAULT-HINTS
  (DEFAULT-HINTS)
  "Set the default hints

    Examples:
    (set-default-hints '((computed-hint-1 clause)
                         (computed-hint-2 clause
                                          stable-under-simplificationp)))
    (set-default-hints nil)

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  It is [local] to the book or [encapsulate] form in which it occurs;
  see [set-default-hints!] for a corresponding non-[local] event.

    General Form:
    (set-default-hints lst)

  where lst is a list. Generally speaking, the elements of lst should
  be suitable for use as [computed-hints].

  Whenever a [defthm] or [thm] command is executed, the default hints
  are appended to the right of any explicitly provided :[hints] in
  the command. The same applies to [defun]s as well (:hints,
  :guard-hints, and (for ACL2(r)) :std-hints). The hints are then
  translated and processed just as though they had been explicitly
  included.

  Technically, we do not put restrictions on lst, beyond that it is a
  true list. It would be legal to execute

    (set-default-hints '((\"Goal\" :use lemma23)))

  with the effect that the given hint is added to subsequent hints
  supplied explicitly. An explicit \"Goal\" hint would, however, take
  priority, as suggested by the mention above of ``appended to the
  right.''

  Note that set-default-hints sets the default hints as specified. To
  add to or remove from the current default, see [add-default-hints]
  and see [remove-default-hints]. To see the current default hints,
  see [default-hints].

  Finally, note that the effects of set-default-hints,
  [add-default-hints], and [remove-default-hints] are [local] to the
  book in which they appear. Thus, users who include a book with such
  forms will not have their default hints affected by such forms. In
  order to export the effect of setting the default hints, use
  [set-default-hints!], [add-default-hints!], or
  [remove-default-hints!].

  For a related feature, which however is only for advanced system
  builders, see [override-hints].")
 (SET-DEFAULT-HINTS!
  (DEFAULT-HINTS)
  "Set the default hints non-[local]ly

  Please see [set-default-hints], which is the same as
  set-default-hints! except that the latter is not [local] to the
  [encapsulate] or the book in which it occurs. Probably
  [set-default-hints] is to be preferred unless you have a good
  reason for wanting to export the effect of this event outside the
  enclosing [encapsulate] or book.")
 (SET-DEFERRED-TTAG-NOTES
  (DEFTTAG)
  "Modify the verbosity of TTAG NOTE printing

    General Form:
    (set-deferred-ttag-notes val state)

  where val is t or nil.

  See [defttag] for a discussion of trust tags (ttags). By default, a
  ``TTAG NOTE'' is printed in order to indicate reliance on a ttag.
  When many such notes are printed, it may be desirable to avoid
  seeing them all. Upon evaluation of the form

    (set-deferred-ttag-notes t state)

  ACL2 will enter a deferred mode for the printing of ttag notes. In
  this mode, only the first ttag note is printed for each top-level
  command, and the remainder are summarized before the next top-level
  prompt (if any) is printed, hence before the next command is
  evaluated. That summary is merely a list of ttags, but the summary
  explains that the full ttag notes may be printed with the command
  (show-ttag-notes).

  Note that (show-ttag-notes) spares you duplicate ttag notes. If you
  want to see every ttag note as it would normally appear, for
  maximum security, do not evaluate the command
  (set-deferred-ttag-notes t state). You can undo the effect of this
  command, returning to an immediate mode for printing ttag notes, by
  evaluating:

    (set-deferred-ttag-notes nil state)")
 (SET-DIFFERENCE$
  (LISTS ACL2-BUILT-INS)
  "Elements of one list that are not elements of another

    General Forms:
    (set-difference$ l1 l2)
    (set-difference$ l1 l2 :test 'eql)   ; same as above (eql as equality test)
    (set-difference$ l1 l2 :test 'eq)    ; same, but eq is equality test
    (set-difference$ l1 l2 :test 'equal) ; same, but equal is equality test

  (Set-difference$ l1 l2) equals a list that contains the [member]s of
  l1 that are not [member]s of l2. More precisely, the resulting list
  is the same as one gets by deleting the members of l2 from l1,
  leaving the remaining elements in the same order as in l1. The
  optional keyword, :TEST, has no effect logically, but provides the
  test (default [eql]) used for comparing members of the two lists.

  The [guard] for a call of set-difference$ depends on the test. In all
  cases, both arguments must satisfy [true-listp]. If the test is
  [eql], then one of the arguments must satisfy [eqlable-listp]. If
  the test is [eq], then one of the arguments must satisfy
  [symbol-listp].

  See [equality-variants] for a discussion of the relation between
  set-difference$ and its variants:

      (set-difference-eq l1 l2) is equivalent to (set-difference$ l1 l2
      :test 'eq);

      (set-difference-equal l1 l2) is equivalent to (set-difference$ l1 l2
      :test 'equal).

  In particular, reasoning about any of these primitives reduces to
  reasoning about the function set-difference-equal.

  Function: 

    (defun
         set-difference-equal (l1 l2)
         (declare (xargs :guard (and (true-listp l1) (true-listp l2))))
         (cond ((endp l1) nil)
               ((member-equal (car l1) l2)
                (set-difference-equal (cdr l1) l2))
               (t (cons (car l1)
                        (set-difference-equal (cdr l1) l2)))))

  Set-difference$ is similar to the Common Lisp primitive
  set-difference. However, Common Lisp does not specify the order of
  elements in the result of a call of set-difference.")
 (SET-DIFFERENCE-EQ (POINTERS)
                    "See [set-difference$].")
 (SET-DIFFERENCE-EQUAL (POINTERS)
                       "See [set-difference$].")
 (SET-DIFFERENCE-THEORIES
  (THEORIES THEORY-FUNCTIONS)
  "Difference of two [theories]

    Example:
    (set-difference-theories (current-theory :here)
                             '(fact (fact)))

    General Form:
    (set-difference-theories th1 th2)

  where th1 and th2 are [theories] (see [theories]). To each of the
  arguments there corresponds a runic theory. This function returns
  the set-difference of those two runic [theories], represented as a
  list and ordered chronologically. That is, a [rune] is in the
  result iff it is in the first runic theory but not in the second.

  The standard way to ``disable'' a theory, lst, is: (in-theory
  (set-difference-theories (current-theory :here) lst)).

  This ``function'' is actually a macro that expands to a term
  mentioning the single free variable [world]. When theory
  expressions are evaluated by [in-theory] or the :[in-theory] hint,
  [world] is bound to the current ACL2 [world].")
 (SET-ENFORCE-REDUNDANCY
  (REDUNDANT-EVENTS)
  "Require most events to be redundant

    General Forms:
    (set-enforce-redundancy nil)   ; do not require redundancy (default)
    (set-enforce-redundancy t)     ; most events (see below) must be redundant
    (set-enforce-redundancy :warn) ; warn for most non-redundant events

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.

    General Form:
    (set-enforce-redundancy flag)

  where flag is nil, t, or :warn, as indicated above. This macro is
  essentially equivalent to

    (table acl2-defaults-table :enforce-redundancy flag)

  and hence is [local] to any [books] and [encapsulate] [events] in
  which it occurs; see [ACL2-defaults-table]. However, unlike the
  above simple call of the [table] event function (see [table]), no
  output results from a set-enforce-redundancy event.

  Set-enforce-redundancy may be thought of as an event that merely sets
  a flag as indicated above, which determines whether most [events],
  including [defun] and [defthm] events, are allowed to be redundant;
  see [redundant-events]. The exceptions are [deflabel], [defpkg],
  [encapsulate], [include-book], [push-untouchable],
  [remove-untouchable], [set-body], and [table] [events]. Any other
  type of non-redundant event will cause an error if flag is t and a
  warning if flag is nil, except in the course of carrying out an
  [include-book] form.

  Note that because [table] [events] that set the [ACL2-defaults-table]
  are implicitly [local], set-enforce-redundancy events are ignored
  when including books. However, the presence of the event
  (set-enforce-redundancy t) in a book guarantees that its subsequent
  definitions and theorems are redundant. This can be a useful
  property to maintain in library development, as we now describe.

  An example of the use of this form can be found in the community
  [books] under directory books/rtl/rel4/. The intention in that
  directory has been to put all the gory details in subdirectories
  support/ and arithmetic/, so that the books in subdirectory lib/
  contain only the ``exported'' definitions and theorems. This
  approach is useful for human readability. Moreover, suppose we want
  to prove new theorems in lib/. Typically we wish to prove the new
  theorems using the existing books in lib/; however, our methodology
  demands that the proofs go into books in support/. If every theorem
  in lib/ is redundant, then we can develop the proofs in lib/ but
  then when we are done, move each book with such proofs into
  support/ as follows. In any such book, we first replace
  [include-book] forms referring to books in lib/ by [include-book]
  forms referring to corresponding books in support/ and/or
  arithmetic/. Then, we add suitable [in-theory] events to get us
  back into the original lib/ proof environment.

  The default behavior of the system is as though the
  :enforce-redundancy value is nil. The current behavior can be
  ascertained by evaluating the following form.

    (cdr (assoc-eq :enforce-redundancy (table-alist 'acl2-defaults-table wrld)))")
 (SET-EVISC-TUPLE
  (IO)
  "Control suppression of details when printing

  ACL2 output is generally printed in full. However, ACL2 can be
  directed to abbreviate, or ``eviscerate'', objects before printing
  them, though the use of a so-called ``evisc-tuple''. See
  [evisc-tuple] for a discussion of evisc-tuples. The utility
  set-evisc-tuple modifies certain global evisc-tuples, as explained
  below, to affect the extent to which ACL2 eviscerates objects
  during printing, for example during proof output or when printing
  top-level evaluation results.

    General Form:
    (set-evisc-tuple evisc-tuple  ; a legal evisc-tuple, or :DEFAULT
                    :iprint val   ; one of *iprint-actions*
                    :sites sites) ; either :ALL, or an element or a subset of
                                  ;   the list of legal sites (see below)

  where the value of :iprint is passed to [set-iprint], :sites :all
  abbreviates :sites '(:term :ld :trace :abbrev :gag-mode), and other
  documentation is provided below. Note that all arguments are
  evaluated.

  See [without-evisc] for how to avoid evisceration for ACL2 output.

  The following example illustrates an invocation of set-evisc-tuple
  that limits the print-level to 3 --- only three descents into list
  structures are permitted before eviscerating a subterm --- and
  limits the print-length to 4 --- only the first four elements of
  any list structure will be printed.

    ACL2 !>(set-evisc-tuple (evisc-tuple 3   ; print-level
                                         4   ; print-length
                                         nil ; alist
                                         nil ; hiding-cars
                                         )
                            :iprint :same ; better yet, T
                            :sites :all)
     (:TERM :LD :TRACE :ABBREV)
    ACL2 !>'((a b ((c d)) e f g) u v w x y)
    ((A B (#) E ...) U V W ...)
    ACL2 !>

  We recommend however using :iprint t so that eviscerated terms may be
  read back in; see [set-iprint]. Indeed, the :iprint argument is
  required as a reminder to the user to consider that issue, unless
  iprinting has been enabled at least once. If :sites or a required
  :iprint argument is omitted, however, ACL2 will query the user for
  the missing arguments rather than causing an error.

  ACL2 eviscerates by default only in a few cases, primarily in
  informational messages for errors, warnings, and queries (i.e., in
  the :EVISC case below). Users can modify the default behavior by
  supplying a suitable argument to set-evisc-tuple. The argument may
  be :default, which denotes the evisceration provided when ACL2
  starts up. Otherwise that argument is an evisc-tuple, which is
  either nil (no evisceration) or as described above. Moreover, there
  are four evisc-tuple ``evisceration contexts'', each with its own
  evisceration control. The value returned by set-evisc-tuple
  indicates the evisceration contexts whose evisc-tuple has been set.
  The evisceration contexts are as follows, all of which use a
  default value of nil for the hiding-cars. Accessors are also shown
  for retrieving the corresponding evisc-tuple.

    * :TERM --- used for printing terms. The accessor is (term-evisc-tuple
      flg state), where flg is ignored if set-evisc-tuple has been
      called for :term with value other than :default, and otherwise
      (hence initially): a flg of nil indicates an evisc-tuple of
      nil, and otherwise the term-evisc-tuple has a print-level of 3
      and print-length of 4.
    * :ABBREV --- used for printing informational messages for errors,
      warnings, and queries. Initially, the alist abbreviates the
      ACL2 world, print-level is 5, and print-level is 7. The
      accessor is (abbrev-evisc-tuple state).
    * :GAG-MODE --- used for printing induction schemes (and perhaps, in
      the future, for other printing) when [gag-mode] is on. If
      gag-mode is off, the value used for this [evisc-tuple] is
      (term-evisc-tuple nil state). But if gag-mode is on (i.e.,
      (gag-mode) evaluates to a non-nil value), then with one
      exception, the value is an evisc-tuple or nil, to be used in
      gag-mode for printing of induction schemes and, during proofs,
      the ``The non-trivial part of the guard conjecture''. The
      exceptional value is t, which indicates that in gag-mode, no
      printing of induction schemes should be and the guard
      conjecture should be printed using (term-evisc-tuple t state).
      The accessor is (gag-mode-evisc-tuple state).
    * :LD --- used by the ACL2 read-eval-print loop. The accessor is
      ([ld-evisc-tuple] state).
    * :TRACE --- used for printing [trace] output. No accessor is available
      (though in raw Lisp, (trace-evisc-tuple) returns the
      trace-evisc-tuple).

  Each context ectx also has an updater, (set-ectx-evisc-tuple val
  state), where val is a legal value for set-evisc-tuple as described
  above: :default or an [evisc-tuple] (possibly nil).

  Note that the [break-rewrite] commands and the [proof-checker]
  generally do their printing using the term-evisc-tuple.")
 (SET-FC-CRITERIA
  (FORWARD-CHAINING-REPORTS)
  "To set the tracking criteria for forward chaining reports

    Examples:
    (set-fc-criteria)                 ; shut off all tracking
    (set-fc-criteria nil)

    (set-fc-criteria t)               ; to track all forward chaining
    (set-fc-criteria (t t t))

    (set-fc-criteria
     ((:FORWARD-CHAINING LEMMA1)      ; track all uses of LEMMA1,
       t
       t)
      ((:FORWARD-CHAINING LEMMA2)     ; uses of LEMMA2 triggered
       (ALISTP (BASIC-MAPPER A B))    ; by this specific ALISTP term
       t)
      (t t (TRUE-LISTP (DLT D))))     ; and every rule deriving
                                      ; this TRUE-LISTP term.

    General Forms:
    (set-fc-criteria nil)
    (set-fc-criteria t)
    (set-fc-criteria triple1 triple2 ...)

  where each triple is of the form (rune inst-trigger inst-concl). If
  rune is non-t is must be a forward chaining [rune]. The other two
  components, inst-trigger and inst-concl, if non-t, must be terms.
  The list of all the triples supplied is called the ``criteria.'' In
  the form (set-fc-criteria nil), the criteria used is the empty list
  of triples. (Technically, supplying nil as a triple ``ought'' to be
  an error, but it is a more ``natural'' way to say the list of
  criteria is empty than to use the correct form (set-fc-criteria).)
  In the form (set-fc-criteria t) the criteria used is the list
  containing the single triple (t t t).

  This function sets the tracking criteria for forward chaining
  reporting. See [forward-chaining-reports] for a general discussion
  of tracking and reporting forward chaining activity.

  Think of the forward chaining criteria as a list of triples,
  representing a disjunction of conjunctions. The activation of a
  :[forward-chaining] rune by some triggering term in the current
  context satisfies the criteria if it satisfies one of the triples.
  To satisfy the triple (rune inst-trigger inst-concl), the
  activation must satisfy each component of the triple. Any t
  component is always satisfied. If rune is non-t it is satisfied if
  the activation is for the given rune. If inst-trigger is non-t, it
  is satisfied if the activation is triggered by the given term.
  (``Inst-trigger'' stands for ``instantiated trigger.'' It is not
  the trigger term of the rule but is supposed to be an instance of
  that term that you believe will arise in some proof attempt you are
  debugging -- an instance you want to ``watch'' as it fires the
  rule.) If inst-concl is non-t, it is satisfied if the activation
  could possibly derive the conclusion given. (Again, ``inst-concl''
  stands for ``instantiated conclusion'' and shows the term in your
  problem that you expect to be derived by forward chaining.)

  Note that if the criteria is empty, it is never satisfied, so
  tracking is turned off. If the criteria is the singleton list
  containing just the triple (t t t), then every activation satisfies
  it and so all :forward chaining rules are tracked.

  See [forward-chaining-reports] for details.")
 (SET-FC-REPORT-ON-THE-FLY
  (FORWARD-CHAINING-REPORTS)
  "To determine when forward-chaining reports are printed

    Examples:  (set-fc-report-on-the-fly t)
               (set-fc-report-on-the-fly nil)

  If the flag is set to t, forward chaining tracking reports are
  printed when forward chaining occurs. If the flag is set to nil,
  very short reports (giving just the caller and the report number)
  are printed during forward chaining but you can use [fc-report] to
  see the full report afterwards.

  Since nothing is tracked when the criteria is nil, this function also
  prints out the current criteria to remind you of what it is.

  The flag manipulated by this function does not shut off tracking. It
  only determines whether reports are printed on-the-fly or not. To
  shut off tracking [set-fc-criteria].

  See [forward-chaining-reports] for details.")
 (SET-FMT-HARD-RIGHT-MARGIN
  (IO ACL2-BUILT-INS)
  "Set the right margin for formatted output

  In this documentation topic we discuss setting of both a ``soft'' and
  a ``hard'' right margin.

    Example Forms:
    (set-fmt-soft-right-margin 55 state) ; set soft right margin to 55
    (set-fmt-hard-right-margin 68 state) ; set hard right margin to 68

  [Fmt] and related functions insert linebreaks when lines get too
  long. A linebreak is inserted at an aesthetically appropriate point
  once the column exceeds the value of (@ fmt-soft-right-margin). If
  however the column exceeds the value of (@ fmt-hard-right-margin),
  then a linebreak is soon inserted. Such a ``hard'' linebreak
  follows the insertion of a backslash (\\) character unless [fmt!],
  [fms!], or [fmt1!] is used, or state global write-for-read is true.")
 (SET-FMT-SOFT-RIGHT-MARGIN
  (IO ACL2-BUILT-INS)
  "Set the soft right margin for formatted output

  See [set-fmt-hard-right-margin] for a discussion of the soft and hard
  right margin for formatted output.")
 (SET-GAG-MODE
  (PROVER-OUTPUT)
  "Modify the nature of proof output

    Examples:

    :set-gag-mode t      ; enable gag-mode, suppressing most proof commentary
    (set-gag-mode t)     ; same as above
    :set-gag-mode :goals ; same as above, but print names of goals when produced
    :set-gag-mode nil    ; disable gag-mode

    General Forms:
    (set-gag-mode val)
    :set-gag-mode val

  where val is one of t, nil, or :goals.

  The basic idea of [gag-mode] is to avoid much of the verbose output
  from the theorem prover, leaving only output that is expected to be
  helpful. The first two forms below set gag-mode on, while the other
  turns it off; these may be placed in your ACL2 customization file;
  see [ACL2-customization].

    (set-gag-mode :goals) ; (default) avoid most prover output; show goal names
    (set-gag-mode t)      ; avoid most prover output; also, hide goal names
    (set-gag-mode nil)    ; allow prover output

  Gag-mode focuses attention on so-called ``key checkpoints''. By
  default, a checkpoint is a goal that cannot be simplified. (Below
  we discuss how to change this default.) A key checkpoint is a
  checkpoint that is not descended from another checkpoint.
  (Technical point: ``descended'' signifies that both goals are at
  the top level in the same forcing round, or are in the same proof
  by induction.) Successful ACL2 users generally focus their
  attention on key checkpoints, or less often, induction schemes. (To
  suppress or abbreviate induction schemes in gag-mode, see
  [set-evisc-tuple], specifically, the discussion of :GAG-MODE.) For
  a discussion of how to use ACL2 prover output in an effective
  manner, see [the-method], and see
  [introduction-to-the-theorem-prover] for a more detailed tutorial.
  In gag-mode, a key checkpoint is only displayed when ACL2 is unable
  to make any further progress on that goal or some descendent of it,
  other than with a proof by induction.

  Evaluation of set-gag-mode t enters gag-mode, so that only key
  checkpoints are printed. Evaluation of set-gag-mode :goals also
  enters gag-mode, but will additionally cause the name of a goal to
  be printed as soon as it is generated (by invoking
  [set-print-clause-ids]). The :goals setting is the default, and is
  useful for cases in which the prover spends very little of its time
  generating goals to be proved by induction, yet you want to see
  that it is making progress. For finer-grained feedback about the
  simplifier's activity, see [dmr].

  The current value of [gag-mode] is returned by a macro of the same
  name:

    (gag-mode) ; evaluates to t, nil, or :goals

  An alternative to gag-mode is to use proof-trees; see [proof-tree].
  With proof-trees it is not so important to avoid excessive prover
  output, since the proof-tree display provides structure that makes
  it easy to monitor proof attempts and navigate output for a proof
  that has failed or seems to be failing. Still, output can take time
  to print, so you may get better performance with gag-mode.

  The intention of gag-mode is to show you only the parts of a proof
  attempt that are relevant for debugging a failure; additional
  output is generally more likely to be distracting than truly
  helpful. But on occasion you may want to see the full proof output
  after an attempt made with gag-mode. This can be done provided
  proof output is not inhibited (see [set-inhibit-output-lst]) during
  the proof attempt; see [pso] and see [pso!]. Since set-gag-mode
  takes responsibility for the saving of output, related utility
  [set-saved-output] is disabled when gag-mode is active. Also note
  that calling set-gag-mode erases the currently saved output, if
  any.

  You may notice that gag-mode tends to print relatively little
  information about goals pushed for proof by sub-induction --- i.e.,
  a proof of *i.j, *i.j.k, etc. That feature emphasizes that
  unsuccessful sub-inductions should generally be avoided, not
  analyzed for ways to make them succeed. Instead, the key checkpoint
  that generated the goal pushed for this induction is more
  appropriate to analyze. In general, the ``higher level'' the
  checkpoint, the more worthy it is of attention. Thus, we suggest
  that look at the top-level checkpoints before looking at those
  labeled ``Key checkpoints under a top-level induction''.

  We conclude with remarks for advanced users.

  The notion of ``checkpoint'' can be modified by the user. The
  default, as discussed above, is for a checkpoint to be a goal that
  cannot be simplified. Put differently, a checkpoint is acted on by
  one of the processes in the value of the form (@
  checkpoint-processors); see [@]. Any or all of the symbols
  eliminate-destructors-clause, fertilize-clause, generalize-clause,
  or eliminate-irrelevance-clause can be removed from this value in
  order that invocation of the corresponding proof process does not
  cause its input goal to be labeled a checkpoint. For example, if
  you do not want destructor elimination to be treated differently
  from simplification for purposes of labeling checkpoints, you can
  evaluate the following form (see [assign]):

    (assign checkpoint-processors
            (remove 'eliminate-destructors-clause
                    (@ checkpoint-processors)))

  Note that the value of (@ checkpoint-processors) also affects the
  proof tree display; see [proof-tree-details]. End of Remark.)

  See [set-evisc-tuple], in particular the discussion there of
  :GAG-MODE, for how to influence slightly just what is printed in
  gag-mode.


Subtopics

  [Set-checkpoint-summary-limit]
      Control printing of key checkpoints upon a proof's failure

  [Set-saved-output]
      Save proof output for later display with :[pso] or :[pso!]")
 (SET-GUARD-CHECKING
  (GUARD)
  "Control checking [guard]s during execution of top-level forms

  Detailed comments about the arguments of this function may be found
  elsewhere: see [guard-evaluation-table]. Here we provide an
  introduction to the use of set-guard-checking.

  New users are encouraged to execute one of the following forms in
  order to avoid evaluation errors due to [guard]s:

    (set-guard-checking :none)
    (set-guard-checking nil)

  The former avoids all guard-checking on user-defined functions and
  should generally work fine for new users, the only drawback being
  efficiency loss on compute-intensive problems. All settings other
  than :none check guards, but a value of nil allows evaluation to
  continue in the logic when guards fail (avoiding the raw Lisp
  definition in that case).

  You may put one of the above forms in the \"acl2-customization.lsp\"
  file in your current directory (see [cbd]) or your home directory;
  see [ACL2-customization].

  Note that [guard]s are not part of the ACL2 logic, and hence new
  users can completely ignore the notion of [guard] (and the rest of
  this documentation section after this paragraph!). For example,
  (car 3) and nil can be proved equal in the ACL2 logic, as follows,
  even though the [guard] on [car] requires its first argument to be
  a [cons] pair or nil.

    (thm (equal (car 3) nil))

  Moreover, unless your functions or top-level forms call built-in ACL2
  functions that are defined in :[program] mode, the following
  property will hold.

      Evaluation of (set-guard-checking :none) will allow evaluation of
      forms such as (car 3) to take place without error in the top
      level loop, not only when proving theorems.

  If you feel bold, then you may wish to read the rest of this
  documentation topic; also see [guard].

  See [guard-evaluation-table] for a succinct table, with associated
  discussion, that covers in detail the material presented in the
  rest of the present topic.

  The top-level ACL2 loop has a variable which controls which sense of
  execution is provided. To turn ``[guard] checking on,'' by which we
  mean that [guard]s are checked at runtime, execute the top-level
  form :set-guard-checking t. To allow guard violations, do
  :set-guard-checking nil, or do :set-guard-checking :none to turn
  off all guard-checking, so that raw Lisp definitions of
  user-defined functions are avoided unless their [guard] is t. The
  status of guard-checking is reflected in the [prompt].

    ACL2 !>

  means [guard] checking is on and

    ACL2 >

  means [guard] checking is off. The exclamation mark can be thought of
  as ``barring'' certain computations. The absence of the mark
  suggests the absence of error messages or unbarred access to the
  logical axioms. Thus, for example

    ACL2 !>(car 'abc)

  will signal an error, while

    ACL2 >(car 'abc)

  will return nil.

  We will return at the end of this documentation topic to discuss two
  other values, :all and :nowarn, for :set-guard-checking. We also
  note that evaluation of built-in :program mode functions always
  takes place in raw Lisp.

  Whether [guard]s are checked during evaluation is independent of the
  [default-defun-mode]. We note this simply because it is easy to
  confuse ``:[program] mode'' with ``evaluation in Common Lisp'' and
  thus with ``[guard] checking on;'' and it is easy to confuse
  ``:[logic] mode'' with ``evaluation in the logic'' and with
  ``[guard] checking off.'' But the [default-defun-mode] determines
  whether newly submitted definitions introduce programs or add
  logical axioms. That mode is independent of whether evaluation
  checks [guard]s or not. You can operate in :[logic] mode with
  runtime [guard] checking on or off. Analogously, you can operate in
  :[program] mode with runtime [guard] checking on or off.

  For further discussion on evaluation and guards see
  [guards-and-evaluation], in particular the exception for safe-mode
  in the ``Aside'' there. See [guard] for a general discussion of
  [guard]s.

  Now we fulfill our promise above to discuss two other values for
  :set-guard-checking:

    :set-guard-checking :nowarn
    :set-guard-checking :all

  The meaning of these values is perhaps best described by the
  following example provided by David Rager.

    ACL2 !>(defun my-test (expr)
             (declare (xargs :guard (true-listp expr)
                             :verify-guards nil))
             (if (atom expr)
                 expr
               (cons (my-test (car expr))
                     (my-test (cdr expr)))))

    The admission of MY-TEST is trivial, using the relation O< (which is
    known to be well-founded on the domain recognized by O-P) and the measure
    (ACL2-COUNT EXPR).  We could deduce no constraints on the type of MY-
    TEST.  However, in normalizing the definition we used primitive type
    reasoning.

    Summary
    Form:  ( DEFUN MY-TEST ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  None
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     MY-TEST
    ACL2 !>(my-test '(a b c))

    ACL2 Warning [Guards] in TOP-LEVEL:  Guard-checking will be inhibited
    on recursive calls of the executable counterpart (i.e., in the ACL2
    logic) of MY-TEST.  To check guards on all recursive calls:
      (set-guard-checking :all)
    To leave behavior unchanged except for inhibiting this message:
      (set-guard-checking :nowarn)

    (A B C)
    ACL2 !>

  If you think about evaluation of (my-test '(a b c)), you will see
  that it leads to the recursive call (my-test 'a), which one might
  expect to cause a guard violation since the symbol a is not a
  [true-listp]. However, as the warning above explains, we do not by
  default check guards on recursive calls. The reason is efficiency
  --- imagine a simple definition with a guard that is slow to
  evaluate. The values :nowarn and :all for :set-guard-checking have
  been introduced as ways of dealing with the above warning. The
  value :nowarn simply turns off the warning above. The value :all
  causes all guards to be checked, even on recursive calls and even
  on all calls of non-built-in :[program] mode functions --- unless,
  of course, a call is made of a function whose guard has been
  verified (see [verify-guards]), where the arguments satisfy the
  guard, in which case the corresponding call is made in raw Lisp
  without subsidiary guard-checking. We still say that
  ``guard-checking is on'' after :set-guard-checking is invoked with
  values t, :nowarn, and :all, otherwise (after value nil) we say
  ``guard-checking is off.

  For technical reasons, :all does not have its advertised effect in
  the case of built-in :[program]-mode functions. If you are
  interested in this technical detail, see the comment ``In the
  boot-strap world...'' in source function oneify-cltl-code.

  We conclude with a remark about the use of :set-guard-checking for
  experimenting with ACL2 as a logic or as a programming language. If
  one views ACL2 as a logic, one may wish to use :set-guard-checking
  :none, while if instead one views ACL2 as a functional programming
  language, one may wish to use :set-guard-checking :all. The
  following transcript illustrates this distinction by way of
  example. Specifically, (car 3) is equal to nil in the ACL2 logic,
  but may be viewed as a programming error. The default of
  :set-guard-checking t is problematic for learning ACL2 using
  :[program] mode functions, since one can get raw Lisp errors. In
  the example below, the raw Lisp error occurs because foo implicitly
  has a [guard] of t, hence (foo 3) is evaluated in raw Lisp, which
  leads to a raw Lisp call of c[(car 3)].

    ACL2 !>(defun foo (x)
             (declare (xargs :mode :program))
             (car x))

    Summary
    Form:  ( DEFUN FOO ...)
    Rules: NIL
    Warnings:  None
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     FOO
    ACL2 !>(foo 3)
    Error: Attempt to take the car of 3 which is not listp.
      [condition type: TYPE-ERROR]

    Restart actions (select using :continue):
     0: Abort entirely from this (lisp) process.
    [Current process: Initial Lisp Listener]
    [1] ACL2(1): [RAW LISP] :pop
    ACL2 !>:set-guard-checking :none

    Turning off guard checking entirely.  To allow execution in raw Lisp
    for functions with guards other than T, while continuing to mask guard
    violations, :SET-GUARD-CHECKING NIL.  See :DOC set-guard-checking.

    ACL2 >(foo 3)
    NIL
    ACL2 >:set-guard-checking :all

    Turning guard checking on, value :ALL.

    ACL2 !>(foo 3)

    ACL2 Error in TOP-LEVEL:  The guard for the function symbol CAR, which
    is (OR (CONSP X) (EQUAL X NIL)), is violated by the arguments in the
    call (CAR 3).  See :DOC trace for a useful debugging utility.  See :DOC
    set-guard-checking for information about suppressing this check with
    (set-guard-checking :none), as recommended for new users.

    ACL2 !>")
 (SET-GUARD-MSG
  (GUARD DEBUGGING)
  "Specify what is printed when a [guard] is violated

  This is an advanced feature that may require considerable
  understanding of ACL2 programming. ACL2 provides default error
  messages for guard violations. However, ACL2 also provides a
  [table], guard-msg-table, that allows custom error messages for
  guard-checking failures. The macro set-guard-msg provides a
  convenient way to update this table. The keys of the table are
  symbols, which can be expected to be function symbols or names of
  macros. Each value is a (translated) [term] whose only free
  variables are world, args, and coda. When guard-checking fails, the
  term is evaluated to create a message suitable for \"~@\" formatted
  printing directives; see [fmt]. That evaluation is done with world
  bound to the current ACL2 logical [world], with args bound to the
  actual parameters of the call, and with coda bound to the message
  that would typically be printed by default at the end of a guard
  violation. (See ACL2 source function guard-er-message-coda for
  details, or simply experiment.)


Example

  Consider the following example.

    (defun foo (x)
     (declare (xargs :mode :program :guard (consp x)))
     (car x))

    (set-guard-msg foo (msg \"An error for call ~x0.\"
                            (cons 'foo args)))

  Corresponding output for a guard violation is as follows.

    ACL2 !>(foo 3)


    ACL2 Error in TOP-LEVEL:  An error for call (FOO 3).

    ACL2 !>

  Continuing in the same session, suppose we provide this fancier error
  message specification.

    (set-guard-msg foo
                   (msg \"An error for call ~x0 in a world of length ~x1.~@2\"
                        (cons 'foo args)
                        (length world) ; length of the current ACL2 world
                        coda))

  The corresponding error is shown below. Notice that the coda starts
  on a new line, with the same \"See :DOC ...\" message that one would
  see if the default error message were supplied for the same guard
  violation.

    ACL2 !>(foo 3)


    ACL2 Error in TOP-LEVEL:  An error for call (FOO 3) in a world of length
    98582.
    See :DOC set-guard-checking for information about suppressing this
    check with (set-guard-checking :none), as recommended for new users.
    To debug see :DOC print-gv, see :DOC trace, and see :DOC wet.

    ACL2 !>

  The capability shown above for function symbols is also available for
  macro names. However, the variable, coda, should not be used for
  macro names.")
 (SET-IGNORE-OK
  (DECLARE DEFUN)
  "Allow unused formals and locals without an ignore or ignorable
  declaration

    Examples:
    (set-ignore-ok t)
    (set-ignore-ok nil)
    (set-ignore-ok :warn)

  The first example above allows unused formals and locals, i.e.,
  variables that would normally have to be [declare]d ignored or
  ignorable. The second example disallows unused formals and locals;
  this is the default. The third example allows them, but prints an
  appropriate warning.

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  Moreover, its effect is to set the [ACL2-defaults-table], and hence
  its effect is [local] to the book or [encapsulate] form containing
  it; see [ACL2-defaults-table].

    General Form:
    (set-ignore-ok flg)

  where flg is either t, nil, or :warn.

  One might find this event useful when one is generating function
  definitions by an automated procedure, when that procedure does not
  take care to make sure that all formals are actually used in the
  definitions that it generates.

  Note: Defun will continue to report irrelevant formals even if
  :set-ignore-ok has been set to t, unless you also use
  [set-irrelevant-formals-ok] to instruct it otherwise.")
 (SET-INHIBIT-OUTPUT-LST
  (PROVER-OUTPUT)
  "Control output

    Examples:
    (set-inhibit-output-lst '(warning))
    (set-inhibit-output-lst '(proof-tree prove proof-checker))
    (set-inhibit-output-lst *valid-output-names*) ; inhibit all prover output
    :set-inhibit-output-lst (proof-tree prove)

    General Form:
    (set-inhibit-output-lst lst)

  where lst is a form (which may mention [state]) that evaluates to a
  list of names, each of which is the name of one of the following
  ``kinds'' of output produced by ACL2.

    error          error messages
    warning        warnings other than those related to soundness
    warning!       warnings (of all degrees of importance)
    observation    observations
    prove          commentary produced by the theorem prover
    proof-checker  commentary produced by the proof-checker
    event          non-proof commentary produced by events such as defun
                   and encapsulate
    history        output from history commands such as :ubt and :pbt
    summary        the summary at the successful conclusion of an event
    proof-tree     proof-tree output

  It is possible to inhibit each kind of output by putting the
  corresponding name into lst. For example, if 'warning is included
  in (the value of) lst, then no warnings are printed except those
  related to soundness, e.g., the inclusion of an uncertified book.
  Note that [proof-tree] output is affected by
  set-inhibit-output-lst; see [proof-tree].

  Note that proof output can be controlled without inhibiting it using
  this utility, and indeed is already quite limited by default. See
  [set-gag-mode].

  See [with-output] for a variant of this utility that can be used in
  [books]. Also see [set-inhibit-warnings] for how to inhibit
  individual warning types and see [set-inhibited-summary-types] for
  how to inhibit individual parts of the summary.

  Printing of events on behalf of [certify-book] and [encapsulate] is
  inhibited when both 'event and 'prove belong to lst. Otherwise,
  printing of events is controlled by the [ld] special
  [ld-pre-eval-print].

  Note for advanced users. By including warning! in lst, you are
  automatically including warning as well: all warnings will be
  inhibited. This is not the case if you modify value of state global
  variable 'inhibit-output-lst directly (with [assign] or
  f-put-global); then, if you include warning! but not warning, then
  warnings not related to soundness will still be printed (which is
  probably not what was intended).")
 (SET-INHIBIT-WARNINGS
  (PROVER-OUTPUT)
  "Control warnings

    Examples:
    (set-inhibit-warnings \"theory\" \"use\")

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  It is [local] to the book or [encapsulate] form in which it occurs;
  see [set-inhibit-warnings!] for a corresponding non-[local] event.
  Indeed, (set-inhibit-warnings ...) is equivalent to (local
  (set-inhibit-warnings! ...)).

    General Form:
    (set-inhibit-warnings string1 string2 ...)

  where each string is considered without regard to case. This macro is
  equivalent to (local (table inhibit-warnings-table nil 'lst
  :clear)), where lst is the list of strings supplied. This macro is
  an event (see [table]), but no output results from a
  set-inhibit-warnings event.

  ACL2 prints warnings that may, from time to time, seem excessive to
  experienced users. Each warning is ``labeled'' with a string
  identifying the type of warning. Consider for example

    ACL2 Warning [Use] in ( THM ...):  It is unusual to :USE ....

  Here, the label is \"Use\". The argument list for set-inhibit-warnings
  is a list of such labels, each of which is a string. Any warning is
  suppressed if its label is a member of this list, where case is
  ignored. Thus, for example, the warning above will not be printed
  after a call of set-inhibit-warnings that contains the string,
  \"Use\" (or any string that is [string-equal] to \"Use\", such as \"use\"
  or \"USE\"). In summary: the effect of this event is to suppress any
  warning whose label is a member of the given argument list, where
  case is ignored.

  The list of currently inhibited warnings is the list of keys in the
  [table] named inhibit-warnings-table. (The values in the table are
  irrelevant.) One way to get that value is to get the result from
  evaluating the following form: (table-alist 'inhibit-warnings-table
  (w state)). Of course, if warnings are inhibited overall --- see
  [set-inhibit-output-lst] --- then this value is entirely
  irrelevant.")
 (SET-INHIBIT-WARNINGS!
  (PROVER-OUTPUT)
  "Control warnings non-[local]ly

  Please see [set-inhibit-warnings], which is the same as
  set-inhibit-warnings! except that the latter is not [local] to the
  [encapsulate] or the book in which it occurs. Probably
  [set-inhibit-warnings] is to be preferred unless you have a good
  reason for wanting to export the effect of this event outside the
  enclosing [encapsulate] or book.")
 (SET-INHIBITED-SUMMARY-TYPES
  (PROVER-OUTPUT)
  "Control which parts of the summary are printed

    Example:
    (set-inhibited-summary-types '(rules time))

  Note: This is not an event. Rather, it changes the [state], in
  analogy to [set-inhibit-output-lst].

    General Form:
    (set-inhibited-summary-types form)

  where form evaluates to a true-list of symbols, each of which is
  among the values of the constant *summary-types*, i.e.: header,
  form, rules, hint-events, warnings, time, steps, value, and
  splitter-rules. Each specified type inhibits printing of the
  corresponding portion of the summaries printed at the conclusions
  of [events], where header refers to an initial newline followed by
  the line containing just the word Summary.

  Note the distinction between rules and hint-events. Rules provides a
  record of automatic rule usage by the prover, while hint-events
  shows the names of events given to :USE or :BY [hints], as well as
  [clause-processor] functions given to :CLAUSE-PROCESSOR hints that
  have an effect on the proof.

  Also see [set-inhibit-output-lst]. Note that
  set-inhibited-summary-types has no effect when summary is one of
  the types inhibited by [set-inhibit-output-lst], because in that
  case none of the summary will be printed.

  To control summary types for a single event, see [with-output].")
 (SET-INVISIBLE-FNS-TABLE
  (LOOP-STOPPER)
  "Set the invisible functions table

    Examples:
    (set-invisible-fns-table ((binary-+ unary--)
                              (binary-* unary-/)
                              (unary-- unary--)
                              (unary-/ unary-/)))
    (set-invisible-fns-table t) ; restore original invisible-fns-table

  Among other things, the setting above has the effect of making
  [unary--] ``invisible'' for the purposes of applying permutative
  :[rewrite] rules to [binary-+] trees. Thus, arg and (unary-- arg)
  will be given the same weight and will be permuted so as to be
  adjacent. The form (invisible-fns-table (w state)) returns the
  current value of the invisible functions table.

  Also see [add-invisible-fns] and see [remove-invisible-fns] for
  events that add to and remove from the invisible functions table,
  while accounting for macro aliases (see [macro-aliases-table]).

    General Form:
    (set-invisible-fns-table alist)

  where alist is either t or a true list of pairs, each element of
  which is of the form (fn ufn1 ... ufnk), where fn is a function
  symbol and each ufni is a unary function symbol. When alist is t,
  the initial value of this table is used in its place. Modulo the
  replacement of alist by the default setting when alist is t, this
  macro is equivalent to

    (table invisible-fns-table nil 'alist :clear)

  which is also an event (see [table]).

  Note that set-invisible-fns-table does not evaluate its argument.
  However, you can call [table] directly for that purpose. For
  example,

    (set-invisible-fns-table ((binary-+ unary--)
                              (binary-* unary-/)
                              (unary-- unary--)
                              (unary-/ unary-/)))

  ie equivalent to the following; see [table].

    (table invisible-fns-table nil
           (quote ((binary-+ unary--)
                   (binary-* unary-/)
                   (unary-- unary--)
                   (unary-/ unary-/)))
           :clear)

  See [invisible-fns-table] for a description of the invisible
  functions table.")
 (SET-IPRINT
  (IO)
  "Control whether abbreviated output can be read back in

  The following log may be sufficient for you to see how to use
  set-iprint; more explanation is below. The example is taken from a
  session that used the [break-rewrite] utility, but familiarity with
  that utility is not necessary in order to understand this example.
  What it shows is that the form (set-iprint t) allows you to
  recover, using [without-evisc], output that had been hidden.

    ACL2 !>(thm (p y))

    (1 Breaking (:REWRITE AX) on (P Y):
    1 ACL2 >:eval

    1x (:REWRITE AX) failed because :HYP 1 rewrote to
    (EQUAL Y '(NIL NIL NIL NIL ...)).

    1 ACL2 >:a!
    Abort to ACL2 top-level
    Here is the current pstack [see :DOC pstack]:
    (REWRITE-ATM SIMPLIFY-CLAUSE WATERFALL)

    *** Note: No checkpoints to print. ***

    ACL2 Version 6.4.  Level 1.  Cbd \"u/smith/\".
    System books directory \"/u/smith/acl2/v6-4/books/\".
    Type :help for help.
    Type (good-bye) to quit completely out of ACL2.

    ACL2 !>(set-iprint t)

    ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
    ACL2 !>(thm (p y))

    (1 Breaking (:REWRITE AX) on (P Y):
    1 ACL2 >:eval

    1x (:REWRITE AX) failed because :HYP 1 rewrote to
    (EQUAL Y '(NIL NIL NIL NIL . #@2#)).

    1 ACL2 >(without-evisc '(EQUAL Y '(NIL NIL NIL NIL . #@2#)))
    (EQUAL Y
           '(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL
                 NIL NIL NIL NIL NIL NIL NIL NIL NIL))
    1 ACL2 >

  This concludes the introductory example.

  When ACL2 pretty-prints large expressions using formatted printing
  (see [fmt]), it may save time and space by printing tokens `#' or
  `...' in place of certain subexpressions. By default this only
  happens for a few settings such as error and warning messages; see
  [set-evisc-tuple] for controlling such elision in general. The full
  expression is unavailable to the user when `#' or `...' is printed,
  but that is easily solved by evaluating the form

    (set-iprint t)

  to enable a mode called ``iprinting''. Then, instead of printing `#'
  or `...', ACL2 prints `#@i#' for i = 1,2,3,... --- all in base 10.
  ACL2 can read back in such `#@i#' because under the hood, i is
  associated with its corresponding elided form. Thus the term
  ``iprint'' can be viewed as suggesting ``interactive print'' or
  ``index print''. We also think of ``iprint'' as suggesting ``i
  printing'', to suggest the printing of token `#@i#'. We call i the
  ``iprint index'' of that token.

  The following example should suffice to illustrate how to recover
  elided subexpressions. (Below this example we provide details that
  may be of interest only to advanced users.) Here we cause an error
  by defining a macro of one argument and then calling it with two
  arguments. By default, error messages abbreviate subexpressions
  deeper than level 5 with `#' and past the 7th element of a list
  with `...'. We see this behavior below.

    ACL2 !>(defmacro foo (x) x)

    Summary
    Form:  ( DEFMACRO FOO ...)
    Rules: NIL
    Warnings:  None
    Time:  0.02 seconds (prove: 0.00, print: 0.00, other: 0.02)
     FOO
    ACL2 !>(foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n))

    ACL2 Error in macro expansion:  Wrong number of args in macro expansion
    of (FOO ARG1 (A (B (C (D #))) H I J K L ...)).  (See :DOC set-iprint
    to be able to see elided values in this message.)

    ACL2 !>(set-iprint t)

    ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
    ACL2 !>(foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n))

    ACL2 Error in macro expansion:  Wrong number of args in macro expansion
    of (FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)).

    ACL2 !>(acl2-count '(FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)))
    23
    ACL2 !>

  Sometimes you may want to supply the abbreviated form not to compute
  with it, as in the [ACL2-count] example just above, but so that you
  can see it. The macro [without-evisc] eliminates elision during
  printing. Below we show two ways to use this utility: first, we use
  it to print the elided form, and then, we use it instead on the
  original input form to print the entire error message.

    ACL2 !>(without-evisc '(FOO ARG1 (A (B (C (D #@1#))) H I J K L . #@2#)))
    (FOO ARG1
         (A (B (C (D (E (F (G))))))
            H I J K L M N))
    ACL2 !>(without-evisc (foo arg1 (a (b (c (d (e (f (g)))))) h i j k l m n)))

    ACL2 Error in macro expansion:  Wrong number of args in macro expansion
    of (FOO ARG1 (A (B (C (D (E (F (G)))))) H I J K L M N)).

    ACL2 !>

  The documentation above probably suffices for most users. For those
  who want more details, below we detail all the ways to use the
  set-iprint utility.

    Example Forms:
    (set-iprint t)   ; enable iprinting (elision with #@i@)
    (set-iprint nil) ; disable iprinting

    General Form:
    (set-iprint action        ; t, nil, :reset, :reset-enable, or :same
                :soft-bound s ; initially  1000
                :hard-bound h ; initially 10000)

  where all arguments are optional, but ACL2 queries for action if it
  is omitted. We defer the explanations of :soft-bound and
  :hard-bound. The values for action are as follows:

      T --- Enable iprinting.

      NIL --- Disable iprinting.

      :RESET --- Reset iprinting to its initial disabled state, so that
      when enabled, the first index i for which `#@i# is printed will
      be 1. Note that all stored information for existing iprint
      indices will be erased.

      :RESET-ENABLE --- Reset iprinting as with :reset, and then enable
      iprinting.

      :SAME --- Make no change to the iprinting state (other than setting
      the :soft-bound and/or :hard-bound if specified, as explained
      below).

  Immediately after a top-level form is read, hence before it is
  evaluated, a check is made for whether the latest iprint index
  exceeds a certain bound, (iprint-soft-bound state) --- 1000, by
  default. If so, then the (iprint-last-index state) is set back to
  0. This soft bound can be changed to any positive integer k by
  calling set-iprint with :soft-bound k, typically (set-iprint :same
  :soft-bound k)].

  The above ``soft bound'' is applied once for each top-level form, but
  you may want finer control by applying a bound after the
  pretty-printing of each individual form (since many forms may be
  pretty-printed between successive evaluations of top-level forms).
  That bound is (iprint-hard-bound state), and can be set with the
  :hard-bound argument in analogy to how :soft-bound is set, as
  described above.

  A ``rollover'' is the detection that the soft or hard bound has been
  exceeded, along with a state update so that the next iprint index
  will be 1. When a rollover occurs, any index beyond the latest
  iprint index is no longer available for reading. At the top level
  of the ACL2 read-eval-print loop, this works as follows: ACL2 reads
  the next top-level form according to the current iprint state, then
  handles a rollover if the latest iprint index exceeded the current
  soft bound. The following log illustrates a rollover, which follows
  the description above.

    ACL2 !>(set-iprint t :soft-bound 3)

    ACL2 Observation in SET-IPRINT:  The soft-bound for iprinting has been
    set to 3.

    ACL2 Observation in SET-IPRINT:  Iprinting has been enabled.
    ACL2 !>(set-evisc-tuple (evisc-tuple 2 3 nil nil) :sites :ld)
     (:LD)
    ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
    ((A B C . #@1#) (A B C . #@2#) (A B C . #@3#))
    ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
    ((A B C . #@4#) (A B C . #@5#) (A B C . #@6#))
    ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))
    ((A B C D E F G)
     (A B C D E F G)
     (A B C D E F G))
    ACL2 !>'(1 2 3 4 5)
    (1 2 3 . #@1#)
    ACL2 !>'((a b c d e f g) (a b c d e f g) (a b c d e f g))
    ((A B C . #@2#) (A B C . #@3#) (A B C . #@4#))
    ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))
    ((A B C D E F G)
     (A B C D E F G)
     (A B C D E F G))
    ACL2 !>(without-evisc '((A B C . #@4#) (A B C . #@5#) (A B C . #@6#)))

    ***********************************************
    ************ ABORTING from raw Lisp ***********
    Error:  Out-of-bounds index in #@5#.  See :DOC set-iprint.
    ***********************************************

    If you didn't cause an explicit interrupt (Control-C),
    then the root cause may be call of a :program mode
    function that has the wrong guard specified, or even no
    guard specified (i.e., an implicit guard of t).
    See :DOC guards.

    To enable breaks into the debugger (also see :DOC acl2-customization):
    (SET-DEBUGGER-ENABLE T)
    ACL2 !>

  We conclude by mentioning two cases where iprinting and evisc-tuples
  are ignored. (1) This is typically the case when printing results
  in raw Lisp outside the ACL2 loop. To use iprinting and
  evisc-tuples in raw Lisp, use raw-mode; see [set-raw-mode]. In
  raw-mode, results that are ACL2 objects will be printed in the same
  way that ACL2 would print those results if not in raw-mode. (2)
  Iprinting and evisc-tuples are ignored by [print-object$], which
  however is sensitive to many settings that do not affect formatted
  ([fmt] etc.) printing; see [print-control].

  The reader interested in design and implementation issues considered
  during the addition of iprinting to ACL2 is invited to read the
  paper ``Abbreviated Output for Input in ACL2: An Implementation
  Case Study''; see the {proceedings of ACL2 Workshop 2009 |
  http://www.cs.utexas.edu/users/moore/acl2/workshop-2009/}.")
 (SET-IRRELEVANT-FORMALS-OK
  (DEFUN)
  "Allow irrelevant formals in definitions

    Examples:
    (set-irrelevant-formals-ok t)
    (set-irrelevant-formals-ok nil)
    (set-irrelevant-formals-ok :warn)

  The first example above allows irrelevant formals in definitions; see
  [irrelevant-formals]. The second example disallows irrelevant
  formals; this is the default. The third example allows irrelevant
  formals, but prints an appropriate warning.

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  Moreover, its effect is to set the [ACL2-defaults-table], and hence
  its effect is [local] to the book or [encapsulate] form containing
  it; see [ACL2-defaults-table].

    General Form:
    (set-irrelevant-formals-ok flg)

  where flg is either t, nil, or :warn.")
 (SET-LD-KEYWORD-ALIASES (POINTERS)
                         "See [ld-keyword-aliases].")
 (SET-LD-KEYWORD-ALIASES! (POINTERS)
                          "See [ld-keyword-aliases].")
 (SET-LD-REDEFINITION-ACTION (POINTERS)
                             "See [ld-redefinition-action].")
 (SET-LD-SKIP-PROOFS (POINTERS)
                     "See [ld-skip-proofsp].")
 (SET-LD-SKIP-PROOFSP (POINTERS)
                      "See [ld-skip-proofsp].")
 (SET-LET*-ABSTRACTION (POINTERS)
                       "See [set-let*-abstractionp].")
 (SET-LET*-ABSTRACTIONP
  (PROVER-OUTPUT)
  "To shorten many prettyprinted clauses

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  Moreover, its effect is to set the [ACL2-defaults-table], and hence
  its effect is [local] to the book or [encapsulate] form containing
  it; see [ACL2-defaults-table].

  When this flag is set to t, subterms that occur more than once in a
  clause are abstracted away with [let*], generally shortening the
  displayed size of the clauses. This flag only affects how clauses
  are printed. It does not change what terms the theorem prover
  manipulates.

    :set-let*-abstractionp t ;;; or, (set-let*-abstractionp t)

  will cause the prettyprinter to do ``let* abstraction'' on clauses
  before they are printed. The algorithm finds the maximal
  multiply-occuring subterm and extracts it, binding it to some new
  variable and replacing its occurrences by that variable. This
  produces a let* form. This process is iterated until no subterm
  occurs more than once. This process generally takes a little time,
  but less time than to print large clauses. The process can greatly
  reduce the amount of text produced by the prover.

  THIS ONLY AFFECTS HOW THE CLAUSES ARE PRINTED! The unabstracted
  clauses are manipulated by the theorem prover.

    :set-let*-abstractionp nil

  restores normal clause printing.

  The mode is stored in the defaults table, See [ACL2-defaults-table].
  Thus, the mode may be set locally in books.")
 (SET-MATCH-FREE-DEFAULT
  (FREE-VARIABLES)
  "Provide default for :match-free in future rules

    General Forms:
    (set-match-free-default :once)
    (set-match-free-default :all)
    (set-match-free-default nil)

  Note: This utility does not apply to [type-prescription] rules; for a
  related topic pertinent to such rules, see
  [free-variables-type-prescription].

  As described elsewhere (see [free-variables]), a [rewrite], [linear],
  or [forward-chaining] rule may have free variables in its
  hypotheses, and ACL2 can be directed either to try all bindings
  (``:all'') or just the first (``:once'') when relieving that
  hypothesis, as a basis for relieving subsequent hypotheses. This
  directing of :all or :once is generally provided by specifying
  either :match-free :once or :match-free :all in the :[rule-classes]
  of the rule. If neither of these is specified, then the most recent
  set-match-free-default is used by ACL2 to fill in this missing
  :match-free field. See [rule-classes]. Except: If the last
  set-match-free-default specifies nil, then ACL2 reverts to the
  behavior it had at start-up, as described in Remarks (2) and (3)
  below.

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  It uses the [ACL2-defaults-table], and hence its effect is [local]
  to the book or [encapsulate] form in which it occurs.

  Remarks.

  (1) The use of set-match-free-default has no effect on existing
  rules. In order to change the behavior of existing rules with
  respect to free-variable matching, see [add-match-free-override].

  (2) If you submit a [rewrite], [linear], or [forward-chaining] rule
  with a free variable in a hypothesis, and no default setting was
  previously specified with set-match-free-default or the default
  setting is nil, and the rule is not within a book being processed
  with [include-book], [certify-book], or [rebuild], then a warning
  or error is caused. In order to make this an error instead of a
  warning, see [set-match-free-error].

  (3) If you submit a [rewrite], [linear], or [forward-chaining] rule
  with a free variable in a hypothesis, and no default setting has
  been previously specified with set-match-free-default or the
  default setting is nil, and no error is caused (see (2) above),
  then the default :all is used.")
 (SET-MATCH-FREE-ERROR
  (FREE-VARIABLES)
  "Control error vs. warning when :match-free is missing

    Legal Forms:
    (set-match-free-error nil)
    :set-match-free-error nil
    (set-match-free-error t)
    :set-match-free-error t

  As described elsewhere (see [free-variables]), when a [rewrite],
  [linear], or [forward-chaining] rule has free variables in its
  hypotheses, the user can specify whether to try all bindings
  (``:all'') or just the first (``:once'') when relieving its
  hypotheses, as a basis for relieving subsequent hypotheses. This
  direction of :all or :once is generally provided by specifying
  either :match-free :once or :match-free :all in the :[rule-classes]
  of the rule.

  But suppose that neither of these is specified for such a rule.
  (Note: set-match-free-error is not relevant for [type-prescription]
  rules.) Also suppose that set-match-free-default has not specified
  a default of :once or :all (see [set-match-free-default]). In this
  case a warning will occur except when in the context of
  [include-book]. If you prefer to see an error in such cases, except
  in the context of [certify-book], execute (set-match-free-error t).
  If there is no error, then a default of :all is used.

  Note: This is NOT an event! Instead, set-match-free-error sets the
  state global 'match-free-error (see [state] and see [assign]).
  Thus, this form cannot be put into a book. If you are tempted to
  put it into a book, consider the fact that it really isn't needed
  there, since the absence of :match-free does not cause an error in
  the context of [certify-book] or [include-book]. If you still feel
  the need for such a form, consider using set-match-free-default to
  provide a default, at least within the scope of the current book
  (if any); see [set-match-free-default].")
 (SET-MEASURE-FUNCTION
  (DEFUN)
  "Set the default measure function symbol

    Examples:
    (set-measure-function nqthm::count)

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.

    General Form:
    (set-measure-function name)

  where name is a function symbol of one argument. This macro is
  equivalent to (table acl2-defaults-table :measure-function 'name),
  and hence is [local] to any [books] and [encapsulate] [events] in
  which it occurs; see [ACL2-defaults-table]. Although this is thus
  an event (see [table]), nevertheless no output results from a
  set-measure-function event.

  This event sets the default measure function to name. Subsequently,
  if a recursively defined function is submitted to [defun] with no
  explicitly given :measure argument, [defun] ``guesses'' the measure
  (name var), where name is the then current default measure function
  and var is the first formal found to be tested along every branch
  and changed in every recursive call.

  Note that if (table acl2-defaults-table :measure-function 'name) has
  its default value of nil, then the default measure function is
  [ACL2-count].")
 (SET-NON-LINEAR (POINTERS)
                 "See [set-non-linearp].")
 (SET-NON-LINEARP
  (NON-LINEAR-ARITHMETIC)
  "To turn on or off non-linear arithmetic reasoning

    Examples:
    (set-non-linearp t)
    (set-non-linearp nil)

  See [non-linear-arithmetic]. This event is equivalent to (table
  acl2-defaults-table :non-linearp ), and hence is [local]
  to any [books] and [encapsulate] [events] in which it occurs; see
  [ACL2-defaults-table].

  The initial value is nil.")
 (SET-OVERRIDE-HINTS
  (OVERRIDE-HINTS)
  "Set the [override-hints]

  See [override-hints] for a discussion of override-hints. Here we
  describe how to set them. Note that the effects of
  set-override-hints [events] are [local] to the [books] or
  encapsulate [events] in which they reside; see
  [set-override-hints!] to avoid that restriction. Also see
  [add-override-hints] to add to the list of override-hints, rather
  than setting a new list and ignoring the present list.

    General Form:
    (set-override-hints form)

  where form evaluates to a list of computed hint forms. The effect of
  this event is to set the list of [override-hints] to the result of
  that evaluation.")
 (SET-OVERRIDE-HINTS!
  (OVERRIDE-HINTS)
  "Set the [override-hints] non-[local]ly

  Set-override-hints! is the same as [set-override-hints], except that
  the former is not [local] to [books] or [encapsulate] [events] in
  which it occurs. See [set-override-hints]; also see
  [add-override-hints].")
 (SET-PARALLEL-EXECUTION
  (PARALLELISM)
  "For ACL2(p): enabling parallel execution for four parallelism
  primitives

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].
  See [parallelism-tutorial] for an introduction to parallel
  execution in ACL2.

    General Forms:
    (set-parallel-execution nil) ; default for images not built for parallelism
    (set-parallel-execution t)   ; default for images built for parallelism
    (set-parallel-execution :bogus-parallelism-ok)

  Set-parallel-execution takes an argument that specifies the enabling
  or disabling of [parallel] execution for the primitives [pand],
  [por], [plet], and [pargs] (but not [spec-mv-let], whose parallel
  execution remains enabled). However, without using [top-level],
  calls of parallelism primitives made explicitly in the ACL2
  top-level loop, as opposed to inside function bodies, will never
  cause parallel execution; see [parallelism-at-the-top-level].
  Parallel execution is determined by the value of the argument to
  set-parallel-execution, as follows.

  Value t:
  All parallelism primitives used in bodies of function definitions
  are given the opportunity to execute in parallel. However, the use
  of parallelism primitives directly in the ACL2 top-level loop
  causes an error.

  Value :bogus-parallelism-ok:
  Parallel execution is enabled, as for value t. However, the use of
  parallelism primitives directly in the ACL2 top-level loop does not
  cause an error, but rather, simply results in serial execution for
  these primitives.

  Value nil:
  All parallelism primitives degrade to their serial equivalents,
  including their calls made directly in the ACL2 top-level loop.
  Thus, uses of parallelism primitives do not in themselves cause
  errors.")
 (SET-PRINT-BASE
  (IO ACL2-BUILT-INS)
  "Control radix in which numbers are printed

  Also see [set-print-base-radix] for a nice combined use of
  set-print-base and [set-print-radix].

  By default, integers and ratios are printed in base 10. ACL2 also
  supports printing in radix 2, 8, or 16 by calling set-print-base
  with the desired radix (base).

    (set-print-base 10 state) ; Default printing
    (set-print-base 16 state) ; Print integers and ratios in hex

  Here is a sample log.

    ACL2 !>(list 25 25/3)
    (25 25/3)
    ACL2 !>(set-print-base 16 state)
    
    ACL2 !>(list 25 25/3)
    (19 19/3)
    ACL2 !>

  See [set-print-radix] for how to print the radix, for example,
  printing the decimal number 25 in print-base 16 as ``#x25'' rather
  than ``25''. Also see [print-control] for other user-settable print
  controls.

  Note: ACL2 [events] and some other top-level commands (for example,
  [thm], [verify], and history commands such as :pe and :pbt) set the
  print base to 10 during their evaluation. So [set-print-base] has
  no effect while these forms are being processed.")
 (SET-PRINT-BASE-RADIX
  (IO ACL2-BUILT-INS)
  "Control radix in which numbers are printed and printing of the radix

  See [set-print-base] and [set-print-radix] for detailed discussions
  of those functions. Set-print-base-radix combines their
  functionality by setting the radix (as is done by
  [set-print-base]), and then causing the radix to be printed (as is
  done by [set-print-radix]) exactly when the specified radix is not
  10.

  Here is a sample log.

    ACL2 !>(list 25 25/3)
    (25 25/3)
    ACL2 !>(set-print-base-radix 16 state)
    
    ACL2 !>(list 25 25/3)
    (#x19 #x19/3)
    ACL2 !>(set-print-base-radix 10 state)
    
    ACL2 !>(list 25 25/3)
    (25 25/3)
    ACL2 !>")
 (SET-PRINT-CASE
  (IO ACL2-BUILT-INS)
  "Control whether symbols are printed in upper case or in lower case

  By default, symbols are printed in upper case when vertical bars are
  not required, as specified by Common Lisp. As with Common Lisp,
  ACL2 supports printing in a \"downcase\" mode, where symbols are
  printed in lower case. Many printing functions (some details below)
  print characters in lower case for a symbol when the ACL2 [state]
  global variable print-case has value :downcase and vertical bars
  are not necessary for printing that symbol. (Thus, this state
  global functions in complete analogy to the Common Lisp global
  *print-case*.) The value print-case is returned by (print-case),
  and may be set using the function set-print-case as follows.

    (set-print-case :upcase   state) ; Default printing
    (set-print-case :downcase state) ; Print symbols in lower case when
                                     ; vertical bars are not required

  The ACL2 user can expect that the :downcase setting will have an
  effect for formatted output (see [fmt] and see [fms]) when the
  directives are ~p, ~P, ~q, or ~Q, for built-in functions princ$ and
  prin1$, and the ppr family of functions, and not for built-in
  function print-object$. For other printing functions, the effect of
  :downcase is unspecified.

  Also see [print-control] for other user-settable print controls.")
 (SET-PRINT-CIRCLE (POINTERS)
                   "See [print-control].")
 (SET-PRINT-CLAUSE-IDS
  (PROVER-OUTPUT)
  "Cause subgoal numbers to be printed when 'prove output is inhibited

    General Forms:
    (set-print-clause-ids t)
    :set-print-clause-ids t
    (set-print-clause-ids nil)
    :set-print-clause-ids nil

  This command affects output from the theorem prover only when 'prove
  output is inhibited (see [set-inhibit-output-lst]) or gag-mode is
  on (but in that case the :goals setting issues this command
  automatically; see [set-gag-mode]). Calling this macro with value t
  as shown above will cause subsequent proof attempts with 'prove
  output inhibited to print the subgoal number, so that you can see
  the progress of the proof; value nil reverts to the default
  behavior, where this is not the case. On a related note, we point
  out that you can cause output to be saved for later display; see
  [pso] and see [pso!].

  If 'prove output is inhibited or gag-mode is on, and if you issue
  (set-print-clause-ids t) (either explicitly or with (set-gag-mode
  :goals)), then you can restrict when subgoal numbers are printed.
  In the following example we restrict to subgoals that are no more
  than four inductions deep, no more than four casesplits deep, and
  no more than four single-subgoals deep. For additional relevant
  explanation, see [clause-identifier] and see [defattach].

    (defun print-clause-id-okp-level-4 (cl-id)
      (declare (xargs :mode :logic :guard (clause-id-p cl-id)))
      (and (<= (length (access clause-id cl-id :pool-lst))
               4)
           (<= (length (access clause-id cl-id :case-lst))
               4)
           (<= (access clause-id cl-id :primes)
               4)))

    (defattach print-clause-id-okp print-clause-id-okp-level-4)")
 (SET-PRINT-ESCAPE (POINTERS)
                   "See [print-control].")
 (SET-PRINT-LENGTH (POINTERS)
                   "See [print-control].")
 (SET-PRINT-LEVEL (POINTERS)
                  "See [print-control].")
 (SET-PRINT-LINES (POINTERS)
                  "See [print-control].")
 (SET-PRINT-RADIX
  (IO ACL2-BUILT-INS)
  "Control printing of the radix for numbers

  Also see [set-print-base-radix] for a nice combined use of
  [set-print-base] and set-print-radix.

  See [set-print-base] for background on how the print base affects the
  printing of numbers. set-print-radix affects whether a radix
  indicated when a number is printed. The radix is not indicated by
  default, or after evaluating (set-print-radix nil state). But if
  set-print-radix is called with a first argument that evaluates to a
  nonnil value --- for example, (set-print-radix t state) --- then
  the radix is shown when printing. (This behavior is consistent with
  the handling of Common Lisp global *print-radix*.) The following
  log illustrates how this works.

    ACL2 !>(list 25 25/3)
    (25 25/3)
    ACL2 !>(set-print-base 16 state)
    
    ACL2 !>(list 25 25/3)
    (19 19/3)
    ACL2 !>(set-print-radix t state)
    
    ACL2 !>(list 25 25/3)
    (#x19 #x19/3)
    ACL2 !>(set-print-base 10 state)
    
    ACL2 !>(list 25 25/3)
    (25. #10r25/3)
    ACL2 !>(set-print-radix nil state)
    
    ACL2 !>(list 25 25/3)
    (25 25/3)
    ACL2 !>")
 (SET-PRINT-READABLY (POINTERS)
                     "See [print-control].")
 (SET-PRINT-RIGHT-MARGIN (POINTERS)
                         "See [print-control].")
 (SET-PROVER-STEP-LIMIT
  (MISCELLANEOUS)
  "Sets the step-limit used by the ACL2 prover

  This event provides a way to limit the number of so-called ``prover
  steps'' permitted for an event. See [with-prover-step-limit] for a
  way to specify the limit on prover steps for a single event, rather
  than globally. For a related utility based on time instead of
  prover steps, see [with-prover-time-limit]. For examples of how
  step limits work, see the community book
  books/misc/misc2/step-limits.lisp. For a utility that returns an
  indicator of the number of prover steps most recently taken, see
  [last-prover-steps].

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  Moreover, its effect is to set the [ACL2-defaults-table], and hence
  its effect is [local] to the book or [encapsulate] form containing
  it; see [ACL2-defaults-table].

    Example Forms:
    (set-prover-step-limit *default-step-limit*) ; no limit on prover steps
    (set-prover-step-limit nil)   ; abbreviation for the form just above
    (set-prover-step-limit 10000) ; allow at most 10,000 prover steps per event

    General Form:
    (set-prover-step-limit expr)

  where expr evaluates either to nil or else to a natural number not
  exceeding the value of *default-step-limit*. If that value is nil
  or the value of *default-step-limit*, then no default limit is
  placed on the number of prover ``steps'' (see below) during
  processing of an event. Otherwise, that value is the maximum number
  of prover steps permitted before an error occurs.

  This event specifies the limit on the number of ``steps'' counted by
  the ACL2 prover during processing of an event. Currently, a step is
  counted for each call of the system functions rewrite and
  expand-abbreviations. However, the steps counted may change in
  future releases of ACL2, so users would probably be well served by
  avoiding the assumption that only the above two calls are counted
  as prover steps.

  Depending on the computer you are using, you may have less than a
  half-hour of time before the number of prover steps exceeds the
  maximum step-limit, which is one less than the value of
  *default-step-limit*. Note however the exception stated above: if
  the ``limit'' is nil or is the value of *default-step-limit*, then
  no limit is imposed.

  There is at best a loose connection between the counting of steps and
  [with-prover-time-limit]. In particular, for a call of mfc-rw or
  any mfc- function (see [extended-metafunctions]), the steps taken
  during that call are forgotten when returning from that call.

  The limit is relevant for every event, as well as for calls of [thm]
  and [certify-book] --- and more generally, to any form that creates
  a ``summary context'' to print the usual event summary. The limit
  is also put in force when entering the [proof-checker]. A call of
  set-prover-step-limit applies to each subsequent form unless the
  call of set-prover-step-limit is within a summary context, in which
  case its effect disappears when exiting that summary context.

  The limit applies to each event, not just ``atomic'' events. Consider
  the following example.

    (set-prover-step-limit 500)

    (encapsulate
      ()
      (defthm lemma-1 ; takes 380 steps
        (equal (append (append x y) z) (append x y z))
        :rule-classes nil)
      (defthm lemma-2 ; would take 319 steps
        (equal (len (append x y)) (+ (len x) (len y)))
        :rule-classes nil))

  The first [defthm] event, lemma-1 takes 380 steps (as of this
  writing), as shown in the summary:

    Prover steps counted:  380
    LEMMA-1

  The second [defthm] event, lemma-2, takes 319 steps (as of this
  writing) when evaluated at the top level. However, in the context
  above, 380 steps of the available 500 steps (from the
  set-prover-step-limit event above) have already been taken under
  the above [encapsulate] event. Thus, when the number of steps would
  exceed 120, the proof of lemma-2 is aborted:

    ACL2 Error in STEP-LIMIT:  The prover step-limit, which is 120 in the
    current context, has been exceeded.  See :DOC set-prover-step-limit.

  The summary for lemma-2 reflects that situation:

    Prover steps counted:  More than 120

  The summary for the [encapsulate] event then indicates that the
  available steps for that event have also been exceeded:

    Prover steps counted:  More than 500

  The discussion above applies to any event that contains other events,
  hence applies similarly to [progn] events.

  For those who use [make-event], we note that prover steps in the
  expansion phase similarly contribute to the total number of steps
  counted. For example, suppose that the limit is 500 prover steps as
  above, and you submit (make-event EXPR), where 300 prover steps
  take place during evaluation of EXPR, producing event EV. Then
  evaluation of EV will cause an error if it takes more than 200
  prover steps. This observation actually can be used to count prover
  steps for sequences of forms that are not all legal [events] (see
  [embedded-event-form]), such as calls of [thm]. For example, a
  small built-in ACL2 test suite that includes [thm] forms can be run
  by evaluating the form (mini-proveall), and the steps can be
  counted as shown below. (Here we assume a fresh ACL2 session; an
  error would occur if first, we evaluate the event
  (set-prover-step-limit 500) displayed above.)

    ACL2 !>(make-event (er-progn (mini-proveall) (value '(value-triple nil))))
    [[... output omitted here ...]]
    Summary
    Form:  ( MAKE-EVENT (ER-PROGN ...))
    Rules: NIL
    Warnings:  Double-rewrite, Equiv, Subsume and Non-rec
    Time:  0.38 seconds (prove: 0.04, print: 0.29, other: 0.05)
    Prover steps counted:  41090
     NIL
    ACL2 !>


Subtopics

  [Last-prover-steps]
      The number of prover steps most recently taken")
 (SET-RAW-MODE
  (DEFTTAG)
  "Enter or exit ``raw mode,'' a raw Lisp environment

  Below we discuss raw-mode. In brief: The simplest way to turn
  raw-mode on is :SET-RAW-MODE-ON!, and to turn it off, :SET-RAW-MODE
  NIL. Also see [set-raw-mode-on!].

  ACL2 users often find its careful syntax checking to be helpful
  during code development. Sometimes it is even useful to do code
  development in :[logic] mode, where ACL2 can be used to check
  termination of (mutually) recursive functions, verify guards, or
  even prove properties of the functions.

  However, loading code using [include-book] is much slower than using
  Common Lisp load in raw Lisp, and in this sense ACL2 can get in the
  way of efficient execution. Unfortunately, it is error-prone to use
  ACL2 sources (or their compilations) in raw Lisp, primarily because
  a number of ACL2 primitives will not let you do so. Perhaps you
  have seen this error message when trying to do so:

    HARD ACL2 ERROR in ACL2-UNWIND-PROTECT:  Apparently you have tried
    to execute a form in raw Lisp that is only intended to be executed
    inside the ACL2 loop.

  Even without this problem it is important to enter the ACL2 loop (see
  [lp]), for example in order to set the [cbd] and (to get more
  technical) the readtable.

  ACL2 provides a ``raw mode'' for execution of raw Lisp forms. In this
  mode, [include-book] reduces essentially to a Common Lisp load.
  More generally, the ACL2 logical [world] is not routinely extended
  in raw mode (some sneaky tricks are probably required to make that
  happen). To turn raw mode off or on:

    :set-raw-mode t   ; turn raw mode on
    :set-raw-mode nil ; turn raw mode off

  The way you can tell that you are in raw mode is by looking at the
  prompt (see [default-print-prompt]), which uses a capital ``P''
  (suggesting something like program mode, but more so).

    ACL2 P>

  Typical benefits of raw mode are fast loading of source and compiled
  files and the capability to hack arbitrary Common Lisp code in an
  environment with the ACL2 sources loaded (and hence with ACL2
  primitives available). In addition, ACL2 hard errors will put you
  into the Lisp debugger, rather than returning you to the ACL2 loop,
  and this may be helpful for debugging; see [hard-error] and see
  [illegal], but also see [break-on-error]. However, it probably is
  generally best to avoid raw mode unless these advantages seem
  important. We expect the main benefit of raw mode to be in
  deployment of applications, where load time is much faster than the
  time required for a full-blown [include-book], although in certain
  cases the fast loading of books and treatment of hard errors
  discussed above may be useful during development.

  Raw mode is also useful for those who want to build extensions of
  ACL2. For example, the following form can be put into a certifiable
  book to load an arbitrary Common Lisp source or compiled file.

    (progn (defttag my-application)
           (progn! (set-raw-mode t)
                   (load \"some-file\")))

  Also see [include-raw] and [with-raw-mode]. See [defttag], and see
  [progn!].

  Below are several disadvantages to raw mode. These should discourage
  users from using it for general code development, as :[program]
  mode is generally preferable.

    * Forms are in essence executed in raw Lisp. Hence:
        * Syntax checking is turned off; and
        * Guard checking is completely disabled.

    * Table events, including [logic], are ignored, as are many other
      [events], including [defthm] and [comp].
    * Soundness claims are weakened for any ACL2 session in which raw mode
      was ever entered; see [defttag].
    * The normal undoing mechanism (see [ubt]) is not supported.
    * Unexpected behavior may occur when you return from raw-mode. For
      example, if you redefine a :logic mode function whose guards
      have not been verified, you will not see the change inside the
      ACL2 loop because there, the raw Common Lisp definition is only
      executed after guards have been verified; see
      [guards-and-evaluation] and see [guard-evaluation-table].

  We conclude with some details.

  Printing results. The rules for printing results are unchanged for
  raw mode, with one exception. If the value to be printed would
  contain any Lisp object that is not a legal ACL2 object, then the
  print routine is used from the host Lisp, rather than the usual
  ACL2 printing routine. The following example illustrates the
  printing used when an illegal ACL2 object needs to be printed.
  Notice how that ``command conventions'' are observed (see
  [ld-post-eval-print]); the ``[Note'' occurs one space over in the
  second example, and no result is printed in the third example.

    ACL2 P>(find-package \"ACL2\")
    [Note:  Printing non-ACL2 result.]
    #
    ACL2 P>(mv nil (find-package \"ACL2\") state)
     [Note:  Printing non-ACL2 result.]
    #
    ACL2 P>(mv t (find-package \"ACL2\") state)
    ACL2 P>(mv 3 (find-package \"ACL2\"))
    [Note:  Printing non-ACL2 result.]
    (3 #)
    ACL2 P>

  If you have trouble with large structures being printed out, you
  might want to execute appropriate Common Lisp forms in raw mode,
  for example, (setq *print-length* 5) and (setq *print-level* 5).

  Include-book. The [events] [add-include-book-dir],
  [add-include-book-dir!], [delete-include-book-dir], and
  [delete-include-book-dir!] have been designed to work with raw
  mode. However, if you enter raw mode and then evaluate such forms,
  then the effects of these forms will disappear when you exit raw
  mode, in which case you can expect to see a suitable warning.
  Regarding include-book itself: it should work in raw mode as you
  might expect, at least if a compiled file or expansion file was
  created when the book was certified; see [certify-book].

  Packages. Raw mode disallows the use of [defpkg]. If you want to
  create a new package, first exit raw mode with :set-raw-mode nil;
  you can subsequently re-enter raw mode with :set-raw-mode t if you
  wish.


Subtopics

  [Add-raw-arity]
      Add arity information for raw mode

  [Remove-raw-arity]
      Remove arity information for raw mode")
 (SET-RAW-MODE-ON!
  (DEFTTAG)
  "Enter ``raw mode,'' a raw Lisp environment

  This is the same as ([set-raw-mode] t) except that it first
  introduces a so-called ``trust tag'' (``ttag'') so that
  set-raw-mode will be legal. See [defttag] for a discussion of ttags
  and how they affect [certify-book] and [include-book].

  See [set-raw-mode] for a discussion of raw-mode.")
 (SET-RAW-PROOF-FORMAT
  (PROVER-OUTPUT)
  "Print runes as lists in proof output from simplification

    General Forms:
    (set-raw-proof-format t)
    :set-raw-proof-format t
    (set-raw-proof-format nil)
    :set-raw-proof-format nil

  This command affects output from the theorem prover only when 'prove
  output is not inhibited (see [set-inhibit-output-lst]) and gag-mode
  is off (see [set-gag-mode]). Calling this macro with value t as
  shown above will cause simplification steps from proof output,
  including steps from preprocess (see [simple]), to print the list
  of runes used in a list format, rather than in the English proof
  commentary. This ``raw'' format can be handy when you want to use
  that list as a basis for [hints] that you construct for a
  subsequent proof attempt.")
 (SET-REWRITE-STACK-LIMIT
  (REWRITE-STACK-LIMIT)
  "Sets the rewrite stack depth used by the rewriter

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.

    Example Forms:
    (set-rewrite-stack-limit 30)                            ; set to small limit
    :set-rewrite-stack-limit 30                             ; same as above
    (set-rewrite-stack-limit *default-rewrite-stack-limit*) ; the default
    (set-rewrite-stack-limit (1- (expt 2 28)))              ; maximum legal limit
    :set-rewrite-stack-limit nil         ; same as above -- essentially, no limit

  This event sets the maximum stack depth for calls of certain
  functions that implement the ACL2 rewriter; see
  [rewrite-stack-limit]. It must be a non-negative integer less than
  2^28. A call (set-rewrite-stack-limit limit) is equivalent to:

    (table acl2-defaults-table :rewrite-stack-limit limit).

  The use of [ACL2-defaults-table] ensures that this event's effect is
  implicitly [local] to the book or [encapsulate] form in which it
  occurs.

  For a different but somewhat related concept, see [backchain-limit].")
 (SET-RULER-EXTENDERS (POINTERS)
                      "See [ruler-extenders].")
 (SET-RW-CACHE-STATE
  (REWRITE)
  "Set the default rw-cache-state

  The ACL2 rewriter uses a data structure, called the rw-cache
  (rewriter cache), to save failed attempts to apply conditional
  [rewrite] rules. The regression suite has taken approximately 11%
  less time with this mechanism. The rw-cache is active by default
  but this event allows it to be turned off or modified. Note that
  this event is [local] to its context (from [encapsulate] or
  [include-book]). For a non-local version, use
  [set-rw-cache-state!].

    Example forms:
    (set-rw-cache-state :atom)     ; default: rw-cache cleared for each literal
                                   ;   (i.e., hypothesis or conclusion of a goal)
    (set-rw-cache-state nil)       ; rw-cache is inactive
    (set-rw-cache-state t)         ; rw-cache persists beyond each literal
    (set-rw-cache-state :disabled) ; rw-cache is inactive, but the rw-cache-state
                                   ;   transitions to state t after
                                   ;   simplification takes place

    General Form:
    (set-rw-cache-state val)

  where val evaluates to one of the four values shown in ``Example
  forms'' above. The default is :atom, which enables the rw-cache but
  clears it before rewriting a hypothesis or conclusion of any goal.
  The value t is provides more aggresive use of the rw-cache,
  basically preserving the rw-cache when there is a single subgoal.
  The value :disabled is the same as t, except that the rw-cache is
  initially inactive and only becomes active when some simplification
  has taken place. We have seen a few cases where value t will make a
  proof fail but :disabled does not.

  The following example illustrates the rw-cache in action. You will
  see a break during evaluation of the [thm] form. Type :eval and you
  will see a failed rewriting attempt. Type :go to continue, and at
  the next break type :eval again. This time you will see the same
  failed rewriting attempt, but this time labeled with a notation
  saying that the failure was cached earlier, which indicates that
  this time the rewriter did not even attempt to prove the hypothesis
  of the [rewrite] rule f1->f2.

    (defstub f1 (x) t)
    (defstub f2 (x) t)
    (defaxiom f1->f2
             (implies (f1 x) (equal (f2 x) t)))
    :brr t
    :monitor (:rewrite f1->f2) t
    (thm (equal (car (f2 a)) (cdr (f2 a))))

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.
  It is [local] to the book or [encapsulate] form in which it occurs
  (see [set-rw-cache-state!] for a corresponding non-[local] event).

  We also note that rw-cache-state changes may also be caused at the
  subgoal level; see [hints].

  We welcome you to experiment with different rw-cache states. If the
  more aggressive values of t and :disabled cause proofs to fail,
  then you can revert to the default of :atom or even turn off the
  rw-cache using (set-rw-cache-state nil). We don't expect users to
  need a deep knowledge of the rw-cache in order to do such
  experiments, but readers interested in details of the rw-cache
  implementation are invited to read the ``Essay on Rw-cache'' in the
  ACL2 source code.")
 (SET-RW-CACHE-STATE!
  (REWRITE)
  "Set the default rw-cache-state non-[local]ly

  Please see [set-rw-cache-state], which is the same as
  set-rw-cache-state! except that the latter is not [local] to the
  [encapsulate] or the book in which it occurs.")
 (SET-SAVED-OUTPUT
  (SET-GAG-MODE)
  "Save proof output for later display with :[pso] or :[pso!]

    Examples:
    (set-saved-output t t)    ; save proof output for later, but inhibit it now
    (set-saved-output t :all) ; save proof output for later, but inhibit all
                              ;   output (except WARNING!, for critical warnings,
                              ;   and ERROR, unless these are already inhibited)
    :set-saved-output t :all  ; same as the line above
    (set-saved-output t nil)  ; save proof output for later, but print it now too
    (set-saved-output nil t)  ; do not save proof output, and inhibit it
    (set-saved-output nil nil); do not save proof output or inhibit output
    (set-saved-output nil :same), (set-saved-output t :same)
                              ; save proof output or not, as indicated, but do
                              ;   not change which output is inhibited
    (set-saved-output nil :normal)
                              ; the behavior when ACL2 first starts up: do not
                              ;   save output, and only inhibit proof-tree output
    (set-saved-output t '(warning observation proof-tree prove))
                              ; save proof output for later, and inhibit the
                              ;   indicated kinds of output

    General Form:
    (set-saved-output save-flg inhibit-flg)

  Parameter save-flg is t to cause output to be saved for later display
  using pso or pso!; see [pso] and see [pso!], and see the
  documentation for [proof-checker] commands of the same names. Set
  save-flg to nil to turn off this feature; except, it always stays
  on in proof-checker sessions entered with [verify]. The other
  argument, inhibit-flg, controls whether output should be inhibited
  when it is created (normally, during a proof attempt). So a common
  combination is to set both arguments to t, to indicate that output
  should be suppressed for now but saved for printing with [pso] or
  [pso!]. The examples above give a good summary of the functionality
  for the second argument.

  Saved output is cleared at the start of every event, and also at the
  start of every [proof-checker] commands that invoke the prover.
  Note that interactive [proof-checker] commands, that is, from a
  proof-checker session entered with [verify], are always run with
  output saved.

  Also see [set-gag-mode]; and see [set-print-clause-ids], which causes
  subgoal numbers to be printed during proof attempts when output is
  inhibited.

  See [set-inhibit-output-lst] if you want to inhibit certain output
  from the prover but not other output (e.g., not the summary), and
  you don't want to save any output.")
 (SET-SERIALIZE-CHARACTER (POINTERS)
                          "See [with-serialize-character].")
 (SET-SKIP-META-TERMP-CHECKS
  (META CLAUSE-PROCESSOR)
  "Skip output checks for [meta] functions and [clause-processor]s

  WARNING: Use of this macro may render ACL2 unsound, which is why it
  requires a trust tag. If you obtained an error during application
  of a [meta]function, a hypothesis metafunction, or a
  [clause-processor], it might well be best to rewrite that function
  to avoid generating terms with the ``forbidden'' function calls
  described in that error message. However, judicious use of this
  macro can be useful during development; the rest of this topic
  describes its usage.

  The result of applying a [meta]function (or a hypothesis
  metafunction) must be a term. Similarly, the result of applying a
  [clause-processor] must be a list of clauses, where a clause is a
  list of terms. If these conditions fail, then an error occurs; see
  [term-table] for how one obtains some assistance towards avoiding
  such errors.

  By default, ACL2 actually enforces a stronger requirement: the
  resulting term or clause-list cannot contain any calls of
  ``forbidden'' function symbols: ones that would be illegal when
  submitting a theorem. These include function symbols that are
  untouchable (see [remove-untouchable]) as well as those that are
  keys of the alist *ttag-fns-and-macros*.

  These two checks --- that the results are terms and that they contain
  no calls of forbidden function symbols --- can be expensive for
  large terms. The macro set-skip-meta-termp-checks provides a way to
  avoid both checks. Since these checks can be critical for
  soundness, a trust tag (see [defttag]) must be active in order to
  invoke this macro unless the argument is nil. It might be best to
  avoid using this macro except to skip such checks that you have
  identified to be expensive, and to skip them only when using ACL2
  interactively (as opposed to doing batch certification jobs) ---
  though this macro might also be useful in determining when such
  checks are indeed expensive.

  There are two legal ways to call this macro, as follows. Note that
  the arguments are not evaluated.

    ; Skip all such checks:
    (set-skip-meta-termp-checks t)

    ; Skip such checks for functions fn1, ..., fnk (each of which is presumably a
    ; metafunction, hypothesis metafunction, or clause-processor):
    (set-skip-meta-termp-checks (fn1 ... fnk))

  A special case of the second form above is to perform all such
  checks: (set-skip-meta-termp-checks nil). No trust tag is required
  in this case.

  This macro actually generates a [local] [table] event, for the table
  skip-meta-termp-checks-table and its unique key, t. The macro
  [set-skip-meta-termp-checks] generates a corresponding non-[local]
  [table] event.

    ACL2 !>:trans1 (set-skip-meta-termp-checks (f g))
     (LOCAL (SET-SKIP-META-TERMP-CHECKS! (F G)))
    ACL2 !>:trans1 (set-skip-meta-termp-checks! (f g))
     (TABLE SKIP-META-TERMP-CHECKS-TABLE T '(F G))
    ACL2 !>

  It is probably good practice to use set-skip-meta-termp-checks rather
  than set-skip-meta-termp-checks!, except when there is a compelling
  reason to do otherwise.")
 (SET-SKIP-META-TERMP-CHECKS!
  (META CLAUSE-PROCESSOR)
  "Skip output checks non-[local]ly for [meta] functions and
  [clause-processor]s

  See [set-skip-meta-termp-checks].")
 (SET-SPLITTER-OUTPUT
  (SPLITTER)
  "Turn on or off reporting of rules that may have caused case splits

    Examples:
    (set-splitter-output t)   ; enable  reports of ``splitter'' rules (default)
    (set-splitter-output nil) ; disable reports of ``splitter'' rules

  After evaluation of the form (set-splitter-output t) (the default),
  then whenever prove output is not inhibited (see
  [set-inhibit-output-lst]), ACL2 will report [rewrite] and
  [definition] rules that may have reduced a goal to more than one
  subgoal. See [splitter] for how to interpret such reports. We call
  such rules ``splitter rules'' for the goal that is being split.
  This information can be useful in deciding how to eliminate large
  splits, for example of Goal into Subgoal 1000 through Subgoal 1, by
  disabling some splitter rules. If you want to avoid the printing of
  such information, you can put the form (set-splitter-output t) in
  your customization file; see [ACL2-customization].

  Note that this command does not change the ACL2 [world]; it only
  modifies the [state]. More precisely, it sets a state global to the
  indicated value. (See [state] for discussion of the
  ``global-table'' of the state.) When prove output is enabled (see
  [set-inhibit-output-lst]), the value of that state global is the
  value of the form ([splitter-output]); otherwise the value of that
  form is nil.

  Again, see [splitter] for the effects of turning on the reporting of
  splitter rules.")
 (SET-STATE-OK
  (STATE)
  "Allow the use of STATE as a formal parameter

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.

  In brief: The variable symbol [state] has an unusual status in ACL2.
  In order to use it, you either need to issue :set-state-ok t, as we
  explain below, or you need to declare it to be a [stobj], as
  explained elsewhere (see [declare-stobjs]). Now we explain in more
  detail.

  Because the variable symbol [state] denotes the ``current ACL2
  state,'' ACL2 treats the symbol very restrictively when it occurs
  as a formal parameter of a defined function. The novice user, who
  is unlikely to be aware of the special status of that symbol, is
  likely to be confused when error messages about STATE are printed
  in response to the innocent choice of that symbol as a formal
  variable. Therefore the top-level ACL2 loop can operate in a mode
  in which [state] is simply disallowed as a formal parameter.

  For a discussion of STATE, See [state] and see [stobj]. Roughly
  speaking, at the top-level, the ``current ACL2 state'' is denoted
  by the variable symbol STATE. Only the current state may be passed
  into a function expecting a state as an argument. Furthermore, the
  name of the formal parameter into which the current state is passed
  must be STATE and nothing but the current state may be passed into
  a formal of that name. Therefore, only certain access and change
  functions can use that formal --- namely those with a STATE formal
  --- and if any such function produces a new state it becomes the
  ``current state'' and must be passed along in the STATE position
  thereafter. Thus, ACL2 requires that the state be single-threaded.
  This, in turn, allows us to represent only one state at a time and
  to produce new states from it destructively in a von Neumaneque
  fashion. The syntactic restrictions on the variable STATE are
  enforced by the translate mechanism (see [trans] and see [term])
  when terms are read.

  To prevent the novice user from seeing messages prohibiting certain
  uses of the variable symbol STATE ACL2 has a mode in which it
  simply disallows the use of that symbol as a formal parameter. Use
  of the symbol causes a simple error message. The system is
  initially in that mode.

  To get out of that mode, execute:

    :set-state-ok t ;;; or, (set-state-ok t)

  It is not recommended that you do this until you have read the
  documentation of [state].

  To enter the mode in which use of state is prohibited as a formal
  parameter, do:

    :set-state-ok nil

  The mode is stored in the defaults table, See [ACL2-defaults-table].
  Thus, the mode may be set [local]ly in books.")
 (SET-TAU-AUTO-MODE
  (TAU-SYSTEM)
  "Turn on or off automatic (``greedy'') generation of :tau-system rules

    Examples:
    (set-tau-auto-mode t)      ; select automatic (``greedy'') mode
    (set-tau-auto-mode nil)    ; select manual mode

  This event is equivalent to (table acl2-defaults-table
  :tau-auto-modep ), and hence is [local] to any [books]
  and [encapsulate] [events] in which it occurs; see
  [ACL2-defaults-table]. See [introduction-to-the-tau-system] for
  background details.

  The tau system gathers rules for its database in one of two ways:
  greedily or only at the explicit command of the user. ``Greedy''
  mode is officially called ``automatic mode'' and is the default.
  The other mode is called ``manual mode.''

  In automatic mode, all rules processed by ACL2 are also considered
  for inclusion in the tau database: if the :corollary of some proved
  theorem happens to fit into one of the forms described in
  :[tau-system], that rule is quietly added to the tau database
  regardless of what :[rule-classes] the user named for the
  :corollary. Of course, such rules are also stored in the ways named
  by the user. See the Design Philosophy section of
  [introduction-to-the-tau-system] for a discussion of why the tau
  system is greedy by default. More details are given on automatic
  mode after we explain manual mode.

  To more tightly control the rules available to the tau system, the
  user may select manual mode by executing (set-tau-auto-mode nil).
  In manual mode, the only events that create :tau-system rules are
  defthm events explicitly specifying the :[tau-system] rule class in
  the :[rule-classes] argument. Of course, for a :tau-system rule to
  be created from a proved formula (or its specified :corollary), the
  formula must be of the appropriate shape (syntactic form). See
  [tau-system]. In manual mode, if the :tau-system rule class is
  specified but the formula is not of an appropriate form an error is
  signalled. (Note: even in manual mode, monadic functions that are
  recognized as Boolean are classified as tau predicates; but no
  rules are created for them.)

  Returning to our discussion of automatic mode, a :[tau-system] rule
  may be created by any of the events below, provided the definition
  or formula proved is of an appropriate shape:

  (1) defun events introducing ``big switch'' or ``mv-nth synonyms,''

  (2) defun events creating type-prescription rules that may be also
  represented as ``signature rules'' of form 1, and

  (3) any defthm event with a non-nil :rule-classes argument if no
  :tau-system rule is among the rule classes and the formula proved
  is in the shape of any tau-system rule.

  Of course, events such as [defstobj] and [defevaluator] may also add
  rules to the tau database when they execute the [defun] and
  [defthm] events implicit in their descriptions. See [tau-system]
  for a description of the various shapes mentioned above.

  Note that any rule (of any rule class) created when the tau system is
  in manual mode is also created in automatic mode. For example, if
  an event would create a :DEFINITION, :TYPE-PRESCRIPTION,
  FORWARD-CHAINING, or :REWRITE rule when the tau system is in manual
  mode, then the event will create that same rule when the tau system
  is in automatic mode. Automatic mode just means that some
  additional :tau-system rules may be created.

  Of course, if a defthm event explicitly specifies a :tau-system rule
  class, then even if the tau system is in automatic mode, that tau
  rule is created from the proved formula (or the specified
  :corollary) or else an error is caused. But if the tau system is in
  automatic mode and a defthm event doesn't explicitly specify a
  :tau-system rule class, then the system quietly checks each
  specified :corollary --- or, in the absence of any :corollary, it
  checks the proved formula --- for whether it can be stored as a tau
  rule. If so, then the system stores a tau rule, in addition to
  storing the specified rule. Of course, no error is signalled if a
  proved formula of some non-:tau-system rule class fails to be of an
  appropriate shape for the tau system.

  In automatic mode, if the :rule-classes specified for defthm included
  several corollaries and any one of them is of class :tau-system
  then the only tau system rules created are those explicitly classed
  as :tau-system rules. For example, suppose a defthm has one
  :corollary stored as a :rewrite rule and another :corollary stored
  as a :tau-system rule. But suppose the :rewrite rule happens to
  also to fit the form of a :tau-system rule. Is it added to the tau
  database or not? The answer is no. If you have taken the trouble to
  specify :tau-system corollaries for an event, then those
  corollaries are the only ones stored as tau sytem rules from that
  event. Note that had both corollaries been classed as :rewrite
  rules (and been of acceptable :tau-system form) both would have
  also been made :tau-system rules. This also allows you be in
  automatic mode and state a :rewrite or other non-:tau-system rule
  and prevent it from being also made a tau system rule: just add a
  frivolous :tau-system :corollary like (booleanp (integerp x)).

  Recall that the use of tau rules is controlled by the rune
  (:EXECUTABLE-COUNTERPART TAU-SYSTEM). When that rune is disabled,
  no tau rules are used in proofs. However, the tau system continues
  to collect tau rules if the system is in automatic mode. Thus, if
  and when the tau system is re-enabled, rules automatically
  generated while the tau system was disabled will be used as usual
  by the tau system.

  Finally, note that defthm events with :rule-classes nil do not create
  :tau-system rules even if the formula proved is of an appropriate
  shape, regardless of whether the tau system is in automatic or
  manual mode.

  The macro [tau-status] provides a convenient way to enable/disable
  the :[executable-counterpart] of tau-system and/or to switch
  between manual and automatic modes. It may also be used to
  determine the current settings of those two flags.")
 (SET-TOTAL-PARALLELISM-WORK-LIMIT
  (PARALLELISM)
  "For ACL2(p): set thread limit for parallelism primitives

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].
  While the most common use of the limit described below is in
  parallel proof (see [parallel-proof]), it also applies to all
  parallelism primitives (see [parallel-programming]) except
  [spec-mv-let] --- though we expect that rather few programming
  applications will encouter this limit.

    General Forms:
    (set-total-parallelism-work-limit :none)     ; disable the limit
    (set-total-parallelism-work-limit ) ; set limit to 

  See [parallelism-tutorial], Section ``Another Granularity Issue
  Related to Thread Limitations'', for an explanation of how the host
  Lisp can run out of threads. Also see
  [set-total-parallelism-work-limit-error].

  If the underlying runtime system (the Operating System, the host
  Lisp, etc.) is unable to provide enough threads to finish executing
  the parallelism work given to it, the runtime system can crash in a
  very unpleasant manner (ranging from a Lisp error to completely
  freezing the machine). To avoid this unpleasantness, ACL2(p) will
  attempt to avoid creating so much parallelism that the runtime
  system crashes.

  ACL2 initially uses a conservative estimate to limit the number of
  threads. To tell ACL2(p) to use a different limit, call
  set-total-parallelism-work-limit with the new limit. For example,
  if the current default limit is 10,000, then to allow 13,000
  threads to exist, issue the following form at the top level.

    (set-total-parallelism-work-limit 13000)

  To disable this limit altogether, evaluate the following form:

    (set-total-parallelism-work-limit :none)

  The default value of total-parallelism-work-limit can be found by
  calling function default-total-parallelism-work-limit. If the
  default value is too high for your system please notify the ACL2
  maintainers with a limit that does work for your system, as they
  might then lower the default limit.")
 (SET-TOTAL-PARALLELISM-WORK-LIMIT-ERROR
  (PARALLELISM)
  "For ACL2(p): control the action taken when the thread limit is
  exceeded

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

    General Forms:
    (set-total-parallelism-work-limit-error t)   ; cause error (default)
    (set-total-parallelism-work-limit-error nil) ; disable error and
                                                 ; continue serially

  See [parallelism-tutorial], Section ``Another Granularity Issue
  Related to Thread Limitations'', for an explanation of how the host
  Lisp can run out of threads. See [set-total-parallelism-work-limit]
  for further details, including an explanation of how to manage the
  limit that triggers this error.

  The value of state global total-parallelism-work-limit-error dictates
  what occurs when the underlying runtime system runs reaches a limit
  on the number of threads for parallel computation. By default, when
  this limit is reached, the ACL2(p) user will receive an error and
  computation will halt. At this point, the ACL2(p) user has the
  following options.

  (1) Remove the limit by evaluating the following form.

    (set-total-parallelism-work-limit :none)

  (2) Disable the error so that execution continues serially once the
  available thread resources have been exhausted.

    (set-total-parallelism-work-limit-error nil)

  (3) Increase the limit on number of threads that ACL2(p) is willing
  to create, in spite of potential risk (see
  [set-total-parallelism-work-limit]). In this case, the following
  query returns the current limit.

    (f-get-global 'total-parallelism-work-limit)

  Then to increase that limit, evaluate the following form:

    (set-total-parallelism-work-limit )

  For example, suppose that the value of total-parallelism-work-limit
  was originally 10,000. Then evaluation of the following form
  increases that limit to 13,000.

    (set-total-parallelism-work-limit 13000)")
 (SET-TRACE-EVISC-TUPLE
  (TRACE)
  "Set the trace evisc tuple

  A trace evisc-tuple, which is set by this utility, provides a means
  to restrict printing during tracing. See [evisc-tuple] for an
  introduction to evisc-tuples; also see [set-evisc-tuple] and see
  [set-iprint].

  By default the ACL2 [trace] mechanism, [trace$], automatically deals
  with stobjs, the logical world, and certain other large structures.
  See [trace$], in particular the documentation of trace$ option
  :hide. However, even with that default behavior you may want to
  restrict what is printed according to the print-level and
  print-length of an evisc-tuple; see [evisc-tuple].

    Examples:

    ; Set trace evisc tuple to a standard value, using current Lisp *print-level*
    ; and *print-length* variables:
    (set-trace-evisc-tuple t state)

    ; Set trace evisc tuple back to its default:
    (set-trace-evisc-tuple nil state)

    ; Set trace evisc tuple to restrict print-level to 3 and print-length to 4,
    ; while hiding the logical world and suitably printing stobjs even if trace$
    ; option ``:hide nil'' is used.  (Note: calling trace-evisceration-alist
    ; directly requires removing this function as `untouchable', which requires a
    ; trust tag; see [remove-untouchable].)
    (set-trace-evisc-tuple
     (evisc-tuple 3 4 (trace-evisceration-alist state) nil)
     state)

    General Forms:

    (set-trace-evisc-tuple nil state) ; trace evisc-tuple set to standard value
    (set-trace-evisc-tuple   t state) ; trace evisc-tuple set to hide the logical
                                      ;   world and deal with stobjs even when
                                      ;   trace$ option ``:hide nil'' is supplied
    (set-trace-evisc-tuple evisc-tuple state)
                                      ; tracing set to use indicated evisc-tuple

  See [trace$] for a discussion of ACL2 tracing. The [evisc-tuple] used
  by that trace utility is the one last installed by
  set-trace-evisc-tuple (or by [set-evisc-tuple] for the
  trace-evisc-tuple) --- initially to the default of nil --- unless
  overriden by trace option :evisc-tuple.

  Remark. If you use value t, then ACL2 will ensure that the logical
  world and stobjs are kept up-to-date in the trace evisc-tuple.")
 (SET-VERIFY-GUARDS-EAGERNESS
  (GUARD)
  "The eagerness with which [guard] verification is tried.

    Example Forms:                        try guard verification?
    (set-verify-guards-eagerness 0) ; no, unless :verify-guards t
    (set-verify-guards-eagerness 1) ; yes if a guard or type is supplied
    (set-verify-guards-eagerness 2) ; yes, unless :verify-guards nil

  Note: This is an event! It does not print the usual event summary but
  nevertheless changes the ACL2 logical [world] and is so recorded.

    General Form:
    (set-verify-guards-eagerness n)

  where n is a variable-free term that evaluates to 0, 1, or 2. This
  macro is essentially equivalent to

    (table acl2-defaults-table :verify-guards-eagerness n)

  and hence is [local] to any [books] and [encapsulate] [events] in
  which it occurs; see [ACL2-defaults-table]. However, unlike the
  above simple call of the [table] event function (see [table]), no
  output results from a set-verify-guards-eagerness event.

  Set-verify-guards-eagerness may be thought of as an event that merely
  sets a flag to 0, 1, or 2. The flag is used by certain [defun]
  [events] to determine whether [guard] verification is tried. The
  flag is irrelevant to those [defun] [events] in :[program] mode and
  to those [defun] [events] in which an explicit :[verify-guards]
  setting is provided among the [xargs]. In the former case, [guard]
  verification is not done because it can only be done when logical
  functions are being defined. In the latter case, the explicit
  :[verify-guards] setting determines whether [guard] verification is
  tried. So consider a :[logic] mode [defun] in which no
  :[verify-guards] setting is provided. Is [guard] verification
  tried? The answer depends on the eagerness setting as follows. If
  the eagerness is 0, [guard] verification is not tried. If the
  eagerness is 1, it is tried if and only if a guard is explicitly
  specified in the [defun], in the following sense: there is an xargs
  keyword :guard or :stobjs or a [type] declaration. If the eagerness
  is 2, [guard] verification is tried.

  The default behavior of the system is as though the
  :verify-guards-eagerness is 1. The current behavior can be
  ascertained by evaluating the form (default-verify-guards-eagerness
  (w state)).")
 (SET-WATERFALL-PARALLELISM
  (PARALLELISM)
  "For ACL2(p): configuring the parallel execution of the waterfall

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

    General Forms:
    (set-waterfall-parallelism nil)        ; never parallelize (serial execution)
    (set-waterfall-parallelism :full)      ; always parallelize
    (set-waterfall-parallelism :top-level) ; parallelize top-level subgoals
    (set-waterfall-parallelism             ; parallelize if sufficient resources
      :resource-based)                     ;   (recommended setting)
    (set-waterfall-parallelism t)          ; alias for :resource-based
    (set-waterfall-parallelism             ; parallelize if sufficient resources
      :resource-and-timing-based           ;   and suggested by prior attempts
    (set-waterfall-parallelism             ; never parallelize but use parallel
      :pseudo-parallel)                    ;   code base (a debug mode)

  Set-waterfall-parallelism evaluates its argument, which specifies the
  enabling or disabling of the [parallel] execution of ACL2's main
  proof process, the waterfall.

  It also sets [state] global waterfall-printing to an appropriate
  value. See [set-waterfall-printing].

  Note that not all ACL2 features are supported when
  waterfall-parallelism is set to non-nil (see
  [unsupported-waterfall-parallelism-features]).

  A value of t is treated the same as a value of :resource-based and is
  provided for user convenience.

  :Resource-based waterfall parallelism typically achieves the best
  performance in ACL2(p), while maintaining system stability, so
  :resource-based (or equivalently, t) is the recommended value.

  A value of nil indicates that ACL2(p) should never prove subgoals in
  parallel.

  A value of :full indicates that ACL2(p) should always prove
  independent subgoals in parallel.

  A value of :top-level indicates that ACL2(p) should prove each of the
  top-level subgoals in parallel but otherwise prove subgoals in a
  serial manner. This mode is useful when the user knows that there
  are enough top-level subgoals, many of which take a non-trivial
  amount of time to be proved, such that proving them in parallel
  will result in a useful reduction in overall proof time.

  A value of :resource-based (or equivalently, t) indicates that
  ACL2(p) should use its built-in heuristics to determine whether CPU
  core resources are available for parallel execution. Note that
  ACL2(p) does not hook into the operating system to determine the
  workload on the machine. ACL2(p) works off the assumption that it
  is the only process using significant CPU resources, and it
  optimizes the amount of parallelism based on the number of CPU
  cores in the system. (Note that ACL2(p) knows how to obtain the
  number of CPU cores from the operating system in CCL, but that, in
  SBCL and in Lispworks, a constant is used instead).

  During the first proof attempt of a given conjecture, a value of
  :resource-and-timing-based results in the same behavior as with
  :resource-based. However, on subsequent proof attempts, the time it
  took to prove each subgoal will be considered when deciding whether
  to parallelize execution. If a particular theorem's proof is
  already achieving satisfactory speedup via :resource-based
  parallelism, there is no reason to try this setting. However, if
  the user wishes to experiment, the :resource-and-timing-based
  setting may improve performance. Note that since the initial run
  does not have the subgoal proof times available, this mode will
  never be better than the :resource-based setting for
  non-interactive theorem proving.

  A value of :pseudo-parallel results in using the parallel waterfall
  code, but with serial execution. This setting is useful for
  debugging the code base that supports parallel execution of the
  waterfall. For example, you may wish to use this mode if you are an
  ``ACL2 Hacker'' who would like to see comprehensible output from
  tracing (see [trace$]) the @par versions of the waterfall
  functions.

  The following remark pertains to those using [hons-enabled] ACL2
  executables, which are built by default. Since memoization is not
  supported when waterfall parallelism is enabled (see
  [unsupported-waterfall-parallelism-features]), then when
  set-waterfall-parallelism is called with a non-nil value, all
  memoized functions are unmemoized. When set-waterfall-parallelism
  is again called with a nil value, those memoization settings are
  restored.

  Set-waterfall-parallelism is an embedded event form. However, a call
  of this macro will not affect waterfall-parallelism when including
  a certified book that contains that call. For such an effect, you
  may use the following [make-event] form; also see
  [non-parallel-book].

    (make-event (er-progn (set-waterfall-parallelism :full)
                          (value '(value-triple nil)))
                :check-expansion t)

  To enable waterfall parallelism for book certification using ACL2(p),
  see [waterfall-parallelism-for-book-certification].")
 (SET-WATERFALL-PARALLELISM-HACKS-ENABLED
  (PARALLELISM)
  "For ACL2(p): enable waterfall-parallelism hacks

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

    General Forms:
    (set-waterfall-parallelism-hacks-enabled t)
    (set-waterfall-parallelism-hacks-enabled nil)

  Some features (e.g., [override-hints] and [clause-processor]s) of
  serial ACL2 are by default not available in ACL2(p) with waterfall
  parallelism enabled, because they offer a mechanism to modify
  [state] that is unsound. To allow or (once again) disallow the use
  the these features in ACL2(p), call
  set-waterfall-parallelism-hacks-enabled with argument t or nil,
  respectively.

  Set-waterfall-parallelism-hacks-enabled requires the use of a trust
  tag (see [defttag]). One can call
  [set-waterfall-parallelism-hacks-enabled!] instead, which will
  automatically install a trust tag named
  :waterfall-parallelism-hacks.

  See [error-triples-and-parallelism] for further related discussion.")
 (SET-WATERFALL-PARALLELISM-HACKS-ENABLED!
  (PARALLELISM)
  "For ACL2(p): enabling waterfall parallelism hacks

  See [set-waterfall-parallelism-hacks-enabled].")
 (SET-WATERFALL-PRINTING
  (PARALLELISM)
  "For ACL2(p): configuring the printing that occurs within the
  parallelized waterfall

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

    General Forms:
    (set-waterfall-printing :full)    ; print everything
    (set-waterfall-printing :limited) ; print a subset that's thought to be useful
    (set-waterfall-printing :very-limited) ; print an even smaller subset

  Set-waterfall-printing evaluates its argument, which indicates how
  much printing should occur when executing ACL2 with the
  parallelized version of the waterfall. It only affects the printing
  that occurs when parallelism mode is enabled for the waterfall (see
  [set-waterfall-parallelism]).

  A value of :full is intended to print the same output as in serial
  mode. This output will be interleaved unless the
  waterfall-parallelism mode is one of nil or :pseudo-parallel.

  A value of :limited omits most of the output that occurs in the
  serial version of the waterfall. Instead, the proof attempt prints
  key checkpoints (see [ACL2p-key-checkpoints]). The value of
  :limited also prints messages that indicate which subgoal is
  currently being proved, along with the wall-clock time elapsed
  since the theorem began its proof; and if state global
  'waterfall-printing-when-finished has a non-nil value, then such a
  message will also be printed at the completion of each subgoal. The
  function print-clause-id-okp may receive an attachment to limit
  such printing; see [set-print-clause-ids]. Naturally, these subgoal
  numbers can appear out of order, because the subgoals can be proved
  in parallel.

  A value of :very-limited is treated the same as :limited, except that
  instead of printing subgoal numbers, the proof attempt prints a
  period (`.') each time it starts a new subgoal.

  Note that this form cannot be used at the top level of a book, or of
  a [progn] or [encapsulate] event. Here is a workaround for use in
  such contexts; of course, you may replace :very-limited with any
  other legal argument for set-waterfall-printing.

    (make-event (er-progn (set-waterfall-printing :very-limited)
                          (value '(value-triple nil))))

  (For more about event contexts and the use of make-event, see
  [make-event], in particular the section ``Restriction to Event
  Contexts.'')

  The following form has the effect described above, except that it
  will affect waterfall-printing even when including a certified book
  that contains it.

    (make-event (er-progn (set-waterfall-printing :very-limited)
                          (value '(value-triple nil)))
                :check-expansion t)

  Note that set-waterfall-printing is automatically called by
  [set-waterfall-parallelism].

  To enable the printing of information when a subgoal is finished,
  assign a non-nil value to global waterfall-printing-when-finished.
  This can be accomplished by entering the following at the top
  level:

    (f-put-global 'waterfall-printing-when-finished t state)")
 (SET-WELL-FOUNDED-RELATION
  (DEFUN)
  "Set the default well-founded relation

    Examples:
    (set-well-founded-relation lex2)

  provided lex2 has been proved to be a well-founded relation (see
  [well-founded-relation]). Note: This is an event! It does not print
  the usual event summary but nevertheless changes the ACL2 logical
  [world] and is so recorded.

    General Form:
    (set-well-founded-relation rel)

  where rel has been proved to be a well-founded relation on objects
  satisfying some predicate, mp; see [well-founded-relation]. This
  macro is equivalent to (table acl2-defaults-table
  :well-founded-relation 'rel), and hence is [local] to any [books]
  and [encapsulate] [events] in which it occurs; see
  [ACL2-defaults-table].

  This event sets the default well-founded relation to be that imposed
  on mp-measures by the relation rel. Subsequently, if a recursively
  defined function is submitted to [defun] with no explicitly given
  :[well-founded-relation] argument, [defun] uses the default
  relation, rel, and the associated domain predicate mp used in its
  well-foundedness theorem. That is, the termination conditions
  generated will require proving that the measure used by the [defun]
  is an mp-measure and that in every recursive call the measure of
  the arguments decreases according to rel.")
 (SET-WORMHOLE-DATA
  (WORMHOLE)
  "Sets the wormhole data object in a wormhole status object

    General Form:  (set-wormhole-data whs data)

  See [wormhole]. Whs should be a well-formed wormhole status; data is
  arbitrary. This function returns a new status with the same entry
  code as whs but with the new data. It avoids unnecessary consing if
  the data for whs is already set to data. This function does not
  affect state or a wormhole's hidden status. It just returns a
  (possibly) new status object suitable as the value of the lambda
  expressions in [wormhole-eval] and [wormhole].")
 (SET-WORMHOLE-ENTRY-CODE
  (WORMHOLE)
  "Sets the wormhole entry code in a wormhole status object

    General Form:  (set-wormhole-entry-code whs code)

  See [wormhole]. Whs should be a well-formed wormhole status and code
  should be :ENTER or :SKIP. This function returns a new status with
  the specified entry code but the same data as whs. It avoids
  unnecessary consing if the entry code for whs is already set to
  code. This function does not affect state or a wormhole's hidden
  status. It just returns a (possibly) new status object suitable as
  the value of the lambda expressions in [wormhole-eval] and
  [wormhole].")
 (SET-WRITE-ACL2X
  (BOOKS-REFERENCE)
  "Cause [certify-book] to write out a .acl2x file

    Example Forms:
    (set-write-acl2x nil state)
    (set-write-acl2x t state)
    (set-write-acl2x '(nil) state) ; same as just above, but allow inclusion of
                                   ; uncertified books during certify-book
    (set-write-acl2x '(t) state)
    (set-write-acl2x '(include-book-with-locals) state)

    General Form:
    (set-write-acl2x val state)

  where val evaluates to t, nil, or a one-element list whose element is
  a legal value for the global 'ld-skip-proofsp; see
  [ld-skip-proofsp]. The value returned is an error triple, which in
  the non-error case is (mv nil v state), where v is the value of val
  and state is the result of updating the input [state] by assigning
  state global 'write-acl2x the value v.

  The command (set-write-acl2x val state) assigns the value of val to
  the [state] global variable 'write-acl2x, affecting whether or not
  [certify-book] writes out a file with extension acl2x, called a
  ``.acl2x file'' and pronounced ``dot-acl2x file''. Such a file is
  read or written by [certify-book] when it is supplied with keyword
  argument :acl2x t. By default, such a call of certify-book reads a
  .acl2x file; but if the value of state global variable 'write-acl2x
  is not nil, then certify-book writes a .acl2x file (in which case
  it is illegal to specify a non-nil value for [certify-book] keyword
  argument :pcert). Consider for example (certify-book \"foo\" 0 nil
  :acl2x t). By default, this command reads file foo.acl2x, which
  supplies replacements for some forms in foo.lisp, as described
  later below. But if the value of state global 'write-acl2x is not
  nil, then instead, this certify-book command writes such a file
  foo.acl2x.

  Before we discuss the function of .acl2x files, we first explain more
  about how a non-nil value of [state] global 'write-acl2x affects
  the behavior of a command (certify-book ... :acl2x t ...). A
  significant effect on the behavior is that after processing events
  in the given book, ACL2 writes out a .acl2x file and then returns,
  skipping the other subsequent actions typically performed by
  [certify-book]: a [local-incompatibility] check, writing of a
  [certificate] file, and possibly [compilation]. Another effect is
  that proofs may be skipped when processing [events] assuming that
  the the certify-book command does not explicitly specify
  :skip-proofs-okp nil, as we now explain. A non-nil value of
  'write-acl2x should either be t or a one-element list (x), where x
  is a legal value for the [state] global 'ld-skip-proofsp (see
  [ld-skip-proofsp]). In both cases, certify-book will process
  [events] to write out a .acl2x file as described above. But in the
  latter (list) case, event processing will take place according to
  the value of x: in particular, proofs will be skipped when x is not
  nil, and if moreover x is the symbol include-book-with-locals, then
  only one pass will be made through each [encapsulate] form. A third
  effect of a non-nil value of 'write-acl2x, which is restricted to
  the list case, is that [include-book] events encountered during
  event processing are allowed to succeed on uncertified books,
  something that is prohibited during most calls of [certify-book].

  When [certify-book] is used to write out a .acl2x file, there is
  typically a subsequent run of [certify-book] that reads that file.
  Consider how this can work with a book foo.lisp. In the first call
  of certify-book, a file foo.acl2x is written that contains all
  [make-event] expansions, but foo.cert is not written. In the second
  call of certify-book, no [make-event] expansion typically takes
  place, because foo.acl2x supplies the expansions. The command
  (set-write-acl2x t state) should be evaluated before the first
  certification (though another legal non-nil value may be used in
  place of t), setting the value of [state] global 'write-acl2x to t,
  to enable writing of foo.acl2x; and the command (set-write-acl2x
  nil state) may be evaluated before the second run (though this is
  not necessary in a fresh ACL2 session) in order to complete the
  certification (writing out foo.cert) using foo.acl2x to supply the
  [make-event] expansions.

  When [Certify-book] is supplied with keyword argument :acl2x t it
  will read or write the book's .acl2x file; when supplied with
  :acl2x nil, it will not read or write that .acl2x file. The value
  of :acl2x is nil by default. The interaction of [certify-book] with
  the corresponding .acl2x file is as follows.

    o If :acl2x is t, then:
      - If set-write-acl2x has been (most recently) called with a value of
        t for its first argument,then ACL2 writes the corresponding
        .acl2x file.
      - If set-write-acl2x has been (most recently) called with a value of
        nil for its first argument, or not called at all, then ACL2 insists
        on a corresponding .acl2x file that is at least as recent as the
        corresponding .lisp file, causing an error otherwise.
     o If :acl2x is nil,then:
      - If set-write-acl2x has been (most recently) called with a value
        t for its first argument, or if argument :ttagsx is supplied,
        then an error occurs.
      - If the .acl2x file exists, then regardless of whether or how
        set-write-acl2x has been called, ACL2 ignores the .acl2x file
        but issues a warning about it.

  Suppose you use the two-runs approach: first write a .acl2x file,
  then certify using (reading) that .acl2x file. Then with scripts
  such as makefiles, then you may wish to provide a single
  [certify-book] command to use for both runs. For that purpose,
  [certify-book] supports the keyword argument :ttagsx. If this
  argument is supplied and write-acl2x is true, then this argument is
  treated as the :ttags argument, overriding a :ttags argument if
  present. That is, for the two runs, :ttagsx may be used to specify
  the trust tags used in the first certification while :ttags
  specifies the trust tags, if any (else :ttags may be omitted), used
  in the second certification. Note: If the argument :ttagsx is not
  supplied, then its value defaults to the (explicit or default)
  value of the :ttags argument.

  The built-in ACL2 Makefile support automatically generates suitable
  dependencies if you create a .acl2 file with a [certify-book] call
  matching the following regular expression, case-independent:

    (certify-book[^;]*:acl2x t

  For an example .acl2 file with a certify-book call matching the above
  pattern, see community books file
  books/make-event/double-cert-test-1.acl2.

  Note that [include-book] is generally not affected by
  set-write-acl2x, other than through the indirect effect on
  [certify-book]. More precisely: All expansions are stored in the
  [certificate] file, so when [include-book] is applied to a
  certified book, the .acl2x file is not consulted.

  An example of how to put this all together may be found in community
  book books/make-event/double-cert-test-1.lisp. There, we see the
  following form.

    (make-event
     (progn (defttag :my-ttag)
            (progn! (let ((val (sys-call \"pwd\" nil)))
                      (value (list 'defun 'foo () val))))))

  Imagine that in place of the binding computed using [sys-call], which
  by the way requires a trust tag, is some computation of your choice
  (such as reading forms from a file) that is used to construct your
  own event, in place of the [defun] event constructed above. The
  Makefile in that directory contains the following added dependency,
  so that file double-cert-test-1.acl2x will be created:

    double-cert-test-1.cert: double-cert-test-1.acl2x

  There is also the file double-cert-test-1.acl2 in that directory,
  which contains a single form as follows.

    (certify-book \"double-cert-test-1\" ? t :ttagsx :all :ttags nil)

  Thus, a call of `make' first creates file double-cert-test-1.acl2x,
  which uses the above :ttagsx argument in order to support the use
  of [defttag] during [make-event] expansion. Then, `make' goes on to
  cause a second certification in which no trust tags are involved.
  As a result, the parent book double-cert-test.lisp is ultimately
  certified without requiring any trust tags.

  The discussion above is probably sufficient for most users of the
  two-run approach it describes. We conclude with further details for
  those who want more information. Those who wish to see a yet
  lower-level explanation of how all this works are invited to read
  the comment in the ACL2 source code entitled ``Essay on .acl2x
  Files (Double Certification).

  Consider the .acl2x file produced by the first run as described
  above. It contains a single expression, which is an association
  list whose keys are all positive integers, which occur in
  increasing order. When the .acl2x file is present and at least as
  recent as the corresponding .lisp file, then for a subsequent
  [certify-book] with argument :acl2x t and the (default) value of
  nil for [state] global 'write-acl2x, that association list will be
  applied to the top-level events in the book, as follows. Suppose
  the entry (n . ev) belongs to the association list in the .acl2x
  file. Then n is a positive integer, and the nth top-level event in
  the book --- where the 0th event is the initial [in-package] form
  --- will be replaced by ev. In practice, ev is the [make-event]
  expansion created during certification for the nth top-level event
  in the book; and this will always be the case if the .acl2x file is
  created by [certify-book] after execution of the form
  (set-write-acl2x t state). However, you are welcome to associate
  indices manually with any [events] you wish into the alist stored
  in the .acl2x file.

  Note: Also see the community book make-event/acl2x-help.lisp for a
  useful utility that can be used to skip proofs during the writing
  of .acl2x files.")
 (SETENV$
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Set an environment variable

  (Setenv$ str val), where str and val are strings, sets the
  environment variable str to have value val, for subsequent read by
  getenv$ (see [getenv$]), and returns nil. Or, if this operation is
  not implemented for the host Common Lisp, an error will occur.

    Example:
    (setenv$ \"FOO\" \"BAR\")

  It may be surprising that setenv$ returns nil; indeed, it neither
  takes nor returns the ACL2 [state]. The reason is that [getenv$]
  takes responsibility for trafficking in [state]; it is defined in
  the logic using the function [read-ACL2-oracle], which (again, in
  the logic) does modify state, by popping an entry from its
  acl2-oracle field. [getenv$].

  Function: 

    (defun setenv$ (str val)
           (declare (xargs :guard (and (stringp str) (stringp val))))
           (declare (ignore str val))
           nil)")
 (SEVENTH
  (NTH ACL2-BUILT-INS)
  "Seventh member of the list

  See any Common Lisp documentation for details.")
 (SHARP-BANG-READER
  (READER PACKAGES)
  "Package prefix that is not restricted to symbols

    Examples:

    ACL2 !>(defpkg \"FOO\" nil)

    Summary
    Form:  ( DEFPKG \"FOO\" ...)
    Rules: NIL
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     \"FOO\"
    ACL2 !>'#!foo(a b)
    (FOO::A FOO::B)
    ACL2 !>'#!foo(a #!acl2 b)
    (FOO::A B)
    ACL2 !>'#!foo(#!acl2 a b)
    (A FOO::B)
    ACL2 !>'#!foo(#!\"ACL2\" a b)
    (A FOO::B)
    ACL2 !>

  The ACL2 reader supports the syntax #!pkg-name expr where pkg-name is
  a string or symbol that names a package known to ACL2. As
  illustrated above, this syntax nests as one might expect. In the
  special case that expr is a symbol, #!pkg-name expr is equivalent
  to pkg-name::expr.")
 (SHARP-DOT-READER
  (READER DEFCONST)
  "Read-time evaluation of constants

    Example:

    ACL2 !>(defconst *a* '(a b c))

    Summary
    Form:  ( DEFCONST *A* ...)
    Rules: NIL
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     *A*
    ACL2 !>(quote (1 2 #.*a* 3 4))
    (1 2 (A B C) 3 4)
    ACL2 !>

  The ACL2 reader supports the syntax #.*a* where *a* was defined by
  [defconst]. In this case, the reader treats #.*a* as though it were
  reading the value of *a*. This feature can be useful in conjunction
  with the use of [evisc-table] to abbreviate large constants, so
  that the abbreviation can be read back in; see [evisc-table].

  Remarks.

  (1) The ACL2 reader only supports `#.' as described above, unlike
  Common Lisp. Older versions (preceding 3.5) used `#.' to abort, but
  that functionality is now carried out by (a!); see [a!]. For a
  related feature that only pops up one level, see [p!].

  (2) If you call [certify-book] on a book that contains a form
  `#.*foo*', the *foo* must already be defined in the [world] in
  which you issue the certify-book command. The reason is that
  certify-book reads the entire book before evaluating its forms.")
 (SHARP-U-READER
  (READER NUMBERS)
  "Allow underscore characters in numbers

    Example:

    ACL2 !>#ub1000_1000_1000_
    2184
    ACL2 !>#b100010001000
    2184
    ACL2 !>#uo1_1
    9
    ACL2 !>#o11
    9
    ACL2 !>#u34_5
    345
    ACL2 !>#u345
    345
    ACL2 !>345
    345
    ACL2 !>#ux12_a
    298
    ACL2 !>#ux12a
    298
    ACL2 !>#u x12a
    298
    ACL2 !>#x12a
    298
    ACL2 !>#u123_456/7_919
    123456/7919
    ACL2 !>

  The ACL2 reader supports the use of #ub, #uo, and #ux where one would
  otherwise write #b, #o, and #x, respectively (for binary, octal,
  and hexadecimal numerals), but where underscore characters (`_')
  are allowed but ignored. Also supported is the prefix #u in front
  of a an expression that is a decimal numeral except that underscore
  characteres are allowed but ignored.

  The precise specification of #u is as follows. The Lisp reader reads
  one expression after the #u. If the result is a number, then that
  number is returned by the reader. Otherwise the result must be a
  symbol whose name begins with one of the characters `B', `O', or
  `X', or else a decimal digit (one of the characters `0, 1, ...,
  9'). All underscores are removed from the name of that symbol to
  obtain a string and in the first three cases only, a `#' character
  is prepended to that string. The resulting string is then handed to
  the Lisp reader in order to obtain the final result, which must be
  a number or else an error occurs.")
 (SHOW-ACCUMULATED-PERSISTENCE (POINTERS)
                               "See [accumulated-persistence].")
 (SHOW-BDD
  (BDD)
  "Inspect failed BDD proof attempts

  Attempts to use BDDs (see [bdd]), using :[bdd] [hints], can fail for
  various reasons. Sometimes it is useful to explore such failures.
  To do so, one may simply execute the form

    (show-bdd)

  inside the ACL2 loop. The system's response is generally
  self-explanatory. Perhaps you have already seen show-bdd used in
  some examples (see [bdd-introduction] and see [if*]). Here we give
  some details about show-bdd.

  (Show-bdd) prints the goal to which the BDD procedure was applied and
  reports the number of nodes created during the [bdd] computation,
  followed by additional information depending on whether or not the
  computation ran to completion or aborted (for reasons explained
  elsewhere; see [bdd-algorithm]). If the computation did abort, a
  backtrace is printed that should be useful in understanding where
  the problem lies. Otherwise, (show-bdd) prints out ``falsifying
  constraints.'' This list of pairs associates [term]s with values
  and suggests how to construct a binding list for the variables in
  the conjecture that will falsify the conjecture. It also prints out
  the [term] that is the result of simplifying the input [term]. In
  each of these cases, parts of the object may be hidden during
  printing, in order to avoid creating reams of uninteresting output.
  If so, the user will be queried about whether he wishes to see the
  entire object (alist or [term]), which may be quite large. The
  following responses are legal:

      w --- Walk around the object with a structure editor

      t --- Print the object in full

      nil --- Do not print any more of the object

  Show-bdd actually has four optional arguments, probably rarely used.
  The general form is

    (show-bdd goal-name goal-ans falsifying-ans term-ans)

  where goal-name is the name of the goal on which the :[bdd] hint was
  used (or, nil if the system should find such a goal), goal-ans is
  the answer to be used in place of the query for whether to print
  the input goal in full, falsifying-ans is the answer to be used in
  place of the query for whether to print the falsifying constraints
  in full, and term-ans is the answer to be used in place of the
  query for whether to print the resulting [term] in full.")
 (SHOW-BODIES
  (DEFINITION)
  "Show the potential definition bodies

    Examples:
    (show-bodies foo)
    :show-bodies foo

  A definition made using [defun] installs a so-called ``body'' of a
  function symbol, as do certain :[definition] rules. Such bodies are
  used in a number of ways, including the application of :expand
  [hints]; see [definition], in particular the discussion of ``body''
  there, and see [hints] for a discussion of the :expand hint. Also
  see [set-body] for how to change which of the available definitions
  (among the original definition and appropriate :[definition] rules)
  is the one that provides the body. The show-bodies command displays
  the available such bodies in an appropriate format, starting with
  the one that is currently used as the body.

    General Forms:
    (show-bodies function-symbol)
    :show-bodies function-symbol")
 (SHOW-CUSTOM-KEYWORD-HINT-EXPANSION
  (CUSTOM-KEYWORD-HINTS)
  "Print out custom keyword hints when they are expanded

    Examples:
    (show-custom-keyword-hint-expansion t)
    (show-custom-keyword-hint-expansion nil)

    General Form:
    (show-custom-keyword-hint-expansion flg)

  If the value of flg is non-nil, then when custom keyword hints are
  expanded, the system prints the results of each expansion. This is
  sometimes useful for debugging custom keyword hints and, from time
  to time, may be useful in understanding how a custom hint affects
  some proof attempt.

  The default setting is nil.

  For an explanation of how custom keyword hints are processed, see
  [custom-keyword-hints].")
 (SHOW-FC-CRITERIA
  (FORWARD-CHAINING-REPORTS)
  "Print the forward-chaining tracking criteria

    Example:  (show-fc-criteria)

  This function prints the list of triples being used to determine what
  is tracked during forward chaining.

  See [forward-chaining-reports] for details.")
 (SIGNATURE
  (ENCAPSULATE)
  "How to specify the arity of a constrained function

  We start with a gentle introduction to signatures, where we pretend
  that there are no single-threaded objects (more on that below ---
  for now, if you don't know anything about single-threaded objects,
  that's fine!). Here are some simple examples of signatures.

    ((hd *) => *)
    ((pair * *) => *)
    ((foo * *) => (mv * * *))

  The first of these says that hd is a function of one argument, while
  the other two say that pair and foo are functions that each take
  two arguments. The first two say that hd and pair return a single
  value. The third says that foo returns three values, much as the
  following definition returns three values:

    (defun bar (x y)
      (mv y x (cons x y)))

  Corresponding ``old-style'' signatures are as follows. In each case,
  a function symbol is followed by a list of formal parameters and
  then either t, to denote a single value return, or (mv t t t), to
  denote a multiple value return (in this case, returning three
  values).

    (hd (x) t)
    (pair (x y) t)
    (foo (x y) (mv t t t))

  That concludes our gentle introduction. The documentation below is
  more general, for example covering single-threaded objects and
  keyword values such as :guard. When reading what follows below, it
  is sufficient to know about single-threaded objects (or ``stobjs'')
  that each has a unique symbolic name and that [state] is the name
  of the only built-in single-threaded object. All other stobjs are
  introduced by the user via [defstobj] or [defabsstobj]. An object
  that is not a single-threaded object is said to be ``ordinary.''
  For a discussion of single-threaded objects, see [stobj].

    Examples:
    ((hd *) => *)
    ((hd *) => * :formals (x) :guard (consp x))
    ((printer * state) => (mv * * state))
    ((mach * mach-state * state) => (mv * mach-state))

    General Form:
    ((fn ...) => *)
    ((fn ...) => stobj)
    or
    ((fn ...) => (mv ...))
    or for part1 and part2 as above,
    (part1 => part2 :kwd1 val1 ... :kwdn valn)

  where fn is the constrained function symbol, ... is a list of
  asterisks and/or the names of single-threaded objects, stobj is a
  single-threaded object name, and the optional :kwdi and :vali are
  as described below. ACL2 also supports an older style of signature,
  described below after we describe the preferred style.

  Signatures specify three syntactic aspects of a function symbol: (1)
  the ``arity'' or how many arguments the function takes, (2) the
  ``multiplicity'' or how many results it returns via MV, and (3)
  which of those arguments and results are single-threaded objects
  and which objects they are.

  A signature typically has the form ((fn x1 ... xn) => val). Such a
  signature has two parts, separated by the symbol ``=>''. The first
  part, (fn x1 ... xn), is suggestive of a call of the constrained
  function. The number of ``arguments,'' n, indicates the arity of
  fn. Each xi must be a symbol. If a given xi is the symbol ``*''
  then the corresponding argument must be ordinary. If a given xi is
  any other symbol, that symbol must be the name of a single-threaded
  object and the corresponding argument must be that object. No stobj
  name may occur twice among the xi.

  The second part, val, of a signature is suggestive of a term and
  indicates the ``shape'' of the output of fn. If val is a symbol
  then it must be either the symbol ``*'' or the name of a
  single-threaded object. In either case, the multiplicity of fn is 1
  and val indicates whether the result is ordinary or a stobj.
  Otherwise, val is of the form (mv y1 ... yk), where k > 1. Each yi
  must be either the symbol ``*'' or the name of a stobj. Such a val
  indicates that fn has multiplicity k and the yi indicate which
  results are ordinary and which are stobjs. No stobj name may occur
  twice among the yi, and a stobj name may appear in val only if
  appears among the xi.

  A signature may have the form ((fn x1 ... xn) => val . k), where k is
  a [keyword-value-listp], i.e., an alternating list of keywords and
  values starting with a keyword. In this case ((fn x1 ... xn) =>
  val) must be a legal signature as described above. The legal
  keywords in k are :GUARD and :FORMALS (except that for ACL2(r),
  also see the remark about :CLASSICALP later in this topic). The
  value following :FORMALS is to be the list of formal parameters of
  fn, while the value following :GUARD is a term that is to be the
  [guard] of fn. Note that this guard is never actually evaluated,
  and is not subject to the guard verification performed on functions
  introduced by [defun] (see [verify-guards]). Said differently: this
  guard need not itself have a guard of t. Indeed, the guard is only
  used for attachments; see [defattach]. Note that if :GUARD is
  supplied then :FORMALS must also be supplied (in order to related
  the variables occurring in the guard to the parameters of fn). One
  final observation about guards: if the :GUARD keyword is omitted,
  then the guard defaults to T.

  Before ACL2 supported user-declared single-threaded objects there was
  only one single-threaded object: ACL2's built-in notion of [state].
  The notion of signature supported then gave a special role to the
  symbol state and all other symbols were considered to denote
  ordinary objects. ACL2 still supports the old form of signature,
  but it is limited to functions that operate on ordinary objects or
  ordinary objects and state.

    Old-Style General Form:
    (fn formals result . k)

  where fn is the constrained function symbol, formals is a suitable
  list of formal parameters for it, k is an optional
  [keyword-value-listp] (see below), and result is either a symbol
  denoting that the function returns one result or else result is an
  [mv] expression, (mv s1 ... sn), where n>1, each si is a symbol,
  indicating that the function returns n results. At most one of the
  formals may be the symbol STATE, indicating that corresponding
  argument must be ACL2's built-in [state]. If state appears in
  formals then state may appear once in result. All ``variable
  symbols'' other than state in old style signatures denote ordinary
  objects, regardless of whether the symbol has been defined to be a
  single-threaded object name!

  The optional k is as described above for newer-style signatures,
  except that the user is also allowed to declare which symbols
  (besides state) are to be considered single-threaded object names.
  Thus :STOBJS is also a legal keyword. The form

    (fn formals result ... :stobjs names ...)

  specifies that names is either the name of a single-threaded object
  or else is a list of such names. Every name in names must have been
  previously defined as a stobj via [defstobj] or [defabsstobj].

  As promised above, we conclude with a remark about an additional
  keyword, :CLASSICALP, that is legal for ACL2(r) (see [real]). The
  value of this keyword must be t (the default) or nil, indicating
  respectively whether fn is classical or not.")
 (SIGNED-BYTE-P
  (NUMBERS ACL2-BUILT-INS)
  "Recognizer for signed integers that fit in a specified bit width

  (Signed-byte-p bits x) is T when bits is a positive integer and x is
  a signed integer whose 2's complement representation fits in a
  bit-width of bits, i.e., -2^(bits-1) <= x < 2^(bits-1).

  Note that a [type-spec] of (signed-byte i) for a variable x in a
  function's [declare] form translates to a [guard] condition of
  (signed-byte-p i x).

  The [guard] for signed-byte-p is T.

  Function: 

    (defun signed-byte-p (bits x)
           (declare (xargs :guard t))
           (and (integerp bits)
                (< 0 bits)
                (integer-range-p (- (expt 2 (1- bits)))
                                 (expt 2 (1- bits))
                                 x)))")
 (SIGNUM
  (NUMBERS ACL2-BUILT-INS)
  "Indicator for positive, negative, or zero

  (Signum x) is 0 if x is 0, -1 if x is negative, and is 1 otherwise.

  The [guard] for signum requires its argument to be rational ([real],
  in ACL2(r)) number.

  Signum is a Common Lisp function. See any Common Lisp documentation
  for more information.

  From ``Common Lisp the Language'' page 206, we see a definition of
  signum in terms of [abs]. As explained elsewhere (see [abs]), the
  [guard] for [abs] requires its argument to be a rational ([real],
  in ACL2(r)) number; hence, we make the same restriction for signum.

  Function: 

    (defun signum (x)
           (declare (xargs :guard (real/rationalp x)))
           (if (zerop x) 0 (if (minusp x) -1 1)))")
 (SIMPLE
  (REWRITE DEFINITION)
  ":[definition] and :[rewrite] rules used in preprocessing

    Example of simple rewrite rule:
    (equal (car (cons x y)) x)

    Examples of simple definition:
    (defun file-clock-p (x) (integerp x))
    (defun naturalp (x)
      (and (integerp x) (>= x 0)))

  The theorem prover output sometimes refers to ``simple'' definitions
  and rewrite rules. These rules can be used by the preprocessor,
  which is one of the theorem prover's ``processes'' understood by
  the :do-not hint; see [hints].

  The preprocessor expands certain definitions and uses certain rewrite
  rules that it considers to be ``fast''. There are two ways to
  qualify as fast. One is to be an ``abbreviation'', where a rewrite
  rule with no hypotheses or loop stopper is an ``abbreviation'' if
  the right side contains no more variable occurrences than the left
  side, and the right side does not call the functions [if], [not] or
  [implies]. Definitions and rewrite rules can both be abbreviations;
  the criterion for definitions is similar, except that the
  definition must not be recursive. The other way to qualify applies
  only to a non-recursive definition, and applies when its body is a
  disjunction or conjunction, according to a perhaps subtle criterion
  that is intended to avoid case splits.")
 (SINGLE-THREADED-OBJECTS (POINTERS)
                          "See [stobj].")
 (SIXTH
  (NTH ACL2-BUILT-INS)
  "Sixth member of the list

  See any Common Lisp documentation for details.")
 (SKIP-PROOFS
  (EVENTS)
  "Skip proofs for a given form --- a quick way to introduce unsoundness

    Example Form:
    (skip-proofs
      (defun foo (x)
        (if (atom x) nil (cons (car x) (foo (reverse (cdr x)))))))

    General Form:
    (skip-proofs form)

  where form is processed as usual except that the proof obligations
  usually generated are merely assumed.

  Normally form is an event; see [events]. If you want to put
  skip-proofs around more than one event, consider the following (see
  [progn]): (skip-proofs (progn event1 event2 ... eventk)).

  WARNING: Skip-proofs allows inconsistent [events] to be admitted to
  the logic. Use it at your own risk!

  Sometimes in the development of a formal model or proof it is
  convenient to skip the proofs required by a given event. By
  embedding the event in a skip-proofs form, you can avoid the proof
  burdens generated by the event, at the risk of introducing
  unsoundness. Below we list four illustrative situations in which
  you might find skip-proofs useful.

  1. The termination argument for a proposed function definition is
  complicated. You presume you could admit it, but are not sure that
  your definition has the desired properties. By embedding the
  [defun] event in a skip-proofs you can ``admit'' the function and
  experiment with theorems about it before undoing (see [ubt]) and
  then paying the price of its admission. Note however that you might
  still have to supply a measure. The set of formals used in some
  valid measure, known as the ``measured subset'' of the set of
  formals, is used by ACL2's induction heuristics and therefore needs
  to be suitably specified. You may wish to specify the special
  measure of (:? v1 ... vk), where (v1 ... vk) enumerates the
  measured subset.

  2. You intend eventually to verify the [guard]s for a definition but
  do not want to take the time now to pursue that. By embedding the
  [verify-guards] event in a skip-proofs you can get the system to
  behave as though the [guard]s were verified.

  3. You are repeatedly recertifying a book while making many
  experimental changes. A certain [defthm] in the book takes a very
  long time to prove and you believe the proof is not affected by the
  changes you are making. By embedding the [defthm] event in a
  skip-proofs you allow the theorem to be assumed without proof
  during the experimental recertifications.

  4. You are constructing a proof top-down and wish to defer the proof
  of a [defthm] until you are convinced of its utility. You can embed
  the defthm in a skip-proofs. Of course, you may find later (when
  you attempt prove the theorem) that the proposed defthm is not a
  theorem.

  Unsoundness or Lisp errors may result if the presumptions underlying
  a use of skip-proofs are incorrect. Therefore, skip-proofs must be
  considered a dangerous (though useful) tool in system development.

  Roughly speaking, a [defthm] embedded in a skip-proofs is essentially
  a [defaxiom], except that it is not noted as an axiom for the
  purposes of functional instantiation (see [lemma-instance]). But a
  skipped [defun] is much more subtle since not only is the
  definitional equation being assumed but so are formulas relating to
  termination and type. The situation is also difficult to
  characterize if the skip-proofs [events] are within the scope of an
  [encapsulate] in which constrained functions are being introduced.
  In such contexts no clear logical story is maintained; in
  particular, constraints aren't properly tracked for definitions. A
  proof script involving skip-proofs should be regarded as
  work-in-progress, not as a completed proof with some unproved
  assumptions. A skip-proofs event represents a promise by the author
  to admit the given event without further axioms. In other words,
  skip-proofs should only be used when the belief is that the proof
  obligations are indeed theorems in the existing ACL2 logical
  [world].

  ACL2 allows the certification of [books] containing skip-proofs
  [events] by providing the keyword argument :skip-proofs-okp t to
  the [certify-book] command. This is contrary to the spirit of
  certified [books], since one is supposedly assured by a valid
  [certificate] that a book has been ``blessed.'' But certification,
  too, takes the view of skip-proofs as ``work-in-progress'' and so
  allows the author of the book to promise to finish. When such
  [books] are certified, a warning to the author is printed,
  reminding him or her of the incurred obligation. When [books]
  containing skip-proofs are included into a session, a warning to
  the user is printed, reminding the user that the book is in fact
  incomplete and possibly inconsistent. This warning is in fact an
  error if :skip-proofs-okp is nil in the [include-book] form; see
  [include-book].

  We conclude with a technical note. Skip-proofs works by binding the
  [ld] special [ld-skip-proofsp] to t unless it is already bound to a
  non-nil value; see [ld-skip-proofsp].")
 (SLEEP
  (PROGRAMMING)
  "Sleep for some number of seconds

  The call (sleep n) returns nil. However, it takes approximately n
  seconds of real time for this call to return.

  The [guard] for sleep requires its argument to be a non-negative
  rational number.

  Sleep is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: 

    (defun sleep (n)
           (declare (xargs :guard (and (rationalp n) (<= 0 n))))
           (declare (ignore n))
           nil)")
 (SLOW-ALIST-WARNING
  (FAST-ALISTS)
  "Warnings issued when [fast-alists] are used inefficiently

  Obtaining hash-table performance from [hons-get] requires one to
  follow a certain discipline. If this discipline is violated, you
  may see a \"slow alist warning\". This warning means that the alist
  you are extending or accessing does not have a valid hash table
  associated with it, and hence any accesses must be carried out with
  [hons-assoc-equal] instead of gethash.

  You can control whether or not you get a warning and, if so, whether
  or not a break (an error from which you can continue) ensues. For
  instance:

    (set-slow-alist-action :warning)  ; warn on slow access (default)
    (set-slow-alist-action :break)    ; warn and also call break$
    (set-slow-alist-action nil)       ; do not warn or break

  The above forms expand to [table] [events], so they can be embedded
  in [encapsulate]s and [books], wrapped in [local], and so on.")
 (SLOW-ARRAY-WARNING
  (ARRAYS)
  "A warning or error issued when [arrays] are used inefficiently

  If you use ACL2 [arrays] you may sometimes see a slow array warning.
  We explain below what that warning means and some likely
  ``mistakes'' it may signify.

  First, we note that you can control whether or not you get a warning
  and, if so, whether or not a break (error from which you can
  continue; see [break$]) ensues:

    (assign slow-array-action :warning) ; warn on slow array access (default)
    (assign slow-array-action :break)   ; warn as above, and then call break$
    (assign slow-array-action nil) ; do not warn or break on slow array access

  If you are using ACL2 arrays, then you probably care about
  performance, in which case it is probably best to avoid the nil
  setting. Below we assume the default behavior: a warning, but no
  break.

  The discussion in the documentation for [arrays] defines what we mean
  by the semantic value of a name. As noted there, behind the scenes
  ACL2 maintains the invariant that with some names there is
  associated a pair consisting of an ACL2 array alist, called the
  semantic value of the name, and an equivalent raw lisp array.
  Access to ACL2 array elements, as in (aref1 name alist i), is
  executed in constant time when the array alist is the semantic
  value of the name, because we can just use the corresponding raw
  lisp array to obtain the answer. [Aset1] and [compress1] modify the
  raw lisp array appropriately to maintain the invariant.

  If [aref1] is called on a name and alist, and the alist is not the
  then-current semantic value of the name, the correct result is
  computed but it requires linear time because the alist must be
  searched. When this happens, [aref1] prints a slow array warning
  message to the comment window. [Aset1] behaves similarly because
  the array it returns will cause the slow array warning every time
  it is used.

  From the purely logical perspective there is nothing ``wrong'' about
  such use of [arrays] and it may be spurious to print a warning
  message. But because [arrays] are generally used to achieve
  efficiency, the slow array warning often means the user's
  intentions are not being realized. Sometimes merely performance
  expectations are not met; but the message may mean that the
  functional behavior of the program is different than intended.

  Here are some ``mistakes'' that might cause this behavior. In the
  following we suppose the message was printed by [aset1] about an
  array named name. Suppose the alist supplied [aset1] is alist.

  (1) [Compress1] was never called on name and alist. That is, perhaps
  you created an alist that is an [array1p] and then proceeded to
  access it with [aref1] but never gave ACL2 the chance to create a
  raw lisp array for it. After creating an alist that is intended for
  use as an array, you must do (compress1 name alist) and pass the
  resulting alist' as the array.

  (2) Name is misspelled. Perhaps the array was compressed under the
  name 'delta-1 but accessed under 'delta1?

  (3) An [aset1] was done to modify alist, producing a new array,
  alist', but you subsequently used alist as an array. Inspect all
  (aset1 name ...) occurrences and make sure that the alist modified
  is never used subsequently (either in that function or any other).
  It is good practice to adopt the following syntactic style. Suppose
  the alist you are manipulating is the value of the local variable
  alist. Suppose at some point in a function definition you wish to
  modify alist with [aset1]. Then write

    (let ((alist (aset1 name alist i val))) ...)

  and make sure that the subsequent function body is entirely within
  the scope of the [let]. Any uses of alist subsequently will refer
  to the new alist and it is impossible to refer to the old alist.
  Note that if you write

    (foo (let ((alist (aset1 name alist i val))) ...)  ; arg 1
         (bar alist))                                  ; arg 2

  you have broken the rules, because in arg 1 you have modified alist
  but in arg 2 you refer to the old value. An appropriate rewriting
  is to lift the [let] out:

    (let ((alist (aset1 name alist alist i val)))
      (foo ...                                         ; arg 1
           (bar alist)))                               ; arg 2

  Of course, this may not mean the same thing.

  (4) A function which takes alist as an argument and modifies it with
  [aset1] fails to return the modified version. This is really the
  same as (3) above, but focuses on function interfaces. If a
  function takes an array alist as an argument and the function uses
  [aset1] (or a subfunction uses [aset1], etc.), then the function
  probably ``ought'' to return the result produced by [aset1]. The
  reasoning is as follows. If the array is passed into the function,
  then the caller is holding the array. After the function modifies
  it, the caller's version of the array is obsolete. If the caller is
  going to make further use of the array, it must obtain the latest
  version, i.e., that produced by the function.")
 (SOLUTION-TO-SIMPLE-EXAMPLE
  (ANNOTATED-ACL2-SCRIPTS)
  "Solution to a simple example

  To see a statement of the problem solved below, see
  [annotated-ACL2-scripts] (in particular the end of that topic).

  Here is a sequence of ACL2 [events] that illustrates the use of ACL2
  to make definitions and prove theorems. We will introduce the
  notion of the fringe of a tree, as well as the notion of a leaf of
  a tree, and then prove that the members of the fringe are exactly
  the leaves.

  We begin by defining the fringe of a tree, where we identify trees
  simply as [cons] structures, with [atom]s at the leaves. The
  definition is recursive, breaking into two cases. If x is a [cons],
  then the fringe of x is obtained by appending together the fringes
  of the [car] and [cdr] (left and right child) of x. Otherwise, x is
  an [atom] and its fringe is the one-element list containing only x.

    (defun fringe (x)
      (if (consp x)
          (append (fringe (car x))
                  (fringe (cdr x)))
        (list x)))

  Now that fringe has been defined, let us proceed by defining the
  notion of an atom appearing as a ``leaf'', with the goal of proving
  that the leaves of a tree are exactly the members of its fringe.

    (defun leaf-p (atm x)
      (if (consp x)
          (or (leaf-p atm (car x))
              (leaf-p atm (cdr x)))
        (equal atm x)))

  The main theorem is now as follows. Note that the rewrite rule below
  uses the equivalence relation [iff] (see [equivalence]) rather than
  [equal], since [member] returns the tail of the given list that
  begins with the indicated member, rather than returning a Boolean.
  (Use :pe member to see the definition of [member].)

    (defthm leaf-p-iff-member-fringe
      (iff (leaf-p atm x)
           (member-equal atm (fringe x))))")
 (SPEC-MV-LET
  (PARALLEL-PROGRAMMING ACL2-BUILT-INS)
  "Modification of [mv-let] supporting speculative and parallel
  execution

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism],
  and see [parallel-programming], which has a disclaimer.

    Example Form:
    (defun pfib-with-step-count (x)
      (declare (xargs :mode :program))
      (if (or (zp x) (< x 33))
          (fib-with-step-count x)
        (spec-mv-let
         (a cnt1)
         (pfib-with-step-count (- x 1))
         (mv-let (b cnt2)
                 (pfib-with-step-count (- x 2))
                 (if t
                     (mv (+ a b)
                         (+ 1 cnt1 cnt2))
                   (mv \"speculative result is always needed\"
                       -1))))))

    General Form:
    (spec-mv-let
     (v1 ... vn)  ; bind distinct variables
            ; evaluate speculatively; return n values
     (mv-let      ; or, use mv?-let if k=1 below
      (w1 ... wk) ; bind distinct variables
           ; evaluate eagerly
      (if   ; use results from  if true
           ; may mention v1 ... vn
        )))  ; does not mention v1 ... vn

  Our design of spec-mv-let is guided by its use in ACL2 source code to
  parallelize part of ACL2's proof process, in the experimental
  parallel extension of ACL2. The user can think of spec-mv-let as a
  speculative version of [mv-let]. (In ordinary ACL2, the semantics
  agree with this description but without speculative or parallel
  execution.)

  Evaluation of the above general form proceeds as suggested by the
  comments. First,  is executed speculatively. Control then
  passes immediately to the [mv-let] call, without waiting for the
  result of evaluating . The variables (w1 ... wk) are bound to
  the result of evaluating , and then  is evaluated. If
  the value of  is true, then the values of (v1 ... vn) are
  needed, and  blocks until they are available. If the
  value of  is false, then the values of (v1 ... vn) are not
  needed, and the evaluation of  may be aborted.

  The calls to mv-let and to if displayed above in the General Form are
  an essential part of the design of spec-mv-let, and are thus
  required.

  The following definition of fib-with-step-count completes the example
  above:

    (defun fib-with-step-count (x)
    (declare (xargs :mode :program))
    (cond ((<= x 0)
           (mv 0 1))
          ((= x 1) (mv 1 1))
          (t (mv-let (a cnt1)
                     (fib-with-step-count (- x 1))
                     (mv-let (b cnt2)
                             (fib-with-step-count (- x 2))
                             (mv (+ a b)
                                 (+ 1 cnt1 cnt2)))))))")
 (SPECIAL-CASES-FOR-REWRITE-RULES
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Convenient short forms for rewrite rule formulas

  In principle, every rewrite rule is made from a formula of this
  shape:

    (IMPLIES (AND hyp1 ... hypk)
             (eqv lhs rhs))

  where eqv is either EQUAL or IFF and the result of expanding any
  abbreviations in lhs is the application of some function symbol
  other than IF.

  * In the special case where there is only one hyp term, i.e., k=1,
  the (AND hyp1) can be written hyp1.

  * In the special case where there are no hyp terms, k=0, the (AND)
  term is logically just T and the whole IMPLIES can be dropped; such
  a formula may be written as an unconditional EQUAL or IFF term.

  * If you build a rewrite rule from a formula that concludes with (NOT
  x), it is treated as though it were (EQUAL x NIL), which is
  logically equivalent to what you typed.

  * If you build a rewrite rule from a formula that concludes with an
  AND, ACL2 will build a rewrite rule for each conjunct of the AND.
  This is because

    (IMPLIES hyp (AND concl1 concl2))

  is propositionally equivalent to

    (AND (IMPLIES hyp concl1)
         (IMPLIES hyp concl2)).

  However, if you use an OR-expression as a hypothesis, ACL2 does not
  do the dual transformation. Thus, (IMPLIES (OR hyp1 hyp2) concl)
  generates one rewrite rule.

  * Finally, if you build a rewrite rule from a formula that does not
  conclude with an EQUAL, an IFF, a NOT, or an AND, but with some
  other term, say, lhs, then ACL2 acts like you typed (IFF lhs T),
  which is logically equivalent to what you typed.

  Thus, regardless of what you type, every rule has k hypotheses. For
  unconditional rules, k is 0 and the hypotheses are vacuously true.
  Whether or not you write an EQUAL or an IFF in the conclusion,
  every rule is either an equality or a propositional equivalence,
  every rule has a left-hand side, and every rule has a right-hand
  side.

  Use your browser's Back Button now to return to
  [introduction-to-rewrite-rules-part-1].")
 (SPECIFIC-KINDS-OF-FORMULAS-AS-REWRITE-RULES
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Advice about how to handle commonly occurring formulas as rewrite
  rules

  Below we give you some guidelines for handling specific, commonly
  occurring situations.

  * Associativity: If a function f is associative, prove

    (equal (f (f x y) z) (f x (f y z)))

  ACL2 will use this to flatten f-nests ``to the right.''

  * Commutativity: If a function f is commutative, prove both

    (equal (f x y) (f y x))

  and

    (equal (f x (f y z)) (f y (f x z)))

  ACL2's heuristics will use these rules to order the arguments
  alphabetically, so that (f B (f D (f A C))) becomes (f A (f B (f C
  D))).

  * Distributivity: If you have a pair of functions f and g so that (f
  x (g y z)) is (g (f x y) (f x z)) or some other form of
  distributivity is provable, arrange your rules to move the lighter
  function symbol up and the heavier one toward the variable symbols.
  For example, our arithmetic libraries drive multiplication through
  addition, producing sums of products rather than products of sums.

  * Identity and Other Laws: Prove the obvious identity and zero laws
  (or at least anticipate that you might need them down the road) so
  as to eliminate operators.

  * Get Rid of Tail Recursive Functions: A corollary to the above
  advice concerns tail recursive functions that use auxiliary
  variables. New users often define concepts using tail recursions,
  accumulating partial results in auxiliary variables, because
  creating such functions is similar to programming with while loops.
  Expert users will use tail recursion when necessary for execution
  efficiency. But tail recursive functions are messy to reason about:
  their auxiliary variables have to be properly initialized to make
  the functions compute the expected results, but to state
  inductively provable properties of tail recursive functions you
  must identify the invariants on those auxiliary variables. This
  problem tends not to happen with primitive recursive functions. A
  primitive recursive function is one that recurs down one variable
  and holds all the other variables constant in recursion. Most
  tail-recursive functions can be written elegantly as primitive
  recursive functions, though one might have to ignore the
  programmer's desire to make things efficient and define auxiliary
  functions to appropriately transform the value returned by the
  recursive call. The classic example is reverse defined in terms of
  the auxiliary function append versus reverse defined tail
  recursively with an accumulator. By introducing append you
  introduce a concept about which you can state lemmas and decompose
  the proofs of properties of reverse. So if your problem involves
  tail recursive functions with auxiliary variables, define the
  primitive recursive version, prove that the tail recursive function
  is equivalent to the primitive recursive one, and arrange the
  rewrite rule to eliminate the tail recursive function.

  * Get Rid of Mutually Recursive Functions: Similarly, if you have
  used mutual-recursion to introduce a clique of mutually recursive
  functions, f1, f2, ..., you will find that to reason about any one
  function in the nest you have to reason about all of them. Any
  mutually recursive function can be defined in a singly recursive
  way. So do that and then prove a rewrite rule that gets rid of all
  the mutually recursive functions by proving

    (and (equal (f1 ...) (g1 ...))
         (equal (f2 ...) (g2 ...))
         ...)

  where the gi are singly recursive. You may need to appeal to a trick
  to define the gi: define a singly recursive function that takes a
  flag argument and mimics whichever mutually recursive function the
  flag specifies. See [mutual-recursion] [{ICON}] and see
  [mutual-recursion-proof-example] [{ICON}].

  If you got to this documentation page from the tutorial discussion of
  rewrite rules, use your browser's Back Button now to return to
  [introduction-to-rewrite-rules-part-2].")
 (SPECIOUS-SIMPLIFICATION
  (MISCELLANEOUS)
  "Nonproductive proof steps

  Occasionally the ACL2 theorem prover reports that the current goal
  simplifies to itself or to a set including itself. Such
  simplifications are said to be ``specious'' and are ignored in the
  sense that the theorem prover acts as though no simplification were
  possible and tries the next available proof technique. Specious
  simplifications are almost always caused by forcing.

  The simplification of a formula proceeds primarily by the local
  application of :[rewrite], :[type-prescription], and other rules to
  its various subterms. If no rewrite rules apply, the formula cannot
  be simplified and is passed to the next ACL2 proof technique, which
  is generally the elimination of destructors. The experienced ACL2
  user pays special attention to such ``maximally simplified''
  formulas; the presence of unexpected terms in them indicates the
  need for additional rules or the presence of some conflict that
  prevents existing rules from working harmoniously together.

  However, consider the following interesting possibility: local
  rewrite rules apply but, when applied, reproduce the goal as one of
  its own subgoals. How can rewrite rules apply and reproduce the
  goal? Of course, one way is for one rule application to undo the
  effect of another, as when commutativity is applied twice in
  succession to the same term. Another kind of example is when two
  rules conflict and undermine each other. For example, under
  suitable hypotheses, (length x) might be rewritten to (+ 1 (length
  (cdr x))) by the :[definition] of [length] and then a :[rewrite]
  rule might be used to ``fold'' that back to (length x). Generally
  speaking the presence of such ``looping'' rewrite rules causes
  ACL2's simplifier either to stop gracefully because of heuristics
  such as that described in the documentation for [loop-stopper] or
  to cause a stack overflow because of indefinite recursion.

  A more insidious kind of loop can be imagined: two rewrites in
  different parts of the formula undo each other's effects ``at a
  distance,'' that is, without ever being applied to one another's
  output. For example, perhaps the first hypothesis of the formula is
  simplified to the second, but then the second is simplified to the
  first, so that the end result is a formula propositionally
  equivalent to the original one but with the two hypotheses
  commuted. This is thought to be impossible unless forcing or
  case-splitting occurs, but if those features are exploited (see
  [force] and see [case-split]) it can be made to happen relatively
  easily.

  Here is a simple example. Declare foo to be a function of one
  argument returning one result:

    (defstub p1 (x) t)

  Prove the following silly rule:

    (defthm bad
      (implies (case-split (p1 x))
               (p1 x)))

  Now suppose we try the following.

    (thm (p1 x))

  The [rewrite] rule bad will rewrite (p1 x) to t, but it will be
  unable to prove the hypothesis (case-split (p1 x)). As a result,
  the prover will spawn a new goal, to prove (p1 x). However, since
  this new goal is the same as the original goal, ACL2 will recognize
  the simplification as specious and consider the attempted
  simplification to have failed.

  In other words, despite the rewriting, no progress was made! In more
  common cases, the original goal may simplify to a set of subgoals,
  one of which includes the original goal.

  If ACL2 were to adopt the new set of subgoals, it would loop
  indefinitely. Therefore, it checks whether the input goal is a
  member of the output subgoals. If so, it announces that the
  simplification is ``specious'' and pretends that no simplification
  occurred.

  ``Maximally simplified'' formulas that produce specious
  simplifications are maximally simplified in a very technical sense:
  were ACL2 to apply every applicable rule to them, no progress would
  be made. Since ACL2 can only apply every applicable rule, it cannot
  make further progress with the formula. But the informed user can
  perhaps identify some rule that should not be applied and make it
  inapplicable by disabling it, allowing the simplifier to apply all
  the others and thus make progress.

  When specious simplifications are a problem it might be helpful to
  [disable] all forcing (including [case-split]s) and resubmit the
  formula to observe whether forcing is involved in the loop or not.
  See [force]. The commands

    ACL2 !>:disable-forcing
    and
    ACL2 !>:enable-forcing

  [disable] and [enable] the pragmatic effects of both force and
  case-split. If the loop is broken when forcing is [disable]d, then
  it is very likely some [force]d hypothesis of some rule is
  ``undoing'' a prior simplification. The most common cause of this
  is when we [force] a hypothesis that is actually false but whose
  falsity is somehow temporarily hidden (more below). To find the
  offending rule, compare the specious simplification with its
  non-specious counterpart and look for rules that were speciously
  applied that are not applied in the non-specious case. Most likely
  you will find at least one such rule and it will have a [force]d
  hypothesis. By disabling that rule, at least for the subgoal in
  question, you may allow the simplifier to make progress on the
  subgoal.")
 (SPLIT-TYPES (POINTERS)
              "See [xargs] for keyword :split-types.")
 (SPLITTER
  (DEBUGGING)
  "Reporting of rules whose application may have caused case splits

  The application of a rule to a term may cause a goal to simplify to
  more than one subgoal. A rule with such an application is called a
  ``splitter''. Here, we explain the output produced for splitters
  when proof output is enabled (see [set-inhibit-output-lst]) and
  such reporting is turned on (as it is by default) --- that is, when
  the value of ([splitter-output]) is true.

  See [set-splitter-output] for how to turn off, or on, the reporting
  of splitters. Also see [set-case-split-limitations] for information
  on how to control case splits. Note that since splitters are rule
  applications, splitter output is not generated for case splits that
  are caused by other than rules, such as the mere presence of calls
  of the function symbol, [if], in the goal.

  We begin by describing three types of splitters.

      if-intro: The rule application may have introduced a call of IF, in
      the sense discussed at the end below.

      case-split: For the application of a rule with hypothesis of the form
      (case-split ),  did not simplify to true or false.

      immed-forced: For the application of a rule with hypothesis of the
      form (force ),  did not simplify to true or false,
      where immediate-force-modep is enabled (see
      [immediate-force-modep]).

  These three annotations --- if-intro, case-split, and immed-forced
  --- may be used in proof output and summaries for describing rule
  applications, as discussed below. A fourth annotation, forced, may
  also be used in proof output to indicate the application of a rule
  with hypothesis of the form (force ) when  did not
  simplify to true or false, where immediate-force-modep is disabled
  (see [immediate-force-modep]). We don't consider such uses of
  [force] to be splitters, because they do not cause case splits
  (though they do produce goals to prove after lower-case ``q.e.d.''
  is printed); see [force].

  There are three kinds of output affected by splitters, illustrated in
  turn below using examples.

      (a) During the proof, [gag-mode] off
      (b) During the proof, [gag-mode] on
      (c) Summary

  Of course, (a) and (b) are skipped if proof output is inhibited,
  which (c) is skipped if summary output is inhibited; see
  [set-inhibit-output-lst].

  (a) During the proof, [gag-mode] off

  With [gag-mode] off (or when using :[pso], :[psof], or :[psog]) one
  normally gets an English commentary. The following output indicates
  that at least one application of each rule F and G is of type
  if-intro, at least one application of rules G and R1 are of type
  case-split, and at least one application of rule R3 is of type
  immed-forced. If [immediate-force-modep] is off then
  ``immed-forced'' would be replaced by ``forced''.

    This simplifies, using the :definitions F (if-intro), G (case-split and
    if-intro) and H and the :rewrite rules R1, R2 (case-split), and
    R3 (immed-forced), to the following two conjectures.

  Note that any such printing of ``forced'' is done even if
  (splitter-output) is false. Such forcing indication is also made
  when raw proof format is used --- see [set-raw-proof-format] ---
  but in that case, no indication is made for splitters in the proof
  output.

  (b) During the proof, [gag-mode] on

  With [gag-mode] on the proof output is greatly abbreviated. However,
  ``Splitter Notes'' are printed so that even with [gag-mode] on, one
  can get important information to help control large case splits, by
  disabling splitter rules as appropriate. These are printed at the
  point when a goal splits into subgoals. Here, for example, is the
  Splitter Note that corresponds to the output shown in (a) above. It
  shows the goal whose simplification has produced a split into more
  than one subgoal, and it shows how many subgoals have been created.

    Splitter note (see :DOC splitter) for Subgoal *1/2.2.1' (2 subgoals).
      case-split: ((:DEFINITION G) (:REWRITE R2))
      immed-forced: ((:REWRITE R3))
      if-intro: ((:DEFINITION G) (:DEFINITION F))

  No such splitter notes are printed for the use of [force] (when
  [immediate-force-modep] is off).

  (c) Summary

  Here is a possible summary corresponding to our running example. In
  the summary, ``Splitter rules'' is omitted if there are no splitter
  rules, and a splitter type is only mentioned if there is at least
  one corresponding splitter rule.

    Summary
    Form:  ( THM ...)
    Rules: ((:DEFINITION F)
            (:DEFINITION G)
            (:DEFINITION H)
            (:REWRITE R1)
            (:REWRITE R2)
            (:REWRITE R3))
    Splitter rules (see :DOC splitter):
      case-split: ((:DEFINITION G) (:REWRITE R2))
      immed-forced: ((:REWRITE R3))
      if-intro: ((:DEFINITION G) (:DEFINITION F))
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.00)
    Prover steps counted:  145

  No indication for ``forced'' is given for ``Splitter rules''. (As
  discussed earlier above, the [force]d hypotheses are not considered
  relevant for determining splitter rule applications unless
  [immediate-force-modep] is on.)

  We conclude by giving the criteria for a [rewrite] or [definition]
  rule application to be a splitter of type if-intro.

    * Reporting of splitter rules is on, i.e., the value of
      ([splitter-output]) is true.
    * At least two subgoals are created, even before considering subgoals
      generated by hypotheses that are calls of [case-split] or
      [force].
    * The term to which the rule is applied is at the top level, rather
      than being encountered when trying to establish the hypothesis
      of a rule.
    * The rule is a [rewrite] rule, a [definition] rule, or a [meta] rule.
    * There is a call of the function symbol IF in the right-hand side of
      the [rewrite] rule; or, in the case of a [definition] rule, in
      the body of the definition; or, in the case of a [meta] rule,
      in the result of applying the metafunction.
    * There is a call of the function symbol IF in the result of rewriting:
      the right-hand side (for a [rewrite] rule), the definition body
      (for a [definition] rule), or the metafunction application (for
      a [meta] rule).

  Any rule application meeting the above criteria will be considered a
  splitter of type if-intro, even if the call does not actually cause
  a case split. For example, if you are proving (implies (hyp x)
  (conc x)) and rule R rewrites (hyp x) to (if (h1 x) (h2 x) nil),
  which is really the term (and (h1 x) (h2 x)), then R may be
  labelled as a splitter rule. If you want to find the causes of
  case-splitting, the list of if-intro splitters can help you narrow
  your search, but may include irrelevant rules as well.

  Finally, note that you may see splits not attributed to splitters. We
  believe that this will be uncommon during simplification, though it
  can occur for example when a call of IF is in the body of a [let]
  expression, i.e., in a call of a [lambda] expression. But splits
  caused by other processes, notably destructor elimination (see
  [elim]), will typically not be attributed to splitters.


Subtopics

  [Set-splitter-output]
      Turn on or off reporting of rules that may have caused case splits

  [Splitter-output]
      Status for reporting of [splitter] rules")
 (SPLITTER-OUTPUT
  (SPLITTER)
  "Status for reporting of [splitter] rules

  See [splitter] for a discussion of splitter rules. See
  [set-splitter-output] for how to turn off, or on, the reporting of
  splitter rules. When splitter-output is off, because either prove
  output is inhibited (see [set-inhibit-output-lst]) or
  ([set-splitter-output] nil) has been invoked, then the value of
  (splitter-output) is nil. Otherwise, such reporting is on and the
  value is non-nil.")
 (STANDARD-CHAR-LISTP
  (CHARACTERS LISTS ACL2-BUILT-INS)
  "Recognizer for a true list of standard characters

  (standard-char-listp x) is true if and only if x is a null-terminated
  list all of whose members are standard [characters]. See
  [standard-char-p].

  Standard-char-listp has a [guard] of t.

  Function: 

    (defun standard-char-listp (l)
           (declare (xargs :guard t))
           (cond ((consp l)
                  (and (characterp (car l))
                       (standard-char-p (car l))
                       (standard-char-listp (cdr l))))
                 (t (equal l nil))))")
 (STANDARD-CHAR-P
  (CHARACTERS ACL2-BUILT-INS)
  "Recognizer for standard characters

  (Standard-char-p x) is true if and only if x is a ``standard''
  character, i.e., a member of the list *standard-chars*. This list
  includes #\\Newline and #\\Space [characters], as well as the usual
  punctuation and alphanumeric [characters].

  Standard-char-p has a [guard] requiring its argument to be a
  character.

  Standard-char-p is a Common Lisp function. See any Common Lisp
  documentation for more information.

  Function: 

    (defun standard-char-p (x)
           (declare (xargs :guard (characterp x)))
           (if (member x *standard-chars*) t nil))")
 (STANDARD-CO
  (IO ACL2-BUILT-INS)
  "The character output channel to which [ld] prints

  Standard-co is an [ld] special (see [ld]). The accessor is
  (standard-co state) and the updater is (set-standard-co val state).
  Standard-co must be an open character output channel. It is to this
  channel that [ld] prints the [prompt], the form to be evaluated,
  and the results. The event [command]s such as [defun], [defthm],
  etc., which print extensive commentary do not print to standard-co
  but rather to a different channel, [proofs-co], so that you may
  redirect this commentary while still interacting via standard-co.
  See [proofs-co].

  ``Standard-co'' stands for ``standard character output.'' The initial
  value of standard-co is the same as the value of [*standard-co*]
  (see [*standard-co*]).")
 (STANDARD-OI
  (IO ACL2-BUILT-INS)
  "The standard object input ``channel''

  Standard-oi is an [ld] special (see [ld]). The accessor is
  (standard-oi state) and the updater is (set-standard-oi val state).
  Standard-oi must be an open object input channel, a true list of
  objects, or a list of objects whose last [cdr] is an open object
  input channel. It is from this source that [ld] takes the input
  forms to process. When [ld] is called, if the value specified for
  standard-oi is a string or a list of objects whose last [cdr] is a
  string, then [ld] treats the string as a file name and opens an
  object input channel from that file, where the connected book
  directory (see [cbd]) is used to resolve relative pathnames. The
  channel opened by [ld] is closed by [ld] upon termination.

  ``Standard-oi'' stands for ``standard object input.'' The
  read-eval-print loop in [ld] reads the objects in standard-oi and
  treats them as forms to be evaluated. The initial value of
  standard-oi is the same as the value of [*standard-oi*] (see
  [*standard-oi*]).")
 (STANDARD-PART
  (REAL)
  "ACL2(r) function mapping limited numbers to standard numbers

  (Standard-part x) is, for a given [i-limited] number x, the unique
  real number infinitesimally close (see [i-close]) to x. This
  function is only defined in ACL2(r) (see [real]).")
 (STANDARD-STRING-ALISTP
  (ALISTS ACL2-BUILT-INS)
  "Recognizer for association lists with standard strings as keys

  (Standard-string-alistp x) is true if and only if x is a list of
  pairs of the form (cons key val) where key is a string all of whose
  characters are standard (see [standard-char-p]).

  Standard-string-alistp has a [guard] of t.

  Function: 

    (defun
        standard-string-alistp (x)
        (declare (xargs :guard t))
        (cond ((atom x) (eq x nil))
              (t (and (consp (car x))
                      (stringp (car (car x)))
                      (standard-char-listp (coerce (car (car x)) 'list))
                      (standard-string-alistp (cdr x))))))")
 (STANDARDP
  (REAL)
  "ACL2(r) recognizer for standard objects

  (Standardp x) is true if and only if x is a ``standard'' object. This
  notion of ``standard'' comes from non-standard analysis and is
  discussed in Ruben Gamboa's dissertation. In brief, all the
  familiar objects are standard: e.g., the familiar real numbers are
  standard, but non-zero infinitesimals are not standard, and the
  familiar integers are standard, but not those that exceed every
  integer that you can express in the usual way (1, 2, 3, and so on).
  Similarly, the familiar lists are standard, but not so a list that
  contains a large number of integers, where ``large'' means more
  than the standard integers. The set of standard numbers is closed
  under the usual arithmetic operations, hence the sum of a standard
  number and a non-zero infinitesimal is not standard, though it is
  what is called ``limited'' (see [i-limited]).

  This predicate is only defined in ACL2(r) (see [real]).")
 (START-PROOF-TREE
  (PROOF-TREE)
  "Start displaying proof trees during proofs

  Also see [proof-tree] and see [stop-proof-tree]. Note that
  :start-proof-tree works by removing '[proof-tree] from the
  inhibit-output-lst; see [set-inhibit-output-lst].

  Explanations of proof tree displays may be found elsewhere: see
  [proof-tree]. In a nutshell: :start-proof-tree causes proof tree
  display to be turned on, once it has been turned off by
  :[stop-proof-tree].

  Do not attempt to invoke start-proof-tree during an interrupt in the
  middle of a proof.")
 (STARTUP
  (ACL2-TUTORIAL)
  "How to start using ACL2; the ACL2 [command] loop

  When you start up ACL2, you'll probably find yourself inside the ACL2
  [command] loop, as indicated by the following [prompt].

    ACL2 !>

  If not, you should type (LP). See [lp], which has a lot more
  information about the ACL2 [command] loop.

  You should now be in ACL2. The current ``[default-defun-mode]'' is
  :[logic]; the other mode is :[program], which would cause the
  letter p to be printed in the [prompt]. :[Logic] means that any
  function we define is not only executable but also is axiomatically
  defined in the ACL2 logic. See [defun-mode] and see
  [default-defun-mode]. For example we can define a function my-cons
  as follows. (You may find it useful to start up ACL2 and submit
  this and other [command]s below to the ACL2 [command] loop, as we
  won't include output below.)

    ACL2 !>(defun my-cons (x y) (cons x y))

  An easy theorem may then be proved: the [car] of (my-cons a b) is A.

    ACL2 !>(defthm car-my-cons (equal (car (my-cons a b)) a))

  You can place raw Lisp forms to evaluate at start-up into file
  acl2-init.lsp in your home directory, except on Windows systems.
  For example, if you put the following into acl2-init.lsp, then ACL2
  will print \"HI\" when it starts up.

    (print \"HI\")

  But be careful; all bets are off when you submit forms to raw Lisp,
  so this capability should only be used when you are hacking or when
  you are setting some Lisp parameters (e.g., (setq si::*notify-gbc*
  nil) to turn off garbage collection notices in GCL).

  Notice that unlike Nqthm, the theorem [command] is [defthm] rather
  than prove-lemma. See [defthm], which explains (among other things)
  that the default is to turn theorems into [rewrite] rules.

  Various keyword commands are available to query the ACL2 ``[world]'',
  or database. For example, we may view the definition of my-cons by
  invoking a command to print [events], as follows.

    ACL2 !>:pe my-cons

  Also see [pe]. We may also view all the lemmas that [rewrite] [term]s
  whose top function symbol is [car] by using the following command,
  whose output will refer to the lemma car-my-cons proved above.

    ACL2 !>:pl car

  Also see [pl]. Finally, we may print all the [command]s back through
  the initial [world] as follows.

    ACL2 !>:pbt 0

  See [history] for a list of commands, including these, for viewing
  the current ACL2 [world].

  Continue with the [documentation] for [annotated-ACL2-scripts] to see
  a simple but illustrative example in the use of ACL2 for reasoning
  about functions.")
 (STATE
  (PROGRAMMING)
  "The von Neumannesque ACL2 state object

  Note: If you are interested in programming with state, see
  [programming-with-state] after reading the information below.

  The ACL2 state object is used extensively in programming the ACL2
  system, and has been used in other ACL2 programs as well. However,
  most users, especially those interested in specification and
  verification (as opposed to programming per se), need not be aware
  of the role of the state object in ACL2, and will not write
  functions that use it explicitly. We say more about this point at
  the end of this documentation topic.

  The ACL2 state object is an example of a single-threaded object or
  [stobj]. ACL2 allows the user to define new single-threaded
  objects. Generally, ACL2 may need to access the ACL2 state but
  should not (cannot) change it except via a certain set of approved
  functions such as [defun] and [defthm]. If you need a state-like
  object to which you have complete rights, you may want a [stobj].

  Key to the idea of our state is the notion of single-threadedness.
  For an explanation, see [stobj]. The upshot of it is that state is
  a variable symbol with severe restrictions on its use, so that it
  can be passed into only certain functions in certain slots, and
  must be returned by those functions that ``modify'' it. Henceforth,
  we do not discuss single-threaded objects in general (which the
  user can introduce with [defstobj] and [defabsstobj]) but one in
  particular, namely ACL2's state object.

  The global table is perhaps the most visible portion of the state
  object. Using the interface functions @ and assign, a user may bind
  global variables to the results of function evaluations (much as an
  Nqthm user exploits the Nqthm utility r-loop). See [@], and see
  [assign]. A particularly interesting global is 'current-acl2-world,
  whose value is the ACL2 logical [world].

  ACL2 supports several facilities of a truly von Neumannesque state
  machine character, including file [io] and global variables.
  Logically speaking, the state is a true list of the 14 components
  described below. There is a ``current'' state object at the
  top-level of the ACL2 [command] loop. This object is understood to
  be the value of what would otherwise be the free variable state
  appearing in top-level input. When any [command] returns a state
  object as one of its values, that object becomes the new current
  state. But ACL2 provides von Neumann style speed for state
  operations by maintaining only one physical (as opposed to logical)
  state object. Operations on the state are in fact destructive. This
  implementation does not violate the applicative semantics because
  we enforce certain draconian syntactic rules regarding the use of
  state objects. For example, one cannot ``hold on'' to an old state,
  access the components of a state arbitrarily, or ``modify'' a state
  object without passing it on to subsequent state-sensitive
  functions.

  Every routine that uses the state facilities (e.g. does [io], or
  calls a routine that does [io]), must be passed a ``state object.''
  And a routine must return a state object if the routine modifies
  the state in any way. Rigid syntactic rules governing the use of
  state objects are enforced by the function translate, through which
  all ACL2 user input first passes. State objects can only be
  ``held'' in the formal parameter state, never in any other formal
  parameter and never in any structure (excepting a multiple-value
  return list field which is always a state object). State objects
  can only be accessed with the primitives we specifically permit.
  Thus, for example, one cannot ask, in code to be executed, for the
  length of state or the [car] of state. In the statement and proof
  of theorems, there are no syntactic rules prohibiting arbitrary
  treatment of state objects.

  Logically speaking, a state object is a true list whose members are
  as follows:

      Open-input-channels, an alist with keys that are symbols in package
      \"ACL2-INPUT-CHANNEL\". The value ([cdr]) of each pair has the
      form ((:header type file-name open-time) . elements), where
      type is one of :character, :byte, or :object and elements is a
      list of things of the corresponding type, i.e. characters,
      integers of type (mod 255), or lisp objects in our theory.
      File-name is a string. Open-time is an integer. See [io].

      Open-output-channels, an alist with keys that are symbols in package
      \"ACL2-OUTPUT-CHANNEL\". The value of a pair has the form
      ((:header type file-name open-time) . current-contents). See
      [io].

      Global-table, an alist associating symbols (to be used as ``global
      variables'') with values. See [@], and see [assign].

      T-stack, a list of arbitrary objects accessed and changed by the
      functions aref-t-stack and aset-t-stack.

      32-bit-integer-stack, a list of arbitrary 32-bit-integers accessed
      and changed by the functions aref-32-bit-integer-stack and
      aset-32-bit-integer-stack.

      Big-clock-entry, an integer, that is used logically to bound the
      amount of effort spent to evaluate a quoted form.

      Idates, a list of dates and times, used to implement the function
      print-current-idate, which prints the date and time.

      Acl2-oracle, a list of objects, used for example to implement the
      functions that let ACL2 report how much time was used, but
      inaccessible to the user. See [read-ACL2-oracle] and also see
      [with-prover-time-limit].

      File-clock, an integer that is increased on every file opening and
      closing, and is used to maintain the consistency of the [io]
      primitives.

      Readable-files, an alist whose keys have the form (string type time),
      where [string] is a file name and time is an integer. The value
      associated with such a key is a list of characters, bytes, or
      objects, according to type. The time field is used in the
      following way: when it comes time to open a file for input, we
      will only look for a file of the specified name and type whose
      time field is that of file-clock. This permits us to have a
      ``probe-file'' aspect to open-file: one can ask for a file,
      find it does not exist, but come back later and find that it
      does now exist.

      Written-files, an alist whose keys have the form (string type time1
      time2), where [string] is a file name, type is one of
      :character, :byte or :object, and time1 and time2 are integers.
      Time1 and time2 correspond to the file-clock time at which the
      channel for the file was opened and closed. This field is
      write-only; the only operation that affects this field is
      close-output-channel, which [cons]es a new entry on the front.

      Read-files, a list of the form (string type time1 time2), where
      [string] is a file name and time1 and time2 were the times at
      which the file was opened for reading and closed. This field is
      write only.

      Writeable-files, an alist whose keys have the form (string type
      time). To open a file for output, we require that the name,
      type, and time be on this list.

      List-all-package-names-lst, a list of true-listps. Roughly speaking,
      the [car] of this list is the list of all package names known
      to this Common Lisp right now and the [cdr] of this list is the
      value of this state variable after you look at its [car]. The
      function, list-all-package-names, which takes the state as an
      argument, returns the [car] and [cdr]s the list (returning a
      new state too). This essentially gives ACL2 access to what is
      provided by CLTL's list-all-packages. [Defpkg] uses this
      feature to ensure that the about-to-be-created package is new
      in this lisp. Thus, for example, in akcl it is impossible to
      create the package \"COMPILER\" with [defpkg] because it is on
      the list, while in Lucid that package name is not initially on
      the list.

      User-stobj-alist, an alist which associates user-defined
      single-threaded objects (see [stobj]) with their values.

  We recommend avoiding the use of the state object when writing ACL2
  code intended to be used as a formal model of some system, for
  several reasons. First, the state object is complicated and
  contains many components that are oriented toward implementation
  and are likely to be irrelevant to the model in question. Second,
  there is currently not much support for reasoning about ACL2
  functions that manipulate the state object, beyond their logical
  definitions. Third, the documentation about state is not as
  complete as one might wish.

  User-defined single-threaded objects offer the speed of state while
  giving the user complete access to all the fields. See [stobj].

  Again, if you are interested in programming with state see
  [programming-with-state].


Subtopics

  [Io]
      Input/output facilities in ACL2

  [Programming-with-state]
      Programming using the von Neumannesque ACL2 [state] object

  [Random$]
      Obtain a random value

  [Set-state-ok]
      Allow the use of STATE as a formal parameter

  [World]
      ACL2 property lists and the ACL2 logical database

  [Wormhole]
      [ld] without [state] --- a short-cut to a parallel universe")
 (STATE-GLOBAL-LET*
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Bind [state] global variables

  See [programming-with-state] for requisite background on programming
  with the ACL2 [state].

    Example Forms:
    (state-global-let*
     ((inhibit-output-lst *valid-output-names*))
     (thm (equal x x)))

    (state-global-let*
     ((fmt-hard-right-margin 1000 set-fmt-hard-right-margin)
      (fmt-soft-right-margin 1000 set-fmt-soft-right-margin))
     (mini-proveall))

    General Form:
    (state-global-let* ((var1 form1) ; or (var1 form1 set-var1)
                        ...
                        (vark formk) ; or (vark formk set-vark)
                       )
                       body)

  where: each vari is a variable; each formi is an expression whose
  value is a single ordinary object (i.e. not multiple values, and
  not [state] or any other [stobj]); set-vari, if supplied, is a
  function with [signature] ((set-vari * state) => state); and body
  is an expression that evaluates to an error triple (see
  [error-triples]). Each formi is evaluated in order, starting with
  form1, and with each such binding the state global variable vari is
  bound to the value of formi, sequentially in the style of [let*].
  More precisely, then meaning of this form is to set (in order) the
  global values of the indicated [state] global variables vari to the
  values of formi using [f-put-global], execute body, restore the
  vari to their previous values (but see the discussion of setters
  below), and return the triple produced by body (with its state as
  modified by the restoration). The restoration is guaranteed even in
  the face of aborts. The ``bound'' variables may initially be
  unbound in state and restoration means to make them unbound again.

  Still referring to the General Form above, let old-vali be the value
  of state global variable vari at the time vari is about to be
  assigned the value of formi. If set-vari is not supplied, then as
  suggested above, the following form is evaluated at the conclusion
  of the evaluation of the state-global-let* form, whether or not an
  error has occurred: (f-put-global 'vari 'old-vali state). However,
  if set-vari is supplied, then instead the form evaluated will be
  (set-vari 'old-vali state). This capability is particularly useful
  if vari is untouchable (see [push-untouchable]), since the above
  call of [f-put-global] is illegal.

  Note that the scope of the bindings of a state-global-let* form is
  the body of that form. This may seem obvious, but to drive the
  point home, let's consider the following example (see
  [set-print-base] and see [set-print-radix]).

    ACL2 !>(state-global-let* ((print-base 16 set-print-base)
                               (print-radix t set-print-radix))
                              (mv nil 10 state))
     10
    ACL2 !>

  Why wasn't the result printed as #xA? The reason is that the result
  was printed after evaluation of the entire form had completed. If
  you want to see #xA, do the printing in the scope of the bindings,
  for example as follows.

    ACL2 !>(state-global-let* ((print-base 16 set-print-base)
                               (print-radix t set-print-radix))
                              (pprogn (fms \"~x0~%\"
                                           (list (cons #0 10))
                                           *standard-co* state nil)
                                      (mv nil 10 state)))

    #xA
     10
    ACL2 !>")
 (STOBJ
  (PROGRAMMING)
  "Single-threaded objects or ``von Neumann bottlenecks''

  In ACL2, a ``single-threaded object'' is a data structure whose use
  is so syntactically restricted that only one instance of the object
  need ever exist and its fields can be updated by destructive
  assignments.

  Note: Novices are advised to avoid using single-threaded objects,
  perhaps instead using [std::defaggregate] or community book
  books/data-structures/structures.lisp. At the least, consider using
  ([set-verify-guards-eagerness] 0) to avoid [guard] verification.

  The documentation in this section is laid out in the form of a tour
  that visits the documented topics in a reasonable order. We
  recommend that you follow the tour the first time you read about
  stobjs. The list of all stobj topics is shown below. The tour
  starts immediately afterwards. Also see [defstobj] and, for
  so-called abstract stobjs, see [defabsstobj].

  As noted, a ``single-threaded object'' is a data structure whose use
  is so syntactically restricted that only one instance of the object
  need ever exist. Updates to the object must be sequentialized. This
  allows us to update its fields with destructive assignments without
  wrecking the axiomatic semantics of update-by-copy. For this
  reason, single-threaded objects are sometimes called ``von Neumann
  bottlenecks.''

  From the logical perspective, a single-threaded object is an ordinary
  ACL2 object, e.g., composed of integers and conses. Logically
  speaking, ordinary ACL2 functions are defined to allow the user to
  ``access'' and ``update'' its fields. Logically speaking, when
  fields in the object, obj, are ``updated'' with new values, a new
  object, obj', is constructed.

  But suppose that by syntactic means we could ensure that there were
  no more references to the ``old'' object, obj. Then we could create
  obj' by destructively modifying the memory locations involved in
  the representation of obj. The syntactic means is pretty simple but
  draconian: the only reference to obj is in the variable named OBJ.

  The consequences of this simple rule are far-reaching and require
  some getting used to. For example, if OBJ has been declared as a
  single-threaded object name, then the following consequences ensue
  (but see the discussion of congruent stobjs below for a slight
  relaxation).

    * OBJ is a top-level global variable that contains the current object,
      obj.
    * If a function uses the formal parameter OBJ, the only ``actual
      expression'' that can be passed into that slot is the variable
      OBJ, not merely a term that ``evaluates to an obj''; thus, such
      functions can only operate on the current object. So for
      example, instead of (FOO (UPDATE-FIELD1 3 ST)) write (LET ((ST
      (UPDATE-FIELD1 3 ST))) (FOO ST)).
    * The accessors and updaters have a formal parameter named OBJ, so by
      the rule just above, those functions can only be applied to the
      current object. The recognizer is the one exception to the
      rule: it may be applied either the OBJ or to an ordinary
      (non-stobj) object.
    * The ACL2 primitives, such as CONS, CAR and CDR, may not be applied to
      the variable OBJ. Thus, for example, obj may not be consed into
      a list (which would create another pointer to it) or accessed
      or copied via ``unapproved'' means.
    * The updaters return a ``new OBJ object'', i.e., obj'; thus, when an
      updater is called, the only variable which can hold its result
      is OBJ.
    * If a function calls an OBJ updater, it must return an OBJ object
      (either as the sole value returned, or in (mv ... OBJ ...); see
      [mv]).
    * When a top-level expression involving OBJ returns an OBJ object, that
      object becomes the new current value of OBJ.

  There are other functional languages supporting single-threadedness,
  for example Haskell's ``monads'' and Clean's ``uniqueness type
  system''. Of course, ACL2 provides a theorem prover that can prove
  theorems that involve such constructs.

  Note that the syntactic restrictions noted above are enforced only
  when single-threaded objects are encountered directly in the
  top-level loop or are used in function definitions; the accessor
  and update functions for single-threaded objects may be used
  without restriction in formulas to be proved. Since function
  evaluation is sometimes necessary during proofs, ACL2 must be able
  to evaluate these functions on logical constants representing the
  object, even when the constant is not ``the current object.'' Thus,
  ACL2 supports both the efficient von Neumann semantics and the
  clean applicative semantics, and uses the first in contexts where
  execution speed is paramount and the second during proofs.

  [Defstobj] and [defabsstobj] [events] introduce stobjs. See
  [defstobj] for more details about stobjs. In particular, a
  relatively advanced notion of ``congruent stobjs'' is discussed
  there. The idea is to allow a stobj, st2, of the same ``shape'' as
  a given stobj, st1, to be used in place of st1. Other [defstobj]
  keywords allow inlining and renaming of stobj accessors and
  updaters.

  But we are getting ahead of ourselves. To start the stobj tour, see
  [stobj-example-1].


Subtopics

  [Declare-stobjs]
      Declaring a formal parameter name to be a single-threaded object

  [Defabsstobj]
      Define a new abstract single-threaded object

  [Defstobj]
      Define a new single-threaded object

  [Nested-stobjs]
      Using [stobj]s that contain stobjs

  [Nth-aliases-table]
      A [table] used to associate names for nth/update-nth printing

  [Resize-list]
      List resizer in support of stobjs

  [Stobj-example-1]
      An example of the use of single-threaded objects

  [Stobj-example-1-defuns]
      The defuns created by the counters stobj

  [Stobj-example-1-implementation]
      The implementation of the counters stobj

  [Stobj-example-1-proofs]
      Some proofs involving the counters stobj

  [Stobj-example-2]
      An example of the use of arrays in single-threaded objects

  [Stobj-example-3]
      Another example of a single-threaded object

  [Update-nth-array]
      Update a stobj array

  [With-local-state]
      Locally bind state

  [With-local-stobj]
      Locally bind a single-threaded object")
 (STOBJ-EXAMPLE-1
  (STOBJ)
  "An example of the use of single-threaded objects

  Suppose we want to sweep a tree and (1) count the number of interior
  nodes, (2) count the number of tips and (3) keep a record of every
  tip we encounter that is an integer. We could use a single-threaded
  object as our ``accumulator''. Such an object would have three
  fields, one holding the number of nodes seen so far, one holding
  the number of tips, and one holding all the integer tips seen.

  The following event declares counters to be a single-threaded object.

    (defstobj counters
      (NodeCnt     :type integer :initially 0)
      (TipCnt      :type integer :initially 0)
      (IntTipsSeen :type t       :initially nil))

  It has three fields, NodeCnt, TipCnt, and IntTipsSeen. (As always in
  ACL2, capitalization is irrelevant in simple symbol names, so the
  first name could be written nodecnt or NODECNT, etc.) Those are the
  name of the accessor functions for the object. The corresponding
  update functions are named update-NodeCnt, update-TipCnt and
  update-IntTipsSeen.

  If you do not like the default function names chosen above, there is
  a feature in the [defstobj] event that allows you to specify other
  names.

  If you want to see the ACL2 definitions of all the functions defined
  by this event, look at [stobj-example-1-defuns].

  If, after this event, we evaluate the top-level ``global variable''
  counters in the ACL2 read-eval-print loop we get:

    ACL2 !>counters
    

  Note that the value printed is ``''. Actually, the value of
  counters in the logic is (0 0 NIL). But ACL2 always prints
  single-threaded objects in this non-informative way because they
  are usually so big that to do otherwise would be unpleasant.

  Had you tried to evaluate the ``global variable'' counters before
  declaring it a single-threaded object, ACL2 would have complained
  that it does not support global variables. So a lesson here is that
  once you have declared a new single-threaded object your top-level
  forms can reference it. In versions of ACL2 prior to Version 2.4
  the only variable enjoying this status was STATE. single-threaded
  objects are a straightforward generalization of the
  long-implemented von Neumann [state] feature of ACL2.

  We can access the fields of counters as with:

    ACL2 !>(NodeCnt counters)
    0
    ACL2 !>(IntTipsSeen counters)
    NIL

  and we can set the fields of counters as with:

    ACL2 !>(update-NodeCnt 3 counters)
    
    ACL2 !>(NodeCnt counters)
    3

  Observe that when we evaluate an expression that returns a counter
  object, that object becomes the ``current value'' of counters.

  Here is a function that ``converts'' the counters object to its
  ``ordinary'' representation:

    (defun show-counters (counters)
      (declare (xargs :stobjs (counters)))
      (list (NodeCnt counters)
            (TipCnt counters)
            (IntTipsSeen counters)))

  Observe that we must declare, at the top of the defun, that we mean
  to use the formal parameter counters as a single-threaded object!
  If we did not make this declaration, the body of show-counters
  would be processed as though counters were an ordinary object. An
  error would be caused because the accessors used above cannot be
  applied to anything but the single-threaded object counters. If you
  want to know why we insist on this declaration, see
  [declare-stobjs].

  When show-counters is admitted, the following message is printed:

    Since SHOW-COUNTERS is non-recursive, its admission is trivial.  We
    observe that the type of SHOW-COUNTERS is described by the theorem
    (AND (CONSP (SHOW-COUNTERS COUNTERS))
         (TRUE-LISTP (SHOW-COUNTERS COUNTERS))).
    We used primitive type reasoning.

    (SHOW-COUNTERS COUNTERS) => *.

    The guard conjecture for SHOW-COUNTERS is trivial to prove.
    SHOW-COUNTERS is compliant with Common Lisp.

  The line above containing the ``=>'' is called the ``signature'' of
  show-counters; it conveys the information that the first argument
  is the single-threaded object counters and the only result is an
  ordinary object. Here is an example of another signature:

    (PROCESSOR * * COUNTERS) => (MV * COUNTERS)

  which indicates that the function PROCESSOR (which we haven't shown
  you) takes three arguments, the third of which is the COUNTERS
  stobj, and returns two results, the second of which is the modified
  COUNTERS.

  Returning to the admission of show-counters above, the last sentence
  printed indicates that the [guard] conjectures for the function
  were proved. When some argument of a function is declared to be a
  single-threaded object via the xargs :stobj, we automatically add
  (conjoin) to the guard the condition that the argument satisfy the
  recognizer for that single-threaded object. In the case of
  show-counters the guard is (countersp counters).

  Here is an example of show-counters being called:

    ACL2 !>(show-counters counters)
    (3 0 NIL)

  This is what we would see had we set the NodeCnt field of the initial
  value of counters to 3, as we did earlier in this example.

  We next wish to define a function to reset the counters object. We
  could define it this way:

    (defun reset-counters (counters)
      (declare (xargs :stobjs (counters)))
      (let ((counters (update-NodeCnt 0 counters)))
        (let ((counters (update-TipCnt 0 counters)))
          (update-IntTipsSeen nil counters))))

  which ``successively'' sets the NodeCnt field to 0, then the TipCnt
  field to 0, and then the IntTipsSeen field to nil and returns the
  resulting object.

  However, the nest of let expressions is tedious and we use this
  definition instead. This definition exploits a macro, here named
  ``seq'' (for ``sequentially'') which evaluates each of the forms
  given, binding their results successively to the stobj name given.

    (defun reset-counters (counters)
      (declare (xargs :stobjs (counters)))
      (seq counters
           (update-NodeCnt 0 counters)
           (update-TipCnt 0 counters)
           (update-IntTipsSeen nil counters)))

  This definition is syntactically identical to the one above, after
  macro expansion. Our definition of seq is shown below and is not
  part of native ACL2.

    (defmacro seq (stobj &rest rst)
      (cond ((endp rst) stobj)
            ((endp (cdr rst)) (car rst))
            (t `(let ((,stobj ,(car rst)))
                 (seq ,stobj ,@(cdr rst))))))

  The signature printed for reset-counters is

    (RESET-COUNTERS COUNTERS) => COUNTERS.

  Here is an example.

    ACL2 !>(show-counters counters)
    (3 0 NIL)
    ACL2 !>(reset-counters counters)
    
    ACL2 !>(show-counters counters)
    (0 0 NIL)

  Here finally is a function that uses counters as a single-threaded
  accumulator to collect the desired information about the tree x.

    (defun sweep-tree (x counters)
      (declare (xargs :stobjs (counters)))
      (cond ((atom x)
             (seq counters
                  (update-TipCnt (+ 1 (TipCnt counters)) counters)
                  (if (integerp x)
                      (update-IntTipsSeen (cons x (IntTipsSeen counters))
                                      counters)
                    counters)))
            (t (seq counters
                    (update-NodeCnt (+ 1 (NodeCnt counters)) counters)
                    (sweep-tree (car x) counters)
                    (sweep-tree (cdr x) counters)))))

  We can paraphrase this definition as follows. If x is an atom, then
  increment the TipCnt field of counters and then, if x is an
  integer, add x to the IntTipsSeen field, and return counters. On
  the other hand, if x is not an atom, then increment the NodeCnt
  field of counters, and then sweep the car of x and then sweep the
  cdr of x and return the result.

  Here is an example of its execution. We have displayed the input tree
  in full dot notation so that the number of interior nodes is just
  the number of dots.

    ACL2 !>(sweep-tree '((((a . 1) . (2 . b)) . 3)
                         . (4 . (5 . d)))
                       counters)
    
    ACL2 !>(show-counters counters)
    (7 8 (5 4 3 2 1))
    ACL2 !>(reset-counters counters)
    
    ACL2 !>(show-counters counters)
    (0 0 NIL)

  The counters object has two integer fields and a field whose type is
  unrestricted. single-threaded objects support other types of
  fields, such as arrays. We deal with that in the [stobj-example-2].
  But we recommend that you first consider the implementation issues
  for the counters example (in [stobj-example-1-implementation]) and
  then consider the proof issues (in [stobj-example-1-proofs]).

  To continue the stobj tour, see [stobj-example-2].")
 (STOBJ-EXAMPLE-1-DEFUNS
  (STOBJ)
  "The defuns created by the counters stobj

  Consider the event shown in [stobj-example-1]:

    (defstobj counters
      (NodeCnt     :type integer :initially 0)
      (TipCnt      :type integer :initially 0)
      (IntTipsSeen :type t       :initially nil))

  Here is a complete list of the defuns added by the event.

  The careful reader will note that the counters argument below is not
  declared with the :stobjs xarg even though we insist that the
  argument be a stobj in calls of these functions. This ``mystery''
  is explained below.

    (defun NodeCntp (x)                 ;;; Recognizer for 1st field
      (declare (xargs :guard t :verify-guards t))
      (integerp x))

    (defun TipCntp (x)                  ;;; Recognizer for 2nd field
      (declare (xargs :guard t :verify-guards t))
      (integerp x))

    (defun IntTipsSeenp (x)             ;;; Recognizer for 3rd field
      (declare (xargs :guard t :verify-guards t) (ignore x))
      t)

    (defun countersp (counters)         ;;; Recognizer for object
      (declare (xargs :guard t :verify-guards t))
      (and (true-listp counters)
           (= (length counters) 3)
           (NodeCntp (nth 0 counters))
           (TipCntp (nth 1 counters))
           (IntTipsSeenp (nth 2 counters))
           t))

    (defun create-counters ()           ;;; Creator for object
      (declare (xargs :guard t :verify-guards t))
      (list '0 '0 'nil))

    (defun NodeCnt (counters)           ;;; Accessor for 1st field
      (declare (xargs :guard (countersp counters) :verify-guards t))
      (nth 0 counters))

    (defun update-NodeCnt (v counters)  ;;; Updater for 1st field
      (declare (xargs :guard
                      (and (integerp v)
                           (countersp counters))
                      :verify-guards t))
      (update-nth 0 v counters))

    (defun TipCnt (counters)            ;;; Accessor for 2nd field
      (declare (xargs :guard (countersp counters) :verify-guards t))
      (nth 1 counters))

    (defun update-TipCnt (v counters)   ;;; Updater for 2nd field
      (declare (xargs :guard
                      (and (integerp v)
                           (countersp counters))
                      :verify-guards t))
      (update-nth 1 v counters))

    (defun IntTipsSeen (counters)       ;;; Accessor for 3rd field
      (declare (xargs :guard (countersp counters) :verify-guards t))
      (nth 2 counters))

    (defun update-IntTipsSeen (v counters) ;;; Updater for 3rd field
      (declare (xargs :guard (countersp counters) :verify-guards t))
      (update-nth 2 v counters))

  Observe that there is a recognizer for each of the three fields and
  then a recognizer for the counters object itself. Then, for each
  field, there is an accessor and an updater.

  Observe also that the functions are guarded so that they expect a
  countersp for their counters argument and an appropriate value for
  the new field values.

  You can see all of the defuns added by a defstobj event by executing
  the event and then using the :pcb! command on the stobj name. E.g.,

    ACL2 !>:pcb! counters

  will print the defuns above.

  We now clear up the ``mystery'' mentioned above. Note, for example in
  TipCnt, that the formal counters is used. From the discussion in
  [stobj-example-1] it has been made clear that TipCnt can only be
  called on the counters object. And yet, in that same discussion it
  was said that an argument is so treated only if it it declared
  among the :stobjs in the definition of the function. So why doesn't
  TipCnt include something like (declare (xargs :stobjs (counters)))?

  The explanation of this mystery is as follows. At the time TipCnt was
  defined, during the introduction of the counters stobj, the name
  ``counters'' was not yet a single-threaded object. The introduction
  of a new single-threaded object occurs in three steps: (1) The new
  primitive recognizers, accessors, and updaters are introduced as
  ``ordinary functions,'' producing their logical axiomatizations.
  (2) The executable counterparts are defined in raw Lisp to support
  destructive updating. (3) The new name is declared a
  single-threaded object to ensure that all future use of these
  primitives respects the single-threadedness of the object. The
  functions defined as part of the introduction of a new
  single-threaded object are the only functions in the system that
  have undeclared stobj formals other than state.

  You may return to [stobj-example-1] here.")
 (STOBJ-EXAMPLE-1-IMPLEMENTATION
  (STOBJ)
  "The implementation of the counters stobj

  the event

    (defstobj counters
      (NodeCnt     :type integer :initially 0)
      (TipCnt      :type integer :initially 0)
      (IntTipsSeen :type t       :initially nil))

  discussed in [stobj-example-1], creates a Common Lisp object to
  represent the current value of counters. That object is created by
  evaluating either of the following ``raw'' (non-ACL2) Common Lisp
  forms:

    (create-counters)

    (vector (make-array 1 :element-type 'integer
                          :initial-element '0)
            (make-array 1 :element-type 'integer
                          :initial-element '0)
            'nil)

  and the value is stored in the Common Lisp global variable named
  *the-live-counters*.

  Thus, the counters object is an array of length three. The first two
  elements are arrays of size 1 and are used to hold the NodeCnt and
  TipCnt fields. The third element is the IntTipsSeen field. The
  first two fields are represented by arrays so that we can implement
  the integer type specification efficiently. Generally, integers are
  ``boxed'' in some Common Lisp implementations, for example, GCL.
  Creating a new integer requires creating a new box to put it in.
  But in some lisps, including GCL, the integers inside arrays of
  integers are not boxed.

  The function NodeCnt is defined in raw Lisp as:

    (defun NodeCnt (counters)
      (the integer
           (aref (the (simple-array integer (1))
                      (svref counters 0))
                 0)))

  Observe that the form (svref counters 0) is evaluated to get an array
  of size 1, which is followed by a call of aref to access the 0th
  element of that array.

  The function update-NodeCnt is defined in raw Lisp as:

    (defun update-NodeCnt (v counters)
      (declare (type integer v))
      (progn
       (setf (aref (the (simple-array integer (1))
                        (svref counters 0))
                   0)
             (the integer v))
       counters))

  Note that when this function is called, it does not create a new
  vector of length three, but ``smashes'' the existing one.

  One way to see all the raw Lisp functions defined by a given defstobj
  is to evaluate the defstobj event and then evaluate, in the ACL2
  loop, the expression (nth 4 (global-val 'cltl-command (w state))).
  Those functions that contain (DECLARE (STOBJ-INLINE-FN T)) will
  generate [defabbrev] forms because the :inline keyword of
  [defstobj] was supplied the value t. The rest will generate
  [defun]s.

  We now recommend that you look at [stobj-example-1-proofs].")
 (STOBJ-EXAMPLE-1-PROOFS
  (STOBJ)
  "Some proofs involving the counters stobj

  Consider again the event

    (defstobj counters
      (NodeCnt     :type integer :initially 0)
      (TipCnt      :type integer :initially 0)
      (IntTipsSeen :type t       :initially nil))

  discussed in [stobj-example-1], followed by the definition

    (defun reset-counters (counters)
      (declare (xargs :stobjs (counters)))
      (seq counters
           (update-NodeCnt 0 counters)
           (update-TipCnt 0 counters)
           (update-IntTipsSeen nil counters)))

  which, because of the seq macro in [stobj-example-1], is just
  syntactic sugar for

    (defun reset-counters (counters)
      (declare (xargs :stobjs (counters)))
      (let ((counters (update-NodeCnt 0 counters)))
        (let ((counters (update-TipCnt 0 counters)))
          (update-IntTipsSeen nil counters)))).

  Here is a simple theorem about reset-counters.

    (defthm reset-counters-is-constant
      (implies (countersp x)
               (equal (reset-counters x)
                      '(0 0 nil))))

  Before we talk about how to prove this theorem, note that the theorem
  is unusual in two respects.

  First, it calls reset-counters on an argument other than the variable
  counters! That is allowed in theorems; logically speaking, the
  stobj functions are indistinguishable from ordinary functions.
  Their use is syntactically restricted only in defuns, which might
  be compiled and run in raw Lisp. Those restrictions allow us to
  implement stobj modification destructively. But logically speaking,
  reset-counters and other stobj ``modifying'' functions just create
  new objects, constructively.

  Second, the theorem above explicitly provides the hypothesis that
  reset-counters is being applied to an object satisfying countersp.
  Such a hypothesis is not always required: reset-counters is total
  and will do something no matter what x is. But in this particular
  case, the result is not '(0 0 nil) unless x is, at least, a
  true-list of length three.

  To make a long story short, to prove theorems about stobj functions
  you behave in exactly the way you would to prove the same theorems
  about the same functions defined without the stobj features.

  How can we prove the above theorem? Unfolding the definition of
  reset-counters shows that (reset-counters x) is equal to

    (update-IntTipsSeen nil
      (update-TipCnt 0
        (update-NodeCnt 0 x)))

  which in turn is

    (update-nth 2 nil
     (update-nth 1 0
      (update-nth 0 0 x))).

  Opening up the definition of update-nth reduces this to

    (list* 0 0 nil (cdddr x)).

  This is clearly equal to '(0 0 nil), provided we know that (cdddr x)
  is nil.

  Unfortunately, that last fact requires a lemma. The most specific
  lemma we could provide is

    (defthm special-lemma-for-counters
      (implies (countersp x)
               (equal (cdddr x) nil)))

  but if you try to prove that lemma you will find that it requires
  some reasoning about len and true-listp. Furthermore, the special
  lemma above is of interest only for counters.

  The following lemma about len is the one we prefer.

    (defthm equal-len-n
      (implies (syntaxp (quotep n))
               (equal (equal (len x) n)
                      (if (integerp n)
                          (if (< n 0)
                              nil
                            (if (equal n 0)
                                (atom x)
                              (and (consp x)
                                   (equal (len (cdr x)) (- n 1)))))
                        nil))))

  This lemma will simplify any equality in which a len expression is
  equated to any explicitly given constant n, e.g., 3, reducing the
  equation to a conjunction of consp terms about the first n cdrs.

  If the above lemma is available then ACL2 immediately proves

    (defthm reset-counters-is-constant
      (implies (countersp x)
               (equal (reset-counters x)
                      '(0 0 nil))))

  The point is presumably well made: proving theorems about
  single-threaded object accessors and updaters is no different than
  proving theorems about other recursively defined functions on
  lists.

  As we have seen, operations on [stobj]s turn into definitions
  involving [nth] and [update-nth] in the logic. Here are two lemmas,
  both due to Matt Wilding, that are useful for simplifying terms
  involving nth and update-nth, which are therefore useful in
  reasoning about single-threaded objects.

    (defthm update-nth-update-nth-same
      (implies (equal (nfix i1) (nfix i2))
               (equal (update-nth i1 v1 (update-nth i2 v2 l))
                      (update-nth i1 v1 l))))

    (defthm update-nth-update-nth-diff
      (implies (not (equal (nfix i1) (nfix i2)))
               (equal (update-nth i1 v1 (update-nth i2 v2 l))
                      (update-nth i2 v2 (update-nth i1 v1 l))))
      :rule-classes ((:rewrite :loop-stopper ((i1 i2)))))

  We now recommend that you see [stobj-example-2].")
 (STOBJ-EXAMPLE-2
  (STOBJ)
  "An example of the use of arrays in single-threaded objects

  The following event

    (defstobj ms
      (pcn  :type integer                  :initially 0)
      (mem  :type (array integer (100000)) :initially -1)
      (code :type t                        :initially nil))

  introduces a single-threaded object named ms (which stands for
  ``machine state''). The object has three fields, a pcn or program
  counter, a mem or memory, and a code field.

  The mem field is occupied by an object initially of type (array
  integer (100000)). Logically speaking, this is a list of length
  100000, each element of which is an integer. But in the underlying
  implementation of the ms object, this field is occupied by a raw
  Lisp array, initially of size 100000.

  You might expect the above defstobj to define the accessor function
  mem and the updater update-mem. That does not happen!.

  The above event defines the accessor function memi and the updater
  update-memi. These functions do not access/update the mem field of
  the ms object; they access/update the individual elements of the
  array in that field.

  In particular, the logical definitions of the two functions are:

    (defun memi (i ms)
      (declare (xargs :guard
                      (and (msp ms)
                           (integerp i)
                           (<= 0 i)
                           (< i (mem-length ms)))))
      (nth i (nth 1 ms)))

    (defun update-memi (i v ms)
      (declare (xargs :guard
                      (and (msp ms)
                           (integerp i)
                           (<= 0 i)
                           (< i (mem-length ms))
                           (integerp v))))
      (update-nth-array 1 i v ms))

  For example, to access the 511th (0-based) memory location of the
  current ms you could evaluate:

    ACL2 !>(memi 511 ms)
    -1

  The answer is -1 initially, because that is the above-specified
  initial value of the elements of the mem array.

  To set that element you could do

    ACL2 !>(update-memi 511 777 ms)
    
    ACL2 !>(memi 511 ms)
    777

  The raw Lisp implementing these two functions is shown below.

    (defun memi (i ms)
      (declare (type (and fixnum (integer 0 *)) i))
      (the integer
           (aref (the (simple-array integer (*))
                      (svref ms 1))
                 (the (and fixnum (integer 0 *)) i))))

    (defun update-memi (i v ms)
      (declare (type (and fixnum (integer 0 *)) i)
               (type integer v))
      (progn
       (setf (aref (the (simple-array integer (*))
                        (svref ms 1))
                   (the (and fixnum (integer 0 *)) i))
             (the integer v))
       ms))

  If you want to see the raw Lisp supporting a defstobj, execute the
  defstobj and then evaluate the ACL2 form (nth 4 (global-val
  'cltl-command (w state))).

  To continue the stobj tour, see [stobj-example-3].")
 (STOBJ-EXAMPLE-3
  (STOBJ)
  "Another example of a single-threaded object

  The event

    (defstobj $s
      (x :type integer :initially 0)
      (a :type (array (integer 0 9) (3)) :initially 9 :resizable t))

  introduces a stobj named $S. The stobj has two fields, X and A. The A
  field is an array. The X field contains an integer and is initially
  0. The A field contains a list of integers, each between 0 and 9,
  inclusively. (Under the hood, this ``list'' is actually implemented
  as an array.) Initially, the A field has three elements, each of
  which is 9.

  This event introduces the following sequence of function definitions:

    (DEFUN XP (X) ...)               ; recognizer for X field
    (DEFUN AP (X) ...)               ; recognizer of A field
    (DEFUN $SP ($S) ...)             ; top-level recognizer for stobj $S
    (DEFUN CREATE-$S NIL ...)        ; creator for stobj $S
    (DEFUN X ($S) ...)               ; accessor for X field
    (DEFUN UPDATE-X (V $S) ...)      ; updater for X field
    (DEFUN A-LENGTH ($S) ...)        ; length of A field
    (DEFUN RESIZE-A (K $S) ...)      ; resizer for A field
    (DEFUN AI (I $S) ...)            ; accessor for A field at index I
    (DEFUN UPDATE-AI (I V $S) ...)   ; updater for A field at index I

  Here is the definition of $SP:

    (DEFUN $SP ($S)
      (DECLARE (XARGS :GUARD T :VERIFY-GUARDS T))
      (AND (TRUE-LISTP $S)
           (= (LENGTH $S) 2)
           (XP (NTH 0 $S))
           (AP (NTH 1 $S))
           T))

  This reveals that in order to satisfy $SP an object must be a true
  list of length 2 whose first element satisfies XP and whose second
  satisfies AP. By printing the definition of AP one learns that it
  requires its argument to be a true list, each element of which is
  an integer between 0 and 9.

  The initial value of stobj $S is given by zero-ary ``creator''
  function CREATE-$S. Creator functions may only be used in limited
  contexts. See [with-local-stobj].

  Here is the definition of UPDATE-AI, the updater for the A field at
  index I:

    (DEFUN UPDATE-AI (I V $S)
      (DECLARE (XARGS :GUARD
                      (AND ($SP $S)
                           (INTEGERP I)
                           (<= 0 I)
                           (< I (A-LENGTH $S))
                           (AND (INTEGERP V) (<= 0 V) (<= V 9)))
                      :VERIFY-GUARDS T))
      (UPDATE-NTH-ARRAY 1 I V $S))

  By definition (UPDATE-NTH-ARRAY 1 I V $S) is (UPDATE-NTH 1
  (UPDATE-NTH I V (NTH 1 $S)) $S). This may be a little surprising
  but should be perfectly clear.

  First, ignore the guard, since it is irrelevant in the logic. Reading
  from the inside out, (UPDATE-AI I V $S) extracts (NTH 1 $S), which
  is array a of $S. (Recall that [nth] is 0-based.) The next higher
  expression in the definition above, (UPDATE-NTH I V a),
  ``modifies'' a by setting its Ith element to V. Call this a'. The
  next higher expression, (UPDATE-NTH 1 a' $S), ``modifies'' $S by
  setting its 1st component to a'. Call this result $s'. Then $s' is
  the result returned by UPDATE-AI.

  So the first useful observation is that from the perspective of the
  logic, the type ``restrictions'' on stobjs are irrelevant. They are
  ``enforced'' by ACL2's guard mechanism, not by the definitions of
  the updater functions.

  As one might also imagine, the accessor functions do not really
  ``care,'' logically, whether they are applied to well-formed stobjs
  or not. For example, (AI I $S) is defined to be (NTH I (NTH 1 $S)).

  Thus, you will not be able to prove that (AI 2 $S) is an integer.
  That is,

    (integerp (AI 2 $S))

  is not a theorem, because $S may not be well-formed.

  Now (integerp (AI 2 $S)) will always evaluate to T in the top-level
  ACL2 command loop, because we insist that the current value of the
  stobj $S always satisfies $SP by enforcing the guards on the
  updaters, independent of whether guard checking is on or off; see
  [set-guard-checking]. But in a theorem $S is just another variable,
  implicitly universally quantified.

  So (integerp (AI 2 $S)) is not a theorem because it is not true when
  the variable $S is instantiated with, say,

    '(1 (0 1 TWO))

  because, logically speaking, (AI 2 '(1 (0 1 TWO))) evaluates to the
  symbol TWO. That is,

    (equal (AI 2 '(1 (0 1 TWO))) 'TWO)

  is true.

  However,

    (implies (and ($SP $S) (< 2 (A-LENGTH $S))) (integerp (AI 2 $S)))

  is a theorem. To prove it, you will have to prove a lemma about AP.
  The following will do:

    (defthm ap-nth
      (implies (and (AP x)
                    (integerp i)
                    (<= 0 i)
                    (< i (len x)))
               (integerp (nth i x)))).

  Similarly,

    (implies (and (integerp i)
                  (<= 0 i)
                  (< i (A-LENGTH $S))
                  (integerp v)
                  (<= 0 v)
                  (<= v 9))
             ($SP (UPDATE-AI i v $S)))

  is not a theorem until you add the additional hypothesis ($SP $S). To
  prove the resulting theorem, you will need a lemma such as the
  following.

    (defthm ap-update-nth
      (implies (and (AP a)
                    (integerp v)
                    (<= 0 v)
                    (<= v 9)
                    (integerp i)
                    (<= 0 i)
                    (< i (len a)))
               (AP (update-nth i v a))))

  The moral here is that from the logical perspective, you must provide
  the hypotheses that, as a programmer, you think are implicit on the
  structure of your stobjs, and you must prove their invariance. This
  is a good area for further support, perhaps in the form of a
  library of macros.

  Resizing Array Fields

  Recall the specification of the array field, A for the stobj $S
  introduced above:

    (a :type (array (integer 0 9) (3)) :initially 9 :resizable t)

  Logically, this field is a list, initially of length 3. Under the
  hood, this field is implemented using a Common Lisp array with 3
  elements. In some applications, one may wish to lengthen an array
  field, or even (to reclaim space) to shrink an array field. The
  [defstobj] event provides functions to access the current length of
  an array field and to change the array field, with default names
  obtained by suffixing the field name with ``LENGTH-'' or prefixing
  it with ``RESIZE-,'' respectively. The following log shows the uses
  of these fields in the above example.

    ACL2 !>(A-LENGTH $S)
    3
    ACL2 !>(RESIZE-A 10 $S) ; change length of A to 10
    <$s>
    ACL2 !>(A-LENGTH $S)
    10
    ACL2 !>(AI 7 $S)        ; new elements get value from :initially
    9
    ACL2 !>(RESIZE-A 2 $S)  ; truncate A down to first 2 elements
    <$s>
    ACL2 !>(A-LENGTH $S)
    2
    ACL2 !>(AI 7 $S)        ; error:  access past array bound

    ACL2 Error in TOP-LEVEL:  The guard for the function symbol AI, which
    is (AND ($SP $S) (INTEGERP I) (<= 0 I) (< I (A-LENGTH $S))), is violated
    by the arguments in the call (AI 7 $S).

    ACL2 !>

  Here are the definitions of the relevant functions for the above
  example; also see [resize-list].

    (DEFUN A-LENGTH ($S)
      (DECLARE (XARGS :GUARD ($SP $S) :VERIFY-GUARDS T))
      (LEN (NTH 1 $S)))

    (DEFUN RESIZE-A (K $S)
      (DECLARE (XARGS :GUARD ($SP $S) :VERIFY-GUARDS T))
      (UPDATE-NTH 1
                  (RESIZE-LIST (NTH 1 $S) K 9)
                  $S))

  It is important to note that the implementation of array resizing in
  ACL2 involves copying the entire array into a newly allocated space
  and thus can be quite costly if performed often. This approach was
  chosen in order to make array access and update as efficient as
  possible, with the suspicion that for most applications, array
  access and update are considerably more frequent than resizing
  (especially if the programmer is aware of the relative costs
  beforehand).

  It should also be noted that computations of lengths of stobj array
  fields should be fast (constant-time) in all or most Common Lisp
  implementations.

  Finally, if :resizable t is not supplied as shown above, then an
  attempt to resize the array will result in an error. If you do not
  intend to resize the array, it is better to omit the :resizable
  option (or to supply :resizable nil), since then the length
  function will be defined to return a constant, namely the initial
  length, which can simplify guard proofs (compare with the
  definition of A-LENGTH above).

  This completes the tour through the documentation of [stobj]s.
  However, you may now wish to read the documentation for the event
  that introduces a new single-threaded object; see [defstobj].")
 (STOBJ-LET (POINTERS)
            "See [nested-stobjs].")
 (STOBJS (POINTERS)
         "See [xargs] for keyword :stobjs.")
 (STOP-PROOF-TREE
  (PROOF-TREE)
  "Stop displaying proof trees during proofs

  Also see [proof-tree] and see [start-proof-tree]. Note that
  :stop-proof-tree works by adding '[proof-tree] to the
  inhibit-output-lst; see [set-inhibit-output-lst].

  Proof tree displays are explained in the documentation for
  [proof-tree]. :Stop-proof-tree causes proof tree display to be
  turned off.

  It is permissible to submit the form (stop-proof-tree) during a
  break. Thus, you can actually turn off proof tree display in the
  middle of a proof by interrupting ACL2 and submitting the form
  (stop-proof-tree) in raw Lisp.")
 (STRING
  (STRINGS ACL2-BUILT-INS)
  "[coerce] to a string

  (String x) [coerce]s x to a string.

  The [guard] for string requires its argument to be a string, a
  symbol, or a character.

    * If x is already a string, then it is returned unchanged.
    * If x is a symbol, then its [symbol-name] is returned.
    * If x is a character, the corresponding one-character string is
      returned.

  Note: this is a rather low-level operation that doesn't support
  coercing numbers or conses into strings. If you want to turn
  numbers into strings, see functions such as [str::natstr], or more
  generally the [str::numbers] functions. For conses, see the
  [str::pretty-printing] routines such as [str::pretty].

  String is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: 

    (defun string (x)
           (declare (xargs :guard (or (stringp x)
                                      (symbolp x)
                                      (characterp x))))
           (cond ((stringp x) x)
                 ((symbolp x) (symbol-name x))
                 (t (coerce (list x) 'string))))")
 (STRING-APPEND
  (STRINGS ACL2-BUILT-INS)
  "[concatenate] two strings

  String-append takes two arguments, which are both strings (if the
  [guard] is to be met), and returns a string obtained by
  concatenating together the [characters] in the first string
  followed by those in the second. Also see [concatenate], noting
  that the macro call

    (concatenate 'string str1 str2).

  expands to the call

    (string-append str1 str2).

  Function: 

    (defun string-append (str1 str2)
           (declare (xargs :guard (and (stringp str1) (stringp str2))))
           (mbe :logic (coerce (append (coerce str1 'list)
                                       (coerce str2 'list))
                               'string)
                :exec (concatenate 'string str1 str2)))")
 (STRING-DOWNCASE
  (STRINGS ACL2-BUILT-INS)
  "In a given string, turn upper-case [characters] into lower-case

  For a string x, (string-downcase x) is the result of applying
  [char-downcase] to each character in x.

  The [guard] for string-downcase requires its argument to be a string
  containing only standard characters.

  String-downcase is a Common Lisp function. See any Common Lisp
  documentation for more information.

  Function: 

    (defun
       string-downcase (x)
       (declare
            (xargs :guard (and (stringp x)
                               (standard-char-listp (coerce x 'list)))))
       (coerce (string-downcase1 (coerce x 'list))
               'string))")
 (STRING-EQUAL
  (STRINGS ACL2-BUILT-INS)
  "String equality without regard to case

  For strings str1 and str2, (string-equal str1 str2) is true if and
  only str1 and str2 are the same except perhaps for the cases of
  their [characters].

  The [guard] on string-equal requires that its arguments are strings
  consisting of standard characters (see [standard-char-listp]).

  String-equal is a Common Lisp function. See any Common Lisp
  documentation for more information.

  Function: 

    (defun
     string-equal (str1 str2)
     (declare
         (xargs :guard (and (stringp str1)
                            (standard-char-listp (coerce str1 'list))
                            (stringp str2)
                            (standard-char-listp (coerce str2 'list)))))
     (let ((len1 (length str1)))
          (and (= len1 (length str2))
               (string-equal1 str1 str2 0 len1))))")
 (STRING-LISTP
  (STRINGS LISTS ACL2-BUILT-INS)
  "Recognizer for a true list of strings

  The predicate string-listp tests whether its argument is a
  [true-listp] of strings.

  Function: 

    (defun string-listp (x)
           (declare (xargs :guard t))
           (cond ((atom x) (eq x nil))
                 (t (and (stringp (car x))
                         (string-listp (cdr x))))))")
 (STRING-UPCASE
  (STRINGS ACL2-BUILT-INS)
  "In a given string, turn lower-case [characters] into upper-case

  For a string x, (string-upcase x) is the result of applying
  [char-upcase] to each character in x.

  The [guard] for string-upcase requires its argument to be a string
  containing only standard characters.

  String-upcase is a Common Lisp function. See any Common Lisp
  documentation for more information.

  Function: 

    (defun
       string-upcase (x)
       (declare
            (xargs :guard (and (stringp x)
                               (standard-char-listp (coerce x 'list)))))
       (coerce (string-upcase1 (coerce x 'list))
               'string))")
 (STRING<
  (STRINGS ACL2-BUILT-INS)
  "Less-than test for strings

  (String< str1 str2) is non-nil if and only if the string str1
  precedes the string str2 lexicographically, where character
  inequalities are tested using [char<]. When non-nil, (string< str1
  str2) is the first position (zero-based) at which the strings
  differ. Here are some examples.

    ACL2 !>(string< \"abcd\" \"abu\")
    2
    ACL2 !>(string< \"abcd\" \"Abu\")
    NIL
    ACL2 !>(string< \"abc\" \"abcde\")
    3
    ACL2 !>(string< \"abcde\" \"abc\")
    NIL

  The [guard] for string< specifies that its arguments are strings.

  String< is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: 

    (defun string< (str1 str2)
           (declare (xargs :guard (and (stringp str1) (stringp str2))))
           (string<-l (coerce str1 'list)
                      (coerce str2 'list)
                      0))")
 (STRING<=
  (STRINGS ACL2-BUILT-INS)
  "Less-than-or-equal test for strings

  (String<= str1 str2) is non-nil if and only if the string str1
  precedes the string str2 lexicographically or the strings are
  equal. When non-nil, (string<= str1 str2) is the first position
  (zero-based) at which the strings differ, if they differ, and
  otherwise is their common length. See [string<].

  The [guard] for string<= specifies that its arguments are strings.

  String<= is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: 

    (defun string<= (str1 str2)
           (declare (xargs :guard (and (stringp str1) (stringp str2))))
           (if (equal str1 str2)
               (length str1)
               (string< str1 str2)))")
 (STRING>
  (STRINGS ACL2-BUILT-INS)
  "Greater-than test for strings

  (String> str1 str2) is non-nil if and only if str2 precedes str1
  lexicographically. When non-nil, (string> str1 str2) is the first
  position (zero-based) at which the strings differ. See [string<].

  String> is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: >

    (defun string> (str1 str2)
           (declare (xargs :guard (and (stringp str1) (stringp str2))))
           (string< str2 str1))")
 (STRING>=
  (STRINGS ACL2-BUILT-INS)
  "Less-than-or-equal test for strings

  (String>= str1 str2) is non-nil if and only if the string str2
  precedes the string str1 lexicographically or the strings are
  equal. When non-nil, (string>= str1 str2) is the first position
  (zero-based) at which the strings differ, if they differ, and
  otherwise is their common length. See [string>].

  The [guard] for string>= specifies that its arguments are strings.

  String>= is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: =>

    (defun string>= (str1 str2)
           (declare (xargs :guard (and (stringp str1) (stringp str2))))
           (if (equal str1 str2)
               (length str1)
               (string> str1 str2)))")
 (STRINGP
  (STRINGS ACL2-BUILT-INS)
  "Recognizer for strings

  (stringp x) is true if and only if x is a string.")
 (STRINGS
  (PROGRAMMING)
  "Strings are atomic objects that contain character sequences, like
  \"Hello World\".

  See the [std/strings] library for many additional string functions
  and lemmas about the built-in string functions.


Subtopics

  [Coerce]
      Coerce a character list to a string and a string to a list

  [Concatenate]
      Concatenate lists or strings together

  [Count]
      Count the number of occurrences of an item in a string or true-list

  [Length]
      Length of a string or proper list

  [Position]
      Position of an item in a string or a list

  [Remove-duplicates]
      Remove duplicates from a string or a list

  [Reverse]
      Reverse a list or string

  [Search]
      Search for a string or list in another string or list

  [String]
      [coerce] to a string

  [String-append]
      [concatenate] two strings

  [String-downcase]
      In a given string, turn upper-case [characters] into lower-case

  [String-equal]
      String equality without regard to case

  [String-listp]
      Recognizer for a true list of strings

  [String-upcase]
      In a given string, turn lower-case [characters] into upper-case

  [String<]
      Less-than test for strings

  [String<=]
      Less-than-or-equal test for strings

  [String>]
      Greater-than test for strings

  [String>=]
      Less-than-or-equal test for strings

  [Stringp]
      Recognizer for strings

  [Subseq]
      Subsequence of a string or list

  [Substitute]
      Substitute into a string or a list, using [eql] as test")
 (STRIP-CARS
  (ALISTS ACL2-BUILT-INS)
  "Collect up all first components of pairs in a list

  (strip-cars x) is the list obtained by walking through the list x and
  collecting up all first components ([car]s). This function is
  implemented in a tail-recursive way, despite its logical
  definition.

  (strip-cars x) has a [guard] of (alistp x).

  Function: 

    (defun strip-cars (x)
           (declare (xargs :guard (alistp x)))
           (cond ((endp x) nil)
                 (t (cons (car (car x))
                          (strip-cars (cdr x))))))")
 (STRIP-CDRS
  (ALISTS ACL2-BUILT-INS)
  "Collect up all second components of pairs in a list

  (strip-cdrs x) has a [guard] of (alistp x), and returns the list
  obtained by walking through the list x and collecting up all second
  components ([cdr]s). This function is implemented in a
  tail-recursive way, despite its logical definition.

  Function: 

    (defun strip-cdrs (x)
           (declare (xargs :guard (alistp x)))
           (cond ((endp x) nil)
                 (t (cons (cdr (car x))
                          (strip-cdrs (cdr x))))))")
 (STRONG-REWRITE-RULES
  (INTRODUCTION-TO-THE-THEOREM-PROVER)
  "Formulating good rewrite rules

  Suppose you notice the following term in a Key Checkpoint:

    (MEMBER (CAR A) (REV B)).

  You might think of two theorems for handling this term, which we'll
  call the ``weak'' and ``strong'' version of member-rev.

    (defthm member-rev-weak
      (implies (member e b)
               (member e (rev b)))).

    (defthm member-rev-strong
      (iff (member e (rev b))
           (member e b))).

  The ``strong'' version logically implies the ``weak'' version and so
  deserves the adjective. (Recall that ``p <---> q'' is just ``p --->
  q'' and ``q ---> p.'' So the strong version quite literally says
  everything the weak version does and then some.)

  But the ``strong'' version also produces a better rewrite rule. Here
  are the rules generated from these two formulas, phrased as
  directives to ACL2's simplifier:

  member-rev-weak: If you ever see an instance of (MEMBER e (REV b)),
  backchain to (MEMBER e b) (i.e., turn your attention to that term)
  and if you can show that it is true, replace (MEMBER e (REV b)) by
  T.

  member-rev-strong: If you ever see an instance of (MEMBER e (REV b)),
  replace it by (MEMBER e b).

  Technical Note: Actually, both rules concern propositional
  occurrences of the ``target'' expression, (MEMBER e (REV b)), i.e.,
  occurrences of the target in which its truthvalue is the only thing
  of relevance. (Recall that (MEMBER x y) returns the tail of y
  starting with x! Evaluate some simple MEMBER expressions, like
  (MEMBER 3 '(1 2 3 4 5)) to see what we mean.) Both theorems tell us
  about circumstances in which the target is non-NIL (i.e., ``true'')
  without telling us its identity. But ACL2 keeps track of when the
  target is in a propositional occurrence and can use such rules to
  rewrite the target to propositionally equivalent terms.

  So the strong version is better because it will always eliminate
  (MEMBER e (REV b)) in favor of (MEMBER e b). That simpler
  expression may be further reduced if the context allows it. But in
  any case, the strong version eliminates REV from the problem. The
  weak version only eliminates REV when a side-condition can be
  proved.

  While either version may permit us to prove the Key Checkpoint that
  ``suggested'' the rule, the strong version is a better rule to have
  in the database going forward.

  For example, suppose NATS-BELOW returns the list of natural numbers
  below its argument. Imagine two alternative scenarios in which a
  key checkpoint is about to arise involving this term:

    (MEMBER K (REV (NATS-BELOW J)))

  Scenario 1 is when you've got the strong version in your database: it
  will rewrite the key checkpoint term to

    (MEMBER K (NATS-BELOW J))

  and that's what you'll see in the printed checkpoint unless other
  rules reduce it further.

  Scenario 2 is when you have only the weak version in your database:
  the weak rule will attempt to reduce the term above to T and will,
  if there are sufficient rules and hypotheses about K's membership
  in (NATS-BELOW J). But if no such rules or hypotheses are
  available, you'll be confronted with a key checkpoint involving

    (MEMBER K (REV (NATS-BELOW J)))

  and it will not be obvious that the problem would go away if you
  could establish that K is in (NATS-BELOW J). Clearly, Scenario 1 is
  better.

  We recommend that you now practice formulating strong versions of
  rules suggested by terms you might see. See
  [practice-formulating-strong-rules].

  When you are finished with that, use your browser's Back Button to
  return to [introduction-to-key-checkpoints].")
 (SUBLIS
  (ALISTS ACL2-BUILT-INS)
  "Substitute an alist into a tree

  (Sublis alist tree) is obtained by replacing every leaf of tree with
  the result of looking that leaf up in the association list alist.
  However, a leaf is left unchanged if it is not found as a key in
  alist.

  Leaves are looked up using the function [assoc]. The [guard] for
  (sublis alist tree) requires (eqlable-alistp alist). This [guard]
  ensures that the [guard] for [assoc] will be met for each lookup
  generated by sublis.

  Sublis is defined in Common Lisp. See any Common Lisp documentation
  for more information.

  Function: 

    (defun sublis (alist tree)
           (declare (xargs :guard (eqlable-alistp alist)))
           (cond ((atom tree)
                  (let ((pair (assoc tree alist)))
                       (cond (pair (cdr pair)) (t tree))))
                 (t (cons (sublis alist (car tree))
                          (sublis alist (cdr tree))))))")
 (SUBSEQ
  (LISTS STRINGS ACL2-BUILT-INS)
  "Subsequence of a string or list

  For any natural numbers start and end, where start <= end <= (length
  seq), (subseq seq start end) is the subsequence of seq from index
  start up to, but not including, index end. End may be nil, in which
  case it is treated as though it is (length seq), i.e., we obtain
  the subsequence of seq from index start all the way to the end.

  The [guard] for (subseq seq start end) is that seq is a true list or
  a string, start and end are integers (except, end may be nil, in
  which case it is treated as (length seq) for the rest of this
  discussion), and 0 <= start <= end <= (length seq).

  Subseq is a Common Lisp function. See any Common Lisp documentation
  for more information. Note: In Common Lisp the third argument of
  subseq is optional, but in ACL2 it is required, though it may be
  nil as explained above.

  Function: 

    (defun
         subseq (seq start end)
         (declare (xargs :guard (and (or (true-listp seq) (stringp seq))
                                     (integerp start)
                                     (<= 0 start)
                                     (or (null end)
                                         (and (integerp end)
                                              (<= end (length seq))))
                                     (<= start (or end (length seq))))))
         (if (stringp seq)
             (coerce (subseq-list (coerce seq 'list)
                                  start (or end (length seq)))
                     'string)
             (subseq-list seq start (or end (length seq)))))")
 (SUBSETP
  (LISTS ACL2-BUILT-INS)
  "Test if every [member] of one list is a [member] of the other

    General Forms:
    (subsetp x y)
    (subsetp x y :test 'eql)   ; same as above (eql as equality test)
    (subsetp x y :test 'eq)    ; same, but eq is equality test
    (subsetp x y :test 'equal) ; same, but equal is equality test

  (Subsetp x y) is true if and only if every [member] of the list x is
  a member of the list y. The optional keyword, :TEST, has no effect
  logically, but provides the test (default [eql]) used for comparing
  members of the two lists.

  The [guard] for a call of subsetp depends on the test. In all cases,
  both arguments must satisfy [true-listp]. If the test is [eql],
  then one of the arguments must satisfy [eqlable-listp]. If the test
  is [eq], then one of the arguments must satisfy [symbol-listp].

  See [equality-variants] for a discussion of the relation between
  subsetp and its variants:

      (subsetp-eq x lst) is equivalent to (subsetp x lst :test 'eq);

      (subsetp-equal x lst) is equivalent to (subsetp x lst :test 'equal).

  In particular, reasoning about any of these primitives reduces to
  reasoning about the function subsetp-equal.

  Function: 

    (defun subsetp-equal (x y)
           (declare (xargs :guard (and (true-listp y) (true-listp x))))
           (cond ((endp x) t)
                 ((member-equal (car x) y)
                  (subsetp-equal (cdr x) y))
                 (t nil)))

  Subsetp is defined by Common Lisp. See any Common Lisp documentation
  for more information.")
 (SUBSETP-EQ (POINTERS) "See [subsetp].")
 (SUBSETP-EQUAL (POINTERS)
                "See [subsetp].")
 (SUBST
  (CONSES ACL2-BUILT-INS)
  "A single substitution into a tree

  (Subst new old tree) is obtained by substituting new for every
  occurence of old in the given tree.

  Equality to old is determined using the function [eql]. The [guard]
  for (subst new old tree) requires (eqlablep old), which ensures
  that the [guard] for [eql] will be met for each comparison
  generated by subst.

  Subst is defined in Common Lisp. See any Common Lisp documentation
  for more information.

  Function: 

    (defun subst (new old tree)
           (declare (xargs :guard (eqlablep old)))
           (cond ((eql old tree) new)
                 ((atom tree) tree)
                 (t (cons (subst new old (car tree))
                          (subst new old (cdr tree))))))")
 (SUBSTITUTE
  (LISTS STRINGS ACL2-BUILT-INS)
  "Substitute into a string or a list, using [eql] as test

  (Substitute new old seq) is the result of replacing each occurrence
  of old in seq, which is a list or a string, with new.

  The guard for substitute requires that either seq is a string and new
  is a character, or else: seq is a [true-listp] such that either all
  of its members are [eqlablep] or old is eqlablep.

  Substitute is a Common Lisp function. See any Common Lisp
  documentation for more information. Since ACL2 functions cannot
  take keyword arguments (though macros can), the test used in
  substitute is eql.

  Function: 

    (defun
         substitute (new old seq)
         (declare (xargs :guard (or (and (stringp seq) (characterp new))
                                    (and (true-listp seq)
                                         (or (eqlablep old)
                                             (eqlable-listp seq))))))
         (if (stringp seq)
             (coerce (substitute-ac new old (coerce seq 'list)
                                    nil)
                     'string)
             (substitute-ac new old seq nil)))")
 (SUBSUMPTION_OF_INDUCTION_CANDIDATES_IN_APP_EXAMPLE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Subsumption of Induction Candidates in App Example

  After collecting induction suggestions from these three terms

    (app a b)

    (app b c)

    (app a (app b c))

  the system notices that the first and last suggest the same
  decomposition of a: case split on whether a is empty (i.e., (endp
  a)), and in the case where it is not empty, recursively process
  (cdr a). So we are left with two ideas about how to induct:

  Decompose a as we would to unwind (app a b).

  Decompose b as we would to unwind (app b c).")
 (SUBVERSIVE-INDUCTIONS
  (MISCELLANEOUS)
  "Why we restrict [encapsulate]d recursive functions

  See [subversive-recursions].")
 (SUBVERSIVE-RECURSIONS
  (MISCELLANEOUS)
  "Why we restrict [encapsulate]d recursive functions

  Subtleties arise when one of the ``constrained'' functions, f,
  introduced in the [signature] of an [encapsulate] event, is
  involved in the termination argument for a non-local recursively
  defined function, g, in that encapsulate. During the processing of
  the encapsulated events, f is locally defined to be some witness
  function, f'. Properties of f' are explicitly proved and exported
  from the encapsulate as the constraints on the undefined function
  f. But if f is used in a recursive g defined within the
  encapsulate, then the termination proof for g may use properties of
  f' --- the witness --- that are not explicitly set forth in the
  constraints stated for f.

  Such recursive g are said be ``subversive'' because if naively
  treated they give rise to unsound induction schemes or (via
  functional instantiation) recurrence equations that are impossible
  to satisfy. We illustrate what could go wrong below.

  Subversive recursions are not banned outright. Instead, they are
  treated as part of the constraint. That is, in the case above, the
  definitional equation for g becomes one of the constraints on f.
  This is generally a severe restriction on future functional
  instantiations of f. In addition, ACL2 removes from its knowledge
  of g any suggestions about legal inductions to ``unwind'' its
  recursion.

  What should you do? Often, the simplest response is to move the
  offending recursive definition, e.g., g, out of the encapsulate.
  That is, introduce f by constraint and then define g as an
  ``independent'' event. You may need to constrain ``additional''
  properties of f in order to admit g, e.g., constrain it to reduce
  some ordinal measure. However, by separating the introduction of f
  from the admission of g you will clearly identify the necessary
  constraints on f, functional instantiations of f will be simpler,
  and g will be a useful function which suggests inductions to the
  theorem prover.

  Note that the functions introduced in the [signature] should not even
  occur ancestrally in the termination proofs for non-local recursive
  functions in the encapsulate. That is, the constrained functions of
  an encapsulate should not be reachable in the dependency graph of
  the functions used in the termination arguments of recursive
  functions in encapsulate. If they are reachable, their definitions
  become part of the constraints.

  The following event illustrates the problem posed by subversive
  recursions.

    (encapsulate (((f *) => *))
      (local (defun f (x) (cdr x)))
      (defun g (x)
        (if (consp x) (not (g (f x))) t)))

  Suppose, contrary to how ACL2 works, that the encapsulate above were
  to introduce no constraints on f on the bogus grounds that the only
  use of f in the encapsulate is in an admissible function. We
  discuss the plausibility of this bogus argument in a moment.

  Then it would be possible to prove the theorem:

    (defthm f-not-identity
      (not (equal (f '(a . b)) '(a . b)))
      :rule-classes nil
      :hints ((\"Goal\" :use (:instance g (x '(a . b))))))

  simply by observing that if (f '(a . b)) were '(a . b), then (g '(a .
  b)) would be (not (g '(a . b))), which is impossible.

  But then we could functionally instantiate f-not-identity, replacing
  f by the identity function, to prove nil! This is bad.

    (defthm bad
      nil
      :rule-classes nil
      :hints
      ((\"Goal\" :use (:functional-instance f-not-identity (f identity)))))

  This sequence of events was legal in versions of ACL2 prior to
  Version 1.5. When we realized the problem we took steps to make it
  illegal. However, our steps were insufficient and it was possible
  to sneak in a subversive function (via mutual recursion) as late as
  Version 2.3.

  We now turn to the plausibility of the bogus argument above. Why
  might one even be tempted to think that the definition of g above
  poses no constraint on f? Here is a very similar encapsulate.

    (encapsulate (((f *) => *))
      (local (defun f (x) (cdr x)))
      (defun map (x)
        (if (consp x)
            (cons (f x) (map (cdr x)))
          nil)))

  Here map plays the role of g above. Like g, map calls the constrained
  function f. But map truly does not constrain f. In particular, the
  definition of map could be moved ``out'' of the encapsulate so that
  map is introduced afterwards. The difference between map and g is
  that the constrained function plays no role in the termination
  argument for the one but does for the other.

  As a ``user-friendly'' gesture, ACL2 implicitly moves map-like
  functions out of encapsulations; logically speaking, they are
  introduced after the encapsulation. This simplifies the constraint.
  When the constraint cannot be thus simplfied the user is advised,
  via the ``infected'' warning, to phrase the encapsulation in the
  simplest way possible.

  The lingering bug between Versions 1.5 and 2.3 mentioned above was
  due to our failure to detect the g-like nature of some functions
  when they were defined in mutually recursively cliques with other
  functions. The singly recursive case was recognized. The bug arose
  because our detection ``algorithm'' was based on the ``suggested
  inductions'' left behind by successful definitions. We failed to
  recall that mutually-recursive definitions do not, as of this
  writing, make any suggestions about inductions and so did not leave
  any traces of their subversive natures.

  We conclude by elaborating on the criterion ``involved in the
  termination argument'' mentioned at the outset. Suppose that
  function f is recursively defined in an [encapsulate], where the
  body of f has no ``ancestor'' among the functions introduced in the
  signature of that [encapsulate], i.e.: the body contains no call of
  a signature function, no call of a function whose body calls a
  signature function, and so on. Then ACL2 treats f as though it is
  defined in front of that encapsulate form; so f is not constrained
  by the encapsulate, and its definition is hence certainly not
  subversive in the sense discussed above. But suppose to the
  contrary that some function introduced in the signature is an
  ancestor of the body of f. Then the definition of f is subversive
  if moreover, its termination proof obligation has an ancestor among
  the signature functions. Now, that proof obligation involves terms
  from the first argument of selected calls of IF, as well as
  recursive calls; for a detailed discussion, see [ruler-extenders].
  The important point here is that for the recursive calls, only the
  arguments in ``measured'' positions are relevant to the termination
  proof obligation. Consider the following example.

    (encapsulate
     (((h *) => *))
     (local (defun h (n) n))
     (defun f (i n)
       (if (zp i)
           n
         (f (1- i) (h n)))))

  ACL2 heuristically picks the measure (acl2-count i) for the
  definition of f; thus, i is the only ``measured formal'' of f.
  Since i is the first formal of f, then for the recursive call of f,
  only the first argument contributes to the termination proof
  obligation: in this case, (1- i) but not (h n). Thus, even though h
  is a signature function, the definition of f is not considered to
  be subversive; an induction scheme is thus stored for f. (This
  restriction to measured formal positions of recursive calls, for
  determining subversive definitions, is new in Version_3.5 of ACL2.)")
 (SUGGESTED_INDUCTIONS_IN_THE_ASSOCIATIVITY_OF_APP_EXAMPLE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Suggested Inductions in the Associativity of App Example

  To find a plausible induction argument, the system studies the
  recursions exhibited by the terms in the conjecture.

  Roughly speaking, a call of a recursive function ``suggests'' an
  induction if the argument position decomposed in recursion is
  occupied by a variable.

  In this conjecture, three terms suggest inductions:

    (app a b)

    (app b c)

    (app a (app b c))

  The variable recursively decomposed is indicated in bold.")
 (SYMBOL-<
  (SYMBOLS ACL2-BUILT-INS)
  "Less-than test for symbols

  (symbol-< x y) is non-nil if and only if either the [symbol-name] of
  the symbol x lexicographially precedes the [symbol-name] of the
  symbol y (in the sense of [string<]) or else the [symbol-name]s are
  equal and the [symbol-package-name] of x lexicographically precedes
  that of y (in the same sense). So for example, (symbol-< 'abcd
  'abce) and (symbol-< 'acl2::abcd 'foo::abce) are true.

  The [guard] for symbol specifies that its arguments are symbols.

  Function: 

    (defun symbol-< (x y)
           (declare (xargs :guard (and (symbolp x) (symbolp y))))
           (let ((x1 (symbol-name x))
                 (y1 (symbol-name y)))
                (or (string< x1 y1)
                    (and (equal x1 y1)
                         (string< (symbol-package-name x)
                                  (symbol-package-name y))))))")
 (SYMBOL-ALISTP
  (ALISTS ACL2-BUILT-INS)
  "Recognizer for association lists with symbols as keys

  (Symbol-alistp x) is true if and only if x is a list of pairs of the
  form (cons key val) where key is a [symbolp].

  Function: 

    (defun symbol-alistp (x)
           (declare (xargs :guard t))
           (cond ((atom x) (eq x nil))
                 (t (and (consp (car x))
                         (symbolp (car (car x)))
                         (symbol-alistp (cdr x))))))")
 (SYMBOL-LISTP
  (SYMBOLS LISTS ACL2-BUILT-INS)
  "Recognizer for a true list of symbols

  The predicate symbol-listp tests whether its argument is a true list
  of symbols.

  Function: 

    (defun symbol-listp (lst)
           (declare (xargs :guard t))
           (cond ((atom lst) (eq lst nil))
                 (t (and (symbolp (car lst))
                         (symbol-listp (cdr lst))))))")
 (SYMBOL-NAME
  (SYMBOLS ACL2-BUILT-INS)
  "The name of a symbol (a string)

  Completion Axiom (completion-of-symbol-name):

    (equal (symbol-name x)
           (if (symbolp x)
               (symbol-name x)
             \"\"))

  [Guard] for (symbol-name x):

    (symbolp x)")
 (SYMBOL-PACKAGE-NAME
  (SYMBOLS PACKAGES ACL2-BUILT-INS)
  "The name of the package of a symbol (a string)

  WARNING: While symbol-package-name behaves properly on all ACL2
  objects, it may give surprising results when called in raw Lisp.
  For more details see [pkg-imports], in particular the discussion
  there of the \"COMMON-LISP\" package.

  Completion Axiom (completion-of-symbol-package-name):

    (equal (symbol-package-name x)
           (if (symbolp x)
               (symbol-package-name x)
             \"\"))

  [Guard] for (symbol-package-name x):

    (symbolp x)

  Note: Symbol-package-name may diverge from the name of the symbol's
  package in raw Lisp, in the case that this package is the main Lisp
  package. For example, in GCL (symbol-package-name 'car) evaluates
  to \"COMMON-LISP\" even though the actual package name for the
  symbol, car, is \"LISP\".")
 (SYMBOLIC_EXECUTION_OF_MODELS
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Symbolic Execution of Models

  [{IMAGE}]

  But ACL2 is more than a programming language.

  Initialize x to 5 and let y be any legal value.

  {IMAGE}

  Because ACL2 is a mathematical language, we can simplify the
  expression

    (lookup 'z (mc (s 'mult 5 y) 29))

  and get (+ y y y y y). This is symbolic execution because not all of
  the parameters are known.

  [{IMAGE}]")
 (SYMBOLP
  (SYMBOLS ACL2-BUILT-INS)
  "Recognizer for symbols

  (symbolp x) is true if and only if x is a symbol.


Subtopics

  [Intern]
      Create a new symbol in a given package

  [Intern$]
      Create a new symbol in a given package

  [Intern-in-package-of-symbol]
      Create a symbol with a given name")
 (SYMBOLS
  (PROGRAMMING)
  "Symbols in ACL2 and operations on them

  Symbols are a basic datatype in ACL2 and Common Lisp. Every symbol
  has two components: its name (see [symbol-name]) and its package
  name (see [symbol-package-name]).


Subtopics

  [Add-to-set]
      Add a symbol to a list

  [Keywordp]
      Recognizer for keywords

  [Symbol-<]
      Less-than test for symbols

  [Symbol-listp]
      Recognizer for a true list of symbols

  [Symbol-name]
      The name of a symbol (a string)

  [Symbol-package-name]
      The name of the package of a symbol (a string)

  [Symbolp]
      Recognizer for symbols")
 (SYNTAX
  (MISCELLANEOUS)
  "The syntax of ACL2 is that of Common Lisp

  For the details of ACL2 syntax, see CLTL. For examples of ACL2
  syntax, use :[pe] to print some of the ACL2 system code. For
  example:

    :pe assoc-equal
    :pe dumb-occur
    :pe var-fn-count
    :pe add-linear-variable-to-alist

  There is no comprehensive description of the ACL2 syntax yet, except
  that found in CLTL. Also see [term].")
 (SYNTAXP
  (REWRITE DEFINITION LINEAR META)
  "Attach a heuristic filter on a rule

  A call of syntaxp in the hypothesis of a :[rewrite], :[definition],
  or :[linear] rule is treated specially, as described below. Similar
  treatment is given to the evaluation of a :[meta] rule's hypothesis
  function call.

  For example, consider the :[rewrite] rule created from the following
  formula.

    Example:
    (IMPLIES (SYNTAXP (NOT (AND (CONSP X)
                                (EQ (CAR X) 'NORM))))
             (EQUAL (LXD X)
                    (LXD (NORM X)))).

  The syntaxp hypothesis in this rule will allow the rule to be applied
  to (lxd (trn a b)) but will not allow it to be applied to (lxd
  (norm a)).

    General Form:
    (SYNTAXP test)

  Syntaxp always returns t and so may be added as a vacuous hypothesis.
  However, when relieving the hypothesis, the test ``inside'' the
  syntaxp form is actually treated as a meta-level proposition about
  the proposed instantiation of the rule's variables and that
  proposition must evaluate to true (non-nil) to ``establish'' the
  syntaxp hypothesis.

  Note that the test of a syntaxp hypothesis does not, in general, deal
  with the meaning or semantics or values of the terms, but rather
  with their syntactic forms. In the example above, the syntaxp
  hypothesis allows the rule to be applied to every target of the
  form (lxd u), provided u is not of the form (norm v). Observe that
  without this syntactic restriction the rule above could loop,
  producing a sequence of increasingly complex targets (lxd a), (lxd
  (norm a)), (lxd (norm (norm a))), etc. An intuitive reading of the
  rule might be ``norm the argument of lxd unless it has already been
  normed.''

  Note also that a syntaxp hypothesis deals with the syntactic form
  used internally by ACL2, rather than that seen by the user. In some
  cases these are the same, but there can be subtle differences with
  which the writer of a syntaxp hypothesis must be aware. You can use
  :[trans] to display this internal representation.

  There are two types of syntaxp hypotheses. The simpler type may be a
  hypothesis of a :[rewrite], :[definition], or :[linear] rule
  provided test contains at least one variable but no free variables
  (see [free-variables]). In particular, test may not use [stobj]s;
  any stobj name will be treated as an ordinary variable. The case of
  :[meta] rules is similar to the above, except that it applies to
  the result of applying the hypothesis metafunction. (Later below we
  will describe the second type, an extended syntaxp hypothesis,
  which may use [state].)

  We illustrate the use of simple syntaxp hypotheses by slightly
  elaborating the example given above. Consider a :[rewrite] rule:

    (IMPLIES (AND (RATIONALP X)
                  (SYNTAXP (NOT (AND (CONSP X)
                                     (EQ (CAR X) 'NORM)))))
             (EQUAL (LXD X)
                    (LXD (NORM X))))

  How is this rule applied to (lxd (trn a b))? First, we form a
  substitution that instantiates the left-hand side of the conclusion
  of the rule so that it is identical to the target term. In the
  present case, the substitution replaces x with (trn a b).

    (LXD X) ==> (LXD (trn a b)).

  Then we backchain to establish the hypotheses, in order. Ordinarily
  this means that we instantiate each hypothesis with our
  substitution and then attempt to rewrite the resulting instance to
  true. Thus, in order to relieve the first hypothesis above, we
  rewrite

    (RATIONALP (trn a b)).

  If this rewrites to true, we continue.

  Of course, many users are aware of some exceptions to this general
  description of the way we relieve hypotheses. For example, if a
  hypothesis contains a ``free-variable'' --- one not bound by the
  current substitution --- we attempt to extend the substitution by
  searching for an instance of the hypothesis among known truths. See
  [free-variables]. [Force]d hypotheses are another exception to the
  general rule of how hypotheses are relieved.

  Hypotheses marked with syntaxp, as in (syntaxp test), are also
  exceptions. We instantiate such a hypothesis; but instead of
  rewriting the instantiated instance, we evaluate the instantiated
  test. More precisely, we evaluate test in an environment in which
  its variable symbols are bound to the quotations of the terms to
  which those variables are bound in the instantiating substitution.
  So in the case in point, we (in essence) evaluate

    (NOT (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))).

  This clearly evaluates to t. When a syntaxp test evaluates to true,
  we consider the syntaxp hypothesis to have been established; this
  is sound because logically (syntaxp test) is t regardless of test.
  If the test evaluates to nil (or fails to evaluate because of
  [guard] violations) we act as though we cannot establish the
  hypothesis and abandon the attempt to apply the rule; it is always
  sound to give up.

  The acute reader will have noticed something odd about the form

    (NOT (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))).

  When relieving the first hypothesis, (RATIONALP X), we substituted
  (trn a b) for X; but when relieving the second hypothesis, (SYNTAXP
  (NOT (AND (CONSP X) (EQ (CAR X) 'NORM)))), we substituted the
  quotation of (trn a b) for X. Why the difference? Remember that in
  the first hypothesis we are talking about the value of (trn a b)
  --- is it rational --- while in the second one we are talking about
  its syntactic form. Remember also that Lisp, and hence ACL2,
  evaluates the arguments to a function before applying the function
  to the resulting values. Thus, we are asking ``Is the list (trn a
  b) a [consp] and if so, is its [car] the symbol NORM?'' The quotes
  on both (trn a b) and NORM are therefore necessary. One can verify
  this by defining trn to be, say [cons], and then evaluating forms
  such as

    (AND (CONSP '(trn a b)) (EQ (CAR '(trn a b)) 'NORM))
    (AND (CONSP (trn a b)) (EQ (CAR (trn a b)) NORM))
    (AND (CONSP (trn 'a 'b)) (EQ (CAR (trn 'a 'b)) NORM))
    (AND (CONSP '(trn a b)) (EQ '(CAR (trn a b)) ''NORM))

  at the top-level ACL2 prompt.

  See [syntaxp-examples] for more examples of the use of syntaxp.

  An extended syntaxp hypothesis is similar to the simple type
  described above, but it uses two additional variables, mfc and
  state, which must not be bound by the left hand side or an earlier
  hypothesis of the rule. They must be the last two variables
  mentioned by form; first mfc, then state. These two variables give
  access to the functions mfc-xxx; see [extended-metafunctions]. As
  described there, mfc is bound to the so-called metafunction-context
  and state to ACL2's [state]. See [syntaxp-examples] for an example
  of the use of these extended syntaxp hypotheses.

  We conclude with an example illustrating an error that may occur if
  you forget that a syntaxp hypothesis will be evaluated in an
  environment where variables are bound to syntactic terms, not to
  values. Consider the following [stobj] introduction (see
  [defstobj]).

    (defstobj st
      (fld1 :type (signed-byte 3) :initially 0)
      fld2)

  The following syntaxp hypothesis is ill-formed for evaluation.
  Indeed, ACL2 causes an error because it anticipates that when
  trying to relieve the syntaxp hypothesis of this rule, ACL2 would
  be evaluating (fld1 st) where st is bound to a term, not to an
  actual stobj as required by the function fld1. The error message is
  intended to explain this problem.

    ACL2 !>(defthm bad
             (implies (syntaxp (quotep (fld1 st)))
                      (equal (stp st)
                             (and (true-listp st)
                                  (equal (len st) 2)
                                  (fld1p (car st))))))

    ACL2 Error in ( DEFTHM BAD ...):  The form (QUOTEP (FLD1 ST)), from
    a SYNTAXP hypothesis, is not suitable for evaluation in an environment
    where its variables are bound to terms.  See :DOC SYNTAXP.  Here is
    further explanation:
         The form ST is being used, as an argument to a call of FLD1, where
    the single-threaded object of that name is required.  But in the current
    context, the only declared stobj name is STATE.  Note:  this error
    occurred in the context (FLD1 ST).

    Summary
    Form:  ( DEFTHM BAD ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

    ACL2 Error in ( DEFTHM BAD ...):  See :DOC failure.

    ******** FAILED ********
    ACL2 !>

  Presumably the intention was to rewrite the term (stp st) when the
  fld1 component of st is seen to be an explicit constant. As
  explained elsewhere (see [free-variables]), we can obtain the
  result of rewriting (fld1 st) by binding a fresh variable to that
  term using EQUAL, as follows.

    (defthm good
      (implies (and (equal f (fld1 st))
                    (syntaxp (quotep f)))
               (equal (stp st)
                      (and (true-listp st)
                           (equal (len st) 2)
                           (fld1p (car st))))))

  The event above is admitted by ACL2. We can see it in action by
  disabling the definition of stp so that only the rule above, good,
  is available for reasoning about stp.

    (in-theory (disable stp))

  Then the proof fails for the following, because the syntaxp
  hypothesis of the rule, good, fails: (quotep f) evaluates to nil
  when f is bound to the term (fld1 st).

    (thm (stp st))

  However, the proof succeeds for the next form, as we explain below.

    (thm (stp (list 3 rest)))

  Consider what happens in that case when rule good is applied to the
  term (stp (list 3 rest)). (See [free-variables] for relevant
  background.) The first hypothesis of good binds the variable f to
  the result of rewriting (fld1 st), where st is bound to the
  (internal form of) the term (list 3 rest) --- and that result is
  clearly the term, '3. Then the syntaxp hypothesis is successfully
  relieved, because the evaluation of (quotep f) returns t in the
  environment that binds f to '3.


Subtopics

  [Syntaxp-examples]
      Examples pertaining to syntaxp hypotheses")
 (SYNTAXP-EXAMPLES
  (SYNTAXP)
  "Examples pertaining to syntaxp hypotheses

  See [syntaxp] for a basic discussion of the use of syntaxp to control
  rewriting.

  A common syntactic restriction is

    (SYNTAXP (AND (CONSP X) (EQ (CAR X) 'QUOTE)))

  or, equivalently,

    (SYNTAXP (QUOTEP X)).

  A rule with such a hypothesis can be applied only if x is bound to a
  specific constant. Thus, if x is 23 (which is actually represented
  internally as (quote 23)), the test evaluates to t; but if x prints
  as (+ 11 12) then the test evaluates to nil (because (car x) is the
  symbol [binary-+]). We see the use of this restriction in the rule

    (implies (and (syntaxp (quotep c))
                  (syntaxp (quotep d)))
             (equal (+ c d x)
                    (+ (+ c d) x))).

  If c and d are constants, then the [executable-counterpart] of
  [binary-+] will evaluate the sum of c and d. For instance, under
  the influence of this rule

    (+ 11 12 foo)

  rewrites to

    (+ (+ 11 12) foo)

  which in turn rewrites to (+ 23 foo). Without the syntactic
  restriction, this rule would loop with the built-in rules
  ASSOCIATIVITY-OF-+ or COMMUTATIVITY-OF-+.

  We here recommend that the reader try the affects of entering
  expressions such as the following at the top level ACL2 prompt.

    (+ 11 23)
    (+ '11 23)
    (+ '11 '23)
    (+ ''11 ''23)
    :trans (+ 11 23)
    :trans (+ '11 23)
    :trans (+ ''11 23)
    :trans (+ c d x)
    :trans (+ (+ c d) x)

  We also recommend that the reader verify our claim above about
  looping by trying the affect of each of the following rules
  individually.

    (defthm good
       (implies (and (syntaxp (quotep c))
                     (syntaxp (quotep d)))
                (equal (+ c d x)
                       (+ (+ c d) x))))

    (defthm bad
       (implies (and (acl2-numberp c)
                     (acl2-numberp d))
                (equal (+ c d x)
                       (+ (+ c d) x))))

  on (the false) theorems:

    (thm
      (equal (+ 11 12 x) y))

    (thm
      (implies (and (acl2-numberp c)
                    (acl2-numberp d)
                    (acl2-numberp x))
               (equal (+ c d x) y))).

  One can use :[brr], perhaps in conjunction with [cw-gstack], to
  investigate any looping.

  Here is a simple example showing the value of rule good above.
  Without good, the thm form below fails.

    (defstub foo (x) t)

    (thm (equal (foo (+ 3 4 x)) (foo (+ 7 x))))

  The next three examples further explore the use of quote in [syntaxp]
  hypotheses.

  We continue the examples of [syntaxp] hypotheses with a rule from
  community book books/finite-set-theory/set-theory.lisp. We will not
  discuss here the meaning of this rule, but it is necessary to point
  out that (ur-elementp nil) is true in this book.

    (defthm scons-nil
      (implies (and (syntaxp (not (equal a ''nil)))
                    (ur-elementp a))
               (= (scons e a)
                  (scons e nil)))).

  Here also, [syntaxp] is used to prevent looping. Without the
  restriction, (scons e nil) would be rewritten to itself since
  (ur-elementp nil) is true.
  Question: Why the use of two quotes in ''nil?
  Hints: Nil is a constant just as 23 is. Try :trans (cons a nil),
  :trans (cons 'a 'nil), and :trans (cons ''a ''nil). Also, don't
  forget that the arguments to a function are evaluated before the
  function is applied.

  The next two rules move negative constants to the other side of an
  inequality.

    (defthm |(< (+ (- c) x) y)|
      (implies (and (syntaxp (quotep c))
                    (syntaxp (< (cadr c) 0))
                    (acl2-numberp y))
               (equal (< (+ c x) y)
                      (< (fix x) (+ (- c) y)))))

    (defthm |(< y (+ (- c) x))|
      (implies (and (syntaxp (quotep c))
                    (syntaxp (< (cadr c) 0))
                    (acl2-numberp y))
               (equal (< y (+ c x))
                      (< (+ (- c) y) (fix x)))))

  Questions: What would happen if (< (cadr c) '0) were used? What about
  (< (cadr c) ''0)?

  One can also use syntaxp to restrict the application of a rule to a
  particular set of variable bindings as in the following taken from
  the [ihs] library.

    (encapsulate ()

      (local
       (defthm floor-+-crock
         (implies
          (and (real/rationalp x)
               (real/rationalp y)
               (real/rationalp z)
               (syntaxp (and (eq x 'x) (eq y 'y) (eq z 'z))))
          (equal (floor (+ x y) z)
                 (floor (+ (+ (mod x z) (mod y z))
                           (* (+ (floor x z) (floor y z)) z)) z)))))

      (defthm floor-+
        (implies
         (and (force (real/rationalp x))
              (force (real/rationalp y))
              (force (real/rationalp z))
              (force (not (equal z 0))))
         (equal (floor (+ x y) z)
                (+ (floor (+ (mod x z) (mod y z)) z)
                   (+ (floor x z) (floor y z))))))

      )

  We recommend the use of :brr to investigate the use of floor-+-crock.

  Another useful restriction is defined by

    (defun rewriting-goal-literal (x mfc state)

      ;; Are we rewriting a top-level goal literal, rather than rewriting
      ;; to establish a hypothesis from a rewrite (or other) rule?

      (declare (ignore x state))
      (null (access metafunction-context mfc :ancestors))).

  We use this restriction in the rule

    (defthm |(< (* x y) 0)|
        (implies (and (syntaxp (rewriting-goal-literal x mfc state))
                      (rationalp x)
                      (rationalp y))
                 (equal (< (* x y) 0)
                        (cond ((equal x 0)
                               nil)
                              ((equal y 0)
                               nil)
                              ((< x 0)
                               (< 0 y))
                              ((< 0 x)
                               (< y 0))))))

  which has been found to be useful, but which also leads to excessive
  thrashing in the linear arithmetic package if used
  indiscriminately.

  See [extended-metafunctions] for information on the use of mfc and
  metafunction-context.")
 (SYS-CALL
  (INTERFACING-TOOLS ACL2-BUILT-INS)
  "Make a system call to the host operating system

    Example Forms:
    (sys-call \"cp\" '(\"foo.lisp\" \"foo-copied.lisp\"))
    (prog2$ (sys-call \"cp\" '(\"foo.lisp\" \"foo-copied.lisp\"))
            (sys-call-status state))

  The first argument of sys-call is a command for the host operating
  system, and the second argument is a list of strings that are the
  arguments for that command. In GCL and perhaps some other lisps,
  you can put the arguments with the command; but this is not the
  case, for example, in Allegro CL running on Linux.

  For a related utility, see [sys-call+].

  The use of [prog2$] above is optional, but illustrates a typical sort
  of use when one wishes to get the return status. See
  [sys-call-status].

    General Form:
    (sys-call cmd args)

  This function logically returns nil. However, it makes the indicated
  call to the host operating system, as described above, using a
  function supplied ``under the hood'' by the underlying Lisp system.
  On occasions where one wishes to obtain the numeric status returned
  by the host operating system (or more precisely, by the Lisp
  function under the hood that passes the system call to the host
  operating system), one may do so; see [sys-call-status]. The status
  value is the value returned by that Lisp function, which may well
  be the same numeric value returned by the host operating system for
  the underlying system call.

  Note that sys-call does not touch the ACL2 [state]; however,
  [sys-call-status] updates the acl2-oracle field of the state.

  Be careful if you use sys-call! It can be used for example to
  overwrite files, or worse! We view a use of sys-call as a call to
  the operating system that is made outside ACL2. The following
  example from Bob Boyer shows how to use sys-call to execute, in
  effect, arbitrary Lisp forms. ACL2 provides a ``trust tag''
  mechanism that requires execution of a [defttag] form before you
  can use sys-call; see [defttag]. (Note: The setting of the raw Lisp
  variable *features* below is just to illustrate that any such
  mischief is possible. Normally *features* is a list with more than
  a few elements.)

    % cat foo
    print *0x85d2064=0x838E920
    detach
    q
    % acl2
    ... boilerplate deleted
    ACL2 !>(sys-call \"gdb -p $PPID -w < foo >& /dev/null \" nil)
    NIL
    ACL2 !>:q

    Exiting the ACL2 read-eval-print loop.  To re-enter, execute (LP).
    ACL2>*features*

    (:AKCL-SET-MV)

    ACL2>

  Finally, we note that sys-call does not provide some features that
  one may expect of a shell. In particular, sys-call does not
  generally support shell expansion of its arguments (such as ~/). It
  also does not directly support output redirection. If you want to
  run a program, P, and redirect its output, one option is to create
  a wrapper script, W to call instead. Thus W might be a shell script
  containing the line:

    P $* >& foo.out

  For a different, more direct solution, see [sys-call+].


Subtopics

  [Sys-call+]
      Make a system call to the host OS, returning status and output

  [Sys-call-status]
      Exit status from the preceding system call")
 (SYS-CALL+
  (SYS-CALL ACL2-BUILT-INS)
  "Make a system call to the host OS, returning status and output

    Example Form:
    ; The following returns (mv nil s state), where s is the standard output
    ; from the command: ls -l ./
    (sys-call+ \"ls\" '(\"-l\" \"./\") state)

    General Form:
    (sys-call+ cmd args state)

  where cmd is a command to the host operating system and args is a
  list of strings. Also see [sys-call]; but there are two differences
  between [sys-call] and sys-call+. First, the latter takes an extra
  argument, state. Second, while sys-call returns nil, sys-call+
  returns three values: a so-called error triple (see
  [error-triples]), (mv erp val state). While execution returns
  values as described just below, further below we explain the
  logical return values. In the following, please keep in mind that
  the exact behavior depends on the platform; the description is only
  a guide. For example, on some platforms erp might always be nil,
  even if in the error case, and val might or might not include error
  output. (For details, look at the ACL2 source code for function
  system-call+, whose output is converted by replacing an erp of nil
  by 0.)

      Erp is either nil or a non-zero integer. Normally, nil indicates that
      the command ran without error, and otherwise erp is the exit
      status.

      Val is a string, typically the output generated by the call of cmd.

      State is an ACL2 [state].

  While the description above pertains to the values returned by
  executing sys-call+, the logical values are as follows. For a
  discussion of the acl2-oracle field of an ACL2 state, see
  [read-ACL2-oracle] and [state].

      Erp is the first element of the acl2-oracle of the input state if
      that element is a nonzero integer, and otherwise is nil.

      Val is the second element of the acl2-oracle of the input state if it
      is a string, else the empty string, \"\".

      State is the result of popping the acl2-oracle field twice from the
      input state.

  Note that unlike [sys-call], a call of [sys-call+] has no effect on
  subsequent calls of [sys-call-status].

  As is the case for sys-call, a trust tag is required to call
  sys-call+. For discussion of this and more, see [sys-call].")
 (SYS-CALL-STATUS
  (SYS-CALL ACL2-BUILT-INS)
  "Exit status from the preceding system call

  This function returns two values, (mv status state). The first is the
  status resulting from the most recent invocation of function
  sys-call; see [sys-call]. The second is the ACL2 [state] object,
  which is also the input to this function.

  The function [sys-call] makes a system call to the host operating
  system using a function supplied ``under the hood'' by the
  underlying Lisp system. The status value is the value returned by
  that Lisp function, which may well be the numeric value returned by
  the host operating system for the underlying system call. For more
  information, see [sys-call].")
 (TABLE
  (EVENTS)
  "User-managed tables

    Examples:
    (table tests 1 '(...))                ; set contents of tests[1] to '(...)
    (table tests 25)                      ; get contents of tests[25]
    (table tests)                         ; return table tests as an alist
    (table tests nil nil :clear)          ; clear table tests
    (table tests nil '((foo . 7)) :clear) ; set table tests to ((foo . 7))
    (table tests nil nil :guard)          ; fetch the table guard
    (table tests nil nil :guard term)     ; set the table guard

    General Form:
    (table table-name key-term value-term op term)

  where table-name is a symbol that is the name of a (possibly new)
  table, key-term and value-term, if present, are arbitrary terms
  involving (at most) the single variable [world], op, if present, is
  one of the table operations below, and term, if present, is a term.
  Table returns an ACL2 ``error triple'' (see [error-triples]). The
  effect of table on [state] depends on op and how many arguments are
  presented. Some invocations actually have no effect on the ACL2
  [world] and hence an invocation of table is not always an
  ``event''. We explain below, after giving some background
  information.

  Important Note: The table forms above are calls of a macro that
  expand to involve the special variable [state]. This will prevent
  you from accessing a table from within a hint or theory where you
  do not have the [state] variable. However, the form

    (table-alist 'tests world)

  returns the alist representation of the table named test in the given
  world. Often you have access to world.

  The ACL2 system provides ``tables'' by which the user can associate
  one object with another. Tables are in essence just conventional
  association lists --- lists of pairs --- but the ACL2 environment
  provides a means of storing these lists in the ``ACL2 world'' of
  the current [state]. The ACL2 user could accomplish the same ends
  by using ACL2 ``global variables;'' however, limitations on global
  variable names are imposed to ensure ACL2's soundness. By
  convention, no table is important to ACL2's soundness, even though
  some features of the system use tables, and the user is invited to
  make free use of tables. Because tables are stored in the ACL2
  [world] they are restored by [include-book] and undone by :[ubt].
  Many users of Nqthm requested a facility by which user data could
  be saved in Nqthm ``lib files'' and tables are ACL2's answer to
  that request.

  Abstractly, each table is an association list mapping ``keys'' to
  ``values.'' In addition, each table has a ``:guard,'' which is a
  term that must be true of any key and value used. By setting the
  :guard on a table you may enforce an invariant on the objects in
  the table, e.g., that all keys are positive integers and all values
  are symbols. Each table has a ``name,'' which must be a symbol.
  Given a table name, the following operations can be performed on
  the table.

  :put --- associate a value with a key (possibly changing the value
  currently associated with that key).

  :get --- retrieve the value associated with a key (or nil if no value
  has been associated with that key).

  :alist --- return an alist showing all keys and non-nil values in the
  table.

  :clear --- clear the table (so that every value is nil), or if val is
  supplied then set table to that value (which must be an alist).

  :guard --- fetch or set the :guard of the table.

  When the operations above suggest that the table or its :guard are
  modified, what is actually meant is that the current [state] is
  redefined so that in it, the affected table name has the
  appropriate properties. in such cases, the table form is an event
  (see [events]). In the :put case, if the key is already in the
  table and associated with the proposed value, then the table event
  is redundant (see [redundant-events]).

  Table forms are commonly typed by the user while interacting with the
  system. :Put and :get forms are especially common. Therefore, we
  have adopted a positional syntax that is intended to be convenient
  for most applications. Essentially, some operations admit a ``short
  form'' of invocation.

    (table name key-term value-term :put)   ; long form
    (table name key-term value-term)        ; short form

  evaluates the key- and value-terms, obtaining two objects that we
  call key and value, checks that the key and value satisfy the
  :guard on the named table and then ``modifies'' the named table so
  that the value associated with key is value. When used like this,
  table is actually an event in the sense that it changes the ACL2
  [world]. In general, the forms evaluated to obtain the key and
  value may involve the variable [world], which is bound to the
  then-current [world] during the evaluation of the forms. However,
  in the special case that the table in question is named
  [ACL2-defaults-table], the key and value terms may not contain any
  variables. Essentially, the keys and values used in [events]
  setting the [ACL2-defaults-table] must be explicitly given
  constants. See [ACL2-defaults-table].

    (table name key-term nil :get)          ; long form
    (table name key-term)                   ; short form

  evaluates the key-term (see note below), obtaining an object, key,
  and returns the value associated with key in the named table (or,
  nil if there is no value associated with key). When used like this,
  table is not an event; the value is simply returned.

    (table name nil nil :alist)             ; long form
    (table name)                            ; short form

  returns an alist representing the named table; for every key in the
  table with a non-nil associated value, the alist pairs the key and
  its value. The order in which the keys are presented is
  unspecified. When used like this, table is not an event; the alist
  is simply returned.

    (table name nil val :clear)

  sets the named table to the alist val, making the checks that :put
  makes for each key and value of val. When used like this, table is
  an event because it changes the ACL2 [world].

    (table name nil nil :guard)

  returns the translated form of the guard of the named table.

    (table name nil nil :guard term)

  Provided the named table is empty and has not yet been assigned a
  :guard and term (which is not evaluated) is a term that mentions at
  most the variables key, val and [world], this event sets the :guard
  of the named table to term. Whenever a subsequent :put occurs, term
  will be evaluated with key bound to the key argument of the :put,
  val bound to the val argument of the :put, and [world] bound to the
  then current [world]. An error will be caused by the :put if the
  result of the evaluation is nil.

  Note that it is not allowed to change the :guard on a table once it
  has been explicitly set. Before the :guard is explicitly set, it is
  effectively just t. After it is set it can be changed only by
  undoing the event that set it. The purpose of this restriction is
  to prevent the user from changing the :guards on tables provided by
  other people or the system.

  The intuition behind the :guard mechanism on tables is to enforce
  invariants on the keys and values in a table, so that the values,
  say, can be used without run-time checking. But if the :guard of a
  table is sensitive to the ACL2 [world], it may be possible to cause
  some value in the table to cease satisfying the :guard without
  doing any operations on the table. Consider for example the :guard
  ``no value in this table is the name of an event.'' As described,
  that is enforced each time a value is stored. Thus, 'bang can be
  :put in the table provided there is no event named bang. But once
  it is in the table, there is nothing to prevent the user from
  defining bang as a function, causing the table to contain a value
  that could not be :put there anymore. Observe that not all
  state-sensitive :guards suffer this problem. The :guard ``every
  value is an event name'' remains invariant, courtesy of the fact
  that undoing back through an event name in the table would
  necessarily undo the :put of the name into the table.

  Table was designed primarily for convenient top-level use. Tables are
  not especially efficient. Each table is represented by an alist
  stored on the property list of the table name. :Get is just a
  getprop and [assoc-equal]. :Put does a getprop to the get the table
  alist, a put-assoc-equal to record the new association, and a
  putprop to store the new table alist --- plus the overhead
  associated with :guards and undoable [events], and checking (for
  redundancy) if the key is already bound to its proposed value. Note
  that there are never duplicate keys in the resulting alist; in
  particular, when the operation :clear is used to install new alist,
  duplicate keys are removed from that alist.

  A table name may be any symbol whatsoever. Symbols already in use as
  function or theorem names, for example, may be used as table names.
  Symbols in use only as table names may be defined with [defun],
  etc. Because there are no restrictions on the user's choice of
  table names, table names are not included among the logical names.
  Thus, :pe name will never display a table event (for a logical name
  other than :here). Either :pe name will display a ``normal'' event
  such as (defun name ...) or (defthm name ...) or else :pe name will
  cause an error indicating that name is not a logical name. This
  happens even if name is in use as a table name. Similarly, we do
  not permit table names to have [documentation] strings, since the
  same name might already have a [documentation] string. If you want
  to associate a [documentation] string with a table name that is
  being used no other way, define the name as a label and use the
  :[doc] feature of [deflabel] (see [deflabel]); also see [defdoc].


Subtopics

  [ACL2-defaults-table]
      A [table] specifying certain defaults, e.g., the default
      [defun-mode]

  [Using-tables-efficiently]
      Notes on how to use tables efficiently")
 (TAKE
  (LISTS ACL2-BUILT-INS)
  "Initial segment (first n elements) of a list

  For any natural number n not exceeding the length of l, (take n l)
  collects the first n elements of the list l.

  The following is a theorem (though it takes some effort, including
  lemmas, to get ACL2 to prove it):

    (equal (length (take n l)) (nfix n))

  If n is an integer greater than the length of l, then take pads the
  list with the appropriate number of nil elements. Thus, the
  following is also a theorem.

    (implies (and (integerp n)
                  (true-listp l)
                  (<= (length l) n))
             (equal (take n l)
                    (append l (make-list (- n (length l))))))

  For related functions, see [nthcdr] and see [butlast].

  The [guard] for (take n l) is that n is a nonnegative integer and l
  is a true list.

  Function: 

    (defun take (n l)
           (declare (xargs :guard (and (integerp n)
                                       (not (< n 0))
                                       (true-listp l))))
           (first-n-ac n l nil))")
 (TAU-DATA
  (TAU-SYSTEM)
  "To see what tau knows about a function symbol

    Examples:
    (tau-data binary-+)

    General Form:
    (tau-data fn)

  This macro returns a list structure that indicates what facts about
  the symbol fn are known to the tau system. Fn should either be a
  function symbol or else a macro associated with fn; see
  [macro-aliases-table]. See [introduction-to-the-tau-system] for
  background details.

  The list structure should be self-explanatory given the following
  brief comments. The ``index'' of a function, when non-nil, means
  the function is a monadic Boolean function treated by the tau
  system as a tau predicate.

  The ``positive'' and ``negative implicants'' are conjunctions that
  indicate the tau implied by the given one or its negation.

  The ``signatures'' entry is a formula indicating all the known
  signatures. If the signatures formula is T it means there are no
  known signatures. (Signatures is the conjunction of all signature
  rules and the empty conjunction is T.)

  If you wish to see a long list of all the runes from which some tau
  information has been gleaned, evaluate (global-val 'tau-runes (w
  state)).")
 (TAU-DATABASE
  (TAU-SYSTEM HISTORY)
  "To see the tau database as a (very large) object

    Example:
    (tau-database (w state))

  This function returns a large list object that shows in a
  human-readable way what the tau system knows about every function
  symbol. It is supposed to be self-explanatory. See
  [introduction-to-the-tau-system] for background details.

  If the output is not self-explanatory, please contact the
  implementors and we will improve the output or the documentation.")
 (TAU-INTERVAL-DOM
  (TAU-SYSTEM)
  "Access the domain of a tau interval

  It is the case that

    (tau-interval-dom (make-tau-interval dom lo-rel lo hi-rel hi)) = dom

  For a well-formed interval, dom is one of the symbols INTEGERP,
  RATIONALP, ACL2-NUMBERP, or NIL. When the domain is NIL there is no
  domain restriction.

  When the domain is INTEGERP, there are additional constraints on the
  other components. See [make-tau-interval].")
 (TAU-INTERVAL-HI
  (TAU-SYSTEM)
  "Access the upper bound of a tau interval

  It is the case that

    (tau-interval-hi (make-tau-interval dom lo-rel lo hi-rel hi)) = hi

  For a well-formed interval, hi is either nil, denoting positive
  infinity, or a rational number giving the upper bound of the
  interval. It must be the case that the upper bound is weakly above
  the lower bound of a well-formed interval.

  When the domain of an interval is INTEGERP, there are additional
  constraints on the other components. See [make-tau-interval].")
 (TAU-INTERVAL-HI-REL
  (TAU-SYSTEM)
  "Access the upper bound relation of a tau interval

  It is the case that

    (tau-interval-hi-rel (make-tau-interval dom lo-rel lo hi-rel hi)) = hi-rel

  For a well-formed interval, hi-rel is a Boolean, where t denotes the
  [<] (strong inequality or ``less-than'') relation and nil denotes
  [<=] (weak inequality or ``less-than-or-equal'') relation between
  the elements of the interval and the upper bound.

  When the domain of an interval is INTEGERP, there are additional
  constraints on the other components. See [make-tau-interval].")
 (TAU-INTERVAL-LO
  (TAU-SYSTEM)
  "Access the lower bound of a tau interval

  It is the case that

    (tau-interval-lo (make-tau-interval dom lo-rel lo hi-rel hi)) = lo

  For a well-formed interval, lo is either nil, denoting negative
  infinity, or a rational number giving the lower bound of the
  interval. It must be the case that the lower bound is weakly below
  the upper bound of a well-formed interval.

  When the domain of an interval is INTEGERP, there are additional
  constraints on the other components. See [make-tau-interval].")
 (TAU-INTERVAL-LO-REL
  (TAU-SYSTEM)
  "Access the lower bound relation of a tau interval

  It is the case that

    (tau-interval-lo-rel (make-tau-interval dom lo-rel lo hi-rel hi)) = lo-rel

  For a well-formed interval, lo-rel is a Boolean, where t denotes the
  [<] (strong inequality or ``less-than'') relation and nil denotes
  [<=] (weak inequality or ``less-than-or-equal'') relation between
  the lower bound and the elements of the interval.

  When the domain of an interval is INTEGERP, there are additional
  constraints on the other components. See [make-tau-interval].")
 (TAU-INTERVALP
  (TAU-SYSTEM)
  "Boolean recognizer for tau intervals

    General Form:
    (tau-intervalp x)

  An interval is a structure of the form: (dom (lo-rel . lo) . (hi-rel
  . hi)). Every tau contains an interval used to represent the domain
  and the upper and lower bounds of the objects recognized by the
  tau.

  Restrictions on the components of an interval are as follows. For an
  interpretation of the meaning of the components, see
  [in-tau-intervalp] or [make-tau-interval].

  dom (``domain'') -- must be one of four symbols: INTEGERP, RATIONALP,
  ACL2-NUMBERP, or NIL.

  The two ``relations,'' lo-rel and hi-rel, must be Booleans.

  Lo and hi must be either nil or explicit rational numbers. Lo must be
  no greater than hi (where nils represent negative or positive
  infinity for lo and hi respectively.

  Finally, if the dom is INTEGERP, then both relations must nil and lo
  and hi must be integers when they are non-nil.

  Recall that [make-tau-interval] constructs intervals. The intervals
  it constructs are well-formed only if the arguments to
  make-tau-interval satisfy the rules above; make-tau-interval does
  not coerce or adjust its arguments in any way. Thus, it can be
  (mis-)used to create non-intervals. Here are examples of
  tau-intervalp using make-tau-interval.

    ; integers: 0 <= x <= 10:
    (tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil 10))      = t

    ; integers: 0 <= x (i.e., the natural numbers):
    (tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil nil))     = t

    ; violations of domain rules:
    (tau-intervalp (make-tau-interval 'INTEGERP t 0 t 10))          = nil
    (tau-intervalp (make-tau-interval 'INTEGERP nil 0 nil 10/11))   = nil

    ; violation of rule that bounds must be rational if non-nil:
    (tau-intervalp (make-tau-interval 'ACL2-NUMBERP t 0 t #c(3 5))) = nil

    ; violation of rule that lo <= hi:
    (tau-intervalp (make-tau-interval 'ACL2-NUMBERP t 0 t -10))     = nil

    ; rationals: 0 < x <= 22/7:
    (tau-intervalp (make-tau-interval 'RATIONALP t 0 nil 22/7))     = t

    ; numbers: -10 < x < 10:
    (tau-intervalp (make-tau-interval 'ACL2-NUMBERP t -10 t 10))    = t

    ; any: -10 < x < 10:
    (tau-intervalp (make-tau-interval nil t -10 t 10))              = t

    : any:
    (tau-intervalp (make-tau-interval nil nil nil nil nil))         = t

  Note that the second-to-last interval, with domain nil contains all
  non-numbers as well as numbers strictly between -10 and 10. The
  reason is that the interval contains 0 and all non-numbers are
  coerced to 0 by the inequality functions.

  Note that the last interval contains all ACL2 objects. It is called
  the ``universal interval.''")
 (TAU-STATUS
  (TAU-SYSTEM)
  "Query or set tau system status

    Examples:
    (tau-status)
    (tau-status :system t)
    (tau-status :auto-mode nil)
    (tau-status :system t :auto-mode nil)

    General Form:
    (tau-status :system a :auto-mode b)

  where a and b are Booleans. Both keyword arguments are optional and
  they may be presented in either order. Value a controls whether the
  [tau-system] is used during subsequent proofs. Value b controls
  whether tau system rules are added automatically (``greedily'')
  when rules of other [rule-classes] are added. If no arguments are
  supplied, this is not an event and just returns an error-triple
  (see [error-triples]) indicating the current settings. See
  [introduction-to-the-tau-system] for background details.

  The two flags are independent. For example, the tau system may be
  disabled in proof attempts even though it is automatically (and
  silently) extending its database as rules of other classes are
  added.

  Flag (a) is actually toggled by enabling or disabling the
  :[executable-counterpart] of [tau-system]. Flag (b) is toggled with
  the function [set-tau-auto-mode], which manipulates the
  [ACL2-defaults-table].

  This macro expands into zero, one, or two [events], as required by
  the supplied values of flags a and b.

  If no arguments are supplied the form is not an event and simply
  returns (as an error triple (mv nil ans state); see
  [error-triples]) the current settings of the two flags. For
  example:

    ACL2 !>(tau-system)
     ((:SYSTEM NIL) (:AUTO-MODE T))

  intended to be self-explanatory.")
 (TAU-SYSTEM
  (RULE-CLASSES)
  "Make a rule for the ACL2 ``type checker''

  This documentation topic describes the syntactic form of
  ``tau-system'' rules; these rules extend ACL2's ``type checker.''
  For an introduction to the tau system, see
  [introduction-to-the-tau-system].

  There happens to be a function named tau-system, defined as the
  identity function. Its only role is to provide the rune
  (:EXECUTABLE-COUNTERPART TAU-SYSTEM), which is used to enable and
  disable the tau system. Otherwise the function tau-system has no
  purpose and we recommend that you avoid using it so you are free to
  enable and disable the tau system.

  When in the default (``greedy'') mode (see [set-tau-auto-mode]),
  every [defun] and every :corollary (see :[rule-classes]) of every
  [defthm] stored as a rule of any :rule-class is inspected to
  determine if it is of one of the forms below. Rules of these forms
  are added to the tau database, even if they are not labeled as
  :tau-system rules, e.g., a :[rewrite] rule might contribute to the
  tau database! To add a rule to the tau database without adding any
  other kind of rule, tag it with :[rule-classes] :tau-system. If a
  theorem has :[rule-classes] nil, it is not considered for the tau
  database.

    General Forms:
    Boolean:
    (booleanp (p v))

    Eval:
    (p 'const) or
    (p *const*)

    Simple:
    (implies (p v) (q v))

    Conjunctive:
    (implies (and (p1 v) ... (pk v)) (q v)), ; Here k must exceed 1.

    Signature Form 1:
    (implies (and (p1 x1) (p2 x2) ...)
             (q (fn x1 x2 ...)))

    Signature Form 2:
    (implies (and (p1 x1) (p2 x2) ...)
             (q (mv-nth 'n (fn x1 x2 ...))))

    Bounder Form 1 (or Form 2):
    (implies (and (tau-intervalp i1)
                  ...
                  (or (equal (tau-interval-dom i1) 'dom1-1)
                      ...)
                  ...
                  (in-tau-intervalp x1 i1)
                  ...)
             (and (tau-intervalp (bounder-fn i1 ...))
                  (in-tau-intervalp target
                                    (bounder-fn i1 ...))))

    where target is
    (fn x1 ... y1 ...)             in Form 1, and
    (mv-nth 'n (fn x1 ... y1 ...)) in Form 2

    Big Switch:
    (equal (fn . formals) body)

    MV-NTH Synonym:
    (equal (nth-alt x y) (mv-nth x y)) or
    (equal (mv-nth x y) (nth-alt x y))

  The symbols p, q, p1, etc., denote monadic (one-argument)
  Boolean-valued function symbols, or equalities in which one
  argument is constant, arithmetic comparisons in which one argument
  is a rational or integer constant, or the logical negations of such
  terms. By ``equalities'' we allow [equal], [eq], [eql], and [=]. By
  ``arithmetic comparison'' we mean [<], [<=], [>=], or [>]. Any of
  these tau predicates may appear negated.

  The notation (p v) above might stand for any one of:

    (INTEGERP X)
    (EQUAL V 'MONDAY)
    (<= I 16)
    (NOT (EQUAL X 'SUNDAY))

  The different rule forms above affect different aspects of the tau
  system. We discuss each form in more detail below.

  The documentation below is written as though the tau system is in
  auto mode! To insure that the only rules added to the tau system
  are those explicitly assigned to :rule-class :tau-system, you
  should use [set-tau-auto-mode] to select manual mode.

    General Form: Boolean:
    (booleanp (p v))

  Here p must be a function symbol and v must be a variable. Such a
  :tau-system rule adds p to the list of tau predicates. If p was
  recognized as Boolean when it was defined, there is no need to
  state this rule. This form is needed if you define a monadic
  Boolean function in such a way that the system does not recognize
  that it is Boolean.

    General Form: Eval:
    (p 'const) or
    (p *const*)

  Here p must be a function symbol. In addition, recall that these
  general tau predicate forms may appear negated. So the form above
  includes such theorems as (NOT (GOOD-STATEP *INITIAL-STATE*)). A
  theorem of this form thus records whether a named predicate is true
  or false on the given constant.

  Generally, when the tau system must determine whether an enabled tau
  predicate is true or false on a constant, it simply evaluates the
  predicate on the constant. This can be impossible or very
  inefficient if p is not defined but constrained, or if p is defined
  in a hard-to-compute way (e.g., (defun p (x) (evenp (ack x x)))
  where ack is the Ackermann function), or perhaps if the constant is
  very large. By proving a :tau-system rule of Eval form, you cause
  the tau system to note the value of the predicate on the constant
  and henceforth to look it up instead of evaluating the definition.

  A difficulty, however, is determining that a slow down is due to the
  evaluation of tau predicates and not some other reason. The first
  step is determining that tau is slowing the proof down. See
  [time-tracker-tau] for an explanation of TIME-TRACKER-NOTEs output
  during some proofs involving tau reasoning. These notes can alert
  you to the fact that significant amounts of time are being spent in
  the tau system. [Time-tracker-tau] gives some ways of determining
  whether tau predicate evaluation is involved. (If worse comes to
  worst, consider the following hack: In the ACL2 source file
  tau.lisp, immediately after the definition of the system function
  ev-fncall-w-tau-recog, there is a comment which contains some raw
  Lisp code that can be used to investigate whether tau's use of
  evaluation on constants is causing a problem.) However, once a
  recognizer and the constants on which it is being evaluated are
  identified, the tau system can be sped up by proving Eval rules to
  pre-compute and store the values of the recognizer on those
  constants. Alternatively, at the possible loss of some completeness
  in the tau system, the executable counterpart of the recognizer can
  be disabled.

    General Form: Simple:
    (implies (p v) (q v))

  Here v must be a variable symbol. This rule builds-in the information
  that anything satisfying p must also satisfy q, i.e., the ``type''
  q includes the ``type'' p. Recall that the forms may be negated.
  Most of the time, p and q will be predicate symbols but it is
  possible they will be equalities- or inequalities-with-constants.
  Examples of Simple rules include the following, which are in fact
  built-in:

    (implies (natp x) (integerp x))
    (implies (integerp x) (rationalp x))
    (implies (integerp x) (not (true-listp x)))
    (implies (natp x) (not (< x 0)))
    (implies (symbol-alistp x) (alistp x))

  Because the tau system records the transitive closure of the Simple
  rules, any time a term is known to satisfy natp it is also known to
  satisfy integerp and rationalp, and known not to satisfy
  true-listp, and known to be non-negative.

    General Form: Conjunctive:
    (implies (and (p1 v) ... (pk v)) (q v)), ; Here k must exceed 1.

  The pi and q may be any tau predicates or their negations, v must be
  a variable symbol, and i must exceed 1 or else this is a Simple
  rule. An obvious operational interpretation of this rule is that if
  an object is known to satisfy all of the pi, then it is known to
  satisfy q. However, the actual interpretation is more general. For
  example, if an object is known to satisfy all but one of the pi and
  is known not to satisfy q, then the object is known not to satisfy
  the ``missing'' pi.

  For example, the following Conjunctive rule allows tau to conclude
  that if weekday D is not MON, TUE, THU or FRI, then it is WED:

    (implies (and (weekdayp d)
                  (not (eq d 'MON))
                  (not (eq d 'TUE))
                  (not (eq d 'WED))
                  (not (eq d 'THU)))
             (eq d 'FRI))

  The tau database is not closed under conjunctive rules; they are
  applied dynamically.

    General Form: Signature Form 1:
    (implies (and (p1 x1) (p2 x2) ... (pn xn) dep-hyp)
             (q (fn x1 x2 ... xn)))

  The pi and q may be any tau predicates or their negations, fn must be
  a function symbol of arity n, the xi must be distinct variable
  symbols and dep-hyp may be any term, provided it is not of the (pi
  xi) shape and the only the variables in it are the xi.

  The Signature form actually allows multiple tau predicates to be
  applied to each variable, e.g., x1 might be required to be both an
  INTEGERP and EVENP. The Signature form allows there to be multiple
  hypotheses classified as dep-hyps, i.e., not fitting any of the
  previous shapes, and they are implicitly just conjoined. The name
  ``dep-hyp'' is an abbreviation of ``dependent hypothesis'' and
  stems from the fact they often express relations between several of
  the function's inputs rather than type-like constraints on
  individual inputs.

  A Signature rule informs tau that the function fn returns an object
  satisfying q provided that the arguments satisfy the respective pi
  and provided that dep-hyp occurs in the current context. Note: to
  be precise, dependent hypotheses are relieved only by applying
  ACL2's most primitive form of reasoning, [type-set]. In particular,
  tau reasoning is not used to establish dependent hypotheses. The
  presence of a dep-hyp in a signature rule may severely restrict its
  applicability. We discuss this after showing a few mundane
  examples.

  An example Signature rule is

    (implies (and (integer-listp x)
                  (integer-listp y))
             (integer-listp (append x y)))

  Of course, a function may have multiple signatures:

    (implies (and (symbol-listp x)
                  (symbol-listp y))
             (symbol-listp (append x y)))

  Here is a Signature rule for the function pairlis$:

    (implies (and (symbol-listp x)
                  (integer-listp y))
             (symbol-alistp (pairlis$ x y)))

  The tau system can consequently check this theorem by composing the
  last two rules shown and exploiting Simple rule stating that
  symbol-alists are also alists:

    (thm (implies (and (symbol-listp a)
                       (symbol-listp b)
                       (integer-listp y))
                  (alistp (pairlis$ (append a b) y))))

  Since a and b are known to be lists of symbols and a signature for
  append is that it preserves that predicate, the first argument to
  the pairlis$ expression is known to be a list of symbols. This
  means the Signature rule for pairlis$ tells us the result is a
  symbol-alistp, but the previously mentioned Simple rule, (implies
  (symbol-alistp x) (alistp x)), tells us the result is also an
  alistp.

  When a Signature rule has an dep-hyp, that hypothesis is not an
  expression in the tau system. Tau is not used to check that
  hypothesis. Instead, tau uses the more primitive [type-set]
  mechanism of ACL2. Here is an example of a Signature rule with a
  dep-hyp:

    (implies (and (natp n)
                  (integer-listp a)
                  (< n (len a)))
             (integerp (nth n a)))

  Note that the last hypothesis is a dependent hypothesis: it is not a
  tau predicate but a relationship between n and a. It is relieved by
  [type-set]. If one is trying to compute the signature of an (nth n
  a) expression in a context in which (< n (len a)) is explicitly
  assumed, then this mechanism would establish the dependent
  hypothesis. But one can easily imagine an almost identical context
  where, say (< n (len (rev a))) is explicitly assumed. In that
  context, the Signature rule would not be fired because [type-set]
  cannot establish (< n (len a)) from (< n (len (rev a))), even
  though it would be easily proved by rewriting using the theorem
  (equal (len (rev a)) (len a)).

  Note also that if this signature could be phrased in a way that
  eliminates the dependency between n and a it would be more
  effective. For example, here is a related Signature rule without a
  dependent hypothesis:

    (implies (and (natp n)
                  (register-filep a)
                  (< n 16))
             (integerp (nth n a)))

  In this theorem we require only that n be less than 16, which is a
  tau predicate and hence just an additional tau constraint on n.

    General Form: Signature Form 2:
    (implies (and (p1 x1) (p2 x2) ... (pn xn) dep-hyp)

             (q (mv-nth 'n (fn x1 x2 ... xn))))

  This form of signature rule is just like form 1 except that it is
  useful for functions that return multiple-values and allows us to
  ``type-check'' their individual outputs.

    General Form: Bounder Forms 1 and 2:
    (implies (and (tau-intervalp i1)
                  ...
                  (or (equal (tau-interval-dom i1) 'dom1-1)
                      ...)
                  ...
                  (in-tau-intervalp x1 i1)
                  ...)
             (and (tau-intervalp (bounder-fn i1 ...))
                  (in-tau-intervalp target
                                    (bounder-fn i1 ...))))

  where target is either (fn x1 ... y1 ...) in Form 1 or (mv-nth 'n (fn
  x1 ... y1 ...)) in Form 2.

  This form is for advanced users only and the schema given above is
  just a reminder of the general shape. A ``bounder'' for a given
  function symbol, fn, is a function symbol bounder-fn that computes
  an interval containing (fn x1 ... y1 ...) (or its nth component in
  the case of Form 2 rules) from the intervals containing certain of
  the arguments of fn. The correctness theorem for a bounder function
  informs the tau system that bounds for fn are computed by
  bounder-fn and sets up the correspondence between the relevant
  arguments, xi, of fn and the intervals containing those arguments,
  ii to which bounder-fn is applied. When the tau system computes the
  tau for a call of fn, it computes the tau of the relevant arguments
  and applies the bounder to the intervals of those tau. This
  provides a domain and upper and/or lower bounds for the value of
  the term. The tau system then further augments that with signature
  rules. See [bounders] for details on intervals, bounders, and
  bounder correctness theorems.

    General Form: Big Switch:
    (equal (fn . formals) body)

  In the Big Switch form, fn must be a function symbol, formals must be
  a list of distinct variable symbols, and body must be a ``big
  switch'' term, i.e., one that case splits on tau predicates about a
  single variable and produces a term not involving that variable. An
  example of a Big Switch rule is

    (equal (conditional-type x y)
           (if (consp x)
               (consp y)
               (integerp y)))

  The idea is that the tau system can treat calls of conditional-type
  as a tau-predicate after determining the tau of an argument.

  Since equality-to-constants are tau predicates, a more common example
  of a Big Switch rule is

    (equal (dtypep x expr)
           (case x
                 (STMT (stmt-typep expr))
                 (EXPR (expr-typep expr))
                 (MODULE (module-typep expr))
                 (otherwise nil)))

  This is because (case x (STMT ...) ...) macroexpands in ACL2 to (if
  (eql x 'STMT) ... ...) and (eql x 'STMT) is a tau predicate about
  x.

  Big Switch rules are recognized when a function is defined (if tau is
  in automatic mode). They generally do not have to be proved
  explicitly, though they might be when mutual recursion is involved.
  Only the first detected Big Switch rule about a function fn is
  recognized.

    General Form: MV-NTH Synonym:
    (equal (nth-alt x y) (mv-nth x y)) or
    (equal (mv-nth x y) (nth-alt x y))

  Rules of this form just tell the tau system that the user-defined
  function nth-alt is synonymous with the ACL2 primitive function
  mv-nth. Because ACL2's rewriter gives special handling to mv-nth,
  users sometimes define their own versions of that function so they
  can disable them and control rewriting better. By revealing to the
  tau system that such a synonym has been introduced you allow
  Signature rules of Form 2 to be used.


Subtopics

  [Bounders]
      Intervals, bounder functions, and bounder correctness

  [In-tau-intervalp]
      Boolean membership in a tau interval

  [Introduction-to-the-tau-system]
      A decision procedure for runtime types

  [Make-tau-interval]
      Make a tau interval

  [Set-tau-auto-mode]
      Turn on or off automatic (``greedy'') generation of :tau-system
      rules

  [Tau-data]
      To see what tau knows about a function symbol

  [Tau-database]
      To see the tau database as a (very large) object

  [Tau-interval-dom]
      Access the domain of a tau interval

  [Tau-interval-hi]
      Access the upper bound of a tau interval

  [Tau-interval-hi-rel]
      Access the upper bound relation of a tau interval

  [Tau-interval-lo]
      Access the lower bound of a tau interval

  [Tau-interval-lo-rel]
      Access the lower bound relation of a tau interval

  [Tau-intervalp]
      Boolean recognizer for tau intervals

  [Tau-status]
      Query or set tau system status

  [Time-tracker-tau]
      Messages about expensive use of the [tau-system]")
 (TENTH
  (NTH ACL2-BUILT-INS)
  "Tenth member of the list

  See any Common Lisp documentation for details.")
 (TERM
  (MISCELLANEOUS)
  "The three senses of well-formed ACL2 expressions or formulas

    Examples of Terms:
    (cond ((caar x) (cons t x)) (t 0))   ; an untranslated term

    (if (car (car x)) (cons 't x) '0)    ; a translated term

    (car (cons x y) 'nil v)              ; a pseudo-term

  In traditional first-order predicate calculus a ``term'' is a
  syntactic entity denoting some object in the universe of
  individuals. Often, for example, the syntactic characterization of
  a term is that it is either a variable symbol or the application of
  a function symbol to the appropriate number of argument terms.
  Traditionally, ``atomic formulas'' are built from terms with
  predicate symbols such as ``equal'' and ``member;'' ``formulas''
  are then built from atomic formulas with propositional
  ``operators'' like ``not,'' ``and,'' and ``implies.'' Theorems are
  formulas. Theorems are ``valid'' in the sense that the value of a
  theorem is true, in any model of the axioms and under all possible
  assignments of individuals to variables.

  However, in ACL2, terms are used in place of both atomic formulas and
  formulas. ACL2 does not have predicate symbols or propositional
  operators as distinguished syntactic entities. The ACL2 universe of
  individuals includes a ``true'' object (denoted by t) and a
  ``false'' object (denoted by nil), predicates and propositional
  operators are functions that return these objects. Theorems in ACL2
  are terms and the ``validity'' of a term means that, under no
  assignment to the variables does the term evaluate to nil.

  We use the word ``term'' in ACL2 in three distinct senses. We will
  speak of ``translated'' terms, ``untranslated'' terms, and
  ``pseudo-'' terms.

  Translated Terms: The Strict Sense and Internal Form

  In its most strict sense, a ``term'' is either a legal variable
  symbol, a quoted constant, or the application of an n-ary function
  symbol or closed lambda expression to a true list of n terms.

  The legal variable symbols are symbols other than t or nil which are
  not in the keyword package, do not start with ampersand, do not
  start and end with asterisks, and if in the main Lisp package, do
  not violate an appropriate restriction (see [name]).

  Quoted constants are expressions of the form (quote x), where x is
  any ACL2 object. Such expressions may also be written 'x.

  Closed lambda expressions are expressions of the form (lambda (v1 ...
  vn) body) where the vi are distinct legal variable symbols, body is
  a term, and the only free variables in body are among the vi.

  The function termp, which takes two arguments, an alleged term x and
  a logical world w (see [world]), recognizes terms of a given
  extension of the logic. Termp is defined in :[program] mode. Its
  definition may be inspected with :[pe] termp for a complete
  specification of what we mean by ``term'' in the most strict sense.
  Most ACL2 term-processing functions deal with terms in this strict
  sense and use termp as a [guard]. That is, the ``internal form'' of
  a term satisfies termp, the strict sense of the word ``term.''

  Untranslated Terms: What the User Types

  While terms in the strict sense are easy to explore (because their
  structure is so regular and simple) they can be cumbersome to type.
  Thus, ACL2 supports a more sugary syntax that includes uses of
  macros and constant symbols. Very roughly speaking, macros are
  functions that produce terms as their results. Constants are
  symbols that are associated with quoted objects. Terms in this
  sugary syntax are ``translated'' to terms in the strict sense; the
  sugary syntax is more often called ``untranslated.'' Roughly
  speaking, translation just implements macroexpansion, the
  replacement of constant symbols by their quoted values, and the
  checking of all the rules governing the strict sense of ``term.''

  More precisely, macro symbols are as described in the documentation
  for [defmacro]. A macro, mac, can be thought of as a function,
  mac-fn, from ACL2 objects to an ACL2 object to be treated as an
  untranslated term. For example, [caar] is defined as a macro
  symbol; the associated macro function maps the object x into the
  object (car (car x)). A macro form is a ``call'' of a macro symbol,
  i.e., a list whose [car] is the macro symbol and whose [cdr] is an
  arbitrary true list of objects, used as a term. Macroexpansion is
  the process of replacing in an untranslated term every occurrence
  of a macro form by the result of applying the macro function to the
  appropriate arguments. The ``appropriate'' arguments are determined
  by the exact form of the definition of the macro; macros support
  positional, keyword, optional and other kinds of arguments. See
  [defmacro].

  In addition to macroexpansion and constant symbol dereferencing,
  translation implements the mapping of [let] and [let*] forms into
  applications of lambda expressions and closes lambda expressions
  containing free variables. Thus, the translation of

    (let ((x (1+ i))) (cons x k))

  can be seen as a two-step process that first produces

    ((lambda (x) (cons x k)) (1+ i))

  and then

    ((lambda (x k) (cons x k)) (1+ i) k) .

  Observe that the body of the [let] and of the first lambda expression
  contains a free k which is finally bound and passed into the second
  lambda expression.

  Translation also maps [flet] forms into applications of lambda
  expressions. See [flet].

  When we say, of an event-level function such as [defun] or [defthm],
  that some argument ``must be a term'' we mean an untranslated term.
  The event functions translate their term-like arguments.

  To better understand the mapping between untranslated terms and
  translated terms it is convenient to use the keyword command
  :[trans] to see examples of translations. See [trans] and also see
  [trans1].

  Finally, we note that the theorem prover prints terms in untranslated
  form. But there can be more than one correct untranslated term
  corresponding to a given translated term. For example, the
  translated term (if x y 'nil) can be untranslated as (if x y nil)
  and can also be untranslated as (and x y). The theorem prover
  attempts to print an untranslated term that is as helpful to the
  user as possible. In particular, consider a term of the form (nth k
  st) where st is a single-threaded object (see [stobj]) and the kth
  accessor of st is, say, kn. The theorem prover typically would
  expand (kn st) to (nth k st). If k is large then it could be
  difficult for the user to make sense out of a proof transcript that
  mentions the expanded term. Fortunately, the untranslation of (nth
  k st) would be (nth *kn* st); here *kn* would be a constant (see
  [defconst]) added by the [defstobj] event introducing st, defined
  to have value k. The user can extend this user-friendly style of
  printing applications of [nth] to stobjs; see [add-nth-alias].
  These remarks about printing applications of function [nth] extend
  naturally to function [update-nth]. Moreover, the prover will
  attempt to treat terms as [stobj]s for the above purpose when
  appropriate. For example, if function foo has [signature] ((foo *
  st) => (mv * * * st)), where st is introduced with (defstobj st f0
  f1), then the [term] (nth '1 (mv-nth '3 (foo x st0))) will be
  printed as (nth *f1* (mv-nth 3 (foo x st0))).

  Pseudo-Terms: A Common Guard for Metafunctions

  Because termp is defined in :[program] mode, it cannot be used
  effectively in conjectures to be proved. Furthermore, from the
  perspective of merely guarding a term processing function, termp
  often checks more than is required. Finally, because termp requires
  the logical [world] as one of its arguments it is impossible to use
  termp as a [guard] in places where the logical [world] is not
  itself one of the arguments.

  For these reasons we support the idea of ``pseudo-terms.'' A
  pseudo-term is either a symbol (but not necessarily one having the
  syntax of a legal variable symbol), a true list beginning with
  quote (but not necessarily well-formed), or the ``application of''
  a symbol or pseudo lambda expression to a true list of
  pseudo-terms. A pseudo lambda expression is an expression of the
  form (lambda (v1 ... vn) body) where the vi are all symbols and
  body is a pseudo-term.

  Pseudo-terms are recognized by the unary function [pseudo-termp]. If
  (termp x w) is true, then (pseudo-termp x) is true. However, if x
  fails to be a (strict) term it may nevertheless still be a
  pseudo-term. For example, (car a b) is not a term, because [car] is
  applied to the wrong number of arguments, but it is a pseudo-term.

  The structures recognized by [pseudo-termp] can be recursively
  explored with the same simplicity that terms can be. In particular,
  if x is not a variablep or an fquotep, then (ffn-symb x) is the
  function (symbol or lambda expression) and (fargs x) is the list of
  argument pseudo-terms. A metafunction (see [meta]) or
  clause-processor (see [clause-processor]) may use [pseudo-termp] as
  the [guard].


Subtopics

  [Guard-holders]
      Remove trivial calls from a [term]

  [Kwote]
      Quote an arbitrary object

  [Kwote-lst]
      Quote an arbitrary true list of objects

  [Pseudo-termp]
      A predicate for recognizing term-like s-expressions

  [Term-order]
      The ordering relation on terms used by ACL2")
 (TERM-ORDER
  (TERM ACL2-BUILT-INS)
  "The ordering relation on terms used by ACL2

  ACL2 must occasionally choose which of two terms is syntactically
  smaller. The need for such a choice arises, for example, when using
  equality hypotheses in conjectures (the smaller term is substituted
  for the larger elsewhere in the formula), in stopping loops in
  permutative rewrite rules (see [loop-stopper]), and in choosing the
  order in which to try to cancel the addends in linear arithmetic
  inequalities. When this notion of syntactic size is needed, ACL2
  uses ``term order.'' Popularly speaking, term order is just a
  lexicographic ordering on terms. But the situation is actually more
  complicated.

  We define term order only with respect to terms in translated form.
  See [trans]. Constants are viewed as built up by pseudo-function
  applications, as described at the end of this documentation.

  Term1 comes before term2 in the term order iff

      (a) the number of variable occurrences in term1 is less than that in
      term2, or

      (b) the numbers of variable occurrences in the two terms are equal
      but the number of function applications in term1 is less than
      that in term2, or

      (c) the numbers of variable occurrences in the two terms are equal,
      the numbers of functions applications in the two terms are
      equal, but pseudo-function application count for term1 is less
      than that for term2, or

      (d) the numbers of variable occurrences in the two terms are equal,
      the numbers of functions applications in the two terms are
      equal, the pseudo-function application counts for the two terms
      are equal, and term1 comes before term2 in a lexicographic
      ordering, [lexorder], based their structure as Lisp objects:
      see [lexorder].

  The function term-order, when applied to the translations of two ACL2
  terms, returns t iff the first is ``less than or equal'' to the
  second in the term order.

  By ``number of variable occurrences'' we do not mean ``number of
  distinct variables'' but ``number of times a variable symbol is
  mentioned.'' (Cons x x) has two variable occurrences, not one.
  Thus, perhaps counterintuitively, a large term that contains only
  one variable occurrence, e.g., (standard-char-p (car (reverse x)))
  comes before (cons x x) in the term order.

  Since constants contain no variable occurrences and non-constant
  expressions must contain at least one variable occurrence,
  constants come before non-constants in the term order, no matter
  how large the constants. For example, the list constant

    '(monday tuesday wednesday thursday friday)

  comes before x in the term order. Because term order is involved in
  the control of permutative rewrite rules and used to shift smaller
  terms to the left, a set of permutative rules designed to allow the
  permutation of any two tips in a tree representing the nested
  application of some function will always move the constants into
  the left-most tips. Thus,

    (+ x 3 (car (reverse klst)) (dx i j)) ,

  which in translated form is

    (binary-+ x
              (binary-+ '3
                        (binary-+ (dx i j)
                                  (car (reverse klst))))),

  will be permuted under the built-in commutativity rules to

    (binary-+ '3
              (binary-+ x
                        (binary-+ (car (reverse klst))
                                  (dx i j))))

  or

    (+ 3 x (car (reverse klst)) (dx i j)).

  Two terms with the same numbers of variable occurrences and function
  applications and the same pseudo-function application count are
  ordered by lexicographic means, based on their structures. See
  [lexorder]. Thus, if two terms (member ...) and (reverse ...)
  contain the same numbers of variable occurrences and function
  applications, and no quoted constants, then the [member] term is
  first in the term order because [member] comes before [reverse] in
  the term order (which is here reduced to alphabetic ordering).

  It remains to discuss the notion of pseudo-function application
  count.

  Clearly, two constants are ordered using cases (c) and (d) of term
  order, since they each contain 0 variable occurrences and no
  function calls. This raises the question ``How many function
  applications are in a constant?'' Because we regard the number of
  function applications as a more fundamental measure of the size of
  a constant than lexicographic considerations, we decided that for
  the purposes of term order, constants would be seen as being built
  by primitive constructor functions. These constructor functions are
  not actually defined in ACL2 but merely imagined for the purposes
  of term order. We here use suggestive names for these imagined
  functions, ignoring entirely the prior use of these names within
  ACL2. The imagined applications of these functions are what we
  refer to as pseudo-function applications.

  The constant function z constructs 0. Positive integers are
  constructed from (z) by the successor function, s. Thus 2 is (s (s
  (z))) and contains three function applications. 100 contains one
  hundred and one applications. Negative integers are constructed
  from their positive counterparts by [-]. Thus, -2 is (- (s (s
  (z)))) and has four applications. Ratios are constructed by the
  dyadic function [/]. Thus, -1/2 is

    (/ (- (s (z))) (s (s (z))))

  and contains seven applications. Complex rationals are similarly
  constructed from rationals. All character objects are considered
  primitive and are constructed by constant functions of the same
  name. Thus #\\a and #\\b both contain one application. Strings are
  built from the empty string, (o) by the ``string-cons'' function
  written cs. Thus \"AB\" is (cs (#\\a) (cs (#\\b) (o))) and contains
  five applications. Symbols are obtained from strings by ``packing''
  the [symbol-name] with the unary function p. Thus 'ab is

    (p (cs (#\\a) (cs (#\\b) (o))))

  and has six applications. Note that packages are here ignored and
  thus 'acl2::ab and 'my-package::ab each contain just six
  applications. Finally, [cons]es are built with [cons], as usual. So
  '(1 . 2) is (cons '1 '2) and contains six applications, since '1
  contains two and '2 contains three. This, for better or worse,
  answers the question ``How many function applications are in a
  constant?''

  Finally, when we refer to the ``pseudo-function application count'',
  we mean the number of pseudo-function applications as described
  above, except that we bound this number by the constant
  (fn-count-evg-max-val). (This bound is important for efficiency, so
  that constants that are very large cons structures do not cause
  significant slowdown as ACL2 attempts to walk through them while
  computing their pseudo-function application count.)")
 (TERM-TABLE
  (META)
  "A table used to validate meta rules

    Example:
    (table term-table t '((binary-+ x y) '3 'nil (car x)))

  See [table] for a general discussion of tables and the table event
  used to manipulate tables.

  The ``term-table'' is used at the time a meta rule is checked for
  syntactic correctness. Each proposed metafunction is run on each
  term in this table, and the result in each case is checked to make
  sure that it is a termp in the current world. In each case where
  this test fails, a warning is printed.

  Whenever a metafunction is run in support of the application of a
  meta rule, the result must be a term in the current world. When the
  result is not a term, a hard error arises. The term-table is simply
  a means for providing feedback to the user at the time a meta rule
  is submitted, warning of the definite possibility that such a hard
  error will occur at some point in the future.

  The key used in term-table is arbitrary. The top-most value is always
  the one that is used; it is the entire list of terms to be
  considered. Each must be a termp in the current ACL2 world.")
 (THE
  (GUARD COMPILATION ACL2-BUILT-INS)
  "The is a special form that can be used to optimize the execution
  efficiency of [guard]-verified ACL2 definitions, or (less
  frequently) to carry out a low-level run-time type checks.
  (Advanced)

  The is a special Common Lisp form. It is usually used as a way to
  boost the performance of ACL2 definitions by telling the Common
  Lisp compiler that a certain expression will always produce a
  result of a certain type. This information may allow the Common
  Lisp compiler to avoid certain run-time checks. See [declare] and
  [type-spec] for general, related background.

  General form:

    (the  )   ;; returns , or causes a run-time error

    *  is a [type-spec]
    *  is some expression that should produce a value of that type.

  Typical example:

    (defun merge-bytes (b1 b2)
      ;; Combine two 8-bit bytes into a 16-bit result.
      (declare (type (unsigned-byte-p 8) b1 b2))
      (the (unsigned-byte 16)
           (logior (the (unsigned-byte 16) (ash b1 8))
                   b2)))

  On most Lisp implementations 16-bit numbers are fixnums. The the
  forms above are promises to the Lisp compiler that these ash and
  logior operations will always produce 16-bit numbers. Ideally, the
  compiler could use this information to generate more efficient
  code, i.e., by omitting whatever code is normally required to
  handle bignum results. (Of course, a sufficiently smart compiler
  could have figured this out on its own; in practice Lisp compilers
  vary in their reasoning abilities.)


Relation to Guards

  To justify that type declarations are correct, the is integrated into
  ACL2's [guard] mechanism. When a call of (the TYPE EXPR) in the
  body of a function definition generates a guard proof obligation
  that the type, TYPE, holds for the value of the expression, EXPR.
  Consider the following example.

    (defun f (x)
      (declare (xargs :guard (p1 x)))
      (if (p2 x)
          (the integer (h x))
        17))

  The [guard] proof obligation generated for the THE expression above
  is as follows.

    (implies (and (p1 x) (p2 x))
             (let ((var (h x))) (integerp var)))

  For the to provide any execution speed benefit, [guard]s must be
  [verified].

  In contexts where guards have not been verified, the acts as a
  low-level, run-time type check that val satisfies the type
  specification typ (see [type-spec]). An error is caused if the
  check fails; otherwise, val is returned. Here are some examples:

    (the integer 3)       ; returns 3
    (the (integer 0 6) 3) ; returns 3
    (the (integer 0 6) 7) ; causes an error (see below for exception)

  There is an exception to the rule that failure of the type-check
  causes an error: there is no error when [guard]-checking has been
  turned off, that is, in any of the following ways; also
  [set-guard-checking] and see [with-guard-checking].

    * :set-guard-checking nil
    * (with-guard-checking nil ...)
    * :set-guard-checking :none
    * (with-guard-checking :none ...)


Further resources

  The [b*] macro provides a special syntax that may make using the
  forms more pleasant; see [patbind-the] for more information.

  When optimizing functions with type declarations, you may wish to
  manually inspect the compiler's output with [disassemble$] or
  conduct experiments to measure the impact of your optimizations.

  THE is defined in Common Lisp. See any Common Lisp documentation for
  more information.


Subtopics

  [Type-spec]
      Type specifiers can be used in Common Lisp type declarations and
      [the] forms, and may result in improved efficiency of
      execution.")
 (THE-METHOD
  (ACL2-TUTORIAL)
  "How to find proofs

  Also see [introduction-to-the-theorem-prover] for a more detailed
  tutorial on how to prove theorems with ACL2.

  Many users develop proof scripts in an Emacs buffer and submit one
  event at a time to the theorem prover running in a *shell* buffer.
  The script buffer is logically divided into two regions: the events
  that have been accepted by the theorem prover and those that have
  not yet been accepted. An imaginary ``barrier'' divides these two
  regions. The region above the barrier describes the state of the
  *shell* buffer (and ACL2's logical world). The region below the
  barrier is the ``to do'' list.

  We usually start a proof project by typing the key lemmas, and main
  goal into the to do list. Definitions are here just regarded as
  theorems to prove (i.e., the measure conjectures). Then we follow
  ``The Method.''

  (1) Think about the proof of the first theorem in the to do list.
  Structure the proof either as an induction followed by
  simplification or just simplification. Have the necessary lemmas
  been proved? That is, are the necessary lemmas in the done list
  already? If so, proceed to Step 2. Otherwise, add the necessary
  lemmas at the front of the to do list and repeat Step 1.

  (2) Call the theorem prover on the first theorem in the to do list
  and let the output stream into the *shell* buffer. Abort the proof
  if it runs more than a few seconds.

  (3) If the theorem prover succeeded, advance the barrier past the
  successful command and go to Step 1.

  (4) Otherwise, inspect the failed proof attempt, starting from the
  beginning, not the end. Basically you should look for the first
  place the proof attempt deviates from your imagined proof. If your
  imagined proof was inductive, inspect the induction scheme used by
  ACL2. If that is ok, then find the first subsequent subgoal that is
  stable under simplification and think about why it was not proved
  by the simplifier. If your imagined proof was not inductive, then
  think about the first subgoal stable under simplification, as
  above. Modify the script appropriately. It usually means adding
  lemmas to the to do list, just in front of the theorem just tried.
  It could mean adding hints to the current theorem. In any case,
  after the modifications go to Step 1.

  We do not seriously suggest that this or any rotely applied algorithm
  will let you drive ACL2 to difficult proofs. Indeed, to remind you
  of this we call this ``The Method'' rather than ``the method.''
  That is, we are aware of the somewhat pretentious nature of any
  such advice. But these remarks have helped many users approach ACL2
  in a constructive and disciplined way.

  We say much more about The Method in the ACL2 book. See the home
  page. Also see [set-gag-mode] for a discussion of a way for ACL2 to
  help you to use The Method. And again, see
  [introduction-to-the-theorem-prover] for a more detailed tutorial.

  Learning to read failed proofs is a useful skill. There are several
  kinds of ``checkpoints'' in a proof: (1) a formula to which
  induction is being (or would be) applied, (2) the first formula
  stable under simplification, (3) a formula that is possibly
  generalized, either by cross-fertilizing with and throwing away an
  equivalence hypothesis or by explicit generalization of a term with
  a new variable.

  At the induction checkpoint, confirm that you believe the formula
  being proved is a theorem and that it is appropriately strong for
  an inductive proof. Read the selected induction scheme and make
  sure it agrees with your idea of how the proof should go.

  At the post-simplification checkpoint, which is probably the most
  commonly seen, consider whether there are additional rewrite rules
  you could prove to make the formula simplify still further. Look
  for compositions of function symbols you could rewrite. Look for
  contradictions among hypotheses and prove the appropriate
  implications: for example, the checkpoint might contain the two
  hypotheses (P (F A)) and (NOT (Q (G (F A)))) and you might realize
  that (implies (p x) (q (g x))) is a theorem. Look for signs that
  your existing rules did not apply, e.g., for terms that should have
  been rewritten, and figure out why they were not. Possible causes
  include that they do not exactly match your old rules, that your
  old rules have hypotheses that cannot be relieved here -- perhaps
  because some other rules are missing, or perhaps your old rules are
  disabled. If you cannot find any further simplifications to make in
  the formula, ask yourself whether it is valid. If so, sketch a
  proof. Perhaps the proof is by appeal to a combination of lemmas
  you should now prove?

  At the two generalization checkpoints --- where hypotheses are
  discarded or terms are replaced by variables --- ask yourself
  whether the result is a theorem. It often is not. Think about
  rewrite rules that would prove the formula. These are often
  restricted versions of the overly-general formulas created by the
  system's heuristics.

  See [proof-tree] for a discussion of a tool to help you navigate
  through ACL2 proofs.")
 (THEORIES
  (ACL2)
  "Sets of [rune]s to [enable]/[disable] in concert

    Example: '((:definition app) ; or (:d app)
               (:executable-counterpart app)
               (:i app)
               rv
               (rv)
               assoc-of-app)

  See:

  A theory is a list of ``runic designators'' as described below. Each
  runic designator denotes a set of ``runes'' (see [rune]) and by
  unioning together the runes denoted by each member of a theory we
  define the set of runes corresponding to a theory. Theories are
  used to control which rules are ``[enable]d,'' i.e., available for
  automatic application by the theorem prover. There is always a
  ``current'' theory. A rule is [enable]d precisely if its [rune] is
  an element of the set of [rune]s corresponding to the current
  theory. At the top-level, the current theory is the theory selected
  by the most recent [in-theory] event, extended with the rule names
  introduced since then. Inside the theorem prover, the :[in-theory]
  hint (see [hints]) can be used to select a particular theory as
  current during the proof attempt for a particular goal.

  Theories are generally constructed by ``theory expressions.''
  Formally, a theory expression is any term, containing at most the
  single free variable [world], that when evaluated with [world]
  bound to the current ACL2 world (see [world]) produces a theory.
  ACL2 provides various functions for the convenient construction and
  manipulation of theories. These are called ``theory functions''(see
  [theory-functions]). For example, the theory function
  [union-theories] takes two theories and produces their union. The
  theory function [universal-theory] returns the theory containing
  all known rule names as of the introduction of a given logical
  name. But a theory expression can contain constants, e.g.,

    '(len (len) (:rewrite car-cons) car-cdr-elim)

  and user-defined functions. The only important criterion is that a
  theory expression mention no variable freely except [world] and
  evaluate to a theory.

  More often than not, theory expressions typed by the user do not
  mention the variable [world]. This is because user-typed theory
  expressions are generally composed of applications of ACL2's theory
  functions. These ``functions'' are actually macros that expand into
  terms in which [world] is used freely and appropriately. Thus, the
  technical definition of ``theory expression'' should not mislead
  you into thinking that interestng theory expressions must mention
  [world]; they probably do and you just didn't know it!

  One aspect of this arrangement is that theory expressions cannot
  generally be evaluated at the top-level of ACL2, because [world] is
  not bound. To see the value of a theory expression, expr, at the
  top-level, type

    ACL2 !>(LET ((WORLD (W STATE))) expr).

  However, because the built-in theories are quite long, you may be
  sorry you printed the value of a theory expression!

  A theory is a true list of runic designators and to each theory there
  corresponds a set of [rune]s, obtained by unioning together the
  sets of [rune]s denoted by each runic designator. For example, the
  theory constant

    '(len (len) (:e nth) (:rewrite car-cons) car-cdr-elim)

  corresponds to the set of [rune]s

    {(:definition len)
     (:induction len)
     (:executable-counterpart len)
     (:executable-counterpart nth)
     (:elim car-cdr-elim)
     (:rewrite car-cons)} .

  Observe that the theory contains five elements but its runic
  correspondent contains six. That is because runic designators can
  denote sets of several [rune]s, as is the case for the first
  designator, len. If the above theory were selected as current then
  the six rules named in its runic counterpart would be [enable]d and
  all other rules would be [disable]d.

  We now precisely define the runic designators and the set of [rune]s
  denoted by each. When we refer below to the ``macro-aliases
  dereference of'' a symbol, symb, we mean the (function) symbol
  corresponding symb in the macro-aliases-table if there is such a
  symbol, else symb itself; see [macro-aliases-table]. For example,
  the macro-aliases dereference of [append] is [binary-append], and
  the macro-aliases dereference of [nth] is nth.

    * A [rune] is a runic designator and denotes the singleton set
      containing that rune.
    * Suppose that symb is a symbol and symb' is the macro-aliases
      dereference of symb, where symb' is a function symbol
      introduced with a [defun] (or [defuns]) event. Then symb is a
      runic designator and denotes the set containing the runes
      (:definition symb') and (:induction symb'), omitting the latter
      if no such [induction] rune exists (presumably because the
      definition of symb' is not singly recursive).
    * Suppose that symb is a symbol and symb' is the macro-aliases
      dereference of symb, where symb' is a function symbol
      introduced with a [defun] (or [defuns]) event. Then (symb) is a
      runic designator and denotes the singleton set containing the
      rune (:executable-counterpart symb').
    * If symb is the name of a [defthm] (or [defaxiom]) event that
      introduced at least one rule, then symb is a runic designator
      and denotes the set of the names of all rules introduced by the
      named event.
    * If str is the string naming some [defpkg] event and symb is the
      symbol returned by (intern str \"ACL2\"), then symb is a runic
      designator and denotes the singleton set containing (:rewrite
      symb), which is the name of the rule stating the conditions
      under which the [symbol-package-name] of (intern x str) is str.
    * If symb is the name of a [deftheory] event, then symb is a runic
      designator and denotes the runic theory corresponding to symb.
    * Finally, suppose that symb is a symbol and symb' is the macro-aliases
      dereference of symb. Then (:KWD symb . rest) is a runic
      designator, known as a ``runic abbreviation'', if (:KWD' symb'
      . rest) is a [rune], where: :KWD is one of :d, :e, :i, or :t;
      and :KWD' is :definition, :executable-counterpart, :induction,
      or :type-prescription, respectively. In this case, (:KWD symb .
      rest) denotes the runic theory corresponding to the rune (:KWD'
      symb' . rest).

  Note that including a function name, e.g., [len], in the current
  theory [enable]s that function but does not [enable] the executable
  counterpart. Similarly, including (len) or (:e len) [enable]s the
  executable counterpart but not the symbolic definition. And
  including the name of a proved lemma [enable]s all of the rules
  added by the event. Of course, one can include explicitly the
  [rune]s naming the rules in question and so can avoid entirely the
  use of non-runic elements in theories.

  Because a [rune] is a runic designator denoting the set containing
  that [rune], a list of [rune]s is a theory and denotes itself. We
  call such theories ``runic theories.'' To every theory there
  corresponds a runic theory obtained by unioning together the sets
  denoted by each designator in the theory. When a theory is selected
  as ``current'' it is actually its runic correspondent that is
  effectively used. That is, a [rune] is [enable]d iff it is a member
  of the runic correspondent of the current theory. The value of a
  theory defined with [deftheory] is the runic correspondent of the
  theory computed by the defining theory expression. The theory
  manipulation functions, e.g., [union-theories], actually convert
  their theory arguments to their runic correspondents before
  performing the required set operation. The manipulation functions
  always return runic theories. Thus, it is sometimes convenient to
  think of (non-runic) theories as merely abbreviations for their
  runic correspondents, abbreviations which are ``expanded'' at the
  first opportunity by theory manipulation functions and the ``theory
  consumer'' functions such as [in-theory] and [deftheory].


Subtopics

  [Active-runep]
      Check that a [rune] exists and is [enable]d

  [Current-theory]
      Currently [enable]d rules as of logical name

  [Deftheory]
      Define a theory (to [enable] or [disable] a set of rules)

  [Deftheory-static]
      Define a `static' theory (to [enable] or [disable] a set of rules)

  [Disable]
      Deletes names from current theory

  [Disabledp]
      Determine whether a given name or rune is disabled

  [E/d]
      Enable/disable rules

  [Enable]
      Adds names to current theory

  [Executable-counterpart-theory]
      Executable counterpart rules as of logical name

  [Function-theory]
      Function symbol rules as of logical name

  [Ground-zero]
      [enable]d rules in the [startup] theory

  [In-theory]
      Designate ``current'' theory (enabling its rules)

  [Incompatible]
      Declaring that two rules should not both be [enable]d

  [Intersection-theories]
      Intersect two [theories]

  [Minimal-theory]
      A minimal theory to enable

  [Rule-names]
      How rules are named.

  [Rune]
      A rule name

  [Set-difference-theories]
      Difference of two [theories]

  [Theories-and-primitives]
      Warnings from disabling certain built-in functions

  [Theory]
      Retrieve named theory

  [Theory-functions]
      Functions for obtaining or producing [theories]

  [Union-theories]
      Union two [theories]

  [Universal-theory]
      All rules as of logical name

  [Using-enabled-rules]
      Avoiding :use [hints] for [enable]d :[rewrite] rules")
 (THEORIES-AND-PRIMITIVES
  (THEORIES)
  "Warnings from disabling certain built-in functions

  When you [disable] the [definition] or [executable-counterpart] of a
  built-in function, you may see a warning, for example as follows.

    ACL2 !>(in-theory (disable mv-nth))

    ACL2 Warning [Theory] in ( IN-THEORY (DISABLE ...)):  The :DEFINITION
    rule for MV-NTH is disabled by the theory expression (DISABLE MV-NTH),
    but because this built-in function is given certain special handling,
    some expansions of its calls may still occur.  See :DOC theories-and-
    primitives.

  This warning can be eliminated by turning off all theory warnings
  (see [set-inhibit-warnings]) or simply by evaluating the following
  form.

    (assign verbose-theory-warning nil)

  But before you eliminate such warnings, you may wish to read the
  following to understand their significance.

  First consider the following example, evaluated after the [in-theory]
  event displayed above.

    ACL2 !>(thm (equal (mv-nth 2 (list a b c d e)) c))

    Q.E.D.

    Summary
    Form:  ( THM ...)
    Rules: ((:DEFINITION MV-NTH)
            (:FAKE-RUNE-FOR-TYPE-SET NIL))
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
    Prover steps counted:  19

    Proof succeeded.
    ACL2 !>

  Note that even though the [definition] of [mv-nth] had been
  [disable]d, nevertheless its definition rule was used in proving
  this theorem. It is as though [mv-nth] had not been been disabled
  after all! The warning is intended to indicate that expansion of
  mv-nth calls may be made by the theorem prover even when mv-nth is
  disabled. Indeed, the prover has special-purpose code for
  simplifying certain mv-nth calls.

  A similar issue can arise for executable-counterpart rules, as the
  following log illustrates.

    ACL2 !>(in-theory (disable (:e symbolp)))

    ACL2 Warning [Theory] in ( IN-THEORY (DISABLE ...)):  The :EXECUTABLE-
    COUNTERPART rule for SYMBOLP is disabled by the theory expression
    (DISABLE (:E SYMBOLP)), but because this built-in function is given
    certain special handling, some evaluations of its calls may still occur.
    See :DOC theories-and-primitives.


    Summary
    Form:  ( IN-THEORY (DISABLE ...))
    Rules: NIL
    Warnings:  Theory
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     (:NUMBER-OF-ENABLED-RUNES 3233)
    ACL2 !>(thm (symbolp 'a))

    Q.E.D.

    Summary
    Form:  ( THM ...)
    Rules: NIL
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

    Proof succeeded.
    ACL2 !>

  In general, ACL2 warns when [in-theory] [events] or [hints] leave you
  in a theory where a rule for a built-in function has just been
  disabled, but may be applied in some cases nonetheless, because of
  special-purpose prover code for handling calls of that function.
  The built-in function symbols with such [definition] rules or
  [executable-counterpart] rules are those in the following two
  lists, respectively.

  Definition: <*definition-minimal-theory*>

    (defconst *definition-minimal-theory*
              (list* 'mv-nth
                     'iff
                     *expandable-boot-strap-non-rec-fns*))

  Definition: <*built-in-executable-counterparts*>

    (defconst *built-in-executable-counterparts*
              '(acl2-numberp binary-* binary-+ unary-- unary-/
                             < car cdr char-code characterp code-char
                             complex complex-rationalp coerce
                             cons consp denominator equal if imagpart
                             integerp intern-in-package-of-symbol
                             numerator pkg-witness pkg-imports
                             rationalp realpart stringp symbol-name
                             symbol-package-name symbolp not))")
 (THEORY
  (THEORIES THEORY-FUNCTIONS)
  "Retrieve named theory

  Examples:

  For use in [in-theory] [events] or :in-theory [hints]:
  (theory 'ground-zero)

  For direct evaluation at the top-level loop:
  (let ((world (w state))) (theory 'ground-zero))

  In the examples above, the theory returned is the one in force when
  ACL2 is started up (see [ground-zero]).

    General Form:
    (theory name)

  where name is the name of a previously executed [deftheory] event
  (otherwise a hard error occurs). Returns the named theory. See
  [theories].

  This ``function'' is actually a macro that expands to a term
  mentioning the single free variable [world]. When theory
  expressions are evaluated by [in-theory] or the :[in-theory] hint,
  [world] is bound to the current ACL2 [world].")
 (THEORY-FUNCTIONS
  (THEORIES)
  "Functions for obtaining or producing [theories]

    Example Calls of Theory Functions:
    (universal-theory :here)
    (union-theories th1 th2)
    (set-difference-theories th1 th2)

  The theory functions are documented individually:

  The functions (actually, macros) mentioned above are convenient ways
  to produce [theories]. (See [theories].) Some, like
  [universal-theory], take a logical name (see [logical-name]) as an
  argument and return the relevant theory as of the time that name
  was introduced. Others, like [union-theories], take two [theories]
  and produce a new one. See [redundant-events] for a caution about
  the use of logical names in theory expressions.

  Theory expressions are generally composed of applications of theory
  functions. Formally, theory expressions are expressions that
  involve, at most, the free variable [world] and that when evaluated
  with [world] bound to the current ACL2 world (see [world]) return
  [theories]. The ``theory functions'' are actually macros that
  expand into forms that involve the free variable [world]. Thus, for
  example (universal-theory :here) actually expands to
  (universal-theory-fn :here world) and when that form is evaluated
  with [world] bound to the current ACL2 [world], universal-theory-fn
  scans the ACL2 property lists and computes the current universal
  theory. Because the theory functions all implicitly use [world],
  the variable does not generally appear in anything the user types.


Subtopics

  [Current-theory]
      Currently [enable]d rules as of logical name

  [Disable]
      Deletes names from current theory

  [E/d]
      Enable/disable rules

  [Enable]
      Adds names to current theory

  [Executable-counterpart-theory]
      Executable counterpart rules as of logical name

  [Function-theory]
      Function symbol rules as of logical name

  [Ground-zero]
      [enable]d rules in the [startup] theory

  [Intersection-theories]
      Intersect two [theories]

  [Minimal-theory]
      A minimal theory to enable

  [Set-difference-theories]
      Difference of two [theories]

  [Theory]
      Retrieve named theory

  [Union-theories]
      Union two [theories]

  [Universal-theory]
      All rules as of logical name")
 (THEORY-INVARIANT
  (EVENTS)
  "User-specified invariants on [theories]

    Examples:
    (theory-invariant (not (and (active-runep '(:rewrite left-to-right))
                                (active-runep '(:rewrite right-to-left))))
                      :key my-invariant
                      :error nil)

    ; Equivalent to the above:
    (theory-invariant (incompatible (:rewrite left-to-right)
                                    (:rewrite right-to-left))
                      :key my-invariant
                      :error nil)

    General Form:
    (theory-invariant term &key key error)

  where:

    * term is a term that uses no variables other than ens and [state];
    * key is an arbitrary ``name'' for this invariant (if omitted, an
      integer is generated and used); and
    * :error specifies the action to be taken when an invariant is violated
      --- either nil if a warning is to be printed, else t (the
      default) if an error is to be caused.

  Theory-invariant is an event that adds to or modifies the [table] of
  user-supplied theory invariants that are checked each time a theory
  expression is evaluated.

  The theory invariant mechanism is provided via a table (see [table])
  named theory-invariant-table. In fact, the theory-invariant
  ``event'' is just a macro that expands into a use of the [table]
  event. More general access to the theory-invariant [table] is
  provided by [table] itself. For example, the [table] can be
  inspected or cleared with [table]; you can clear an individual
  theory invariant by setting the invariant to t, or eliminate all
  theory invariants with the command (table theory-invariant-table
  nil nil :clear).

  Theory-invariant-table maps arbitrary keys to records containing
  terms that mention, at most, the variables ens and [state]. Every
  time an alleged theory expression is evaluated, e.g., in the
  [in-theory] event or :[in-theory] hint, each of the terms in
  theory-invariant-table is evaluated with ens bound to a so-called
  ``enabled structure'' obtained from the theory expression and
  [state] bound to the current ACL2 state (see [state]). Users
  generally need not know about the enabled structure, other than
  that it can be accessed using the macros active-runep and
  incompatible; see [active-runep] and see [incompatible]. If the
  result is nil, a message is printed and an error occurs (except,
  only a warning occurs if :error nil is specified). Thus, the
  [table] can be thought of as a list of conjuncts. Each term in the
  [table] has a ``name,'' which is just the key under which the term
  is stored. When a theory violates the restrictions specified by
  some term, both the name and the term are printed. By calling
  theory-invariant with a new term but the same name, you can
  overwrite that conjunct of the theory invariant; but see the Local
  Redefinition Caveat at the end of this note. You may want to avoid
  using explicit names, since otherwise the subsequent inclusion of
  another book that defines a theory invariant with the same name
  will override your theory invariant.

  Theory invariants are particularly useful in the context of large
  rule sets intended for re-use. Such sets often contain conflicting
  rules, e.g., rules that are to be [enable]d when certain function
  symbols are [disable]d, rules that rewrite in opposite directions
  and thus loop if simultaneously [enable]d, groups of rules which
  should be [enable]d in concert, etc. The developer of such rule
  sets understands these restrictions and probably documents them.
  The theory invariant mechanism allows the developer to codify his
  restrictions so that the user is alerted when they are violated.

  Since theory invariants are arbitrary terms, macros may be used to
  express commonly used restrictions. For example, executing the
  event

    (theory-invariant (incompatible (:rewrite left-to-right)
                                    (:rewrite right-to-left)))

  would subsequently cause an error any time the current theory
  contained both of the two [rune]s shown. Of course, [incompatible]
  is just defined as a macro. Its definition may be inspected with
  :pe incompatible.

  In order for a theory-invariant event to be accepted, the proposed
  theory invariant must be satisfied by the current theory (see
  [current-theory]). The value returned upon successful execution of
  the event is the key (whether user-supplied or generated).

  Local Redefinition Caveat. Care needs to be taken when redefining a
  theory invariant in a [local] context. Consider the following
  example.

    (theory-invariant
     (active-runep '(:definition binary-append))
     :key app-inv)

    (encapsulate
     ()
     (local (theory-invariant t :key app-inv))
     (in-theory (disable binary-append))
     (defthm ...))

  The second pass of the [encapsulate] will fail, because the
  [in-theory] event violates the original theory-invariant and the
  [local] theory-invariant is skipped in the second pass of the
  [encapsulate]. Of course, [local] [theory-invariant]s in [books]
  can cause the analogous problem in the second ([include-book]) pass
  of a [certify-book]. In both cases, though, the theory invariants
  are only checked at the conclusion of the (include-book or
  encapsulate) event. Indeed, theory invariants are checked at the
  end of every event related to [theories], including [defun],
  [defthm], [in-theory], [encapsulate], and [include-book], except
  for events executed on behalf of an [include-book] or the second
  pass of an [encapsulate].")
 (THE_ADMISSION_OF_APP
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Admission of App

  [{IMAGE}]

  Here is what it looks like to submit the definition of app to ACL2:

  {IMAGE}

    ACL2 !>(defun app (x y)
      (cond ((endp x) y)
            (t (cons (car x)
                     (app (cdr x) y)))))

    The admission of APP is trivial, using the relation O< (which
    is known to be well-founded on the domain recognized by O-P)
    and the measure (ACL2-COUNT X).  We observe that the type of APP is
    described by the theorem (OR (CONSP (APP X Y)) (EQUAL (APP X Y) Y)).
    We used primitive type reasoning.

    Summary
    Form:  ( DEFUN APP ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  None
    Time:  0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
     APP

  {IMAGE}

  The text between the lines above is one interaction with the ACL2
  command loop. Interacting with the latest version of ACL2 may not
  produce the very same output, but we trust you'll recognize the
  basics.

  Above you see the user's input and how the system responds. This
  little example shows you what the syntax looks like and is a very
  typical successful interaction with the definitional principle.

  Let's look at it a little more closely.

  [{IMAGE}]")
 (THE_ASSOCIATIVITY_OF_APP
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Associativity of App

  [{IMAGE}]

  {IMAGE}

    ACL2!>(let ((a '(1 2))
                (b '(3 4))
                (c '(5 6)))
            (equal (app (app a b) c)
                   (app a (app b c))))
    T

  {IMAGE}

  Observe that, for the particular a, b, and c above, (app (app a b) c)
  returns the same thing as (app a (app b c)). Perhaps app is
  associative. Of course, to be associative means that the above
  property must hold for all values of a, b, and c, not just the ones
  tested above.

  Wouldn't it be cool if you could type

    ACL2!>(equal (app (app a b) c)
                 (app a (app b c)))

  and have ACL2 compute the value T? Well, you can't! If you try it,
  you'll get an error message! The message says we can't evaluate
  that form because it contains free variables, i.e., variables not
  given values. Click [here] to see the message.

  We cannot evaluate a form on an infinite number of cases. But we can
  prove that a form is a theorem and hence know that it will always
  evaluate to true.

  [{IMAGE}]")
 (THE_BASE_CASE_IN_THE_APP_EXAMPLE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Base Case in the App Example

  This formula is the Base Case. It consists of two parts, a test
  identifying the non-inductive case and the conjecture to prove.

    (IMPLIES (ENDP A)                 ; Test
             (:P A B C))              ; Conjecture

  When we prove this we can assume

     * A is empty

  and we have to prove the conjecture for A.")
 (THE_END_OF_THE_FLYING_TOUR
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The End of the Flying Tour

  {IMAGE}

  This completes the Flying Tour.

  We recommend that you now take [A Walking Tour of ACL2].

  Thanks.
  Matt Kaufmann and J Moore

  [{IMAGE}]")
 (THE_END_OF_THE_PROOF_OF_THE_ASSOCIATIVITY_OF_APP
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The End of the Proof of the Associativity of App

  [{IMAGE}]

    That [completes] the proof of *1.

    [Q.E.D.]

    Summary
    Form:  ( DEFTHM ASSOCIATIVITY-OF-APP ...)
    [Rules]: ((:REWRITE CDR-CONS)
            (:REWRITE CAR-CONS)
            (:DEFINITION NOT)
            (:DEFINITION ENDP)
            (:FAKE-RUNE-FOR-TYPE-SET NIL)
            (:DEFINITION APP))
    Warnings:  None
    Time:  0.27 seconds (prove: [0.10], print: 0.05, other: 0.12)
     ASSOCIATIVITY-OF-APP

  {IMAGE}

  [{IMAGE}]")
 (THE_END_OF_THE_WALKING_TOUR
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The End of the Walking Tour

  {IMAGE}

  This completes the Walking Tour.

  We intend to document many other parts of the system this way, but we
  just haven't gotten around to it.

  To start the two tours over again from the beginning, click on the
  icons below. If you are really interested in learning how to use
  ACL2, we recommend that you repeat each tour at least once more to
  explore branches of the tour that you might have missed.

  If you want to learn how to use the theorem prover, we now recommend
  that you devote the time necessary to work your way through the
  extended introduction to how to use the prover.

  See [introduction-to-the-theorem-prover].

  This will explain how to interact with ACL2 and has some sample
  problems for you to solve including some challenge proofs to make
  ACL2 find.

  We hope you enjoy ACL2. We do.

  Matt Kaufmann and J Strother Moore

  [{IMAGE}] [{IMAGE}]")
 (THE_EVENT_SUMMARY
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Event Summary

  At the conclusion of most events (click [here] for a brief discussion
  of events or see [events] [{ICON}]), ACL2 prints a summary. The
  summary for app is:

    Summary
    Form:  ( DEFUN APP ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  None
    Time:  0.03 seconds (prove: 0.00, print: 0.00, other: 0.03)
     APP

  The ``rules'' listed are those used in function admission or proof
  summarized. What is actually listed are ``runes'' (see [rune])
  [{ICON}]) which are list-structured names for rules in the ACL2
  database or ``[world]'' [{ICON}]. Using [theories] [{ICON}] you can
  ``enable'' and ``disable'' rules so as to make them available (or
  not) to the ACL2 theorem prover.

  The ``warnings'' mentioned (none are listed for app) remind the
  reader whether the event provoked any warnings. The warnings
  themselves would have been printed earlier in the processing and
  this part of the summary just names the earlier warnings printed.

  The ``time'' indicates how much processing time was used and is
  divided into three parts: the time devoted to proof, to printing,
  and to syntactic checks, pre-processing and database updates.
  Despite the fact that ACL2 is an applicative language it is
  possible to measure time with ACL2 programs. The [state] [{ICON}]
  contains a clock. The times are printed in decimal notation but are
  actually counted in integral units. Note that by default, each time
  is a runtime, also known as a cpu time, as opposed to being a real
  time, also known as a wall clock time.

  The final APP is the value of the defun command and was printed by
  the read-eval-print loop. The fact that it is indented one space is
  a subtle reminder that the command actually returned an ``error
  triple'', consisting of a flag indicating (in this case) that no
  error occurred, a value (in this case the symbol APP), and the
  final [state] [{ICON}]). See [ld-post-eval-print] [{ICON}] for some
  details. If you really want to follow that link, however, you might
  see [ld] [{ICON}] first.

  You should now return to [the Walking Tour].")
 (THE_EXPANSION_OF_ENDP_IN_THE_INDUCTION_STEP_{STEP_0}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Expansion of ENDP in the Induction Step (Step 0)

    Subgoal *1/2
    (IMPLIES (AND (NOT [(]ENDP A))
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (APP (APP A B) C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above (the open parenthesis before ENDP) to replace
  (ENDP A) by its definition.")
 (THE_EXPANSION_OF_ENDP_IN_THE_INDUCTION_STEP_{STEP_1}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Expansion of ENDP in the Induction Step (Step 1)

    Subgoal *1/2
    (IMPLIES (AND [(]NOT (NOT (CONSP A)))
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (APP (APP A B) C)
                    (APP A (APP B C)))).

  {IMAGE}

  The bold text is the instantiated definition of ENDP.

  Now click on the link above to simplify (NOT (NOT (CONSP A)))")
 (THE_EXPANSION_OF_ENDP_IN_THE_INDUCTION_STEP_{STEP_2}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Expansion of ENDP in the Induction Step (Step 2)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (APP (APP A B) C)
                    (APP A (APP B C)))).

  {IMAGE}

  Note that this is Subgoal *1/2'.

  You may click [here] to return to the main proof.")
 (THE_FALLING_BODY_MODEL
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Falling Body Model

  {IMAGE}

  One particularly famous and very simple model is the equation of a
  falling body: the distance d an object falls is proportional to the
  square of the time t. If the time is measured in seconds and the
  distance in feet, the equation relating these two is

           2
    d = 16t

  This equation is a model of falling objects. It can be used to
  predict how long it takes a cannonball to fall from the top of a
  200 foot tower (3.5 seconds). This might be important if your
  product is designed to drop cannonballs on moving targets.")
 (THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE_{STEP_0}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Final Simplification in the Base Case (Step 0)

    Subgoal *1/1'
    (IMPLIES (NOT (CONSP A))
             (EQUAL (APP [(]APP A B) C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above to replace (APP A B) by its definition. Note
  that the hypothesis (NOT (CONSP A)) allows us to simplify the IF in
  APP to its false branch this time.")
 (THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE_{STEP_1}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Final Simplification in the Base Case (Step 1)

    Subgoal *1/1'
    (IMPLIES (NOT (CONSP A))
             (EQUAL (APP B C)
                    [(]APP A (APP B C)))).

  {IMAGE}

  Click on the link above to expand the definition of APP. Again, we
  come out through the false branch because of the hypothesis.")
 (THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE_{STEP_2}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Final Simplification in the Base Case (Step 2)

    Subgoal *1/1'
    (IMPLIES (NOT (CONSP A))
             [(]EQUAL (APP B C)
                    (APP B C))).

  {IMAGE}

  Click on the link above to use the Axiom (EQUAL x x) = t")
 (THE_FINAL_SIMPLIFICATION_IN_THE_BASE_CASE_{STEP_3}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Final Simplification in the Base Case (Step 3)

    Subgoal *1/1'
    (IMPLIES (NOT (CONSP A))
             T)

  {IMAGE}

  Now that its conclusion is identically T the IMPLIES will simplify to
  T (not shown) and we are done with Subgoal *1/1'.

  You may click [here] to return to the main proof.")
 (THE_FIRST_APPLICATION_OF_THE_ASSOCIATIVITY_RULE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The First Application of the Associativity Rule

  So here we see our associativity rule being used!

  The rewriter sweeps the conjecture in a leftmost innermost fashion,
  applying rewrite rules as it goes.

  The associativity rule is used many times in this sweep. The first
  ``target'' is highlighted below. Click on it to see what happens:

    Current Conjecture:
    (equal (app (app [(app (app x1 x2) (app x3 x4))] (app x5 x6)) x7)
           (app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7)))))")
 (THE_INDUCTION_SCHEME_SELECTED_FOR_THE_APP_EXAMPLE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Induction Scheme Selected for the App Example

    (AND
       (IMPLIES (AND (NOT (ENDP A))         ; Induction Step: test
                     (:P (CDR A) B C))      ;  and induction hypothesis
                (:P A B C))                 ;  implies induction conclusion.
       (IMPLIES (ENDP A) (:P A B C)))       ; Base Case

  The formula beginning with this parenthesis is the induction scheme
  suggested by (APP A B) applied to (P A B C).

  It is a conjunction ([and] [{ICON}]) of two formulas.

  The first is the induction step and the second is the base case.")
 (THE_INDUCTION_STEP_IN_THE_APP_EXAMPLE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Induction Step in the App Example

  This formula is the Induction Step. It basically consists of three
  parts, a test identifying the inductive case, an induction
  hypothesis and an induction conclusion.

    (IMPLIES (AND (NOT (ENDP A))      ; Test
                  (:P (CDR A) B C))   ; Induction Hypothesis
             (:P A B C))              ; Induction Conclusion

  When we prove this we can assume

     * A is not empty, and that

      * the associativity conjecture holds for a ``smaller'' version of A,
        namely, (CDR A).

  Under those hypotheses we have to prove the associativity conjecture
  for A itself.")
 (THE_INSTANTIATION_OF_THE_INDUCTION_SCHEME
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Instantiation of the Induction Scheme

  The induction scheme just shown is just an abbreviation for our real
  goal.

  To obtain our actual goals we have to replace the schema :P by the
  associativity conjecture (instantiated as shown in the scheme).

  This produces two actual goals, the induction step and the base case.")
 (THE_JUSTIFICATION_OF_THE_INDUCTION_SCHEME
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Justification of the Induction Scheme

  This paragraph explains why the induction selected is legal. The
  explanation is basically the same as the explanation for why the
  recursion in (APP A B) terminates.")
 (THE_PROOF_OF_THE_ASSOCIATIVITY_OF_APP
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Proof of the Associativity of App

  [{IMAGE}]

  Here is the theorem prover's output when it processes the defthm
  command for the associativity of app. We have highlighted text for
  which we offer some explanation, and broken the presentation into
  several pages. (The most recent version of ACL2 may print slightly
  different output but the basics are the same.) Just follow the
  Walking Tour after exploring the explanations.

  However, before exploring this output you should understand that ACL2
  users rarely read successful proofs! Instead, they look at certain
  subgoals printed in failed proofs, figure whether and how those
  subgoals can be proved, and give ACL2 directions for proving them,
  usually by simply proving other lemmas. Furthermore, to be a good
  user of ACL2 you do not have to understand how the theorem prover
  works. You just have to understand how to interact with it. We
  explain this in great detail later. But basically all new users are
  curious to know how ACL2 works and this little tour attempts to
  give some answers, just to satisfy your curiosity.

  {IMAGE}

    ACL2!>(defthm associativity-of-app
            (equal (app (app a b) c)
                   (app a (app b c))))

    Name the formula above [*1].

    [Perhaps] we can prove *1 by induction.  Three induction schemes are
    [suggested] by this conjecture.  [Subsumption] reduces that number to two.
    However, one of these is [flawed] and so we are left with one viable
    candidate.

    We will induct according to a scheme suggested by (APP A B).  If we
    let  (:P A B C) denote *1 above then the induction scheme we'll use
    is
    [(]AND
       [(]IMPLIES (AND (NOT (ENDP A))
                     (:P (CDR A) B C))
                (:P A B C))
       [(]IMPLIES (ENDP A) (:P A B C))).
    This induction is [justified] by the same argument used to admit APP,
    namely, the measure (ACL2-COUNT A) is decreasing according to the relation
    O< (which is known to be well-founded on the domain recognized
    by O-P).  When [applied] to the goal at hand the above induction
    scheme produces the following two [nontautological subgoals].

  [{IMAGE}]")
 (THE_Q.E.D._MESSAGE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Q.E.D. Message

  Q.E.D. stands for ``quod erat demonstrandum'' which is Latin for
  ``which was to be demonstrated'' and is the signal that a proof is
  completely done.")
 (THE_RULES_USED_IN_THE_ASSOCIATIVITY_OF_APP_PROOF
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Rules used in the Associativity of App Proof

  Note that under Rules we list the [runes] [{ICON}] of all the rules
  used in the proof. This list says that we used the rewrite rules
  CAR-CONS and CDR-CONS, the definitions of the functions NOT, ENDP
  and APP, and primitive type reasoning (which is how we simplified
  the IF and EQUAL terms).

  For what it is worth, IMPLIES and AND are actually [macros] [{ICON}]
  that are expanded into IF expressions before the proof ever begins.
  The use of macros is not reported among the rules.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_0}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 0)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (APP [(]APP A B) C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above to replace (APP A B) by its definition.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_10}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 10)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             [(]EQUAL (APP (APP (CDR A) B) C)
                    (APP (CDR A) (APP B C)))).

  {IMAGE}

  Click on the link above to use the Induction Hypothesis (which is the
  second of the two hypotheses above and which is identical to the
  rewritten conclusion).")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_11}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 11)

    Subgoal *1/2'
    [(]IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             T)

  {IMAGE}

  Click on the link above to use the definition of IMPLIES. Since the
  conclusion of the implication is now identically T, the implication
  simplifies to T.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_12}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 12)

    Subgoal *1/2'
    T

  {IMAGE}

  So, indeed, Subgoal *1/2' does simplify to T!

  You can see that even in an example as simple as this one, quite a
  lot happens in simplification.

  You may click [here] to return to the main proof.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_1}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 1)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (APP (IF [(]CONSP A)
                             (CONS (CAR A) (APP (CDR A) B))
                             B)
                         C)
                    (APP A (APP B C)))).

  {IMAGE}

  Note that the IF expression above is the simplified body of APP. But
  we know the test (CONSP A) is true, by the first hypothesis. Click
  on the link above to replace the test by T. Actually this step and
  several subsequent ones are done during the simplification of the
  body of APP but we want to illustrate the basic principles of
  simplification without bothering with every detail.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_2}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 2)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (APP [(]IF T
                             (CONS (CAR A) (APP (CDR A) B))
                             B)
                         C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above to apply the Axiom (IF T x y) = x.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_3}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 3)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL [(]APP (CONS (CAR A) (APP (CDR A) B))
                         C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above to expand the definition of APP here.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_4}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 4)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (IF [(]CONSP (CONS (CAR A) (APP (CDR A) B)))
                        (CONS (CAR (CONS (CAR A) (APP (CDR A) B)))
                              (APP (CDR (CONS (CAR A) (APP (CDR A) B)))
                                   C))
                        C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above to apply the Axiom (CONSP (CONS x y)) = T.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_5}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 5)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (IF T
                        (CONS [(]CAR (CONS (CAR A) (APP (CDR A) B)))
                              (APP (CDR (CONS (CAR A) (APP (CDR A) B)))
                                   C))
                        C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above to apply the Axiom (CAR (CONS x y)) = x.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_6}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 6)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (IF T
                        (CONS (CAR A)
                              (APP [(]CDR (CONS (CAR A) (APP (CDR A) B)))
                                   C))
                        C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above to apply the Axiom (CDR (CONS x y)) = y.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_7}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 7)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL [(]IF T
                        (CONS (CAR A)
                              (APP (APP (CDR A) B)
                                   C))
                        C)
                    (APP A (APP B C)))).

  {IMAGE}

  Click on the link above to apply the Axiom (IF T x y) = x.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_8}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 8)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             (EQUAL (CONS (CAR A)
                          (APP (APP (CDR A) B)
                               C))
                    [(]APP A (APP B C)))).

  {IMAGE}

  Click on the link above to expand the definition of APP here. This
  time, we'll do the whole expansion at once, including the
  simplification of the resulting IF. This is how ACL2 actually does
  it.")
 (THE_SIMPLIFICATION_OF_THE_INDUCTION_CONCLUSION_{STEP_9}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Simplification of the Induction Conclusion (Step 9)

    Subgoal *1/2'
    (IMPLIES (AND (CONSP A)
                  (EQUAL (APP (APP (CDR A) B) C)
                         (APP (CDR A) (APP B C))))
             [(]EQUAL (CONS (CAR A)
                          (APP (APP (CDR A) B)
                               C))
                    (CONS (CAR A)
                          (APP (CDR A) (APP B C))))).

  {IMAGE}

  Click on the link above to apply the Axiom that (EQUAL (CONS x y)
  (CONS u v)) is equal to the conjunction of (EQUAL x u) and (EQUAL y
  v). In this case, (EQUAL x u) is trivial, (EQUAL (CAR A) (CAR A)).")
 (THE_SUMMARY_OF_THE_PROOF_OF_THE_TRIVIAL_CONSEQUENCE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Summary of the Proof of the Trivial Consequence

  Note that at the conclusion of the proof, the system reminds you of
  the earlier Warning.

  It is a good idea, when the Q.E.D. flys by, to see if there were any
  Warnings.")
 (THE_THEOREM_THAT_APP_IS_ASSOCIATIVE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Theorem that App is Associative

  [{IMAGE}]

    ACL2!>(defthm associativity-of-app
            (equal (app (app a b) c)
                   (app a (app b c))))

  The formula above says app is associative. The [defthm] [{ICON}]
  command instructs ACL2 to prove the formula and to name it
  associativity-of-app. Actually, the defthm command also builds the
  formula into the database as a [rewrite] [{ICON}] rule, but we
  won't go into that just yet.

  What we will consider is how the ACL2 theorem prover proves this
  formula.

  If you proceed you will find the actual output of ACL2 in response to
  the command above. Some of the text is highlighted for the purposes
  of the tour. ACL2 does not highlight its output.

  You will note that we sometimes highlight a single open parenthesis.
  This is our way of drawing your attention to the subformula that
  begins with that parenthesis. By clicking on the parenthesis you
  will get an explanation of the subformula or its processing.

  [{IMAGE}]")
 (THE_TIME_TAKEN_TO_DO_THE_ASSOCIATIVITY_OF_APP_PROOF
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Time Taken to do the Associativity of App Proof

  The time it took us to explain this proof may leave the impression
  that the proof is complicated. In a way, it is. But it happens
  quickly.

  The time taken to do this proof is about 1/10 second. The rest of the
  time (about 2/10 seconds) is spent in pre- and post-processing.

  Basically, this proof flashes across your screen before you can read
  it; you see the Q.E.D. and don't bother to scroll back to read it.
  You have more important things to do than read successful proofs.")
 (THE_TOURS
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The Tours

  ACL2 is a very large, multipurpose system. You can use it as a
  programming language, a specification language, a modeling
  language, a formal mathematical logic, or a semi-automatic theorem
  prover, just to name its most common uses. It has been used on a
  number of [industrial applications]. If you're uncertain as to
  whether your project is appropriate for ACL2 we urge you to look
  over this list or contact the ACL2 developers.

  This home page includes all of ACL2's online documentation, which is
  quite extensive (over 4 megabytes). To help ease your introduction
  to ACL2, we have built two tours through this documentation.

  If you are familiar with at least some of the [industrial
  applications] of ACL2, then you will understand the distance
  between the simple examples we talk about in these tours and the
  kinds of things ACL2 users do with the system.

  Newcomers to ACL2 should first take the ``Flying Tour.'' Then, if you
  want to know more, take the ``Walking Tour.'' On your first
  reading, follow the two Tours linearly, clicking only on the icon
  of the Tour you're on. Beware of other links, which might jump you
  from one tour to the other or into the ACL2 User's Manual! Once
  you've had a coherent overview of the system, you might quickly
  repeat both Tours to see if there are unvisited links you're
  interested in, using your brower's Back Button to return to your
  starting points.

  If after all this you want to learn how to use the theorem prover
  (!), see [introduction-to-the-theorem-prover].

  To start a tour, click on the appropriate icon below.

  [{IMAGE}] [{IMAGE}]

  If you take the tours in a text-based format (such as using the :DOC
  command in Emacs), they will probably be unsatisfying because we
  use gif files and assume you can navigate ``back.''")
 (THE_WARNING_ABOUT_THE_TRIVIAL_CONSEQUENCE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "The WARNING about the Trivial Consequence

  This Warning alerts us to the fact that when treated as a rewrite
  rule, the new rule TRIVIAL-CONSEQUENCE, rewrites terms of the same
  form as a rule we have already proved, namely ASSOCIATIVITY-OF-APP.

  When you see this warning you should think about your rules!

  In the current case, it would be a good idea not to make
  TRIVIAL-CONSEQUENCE a rule at all. We could do this with
  :[rule-classes] [{ICON}] nil.

  ACL2 proceeds to try to prove the theorem, even though it printed
  some warnings. The basic assumption in ACL2 is that the user
  understands what he or she is doing but may need a little reminding
  just to manage a complicated set of facts.")
 (THIRD
  (NTH ACL2-BUILT-INS)
  "Third member of the list

  See any Common Lisp documentation for details.")
 (THM
  (MISCELLANEOUS)
  "Prove a theorem

    Example:
    (thm (equal (app (app a b) c)
                (app a (app b c))))

  Also see [defthm]. Unlike [defthm], thm does not create an event; it
  merely causes the theorem prover to attempt a proof.

    General Form:
    (thm term
         :hints        hints
         :otf-flg      otf-flg
         :doc          doc-string)

  where term is a term alleged to be a theorem, and [hints] and
  [otf-flg] are as described in the corresponding [documentation]
  topics. Doc-string, if non-nil, is an optional string that can
  provide documentation but is essentially ignored by ACL2. The three
  keyword arguments above are all optional.


Subtopics

  [Otf-flg]
      Allow more than one initial subgoal to be pushed for induction")
 (TIDBITS
  (ACL2-TUTORIAL)
  "Some basic hints for using ACL2

  See [books] for a discussion of books. Briefly, a book is a file
  whose name ends in ``.lisp'' that contains ACL2 [events]; see
  [events].

  See [history] for a list of useful commands. Some examples:

    :pbt :here      ; print the current event
    :pbt (:here -3) ; print the last four events
    :u              ; undo the last event
    :pe append      ; print the definition of append

  See [documentation] to learn how to print documentation to the
  terminal. There are also versions of the [documentation] for web
  browsers and for Emacs (see [ACL2-Doc]).

  There are quite a few kinds of rules allowed in ACL2 besides
  :[rewrite] rules, though we hope that beginners won't usually need
  to be aware of them. See [rule-classes] for details. In particular,
  there is support for [congruence] rewriting. See [rune] (``RUle
  NamE'') for a description of the various kinds of rules in the
  system. Also see [theories] for a description of how to build
  [theories] of [rune]s, which are often used in hints; see [hints].

  A ``[programming] mode'' is supported; see [program], see
  [defun-mode], and see [default-defun-mode]. It can be useful to
  prototype functions after executing the command :[program], which
  will cause definitions to be syntaxed-checked only.

  ACL2 supports mutual recursion, though this feature is not tied into
  the automatic discovery of [induction] schemas and is often not the
  best way to proceed when you expect to be reasoning about the
  functions. See [defuns]; also see [mutual-recursion].

  See [ld] for discussion of how to load files of [events]. There are
  many options to [ld], including ones to suppress proofs and to
  control output.

  The :[otf-flg] (Onward Thru the Fog FLaG) is a useful feature that
  Nqthm users have often wished for. It prevents the prover from
  aborting a proof attempt and inducting on the original conjecture.
  See [otf-flg].

  ACL2 supports redefinition and redundancy in [events]; see
  [ld-redefinition-action] and see [redundant-events].

  A [proof-tree] display feature is available for use with Emacs. This
  feature provides a view of ACL2 proofs that can be much more useful
  than reading the stream of [characters] output by the theorem
  prover as its ``proof.'' See [proof-tree].

  An interactive feature similar to Pc-Nqthm is supported in ACL2. See
  [verify] and see [proof-checker].

  ACL2 allows you to [monitor] the use of [rewrite] rules. See
  [break-rewrite].

  See [arrays] to read about applicative, fast [arrays] in ACL2.

  To quit the ACL2 [command] loop, or (in akcl) to return to the ACL2
  [command] loop after an interrupt, type :[q]. To continue (resume)
  after an interrupt (in akcl), type :r. To cause an interrupt (in
  akcl under Unix (trademark of AT&T)), hit control-C (twice, if
  inside Emacs). To exit ACL2 altogether, type :[quit].

  See [state] to read about the von Neumannesque ACL2 [state] object
  that records the ``current state'' of the ACL2 session. Also see
  [@], and see [assign], to learn about reading and setting global
  [state] variables.

  If you want your own von Neumannesque object, e.g., a structure that
  can be ``destructively modified'' but which must be used with some
  syntactic restrictions, see [stobj].")
 (TIME$
  (PROGRAMMING ACL2-BUILT-INS)
  "Time an evaluation

  Semantically, (time$ x ...) equals x. However, its evaluation may
  write timing output to the trace output (which is usually the
  terminal), as explained further below.

    Examples:

    ; Basic examples:

    (time$ (foo 3 4))
    (time$ (mini-proveall))
    (defun bar (x) (time$ (f x)))

    ; Custom examples, which use a custom timing message rather than a built-in
    ; message from Lisp:

    ; Report only if real time is at least 1/2 second (two equivalent forms).
    (time$ (foo) :mintime 1/2)
    (time$ (foo) :real-mintime 1/2)

    ; Report only if allocation is at least 1000 bytes (and if the Lisp supports
    ; :minalloc).
    (time$ (foo) :minalloc 1000)

    ; Report only if real time is at least 1/2 second and (if the Lisp supports
    ; :minalloc) allocation is at least 931 bytes.
    (time$ (foo) :real-mintime 1/2 :minalloc 931)

    ; Print \"Hello Moon, Goodbye World\" instead of any timing data.
    (time$ (foo)
           :msg \"Hello ~s0, ~s1 World.\"
           :args (list \"Moon\" \"Goodbye\"))

    ; Print default custom timing message (same as omitting :mintime 0):
    (time$ (foo)
           :mintime 0)

    ; Print supplied custom timing message.
    (let ((bar ...))
      (time$ (foo)
             :msg \"The execution of ~xf took ~st seconds of real ~
                   time and ~sc seconds of run time (cpu time), and ~
                   allocated ~sa bytes.  In an unrelated note, bar ~
                   currently has the value ~x0.~%\"
             :args (list bar)))

    General Forms:
    (time$ form)
    (time$ form ; arguments below are optional
           :real-mintime  
           :run-mintime   
           :minalloc      
           :msg           
           :args          
           )
    ; Note: :real-mintime can be replaced by :mintime

  where form is processed as usual except that the host Common Lisp
  times its evaluation.

  The simplest form is (time$ x), which will call the time utility in
  the underlying Lisp, and will print a small default message. If you
  want to see a message printed by the host Lisp, use (time$ x
  :mintime nil) instead, which may provide detailed,
  implementation-specific data such as the amounts of time spent in
  user and system mode, the gc time, the number of page faults
  encountered, and so on. Of you can create a custom message,
  configured using the :msg and :args parameters. Time$ can also be
  made to report timing information only conditionally: the
  :real-mintime (or equivalently, :mintime), :run-mintime, and
  :minalloc arguments can be used to avoid reporting timing
  information for computations that take a small amount of time
  (perhaps as might be expected in ordinary cases), but to draw the
  user's attention to computations that take longer or allocate more
  memory than expected.

  We next document the keyword arguments in some detail.

      Keyword arguments :real-mintime (or :mintime) and :run-mintime can be
      used to specify a minimum time threshold for time reporting.
      That is, no timing information will be printed if the execution
      of form takes less than the specified number of seconds of real
      (total) time or run (cpu) time, respectively. Note that
      rational numbers like 1/2 may be used to specify a fractional
      amount of seconds. It is an error to specify both :real-mintime
      and its synonym, :mintime.

      Keyword argument :minalloc is not supported on all Lisps. When it is
      not supported, it is ignored. But on supported Lisps, :minalloc
      can be used to specify a minimum memory allocation threshold.
      If form results in fewer than this many bytes being allocated,
      then no timing information will be reported.

      Keyword argument :msg, when provided, should be a string accepted by
      the fmt family of functions (see [fmt]), and it may refer to
      the elements of :args by their positions, just as for cw (see
      [cw]).

  The following directives allow you to report timing information using
  the :msg string. The examples at the top of this documentation
  topic illustrate the use of these directives.

      ~xf --- the form that was executed

      ~sa --- the amount of memory allocated, in bytes (in supported Lisps)

      ~st --- the real time taken, in seconds

      ~sc --- the run time (cpu time) taken, in seconds

      The following apply only when the host Lisp is GCL. The two system
      times will likely be nil unless the GCL version is 2.6.10 or
      later. Note the upper-case characters for child times.

      ~sC --- the child run time (cpu time) taken, in seconds

      ~ss --- the system time taken, in seconds

      ~sS --- the child system time taken, in seconds

  We turn now to an example that illustrates how time$ can be called in
  function bodies. Consider the following definition of the Fibonacci
  function, followed by the definition of a function that times k
  calls of this function.

    (defun fib (n)
      (if (zp n)
          1
        (if (= n 1)
            1
          (+ (fib (- n 1))
             (fib (- n 2))))))

    (defun time-fib (k)
      (if (zp k)
          nil
        (prog2$
         (time$ (fib k)
                :mintime 1/2
                :msg \"(fib ~x0) took ~st seconds, ~sa bytes allocated.~%\"
                :args (list k))
         (time-fib (1- k)))))

  The following log shows a sample execution of the function defined
  just above.

    ACL2 !>(time-fib 36)
    (fib 36) took 3.19 seconds, 1280 bytes allocated.
    (fib 35) took 1.97 seconds, 1280 bytes allocated.
    (fib 34) took 1.21 seconds, 1280 bytes allocated.
    (fib 33) took 0.75 seconds, 1280 bytes allocated.
    NIL
    ACL2 !>

  Notes:

  (1) Common Lisp specifies that the time utility prints to ``trace
  output'', and time$ follows this convention. Thus, if you have
  opened a [trace] file (see [open-trace-file]), then you can expect
  to find the time$ output there.

  (2) Unless the :msg argument is supplied, an explicit call of time$
  in the top-level loop will show that the form being timed is a call
  of the ACL2 evaluator function ev-rec. This is normal; the curious
  are invited, at their own risk, to see [return-last] for an
  explanation.


Subtopics

  [Time-tracker]
      Display time spent during specified evaluation")
 (TIME-TRACKER
  (DEBUGGING TIME$ ACL2-BUILT-INS)
  "Display time spent during specified evaluation

  The time-tracker macro is a utility for displaying time spent during
  specified evaluation. In general, the user provides this
  specification. However, ACL2 itself uses this utility for tracking
  uses of its [tau-system] reasoning utility (see
  [time-tracker-tau]). We discuss that use as an example before
  discussing the general form for calls of time-tracker.

  Note that by default, the time being tracked is runtime (cpu time);
  to switch to realtime (elapsed time), see [get-internal-time].

  Remark for ACL2(p) users (see [parallelism]): time-tracker is merely
  a no-op in ACL2(p).

  During the development of the [tau-system], we were concerned about
  the possibility that it would slow down proofs without any
  indication of how one might avoid the problem. We wanted a utility
  that would alert the user in such situations. However, the
  tau-system code does not return [state], so we could not track time
  spent in the state. We developed the time-tracker utility to track
  time and print messages, and we did it in a general way so that
  others can use it in their own code. Here is an example of such a
  message that could be printed during a proof.

    TIME-TRACKER-NOTE [:TAU]: Elapsed runtime in tau is 2.58 secs; see
    :DOC time-tracker-tau.

  And here is an example of such a message that could be printed at the
  end of the proof.

    TIME-TRACKER-NOTE [:TAU]: For the proof above, the total time spent
    in the tau system was 20.29 seconds.  See :DOC time-tracker-tau.

  The time-tracker utility tracks computation time spent on behalf of a
  user-specified ``tag''. In the case of the tau-system, we chose the
  tag, :tau. The first argument of time-tracker is the tag, which in
  our running example is always :tau. Note that although all
  arguments of time-tracker are evaluated, the first argument is
  typically a keyword and the second is always a keyword, and such
  arguments evaluate to themselves.

  An ACL2 function invoked at the start of a proof includes
  approximately the following code.

    (progn$
     (time-tracker :tau :end)
     (time-tracker :tau :init
                   :times '(1 2 3 4 5)
                   :interval 5
                   :msg \"Elapsed runtime in tau is ~st secs; see :DOC ~
                         time-tracker-tau.~|~%\")
     ...)

  The first time-tracker call (above) ends any existing time-tracking
  for tag :tau. One might have expected it to be put into code
  managing the proof summary, but we decided not to rely on that code
  being executed, say, in case of an interrupt. When a given tag is
  not already being time-tracked, then :end is a no-op (rather than
  an error).

  The second time-tracker call (above) initiates time-tracking for the
  tag, :tau. Moreover, it specifies the effect of the :print?
  keyword. Consider the following abbreviated definition from the
  ACL2 source code.

    (defun tau-clausep-lst-rec (clauses ens wrld ans ttree state calist)
      (cond
       ((endp clauses)
        (mv (revappend ans nil) ttree calist))
       (t (mv-let
           (flg1 ttree1 calist)
           (tau-clausep (car clauses) ens wrld state calist)
           (prog2$ (time-tracker :tau :print?)
                   (tau-clausep-lst-rec (cdr clauses) ...))))))

  Notice that (time-tracker :tau :print?) is executed immediately after
  tau-clausep is called. The idea is to check whether the total time
  elapsed inside the tau-system justifies printing a message to the
  user. The specification of :times '(1 2 3 4 5) in the :init form
  above says that a message should be printed after 1 second, after 2
  seconds, ..., and after 5 seconds. Thereafter, the specification of
  :interval 5 in the :init form above says that each time we print,
  at least 5 additional seconds should have been tracked before
  (time-tracker :tau :print?) prints again. Finally, the :msg keyword
  above specifies just what should be printed. If it is omitted, then
  a reasonable default message is printed (as discussed below), but
  in this case we wanted to print a custom message. The :msg string
  above is what is printed using formatted printing (see [fmt]),
  where the character #\\t is bound to a string giving a decimal
  representation with two decimal points of the time tracked so far
  for tag :tau. (As our general description below points out, :msg
  can also be a ``message'' list rather than a string.)

  But when is time actually tracked for :tau? Consider the following
  definition from the ACL2 source code.

    (defun tau-clausep-lst (clauses ens wrld ans ttree state calist)
      (prog2$ (time-tracker :tau :start)
              (mv-let
               (clauses ttree calist)
               (tau-clausep-lst-rec clauses ens wrld ans ttree state calist)
               (prog2$ (time-tracker :tau :stop)
                       (mv clauses ttree calist)))))

  The two calls of time-tracker above first start, and then stop,
  time-tracking for the tag, :tau. Thus, time is tracked during
  evaluation of the call of tau-clausep-lst-rec, which is the
  function (discussed above) that does the [tau-system]'s work.

  Finally, as noted earlier above, ACL2 may print a time-tracking
  message for tag :tau at the end of a proof. The ACL2 function
  print-summary contains essentially the following code.

    (time-tracker :tau :print?
                  :min-time 1
                  :msg \"For the proof above, the total runtime ~
                        spent in the tau system was ~st seconds.  ~
                        See :DOC time-tracker-tau.~|~%\")

  The use of :min-time says that we are to ignore the :times and
  :interval established by the :init call described above, and
  instead, print a message if and only if at least 1 second (since 1
  is the value of keyword :min-time) has been tracked for tag :tau.
  Formatted printing (see [fmt]) is used for the value of :msg, where
  the character #\\t is bound to a decimal string representation of
  the time in seconds, as described above.

  The example above covers all legal values for the second argument of
  time-tracker and discusses all the additional legal keyword
  arguments. We conclude with a precise discussion of all arguments.
  Note that all arguments are evaluated; thus when we refer to an
  argument, we are discussing the value of that argument. All times
  discussed are runtimes, i.e., cpu times, unless that default is
  changed; see [get-internal-time].

    General forms:

    (time-tracker t)        ; enable time-tracking (default)

    (time-tracker nil)      ; disable time-tracking

    (time-tracker tag       ; a symbol other than t or nil
                  option    ; :init, :end, :start, :stop, or :print?
                  ;; keyword arguments:
                  :times    ; non-nil if and only if option is :init
                  :interval ; may only be non-nil with :init option
                  :min-time ; may only be non-nil with :print? option
                  :msg      ; may only be non-nil with :init and :print? options

  Time-tracking is enabled by default. If the first argument is t or
  nil, then no other arguments are permitted and time-tracking is
  enabled or disabled, respectively. When time-tracking is disabled,
  nothing below takes place. Thus we assume time-tracking is enabled
  for the remainder of this discussion. We also assume below that the
  first argument is neither t nor nil.

  We introduce some basic notions about time-tracking. A given tag,
  such as :tau in the example above, might or might not currently be
  ``tracked'': :init causes the specified tag to be tracked, while
  :end causes the specified tag not to be tracked. If the tag is
  being tracked, the tag might or might not be ``active'': :start
  causes the tag to be in an active state, whie :stop causes the tag
  not to be active. Note that only tracked tags can be in an active
  or inactive state. For a tag that is being tracked, the
  ``accumulated time'' is the total time spent in an active state
  since the time that the tag most recently started being tracked,
  and the ``checkpoint list'' is a non-empty list of rational numbers
  specifying when printing may take place, as described below.

  We now consider each legal value for the second argument, or
  ``option'', for a call of time-tracker on a given tag.

  :Init specifies that the tag is to be tracked. It also establishes
  defaults for the operation of :print?, as described below, using
  the :times, :interval, and :msg keywords. Of these three, only
  :times is required, and its value must be a non-empty list of
  rational numbers specifying the initial checkpoint list for the
  tag. It is an error to specify :init if the tag is already being
  tracked. (So if you don't care whether or not the tag is already
  being tracked and you want to initiate tracking for that tag, use
  :end first.)

  :End specifies that if the tag is being tracked, then it should nstop
  being tracked. If the tag is not being tracked, then :end has no
  effect.

  :Start specifies that the tag is to be active. It is an error to
  specify :start if the tag is not being tracked or is already
  active.

  :Stop specifies that the tag is to stop being active. It is an error
  to specify :stop if the tag is not being tracked or is not active.

  :Print? specifies that if the tag is being tracked (not necessarily
  active), then a message should be printed if a suitable condition
  is met. The nature of that message and that condition depend on the
  keyword options supplied with :print? as well as those supplied
  with the :init option that most recently initiated tracking.
  :Print? has no effect if the tag is not being tracked, except that
  if certain keyword values are checked if supplied with :print?:
  :min-time must be a rational number or nil, and :msg must be either
  a string, a true-list whose car is a string, or nil. The remainder
  of this documentation describes the :print? option in detail under
  the assumption that the tag is being tracked: first, giving the
  conditions under which it causes a message to be printed, and
  second, explaining what is printed.

  When :print? is supplied a non-nil value of :min-time, that value
  must be a rational number, in which case a message is printed if
  the accumulated time for the tag is at least that value. Otherwise
  a message is printed if the accumulated time is greater than or
  equal to the car of the checkpoint list for the tag. In that case,
  the tracking state for the tag is updated in the following two
  ways. First, the checkpoint list is scanned from the front and as
  long as the accumulated time is greater than or equal to the car of
  the remaining checkpoint list, that car is popped off the
  checkpoint list. Second, if the checkpoint list has been completely
  emptied and a non-nil :interval was supplied when tracking was most
  recently initiated with the :init option, then the checkpoint list
  is set to contain a single element, namely the sum of the
  accumulated time with that value of :interval.

  Finally, suppose the above criteria are met, so that :print? results
  in printing of a message. We describe below the message, msg, that
  is printed. Here is how it is printed (see [fmt]), where
  seconds-as-decimal-string is a string denoting the number of
  seconds of accumulated time for the tag, with two digits after the
  decimal point.

    (fms \"TIME-TRACKER-NOTE [~x0]: ~@1~|\"
         (list (cons #0 tag)
               (cons #1 msg)
               (cons #t seconds-as-decimal-string))
         (proofs-co state) state nil)

  The value of msg is the value of the :msg keyword supplied with
  :print?, if non-nil; else, the value of :msg supplied when most
  recently initialization with the :init option, if non-nil; and
  otherwise, the string \"~st s\" (the final ``s'' abbreviating the
  word ``seconds''). It is convenient to supply :msg as a call (msg
  str arg-0 arg-1 ... arg-k), where str is a string and each arg-i is
  the value to be associated with #\\i upon formatted printing (as
  with [fmt]) of the string str.")
 (TIME-TRACKER-TAU
  (TAU-SYSTEM)
  "Messages about expensive use of the [tau-system]

  This [documentation] topic explains messages printing by the theorem
  prover about the [tau-system], as follows.

  During a proof you may see a message such as the following.

    TIME-TRACKER-NOTE [:TAU]: Elapsed runtime in tau is 4.95 secs; see
    :DOC time-tracker-tau.

  Just below a proof summary you may see a message such as the
  following.

    TIME-TRACKER-NOTE [:TAU]: For the proof above, the total runtime spent
    in the tau system was 30.01 seconds.  See :DOC time-tracker-tau.

  Both of these messages are intended to let you know that certain
  prover heuristics (see [tau-system]) may be slowing proofs down
  more than they are helping. If you are satisfied with the prover's
  performance, you may ignore these messages or even turn them off by
  disabling time-tracking entirely (see [time-tracker]). Otherwise,
  here are some actions that you can take to solve such a performance
  problem.

  The simplest solution is to disable the tau-system, in either of the
  following equivalent ways.

    (in-theory (disable (:executable-counterpart tau-system)))
    (in-theory (disable (tau-system)))

  But if you want to leave the tau-system enabled, you could
  investigate the possibility is that the tau-system is causing an
  expensive :[logic]-mode function to be executed. You can diagnose
  that problem by observing the rewriter --- see [dmr] --- or by
  interrupting the system and getting a backtrace (see
  [set-debugger-enable]). A solution in that case is to disable the
  executable-counterpart of that function, for example in either of
  these equivalent ways.

    (in-theory (disable (:executable-counterpart foo)))
    (in-theory (disable (foo)))

  As a result, the tau-system will be weakened, but perhaps only
  negligibly.

  In either case above, you may prefer to provide :[in-theory] hints
  rather than :in-theory [events]; see [hints].

  A more sophisticated solution is to record values of the
  :[logic]-mode function in question, so that the tau-system will
  look up the necessary values rather than calling the function,
  whether or not the executable-counterpart of that function is
  enabled. Here is an example of a lemma that can provide such a
  solution. See [tau-system].

    (defthm lemma
      (and (foo 0)
           (foo 17)
           (foo t)
           (not (foo '(a b c))))
      :rule-classes :tau-system)")
 (TIPS
  (ACL2-TUTORIAL)
  "Some hints for using the ACL2 prover

  We present here some tips for using ACL2 effectively. Though this
  collection is somewhat ad hoc, we try to provide some organization,
  albeit somewhat artificial: for example, the sections overlap, and
  no particular order is intended. This material has been adapted by
  Bill Young from a very similar list for Nqthm that appeared in the
  conclusion of: ``Interaction with the Boyer-Moore Theorem Prover: A
  Tutorial Study Using the Arithmetic-Geometric Mean Theorem,'' by
  Matt Kaufmann and Paolo Pecchiari, CLI Technical Report 100, June,
  1995. We also draw from a similar list in Chapter 13 of ``A
  Computational Logic Handbook'' by R.S. Boyer and J S. Moore
  (Academic Press, 1988). We'll refer to this as ``ACLH'' below.

  These tips are organized roughly as follows.

      A. ACL2 Basics

      B. Strategies for creating events

      C. Dealing with failed proofs

      D. Performance tips

      E. Miscellaneous tips and knowledge

      F. Some things you DON'T need to know

  ACL2 BASICS

  A1. The ACL2 logic.
  This is a logic of total functions. For example, if A and B are less
  than or equal to each other, then we need to know something more in
  order to conclude that they are equal (e.g., that they are
  numbers). This kind of twist is important in writing definitions;
  for example, if you expect a function to return a number, you may
  want to apply the function [fix] or some variant (e.g., [nfix] or
  [ifix]) in case one of the formals is to be returned as the value.

  ACL2's notion of ordinals is important on occasion in supplying
  ``measure [hints]'' for the acceptance of recursive definitions. Be
  sure that your measure is really an ordinal. Consider the following
  example, which ACL2 fails to admit (as explained below).

    (defun cnt (name a i x)
      (declare (xargs :measure (+ 1 i)))
      (cond ((zp (+ 1 i))
             0)
            ((equal x (aref1 name a i))
             (1+ (cnt name a (1- i) x)))
            (t (cnt name a (1- i) x))))

  One might think that (+ 1 i) is a reasonable measure, since we know
  that (+ 1 i) is a positive integer in any recursive call of cnt,
  and positive integers are ACL2 ordinals (see [o-p]). However, the
  ACL2 logic requires that the measure be an ordinal unconditionally,
  not just under the governing assumptions that lead to recursive
  calls. An appropriate fix is to apply [nfix] to (+ 1 i), i.e., to
  use

    (declare (xargs :measure (nfix (+ 1 i))))

  in order to guarantee that the measure will always be an ordinal (in
  fact, a positive integer).

  For more about admissibility of recursive definitions, see [defun],
  in particular the discussion of termination.

  A2. Simplification.
  The ACL2 simplifier is basically a rewriter, with some ``[linear]
  arithmetic'' thrown in. One needs to understand the notion of
  conditional rewriting. See [rewrite].

  A3. Parsing of rewrite rules.

  ACL2 parses [rewrite] rules roughly as explained in ACLH, except that
  it never creates ``unusual'' rule classes. In ACL2, if you want a
  :[linear] rule, for example, you must specify :[linear] in the
  :[rule-classes]. See [rule-classes], and also see [rewrite] and see
  [linear].

  A4. Linear arithmetic.
  On this subject, it should suffice to know that the prover can
  handle truths about [+] and [-], and that [linear] rules (see
  above) are somehow ``thrown in the pot'' when the prover is doing
  such reasoning. Perhaps it's also useful to know that [linear]
  rules can have hypotheses, and that conditional rewriting is used
  to relieve those hypotheses.

  A5. Events.
  Over time, the expert ACL2 user will know some subtleties of its
  [events]. For example, [in-theory] [events] and [hints] are
  important, and they distinguish between a function and its
  executable counterpart.

  B. STRATEGIES FOR CREATING EVENTS

  In this section, we concentrate on the use of definitions and
  [rewrite] rules. There are quite a few kinds of rules allowed in
  ACL2 besides [rewrite] rules, though most beginning users probably
  won't usually need to be aware of them. See [rule-classes] for
  details. In particular, there is support for [congruence]
  rewriting. Also see [rune] (``RUle NamE'') for a description of the
  various kinds of rules in the system.

  B1. Use high-level strategy.
  Decompose theorems into ``manageable'' lemmas (admittedly,
  experience helps here) that yield the main result ``easily.'' It's
  important to be able to outline non-trivial proofs by hand (or in
  your head). In particular, avoid submitting goals to the prover
  when there's no reason to believe that the goal will be proved and
  there's no ``sense'' of how an induction argument would apply. It
  is often a good idea to avoid induction in complicated theorems
  unless you have a reason to believe that it is appropriate.

  B2. Write elegant definitions.
  Try to write definitions in a reasonably modular style, especially
  recursive ones. Think of ACL2 as a [programming] language whose
  procedures are definitions and lemmas, hence we are really
  suggesting that one follow good [programming] style (in order to
  avoid duplication of ``code,'' for example).

  When possible, complex functions are best written as compositions of
  simpler functions. The theorem prover generally performs better on
  primitive recursive functions than on more complicated recursions
  (such as those using accumulating parameters).

  Avoid large non-recursive definitions which tend to lead to large
  case explosions. If such definitions are necessary, try to prove
  all relevant facts about the definitions and then [disable] them.

  Whenever possible, avoid mutual recursion if you care to prove
  anything about your functions. The induction heuristics provide
  essentially no help with reasoning about mutually defined
  functions. Mutually recursive functions can usually be combined
  into a single function with a ``flag'' argument. (However, see
  [mutual-recursion-proof-example] for a small example of proof
  involving mutually recursive functions.)

  B3. Look for analogies.
  Sometimes you can easily edit sequences of lemmas into sequences of
  lemmas about analogous functions.

  B4. Write useful rewrite rules.
  As explained in A3 above, every [rewrite] rule is a directive to the
  theorem prover, usually to replace one [term] by another. The
  directive generated is determined by the syntax of the [defthm]
  submitted. Never submit a [rewrite] rule unless you have considered
  its interpretation as a proof directive.

  B4a. Rewrite rules should simplify.
  Try to write [rewrite] rules whose right-hand sides are in some
  sense ``simpler than'' (or at worst, are variants of) the left-hand
  sides. This will help to avoid infinite loops in the rewriter.

  B4b. Avoid needlessly expensive rules.
  Consider a rule whose conclusion's left-hand side (or, the entire
  conclusion) is a [term] such as (consp x) that matches many [term]s
  encountered by the prover. If in addition the rule has complicated
  hypotheses, this rule could slow down the prover greatly. Consider
  switching the conclusion and a complicated hypothesis (negating
  each) in that case.

  B4c. The ``Knuth-Bendix problem''.
  Be aware that left sides of [rewrite] rules should match the
  ``normalized forms'', where ``normalization'' (rewriting) is inside
  out. Be sure to avoid the use of nonrecursive function symbols on
  left sides of [rewrite] rules, except when those function symbols
  are [disable]d, because they tend to be expanded away before the
  rewriter would encounter an instance of the left side of the rule.
  Also assure that subexpressions on the left hand side of a rewrite
  rule are in simplified form; see [community-books] example
  books/demos/knuth-bendix-problem-1.lisp.

  B4d. Avoid proving useless rules.
  Sometimes it's tempting to prove a [rewrite] rule even before you
  see how it might find application. If the rule seems clean and
  important, and not unduly expensive, that's probably fine,
  especially if it's not too hard to prove. But unless it's either
  part of the high-level strategy or, on the other hand, intended to
  get the prover past a particular unproved goal, it may simply waste
  your time to prove the rule, and then clutter the database of rules
  if you are successful.

  B4e. State rules as strongly as possible, usually.
  It's usually a good idea to state a rule in the strongest way
  possible, both by eliminating unnecessary hypotheses and by
  generalizing subexpressions to variables.

  Advanced users may choose to violate this policy on occasion, for
  example in order to avoid slowing down the prover by excessive
  attempted application of the rule. However, it's a good rule of
  thumb to make the strongest rule possible, not only because it will
  then apply more often, but also because the rule will often be
  easier to prove (see also B6 below). New users are sometimes
  tempted to put in extra hypotheses that have a ``type restriction''
  appearance, without realizing that the way ACL2 handles (total)
  functions generally lets it handle trivial cases easily.

  B4f. Avoid circularity.
  A stack overflow in a proof attempt almost always results from
  circular rewriting. Use [brr] to investigate the stack; see
  [break-lemma]. Because of the complex heuristics, it is not always
  easy to define just when a [rewrite] will cause circularity. See
  the very good discussion of this topic in ACLH.

  See [break-lemma] for a trick involving use of the forms brr t and
  (cw-gstack) for inspecting loops in the rewriter.

  B4g. Remember restrictions on permutative rules.
  Any rule that permutes the variables in its left hand side could
  cause circularity. For example, the following axiom is
  automatically supplied by the system:

    (defaxiom commutativity-of-+
              (equal (+ x y) (+ y x))).

  This would obviously lead to dangerous circular rewriting if such
  ``permutative'' rules were not governed by a further restriction.
  The restriction is that such rules will not produce a [term] that
  is ``lexicographically larger than'' the original [term] (see
  [loop-stopper]). However, this sometimes prevents intended
  rewrites. See Chapter 13 of ACLH for a discussion of this problem.

  B5. Conditional vs. unconditional rewrite rules.
  It's generally preferable to form unconditional [rewrite] rules
  unless there is a danger of case explosion. That is, rather than
  pairs of rules such as

    (implies p
             (equal term1 term2))

  and

    (implies (not p)
             (equal term1 term3))

  consider:

    (equal term1
           (if p term2 term3))

  However, sometimes this strategy can lead to case explosions: [if]
  [term]s introduce cases in ACL2. Use your judgment. (On the subject
  of [if]: [cond], [case], [and], and [or] are macros that abbreviate
  [if] forms, and propositional functions such as [implies] quickly
  expand into [if] [term]s.)

  B6. Create elegant theorems.
  Try to formulate lemmas that are as simple and general as possible.
  For example, sometimes properties about several functions can be
  ``factored'' into lemmas about one function at a time. Sometimes
  the elimination of unnecessary hypotheses makes the theorem easier
  to prove, as does generalizing first by hand.

  B7. Use [defaxiom]s temporarily to explore possibilities.
  When there is a difficult goal that seems to follow immediately (by
  a :use hint or by rewriting) from some other lemmas, you can create
  those lemmas as [defaxiom] [events] (or, the application of
  [skip-proofs] to [defthm] [events]) and then double-check that the
  difficult goal really does follow from them. Then you can go back
  and try to turn each [defaxiom] into a [defthm]. When you do that,
  it's often useful to [disable] any additional [rewrite] rules that
  you prove in the process, so that the ``difficult goal'' will still
  be proved from its lemmas when the process is complete.

  Better yet, rather than disabling [rewrite] rules, use the [local]
  mechanism offered by [encapsulate] to make temporary rules
  completely [local] to the problem at hand. See [encapsulate] and
  see [local].

  B9. Use books.
  Consider using previously certified [books], especially for
  [arithmetic] reasoning. This cuts down the duplication of effort
  and starts your specification and proof effort from a richer
  foundation. See [community-books].

  C. DEALING WITH FAILED PROOFS

  C1. Look in proof output for goals that can't be further simplified.
  Use the ``[proof-tree]'' utility to explore the proof space.
  However, you don't need to use that tool to use the ``checkpoint''
  strategy. The idea is to think of ACL2 as a ``simplifier'' that
  either proves the theorem or generates some goal to consider. That
  goal is the first ``checkpoint,'' i.e., the first goal that does
  not further simplify. Exception: it's also important to look at the
  induction scheme in a proof by induction, and if induction seems
  appropriate, then look at the first checkpoint after the induction
  has begun.

  Consider whether the goal on which you focus is even a theorem.
  Sometimes you can execute it for particular values to find a
  counterexample.

  When looking at checkpoints, remember that you are looking for any
  reason at all to believe the goal is a theorem. So for example,
  sometimes there may be a contradiction in the hypotheses.

  Don't be afraid to skip the first checkpoint if it doesn't seem very
  helpful. Also, be willing to look a few lines up or down from the
  checkpoint if you are stuck, bearing in mind however that this
  practice can be more distracting than helpful.

  C2. Use the ``break rewrite'' facility.
  [Brr] and related utilities let you inspect the ``rewrite stack.''
  These can be valuable tools in large proof efforts. See
  [break-lemma] for an introduction to these tools, and see
  [break-rewrite] for more complete information.

  The break facility is especially helpful in showing you why a
  particular rewrite rule is not being applied.

  C3. Use induction hints when necessary. Of course, if you can define
  your functions so that they suggest the correct inductions to ACL2,
  so much the better! But for complicated inductions, induction
  [hints] are crucial. See [hints] for a description of :induct
  [hints].

  C4. Use the ``Proof Checker'' to explore.
  The [verify] command supplied by ACL2 allows one to explore problem
  areas ``by hand.'' However, even if you succeed in proving a
  conjecture with [verify], it is useful to prove it without using
  it, an activity that will often require the discovery of [rewrite]
  rules that will be useful in later proofs as well.

  C5. Don't have too much patience.
  Interrupt the prover fairly quickly when simplification isn't
  succeeding.

  C6. Simplify rewrite rules.
  When it looks difficult to relieve the hypotheses of an existing
  [rewrite] rule that ``should'' apply in a given setting, ask
  yourself if you can eliminate a hypothesis from the existing
  [rewrite] rule. If so, it may be easier to prove the new version
  from the old version (and some additional lemmas), rather than to
  start from scratch.

  C7. Deal with base cases first.
  Try getting past the base case(s) first in a difficult proof by
  induction. Usually they're easier than the inductive step(s), and
  rules developed in proving them can be useful in the inductive
  step(s) too. Moreover, it's pretty common that mistakes in the
  statement of a theorem show up in the base case(s) of its proof by
  induction.

  C8. Use :expand hints. Consider giving :expand [hints]. These are
  especially useful when a proof by induction is failing. It's almost
  always helpful to open up a recursively defined function that is
  supplying the induction scheme, but sometimes ACL2 is too timid to
  do so; or perhaps the function in question is [disable]d.

  D. PERFORMANCE TIPS

  D1. Disable rules.
  There are a number of instances when it is crucial to [disable]
  rules, including (often) those named explicitly in :use [hints].
  Also, [disable] recursively defined functions for which you can
  prove what seem to be all the relevant properties. The prover can
  spend significant time ``behind the scenes'' trying to open up
  recursively defined functions, where the only visible effect is
  slowness.

  D2. Turn off the ``break rewrite'' facility. Remember to execute :brr
  nil after you've finished with the ``break rewrite'' utility (see
  [break-rewrite]), in order to bring the prover back up to full
  speed.

  E. MISCELLANEOUS TIPS AND KNOWLEDGE

  E1. Order of application of rewrite rules.
  Keep in mind that the most recent [rewrite] rules in the [history]
  are tried first.

  E2. Relieving hypotheses is not full-blown theorem proving.
  Relieving hypotheses on [rewrite] rules is done by rewriting and
  [linear] arithmetic alone, not by case splitting or by other prover
  processes ``below'' simplification.

  E3. ``Free variables'' in rewrite rules.
  The set of ``free variables'' of a [rewrite] rule is defined to
  contain those variables occurring in the rule that do not occur in
  the left-hand side of the rule. It's often a good idea to avoid
  rules containing free variables because they are ``weak,'' in the
  sense that hypotheses containing such variables can generally only
  be proved when they are ``obviously'' present in the current
  context. This weakness suggests that it's important to put the most
  ``interesting'' (specific) hypotheses about free variables first,
  so that the right instances are considered. For example, suppose
  you put a very general hypothesis such as (consp x) first. If the
  context has several [term]s around that are known to be [consp]s,
  then x may be bound to the wrong one of them. For much more
  information on free variables, see [free-variables].

  E4. Obtaining information
  Use :[pl] foo to inspect [rewrite] rules whose left hand sides are
  applications of the function foo. Another approach to seeing which
  [rewrite] rules apply is to enter the [proof-checker] with
  [verify], and use the show-rewrites or sr command.

  E5. Consider esoteric rules with care.
  If you care to see [rule-classes] and peruse the list of subtopics
  (which will be listed right there in most versions of this
  [documentation]), you'll see that ACL2 supports a wide variety of
  rules in addition to :[rewrite] rules. Should you use them? This is
  a complex question that we are not ready to answer with any
  generality. Our general advice is to avoid relying on such rules as
  long as you doubt their utility. More specifically: be careful not
  to use conditional type prescription rules, as these have been
  known to bring ACL2 to its knees, unless you are conscious that you
  are doing so and have reason to believe that they are working well.

  F. SOME THINGS YOU DON'T NEED TO KNOW

  Most generally: you shouldn't usually need to be able to predict too
  much about ACL2's behavior. You should mainly just need to be able
  to react to it.

  F1. Induction heuristics.
  Although it is often important to read the part of the prover's
  output that gives the induction scheme chosen by the prover, it is
  not necessary to understand how the prover made that choice.
  (Granted, advanced users may occasionally gain minor insight from
  such knowledge. But it's truly minor in many cases.) What is
  important is to be able to tell it an appropriate induction when it
  doesn't pick the right one (after noticing that it doesn't). See C3
  above.

  F2. Heuristics for expanding calls of recursively defined functions.
  As with the previous topic, the important thing isn't to understand
  these heuristics but, rather, to deal with cases where they don't
  seem to be working. That amounts to supplying :expand [hints] for
  those calls that you want opened up, which aren't. See also C8
  above.

  F3. The ``waterfall''.
  As discussed many times already, a good strategy for using ACL2 is
  to look for checkpoints (goals stable under simplification) when a
  proof fails, perhaps using the [proof-tree] facility. Thus, it is
  reasonable to ignore almost all the prover output, and to avoid
  pondering the meaning of the other ``processes'' that ACL2 uses
  besides simplification (such as elimination, cross-fertilization,
  generalization, and elimination of irrelevance). For example, you
  don't need to worry about prover output that mentions ``type
  reasoning'' or ``abbreviations,'' for example.")
 (TOGGLE-PC-MACRO
  (PROOF-CHECKER)
  "Change an ordinary macro command to an atomic macro, or vice-versa

    Example:
    (toggle-pc-macro pro)

  Change pro from an atomic macro command to an ordinary one (or
  vice-versa, if pro happens to be an ordinary macro command)

    General Form:
    (toggle-pc-macro name &optional new-tp)

  If name is an atomic macro command then this turns it into an
  ordinary one, and vice-versa. However, if new-tp is supplied and
  not nil, then it should be the new type (the symbol macro or
  atomic-macro, in any package), or else there is no change.")
 (TOP-LEVEL
  (MISCELLANEOUS)
  "Evaluate a top-level form as a function body

  Some forms, such as calls of [with-local-stobj], are illegal when
  supplied directly to the ACL2 top-level loop. The macro top-level
  provides a workaround in such cases, by defining a temporary
  :[program]-mode function named top-level-fn whose only argument is
  state and whose body is the form to be evaluated. When the call of
  top-level returns there is no change to the existing ACL2 logical
  [world]. The following edited log illustrates all of the above
  points.

    ACL2 !>:pbt 0
              0  (EXIT-BOOT-STRAP-MODE)
    ACL2 !>(defstobj st fld)

    Summary
    Form:  ( DEFSTOBJ ST ...)
    Rules: NIL
    Time:  0.01 seconds (prove: 0.00, print: 0.00, other: 0.01)
     ST
    ACL2 !>(top-level
            (with-local-stobj
             st
             (mv-let (result st)
                     (let ((st (update-fld 17 st)))
                       (mv (fld st) st))
                     result)))
    17
    ACL2 !>(top-level
            (with-local-stobj
             st
             (mv-let (result st)
                     (let ((st (update-fld 17 st)))
                       (mv (fld st) st))
                     (mv nil result state))))
     17
    ACL2 !>(top-level
            (with-local-stobj
             st
             (mv-let (result st)
                     (let ((st (update-fld 17 st)))
                       (mv (fld st) st))
                     (mv result state))))
    (17 )
    ACL2 !>:pbt 0
              0  (EXIT-BOOT-STRAP-MODE)
       d      1:x(DEFSTOBJ ST FLD)
    ACL2 !>

  Each argument of top-level after the first should be a [declare] form
  or [documentation] string, as the list of these extra arguments
  will be placed before the first argument when forming the
  definition of top-level-fn.

  [Top-level] generates a call of [ld], so that the value returned is
  printed in the normal way. The call of [top-level] itself actually
  evaluates to (mv erp :invisible state), where erp is t if and only
  evaluation of the call of top-level-fn caused an error, which
  normally results in no additional output. (For details about
  ``caused an error'', see the definition of top-level in the ACL2
  source code, and see [ld-error-action].)")
 (TRACE
  (DEBUGGING)
  "Tracing functions in ACL2

  ACL2 provides a trace utility, [trace$], with corresponding reverse
  operation [untrace$]. These can be used without any dependence on
  the underlying Lisp utility, and are the tracing utilities of
  choice in ACL2; see [trace$] and see [untrace$].

  However, for advanced users we note that the underlying host Lisp may
  also provide a trace utility, trace, and corresponding untrace.
  Moreover, these have been modified in the case that the host Lisp
  is GCL, Allegro CL, or CCL (OpenMCL), to provide limited support
  for :entry, :exit, and perhaps :cond keywords, to hide certain
  large data structures (world, enabled structure, rewrite constant),
  and to trace executable counterparts. See source files
  *-trace.lisp. For the above Lisps, you can invoke the original
  trace and untrace by invoking old-trace and old-untrace,
  respectively, in raw Lisp rather than in the normal ACL2 loop.


Subtopics

  [Break-on-error]
      Break when encountering a hard or soft error caused by ACL2

  [Close-trace-file]
      Stop redirecting trace output to a file

  [Open-trace-file]
      Redirect trace output to a file

  [Set-trace-evisc-tuple]
      Set the trace evisc tuple

  [Trace!]
      Trace the indicated functions after creating an active trust tag

  [Trace$]
      Trace function evaluations

  [Untrace$]
      Untrace functions

  [Wet]
      Evaluate a form and print subsequent error trace")
 (TRACE!
  (TRACE)
  "Trace the indicated functions after creating an active trust tag

    Example:
    (trace! (fact :native t :entry *foo*))

    General Form:
    (trace! spec1 ... specn)

  where the speci are suitable arguments to [trace$].

  See [trace$] for a way to trace function calls. Some calls of trace$
  are potentially dangerous and thus require a trust tag (see
  [defttag]). But it can be a nuisance to call defttag explicitly, so
  the trace! macro is provided in order to avoid the need to do that:
  trace! automatically defines a (temporary) trust tag.

  See [untrace$] for how to undo the effect of [trace!].

  The evaluation of a trace! form causes temporary creation of an
  active trust tag, :trace!, followed by the corresponding trace$
  form. The trust tag will disappear when the call to trace!
  completes. Even though trace! will remove its temporary ttag, it
  will still print a ``TTAG NOTE'', which indicates that the session
  is suspect. See [defttag] and see [ttags-seen] for further remarks
  on this issue.

  Because of the active trust tag, it is possible to do things with
  trace! that are useful but without logical justification. Below is
  an example of how to use trace! to cause a function call to change
  [state], even though the function does not take [state] as a
  parameter.

    ACL2 !>(defun fact (n)
             (declare (xargs :guard (natp n) :verify-guards nil))
             (if (zp n)
                 1
               (* n (fact (1- n)))))

    The admission of FACT is trivial, using the relation O< (which is known
    to be well-founded on the domain recognized by O-P) and the measure
    (ACL2-COUNT N).  We observe that the type of FACT is described by the
    theorem (AND (INTEGERP (FACT N)) (< 0 (FACT N))).  We used the :compound-
    recognizer rule ZP-COMPOUND-RECOGNIZER and primitive type reasoning.

    Summary
    Form:  ( DEFUN FACT ...)
    Rules: ((:COMPOUND-RECOGNIZER ZP-COMPOUND-RECOGNIZER)
            (:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     FACT
    ACL2 !>(defun update-foo (n value state)
             (declare (xargs :stobjs state :verify-guards nil))
             (assign foo (cons (cons n value) (@ foo))))

    Since UPDATE-FOO is non-recursive, its admission is trivial.  We observe
    that the type of UPDATE-FOO is described by the theorem
    (AND (CONSP (UPDATE-FOO N VALUE STATE))
         (TRUE-LISTP (UPDATE-FOO N VALUE STATE))).
    We used primitive type reasoning.

    (UPDATE-FOO * * STATE) => (MV * * STATE).

    Summary
    Form:  ( DEFUN UPDATE-FOO ...)
    Rules: ((:FAKE-RUNE-FOR-TYPE-SET NIL))
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     UPDATE-FOO
    ACL2 !>(trace! (fact :exit (update-foo n value state)))

    TTAG NOTE: Adding ttag :TRACE! from the top level loop.
     ((FACT :EXIT (UPDATE-FOO N VALUE STATE)))
    ACL2 !>(assign foo nil)
     NIL
    ACL2 !>(fact 7)
    1> (ACL2_*1*_ACL2::FACT 7)
      2> (ACL2_*1*_ACL2::FACT 6)
        3> (ACL2_*1*_ACL2::FACT 5)
          4> (ACL2_*1*_ACL2::FACT 4)
            5> (ACL2_*1*_ACL2::FACT 3)
              6> (ACL2_*1*_ACL2::FACT 2)
                7> (ACL2_*1*_ACL2::FACT 1)
                  8> (ACL2_*1*_ACL2::FACT 0)
                  <8 NIL
                <7 NIL
              <6 NIL
            <5 NIL
          <4 NIL
        <3 NIL
      <2 NIL
    <1 NIL
    5040
    ACL2 !>(@ foo)
    ((7 . 5040)
     (6 . 720)
     (5 . 120)
     (4 . 24)
     (3 . 6)
     (2 . 2)
     (1 . 1)
     (0 . 1))
    ACL2 !>(verify-guards fact)

    Computing the guard conjecture for FACT....

    The guard conjecture for FACT is trivial to prove, given the :compound-
    recognizer rules NATP-COMPOUND-RECOGNIZER and ZP-COMPOUND-RECOGNIZER,
    primitive type reasoning and the :type-prescription rule FACT.  FACT
    is compliant with Common Lisp.

    Summary
    Form:  ( VERIFY-GUARDS FACT)
    Rules: ((:COMPOUND-RECOGNIZER NATP-COMPOUND-RECOGNIZER)
            (:COMPOUND-RECOGNIZER ZP-COMPOUND-RECOGNIZER)
            (:FAKE-RUNE-FOR-TYPE-SET NIL)
            (:TYPE-PRESCRIPTION FACT))
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     FACT
    ACL2 !>(assign foo nil)
     NIL
    ACL2 !>(fact 7)
    1> (ACL2_*1*_ACL2::FACT 7)
      2> (FACT 7)
        3> (FACT 6)
          4> (FACT 5)
            5> (FACT 4)
              6> (FACT 3)
                7> (FACT 2)
                  8> (FACT 1)
                    9> (FACT 0)
                    <9 NIL
                  <8 NIL
                <7 NIL
              <6 NIL
            <5 NIL
          <4 NIL
        <3 NIL
      <2 NIL
    <1 NIL
    5040
    ACL2 !>(@ foo)
    ((7 . 5040)
     (7 . 5040)
     (6 . 720)
     (5 . 120)
     (4 . 24)
     (3 . 6)
     (2 . 2)
     (1 . 1)
     (0 . 1))
    ACL2 !>(trace! (fact :exit (progn (update-foo n value state)
                                      (cons traced-fn values))))

    TTAG NOTE: Adding ttag :TRACE! from the top level loop.
     ((FACT :EXIT (PROGN (UPDATE-FOO N VALUE STATE)
                         (CONS TRACED-FN VALUES))))
    ACL2 !>(assign foo nil)
     NIL
    ACL2 !>(fact 7)
    1> (ACL2_*1*_ACL2::FACT 7)
      2> (FACT 7)
        3> (FACT 6)
          4> (FACT 5)
            5> (FACT 4)
              6> (FACT 3)
                7> (FACT 2)
                  8> (FACT 1)
                    9> (FACT 0)
                    <9 (FACT 1)
                  <8 (FACT 1)
                <7 (FACT 2)
              <6 (FACT 6)
            <5 (FACT 24)
          <4 (FACT 120)
        <3 (FACT 720)
      <2 (FACT 5040)
    <1 (ACL2_*1*_ACL2::FACT 5040)
    5040
    ACL2 !>(@ foo)
    ((7 . 5040)
     (7 . 5040)
     (6 . 720)
     (5 . 120)
     (4 . 24)
     (3 . 6)
     (2 . 2)
     (1 . 1)
     (0 . 1))
    ACL2 !>

  Finally, we remark that using trace! can cause errors in situations
  where tracing is automatically suspended and re-introduced. This is
  likely to be a rare occurrence, but consider the following example.

    (trace! (lexorder :native t :multiplicity 1))
    (certify-book \"foo\" 0 t)

  If the certify-book causes compilation, you may see an error such as
  the following.

    ACL2 Error in (CERTIFY-BOOK \"foo\" ...):  The keyword :NATIVE cannot
    be used in a trace spec unless there is an active trust tag.  The trace
    spec (LEXORDER :NATIVE T :MULTIPLICITY 1) is thus illegal.  Consider
    using trace! instead.  The complete list of keywords that require a
    trust tag for use in a trace spec is: (:NATIVE :DEF :MULTIPLICITY).

  This error is harmless. The function will appear, when calling
  (trace$), to remain traced, but in fact there will be no tracing
  behavior, so you may want to call [untrace$] on the function symbol
  in question.")
 (TRACE$
  (TRACE)
  "Trace function evaluations

    Examples:
    (trace$ foo bar)     ; trace foo and bar
    (trace$)             ; return current trace info (no new tracing specified)
    (trace$ (foo :entry  ; trace foo, printing first actual parameter upon entry
                 (car arglist)))
    (trace$ (foo :exit   ; trace foo, using fmt to print upon exit
                 (:fmt (msg \"Exiting FOO with ~x0\"
                            value))))
    (trace$ (foo :native t))

    General Forms:
    (trace$ spec1 spec2 ... specn) ; n >= 1
    (trace$)

  where the speci are trace specs, as described below.

  Trace$ installs alternate code for the indicated functions that
  prints information upon entry to, and exit from, calls of the
  functions. For an alternate tracing utility used for educational
  purposes in {ACL2s | http://acl2s.ccs.neu.edu/acl2s/doc/}, see
  community book books/misc/trace-star.lisp.

  From a logical perspective all trace printing is a fiction. (But see
  [trace!] for a way to get around this and modify [state].) For a
  related fiction, see [cw]. (Trace$) returns the list of
  currently-active trace specs, while the application of trace$ to at
  least one argument returns the list of its arguments that are
  successfully acted on.

  Output from [trace$] normally goes to the screen, i.e., to
  [standard-co]. But it can be redirected to a file; see
  [open-trace-file].

  See [untrace$] for how to undo the effect of [trace$]. Also see
  [trace] for mention of modifications made to raw Lisp trace, which
  is accessible (as described below) using the :native keyword.

  Note that when trace$ is applied to a function without option
  :native, that function's declarations and documentation are
  discarded.

  Next, we introduce tracing with some examples. After that, we provide
  reference documentation for individual trace options allowed in a
  trace spec. Note that although our example focuses on user-defined
  functions, trace$ can also be applied to built-in functions, though
  perhaps only system hackers should take advantage of this
  observation.

  We begin by illustrating the simplest sort of trace spec: a function
  symbol. For example, the form (trace$ foo bar) directs the tracing
  of functions foo and bar by virtue of the two trace specs foo and
  bar. We can see tracing in action by first defining:

    (defun f (x)
      (cons x x))

    (defun g (x)
      (list (f x) 3))

  The following log then illustrates tracing of these two functions.
  Notice that before [guard]s have been verified, the so-called
  ``*1*'' functions (sometimes called ``executable counterpart
  functions'' or ``logic functions'') are called but the
  corresponding raw Lisp functions are not; but after guard
  verification of f, the raw Lisp counterpart of f is indeed called.
  (See [guard] and see [guard-evaluation-examples-log].)

    ACL2 !>(trace$ f g)
     ((F) (G))
    ACL2 !>(g 7)
    1> (ACL2_*1*_ACL2::G 7)
      2> (ACL2_*1*_ACL2::F 7)
      <2 (ACL2_*1*_ACL2::F (7 . 7))
    <1 (ACL2_*1*_ACL2::G ((7 . 7) 3))
    ((7 . 7) 3)
    ACL2 !>(verify-guards f)

    Computing the guard conjecture for F....

    The guard conjecture for F is trivial to prove.  F is compliant with
    Common Lisp.

    Summary
    Form:  ( VERIFY-GUARDS F)
    Rules: NIL
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     F
    ACL2 !>(g 7)
    1> (ACL2_*1*_ACL2::G 7)
      2> (ACL2_*1*_ACL2::F 7)
        3> (F 7)
        <3 (F (7 . 7))
      <2 (ACL2_*1*_ACL2::F (7 . 7))
    <1 (ACL2_*1*_ACL2::G ((7 . 7) 3))
    ((7 . 7) 3)
    ACL2 !>

  The following example introduces trace specs other than function
  symbols. Consider the following definition.

    (defun fact (n)
      (declare (xargs :guard (natp n)))
      (if (zp n)
          1
        (* n (fact (1- n)))))

  The following log illustrates the use of trace options :cond
  (condition for entering trace), :entry (what to print on entry),
  and :exit (what to print on exit). The reason for two calls on
  argument 4 is that we are seeing such calls for the executable
  counterpart of fact and also its raw Lisp function.

    ACL2 !>(trace$ (fact :cond (evenp (car arglist))
                         :entry (cons 'factorial-call arglist)
                         :exit (car values)))
     ((FACT :COND (EVENP (CAR ARGLIST))
            :ENTRY (CONS 'FACTORIAL-CALL ARGLIST)
            :EXIT (CAR VALUES)))
    ACL2 !>(fact 4)
    1> (FACTORIAL-CALL 4)
      2> (FACTORIAL-CALL 4)
        3> (FACTORIAL-CALL 2)
          4> (FACTORIAL-CALL 0)
          <4 1
        <3 2
      <2 24
    <1 24
    24
    ACL2 !>

  Notice that VALUES above is the list of all values returned, which is
  a one-element list unless [mv] return is used, as illustrated in
  the following example, after defining: (defun two-vals (x) (mv x
  7)).

    ACL2 !>(trace$ two-vals)
     ((TWO-VALS))
    ACL2 !>(two-vals 3)
    1> (ACL2_*1*_ACL2::TWO-VALS 3)
    <1 (ACL2_*1*_ACL2::TWO-VALS 3 7)
    (3 7)
    ACL2 !>(verify-guards two-vals)

    Computing the guard conjecture for TWO-VALS....

    The guard conjecture for TWO-VALS is trivial to prove, given the :executable-
    counterpart of CONS.  TWO-VALS is compliant with Common Lisp.

    Summary
    Form:  ( VERIFY-GUARDS TWO-VALS)
    Rules: ((:EXECUTABLE-COUNTERPART CONS))
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)
     TWO-VALS
    ACL2 !>(two-vals 3)
    1> (ACL2_*1*_ACL2::TWO-VALS 3)
      2> (TWO-VALS 3)
      <2 (TWO-VALS 3 7)
    <1 (ACL2_*1*_ACL2::TWO-VALS 3 7)
    (3 7)
    ACL2 !>

  We now document all of the options that may appear in a trace spec. A
  trace spec with options is of the form

    (fn :kwd1 val1 :kwd2 val2 ... :kwdn valn)

  and here we document each legal keyword :kwdi and corresponding
  expected value vali. Note that trace$ is intended primarily for
  functions defined in the ACL2 command loop (see [lp]). If you want
  to trace a function that is defined in raw Lisp, then you can use
  option :native (see below), but then many other trace$ options will
  not be available to you: all of them except :multiplicity and
  :native itself will be passed directly to the trace utility of the
  underlying Common Lisp.

  :COND, :ENTRY, and :EXIT

  Introduction. For each of these three options, the value is a
  (user-level) term, except that for :entry and :exit the value can
  be of the form (:fmt u) or (:fmt! u), where u is a user-level term.
  We skip these two latter cases for now and return to them later.
  Then the indicated term is evaluated as indicated in the next
  paragraph, and if the :cond term is omitted or evaluates to
  non-nil, then the value of the :entry term is printed on entry and
  the value of the :exit term is printed on exit. By default, where
  :entry is omitted or is specified as nil, the value printed for
  :entry is the list obtained by consing the calling function symbol
  onto the list of actual parameters: in the notation described
  below, this is (cons TRACED-FN ARGLIST). Similarly, the default for
  printing at the exit of the function call, i.e. where :exit is
  omitted or is specified as nil, is (cons TRACED-FN VALUES) where
  VALUES is the list of values returned as described below.

  Available Variables. In the evaluations of the term described below
  upon a call of fn, each formal parameter of the definition of fn
  will be bound to the corresponding actual of the call, the variable
  ARGLIST will be bound to the list of actuals, and the variable
  TRACED-FN will be bound to the function being called (either fn or
  its executable counterpart function; see above). Additionally in
  the case of :exit, the variable VALUES will be bound to the
  multiple values returned (thus, a one-element list if [mv] is not
  used in the return). Also for :exit, we bind VALUE to the logical
  value returned, i.e., to the suitable list of values returned in
  the [mv] case and otherwise to the single value returned. So in the
  mv case, VALUE is the same as VALUES, and otherwise VALUE is (car
  VALUES). Other than these variables and [state], no other variable
  may occur in the term, whose value must be a single non-[stobj]
  value, unless there is an active trust tag (see [defttag]).

  Now suppose fn is called. First: If :cond is supplied and the result
  of evaluating the :cond term is nil, then no tracing is done.
  Otherwise tracing proceeds as follows. First the :entry form is
  evaluated, and the result is printed. Then the call of fn is
  evaluated. Finally the :exit term is evaluated and the result is
  printed. As indicated above, the default for the :entry term if
  omitted or explicitly nil is (cons TRACED-FN ARGLIST), and the
  default for the :exit term if omitted or explicitly nil is (cons
  TRACED-FN VALUES).

  Note that if the function has a formal named ARGLIST, then ARGLIST
  will nevertheless refer to the entire list of formals, not the
  single formal named ARGLIST; similarly for TRACED-FN, and
  additionally for VALUE and VALUES in the case of :exit.

  As mentioned above, for each of :entry and :exit, a value of nil
  specifies the default behavior. If you really want a value of nil,
  use a non-nil form that evaluates to nil, for example (car nil) or
  'nil. However, for :cond a value of nil means what it says: do not
  evaluate the :entry or :exit forms.

  Finally we discuss the case that the :entry or :exit term is of the
  form (:fmt u) or (:fmt! u). In these cases, the term u is evaluated
  as described above to produce a value, say msg, but instead of
  printing msg directly, ACL2 calls fmt1 using the string \"~@0\" and
  the alist that binds just character #\\0 to msg. The following
  example illustrates this point, where fact is defined as above.
  Also see [fmt]. Note that (msg string . vals) produces a value
  suitable for a \"~@\" directive to the fmt family of print functions.

    ACL2 !>(trace$
            (fact
             :entry (:fmt (msg \"Tracing ~x0 on ~x1\" traced-fn arglist))
             :exit (car values)))
     ((FACT :ENTRY (:FMT (MSG \"Tracing ~x0 on ~x1\" TRACED-FN ARGLIST))
            :EXIT (CAR VALUES)))
    ACL2 !>(fact 3)
    1> Tracing ACL2_*1*_ACL2::FACT on (3)
      2> Tracing FACT on (3)
        3> Tracing FACT on (2)
          4> Tracing FACT on (1)
            5> Tracing FACT on (0)
            <5 1
          <4 1
        <3 2
      <2 6
    <1 6
    6
    ACL2 !>

  If :fmt! is used instead of :fmt, then indentation as is the prefix
  string, \"n> \" or \"(trace$
            (fact
             :entry (:fmt! (msg \"Tracing ~x0 on ~x1\" traced-fn arglist))
             :exit (:fmt! (msg \"From input ~x0: ~x1\"
                               (car arglist) (car values)))))
     ((FACT :ENTRY (:FMT! (MSG \"Tracing ~x0 on ~x1\" TRACED-FN ARGLIST))
            :EXIT (:FMT! (MSG \"From input ~x0: ~x1\" (CAR ARGLIST)
                              (CAR VALUES)))))
    ACL2 !>(fact 3)
    Tracing ACL2_*1*_ACL2::FACT on (3)
    Tracing FACT on (3)
    Tracing FACT on (2)
    Tracing FACT on (1)
    Tracing FACT on (0)
    From input 0: 1
    From input 1: 1
    From input 2: 2
    From input 3: 6
    From input 3: 6
    6
    ACL2 !>

  Here is the same example, with user-managed indentation.

    ACL2 !>(trace$
            (fact
             :entry (:fmt! (msg \"~t0Tracing ~x1 on ~x2\"
                                (+ 3 (* 2 (@ trace-level)))
                                traced-fn arglist))
             :exit (:fmt! (msg \"~t0From input ~x1: ~x2\"
                               (1+ (* 2 (@ trace-level)))
                               (car arglist) (car values)))))
     ((FACT :ENTRY (:FMT! (MSG \"~t0Tracing ~x1 on ~x2\"
                               (+ 3 (* 2 (@ TRACE-LEVEL)))
                               TRACED-FN ARGLIST))
            :EXIT (:FMT! (MSG \"~t0From input ~x1: ~x2\"
                              (1+ (* 2 (@ TRACE-LEVEL)))
                              (CAR ARGLIST)
                              (CAR VALUES)))))
    ACL2 !>(fact 3)
       Tracing ACL2_*1*_ACL2::FACT on (3)
         Tracing FACT on (3)
           Tracing FACT on (2)
             Tracing FACT on (1)
               Tracing FACT on (0)
               From input 0: 1
             From input 1: 1
           From input 2: 2
         From input 3: 6
       From input 3: 6
    6
    ACL2 !>

  ADVANCED OPTIONS (alphabetical list)

  :COMPILE

  The tracing of fn installs a substitute definition of fn that prints
  trace information. If the :compile option is omitted or has value
  :same, then the new definition will be compiled if and only if the
  existing definition is already compiled. Otherwise, the new
  definition will be compiled exactly when the value of :compile is
  not nil.

  :DEF, :MULTIPLICITY

  ACL2's trace$ mechanism often needs to know the number of outputs of
  a traced function, in the sense of [mv]. If you trace a function
  that was not defined inside the ACL2 loop (hence you are using the
  :native option), or if you provide an alternative definition using
  option :def (see below) and the new definition changes the number
  of values returned, then a natural number value for :multiplicity
  informs the trace utility of the number of expected outputs of the
  function being traced. In the case that :native is supplied, the
  effect of a non-nil :multiplicity value depends on the host Lisp.
  In the case of Lisps for which ACL2 uses the built-in Lisp
  mechanism for returning multiple values (see [mv]), which are CCL
  and threaded SBCL as of June, 2010, :multiplicity is not needed and
  is ignored with :native t. For GCL and Allegro CL, :multiplicity is
  used to generate a suitable :exit form if the :exit keyword was not
  already supplied. For the other Lisps, the :multiplicity value is
  treated essentially as 1 whether it is supplied or not, because we
  do not know how to pass suitable information based on this value to
  the host Lisp's built-in tracing mechanism.

  Note that even supplying a :multiplicity option does not change the
  meaning of the variable values. See the discussion of :native
  below.

  A useful option can be to supply a definition as the value of :def.
  (Again, note that if :native is used, then all options other than
  :multiplicity are passed directly to the underlying Lisp; in
  particular, :def will have no effect with :native except in the
  unlikely case that the raw Lisp provides some sort of support for
  :def.) Note that this definition should be like a [defun] form, but
  without the leading defun symbol; and it should define the function
  symbol being traced, with the same formal parameter list. However,
  tracing of the so-called ``executable counterpart'' of a function
  (sometimes referred to as the ``*1* function'', for evaluation in
  the ACL2 loop; see [guards] for related discussion) is not
  sensitive to the :def option; rather, if a function has an
  executable counterpart then that executable counterpart is traced.

  :EVISC-TUPLE

  The printing described above is, by default, done using the current
  default trace evisc-tuple, which can be set using
  [set-trace-evisc-tuple] (for the shape of this tuple, see
  [evisc-tuple]); see [set-trace-evisc-tuple]. This tuple is based by
  default on the raw Lisp variables *print-level* and *print-length*,
  and will hide the ACL2 world and handle [stobj]s appropriately. You
  may override this default by supplying an evisc tuple with the
  :evisc-tuple argument in your trace spec. Be careful to supply a
  valid evisc-tuple, or you may get a raw Lisp error!

  A special value, :print, is useful if you are doing system hacking
  that can produce objects that are not valid ACL2 objects, such as
  raw Lisp arrays or objects in supporting packages not visible in
  the ACL2 read-eval-print loop. If you supply :evisc-tuple :print,
  then the printing described above will be done with raw Lisp
  printing rather than ACL2 printing: specifically, with (format
  *trace-output* \"s%\" x), where x is the value to be printed.

  A second special value for :evisc-tuple, :no-print, avoids printing
  the values of the :entry and :exit forms (or their defaults, if not
  specified). This option is of use for side effects; for an example
  see community book books/misc/wet.lisp.

  Note that if :evisc-tuple X is supplied, then the form X will be
  evaluated before the function body is entered. You can thus pull
  some tricks to print extra information before the :entry form is
  evaluated, for example as follows for a factorial function, fact.

    ACL2 !>(trace$ (fact :evisc-tuple
                         (prog2$ (cw \"~|**** HERE IS CW ****~|\")
                                 nil)))
     ((FACT :EVISC-TUPLE (PROG2$ (CW \"~|**** HERE IS CW ****~|\")
                                 NIL)))
    ACL2 !>(fact 3)
    **** HERE IS CW ****
    1> (ACL2_*1*_ACL2::FACT 3)
    **** HERE IS CW ****
      2> (ACL2_*1*_ACL2::FACT 2)
    **** HERE IS CW ****
        3> (ACL2_*1*_ACL2::FACT 1)
    **** HERE IS CW ****
          4> (ACL2_*1*_ACL2::FACT 0)
          <4 (ACL2_*1*_ACL2::FACT 1)
        <3 (ACL2_*1*_ACL2::FACT 1)
      <2 (ACL2_*1*_ACL2::FACT 2)
    <1 (ACL2_*1*_ACL2::FACT 6)
    6
    ACL2 !>

  :FORMALS

  Normally ACL2 can figure out the formals for a given function. This
  is always the case for functions defined in the ACL2 command loop
  and when option :def is supplied. If neither of these cases applies
  then you can still trace a function (even without using the :native
  option) by supplying option :notinline :fncall, but you will still
  need to supply the list of formal parameters. The value of the
  :formals option should be the list of formals in this case.

  :HIDE

  The default value for this advanced option is t, which causes
  [stobj]s and the logical [world] to be printed as single symbols,
  along with certain large structures of interest to developers
  (rewrite contants, enabled structures, and event and command index
  structures). If however the value nil is supplied, then this
  default behavior is defeated. In that case, you can still arrange
  to print the logical world as a symbol and to print [stobj]s
  without breaking the trace printing: see [set-trace-evisc-tuple]
  for how to do this globally, or similarly use the :evisc-tuple
  option to trace$ to do this with a single trace spec. Note however
  that with value nil specified for :hide, such use of an evisc-tuple
  will not deal properly with local stobjs (see [with-local-stobj])
  or stobjs bound by [stobj-let], or with the aforementioned large
  structures other than the logical [world].

  :NATIVE

  If :native is supplied with a non-nil value, then the trace spec is
  passed to the native Lisp trace (after removing the :native
  option). A trust tag (see [defttag]) is required in order to use
  this option, because no syntactic check is made on the :cond,
  :entry, or :exit forms -- arbitrary raw Lisp may occur in them!

  Note that by ``native Lisp trace'' we mean the currently installed
  trace. As discussed briefly elsewhere (see [trace]), ACL2 has
  modified that trace to be more useful if the underlying host Lisp
  is GCL, Allegro CL, or CCL (OpenMCL). If you need the original
  trace utility supplied for those Lisps, quit the ACL2 loop with :q
  and call old-trace and old-untrace in raw Lisp where you would
  otherwise call trace and untrace. Note that the original trace
  utility supplied with a given Lisp will not hide the ACL2 logical
  [world] or give special treatment to [stobj]s.

  It is important to understand that if :native t is specified, then
  all other options are interpreted by the native Lisp trace. For
  example, that trace probably has no understanding of the use of
  :fmt described above for :entry or :exit. Indeed, the native trace
  may not even accept any of :cond, :entry or :exit, let alone any of
  the advanced options! Moreover, if :native t is specified, then
  even a :multiplicity option does not provide the meaning of the
  variable values that one might desire. In GCL for example, in the
  case of an [mv] return of a function defined only in raw Lisp (not
  in ACL2), this variable will be bound to a list containing only the
  first result.

  :NOTINLINE

  By default, a new definition installed by trace$ will include a
  notinline declaration so that recursive calls will always be
  traced. To avoid this declaration, supply value nil.

  A special value for :notinline, :fncall, will cause the traced
  function to call its original definition. Without this special
  value, the new installed definition for the traced function will
  include the body of the original definition. This :fncall behavior
  is the default only in the following cases:

    * for functions whose definitions are built into ACL2;
    * for functions that have been added (using a trust tag, an advanced
      feature, so most users can probably ignore this case) to either
      of the [state] global variables program-fns-with-raw-code or
      logic-fns-with-raw-code;
    * ([hons-enabled] ACL2 executables only) for [memoize]d functions.

  The legal values for :notinline are t (the default for other than the
  cases displayed above), nil, and :fncall. (Except: For the
  [hons-enabled] ACL2 executables, only :fncall is legal.)

  Remarks.

  (1) If some of the given trace specs have errors, then trace$ will
  generally print error messages for those but will still process
  those that do not have errors. The value returned will indicate the
  trace specs that were processed successfully.

  (2) If you certify or include a book that redundantly defines a
  function that is currently traced, then tracing behavior may
  disappear if a compiled definition is installed for the function or
  its in-the-logic (so-called `*1*') counterpart.

  (3) Some predefined functions are called during tracing. In order to
  avoid infinite loops, such calls of traced predefined functions
  will be made using the original predefined functions, not using
  their code installed by trace$.")
 (TRANS
  (MACROS)
  "Print the macroexpansion of a form

    Examples:
    :trans (list a b c)
    :trans (caddr x)
    :trans (cond (p q) (r))

  This function takes one argument, an alleged term, and translates it,
  expanding the macros in it completely. Either an error is caused or
  the formal meaning of the term is printed. We also print the
  ``output signature'' which indicates how many results are returned
  and which are single-threaded objects. For example, a term that
  returns one ordinary object (e.g., an object other than [state] or
  a user-defined single-threaded object (see [defstobj])) has the
  output signature

    => *

  A term that returns the single-threaded object STATE has the output
  signature

    => STATE

  and a term that returns four results might have the output signature

    => (MV $MEM * * STATE)

  This signature indicates that the first result is the (user defined)
  single-threaded object $MEM, that the next two results are
  ordinary, and that the last result is STATE.

  See [trans!] for a corresponding command that does not enforce
  restrictions of single-threaded objects.

  It is sometimes more convenient to use [trans1] which is like trans
  but which only does top-level macroexpansion.

  For more, see [term].")
 (TRANS!
  (MACROS)
  "Print the macroexpansion of a form without single-threadedness
  concerns

    Examples:
    :trans! (list a b c)
    :trans! (append x state)

  :Trans! is identical to :[trans], except that unlike :trans, :trans!
  ignores single-threadedness restrictions. Thus, the second form
  above is legal for :trans!. Also see [trans] and see [trans1].")
 (TRANS1
  (MACROS)
  "Print the one-step macroexpansion of a form

    Examples:
    :trans1 (list a b c)
    :trans1 (caddr x)
    :trans1 (cond (p q) (r))

  This function takes one argument, an alleged term, and expands the
  top-level macro in it for one step only. Either an error is caused,
  which happens when the form is not a call of a macro, or the result
  is printed. Also see [trans], which translates the given form
  completely.")
 (TRUE-LIST-LISTP
  (LISTS TRUE-LISTP ACL2-BUILT-INS)
  "Recognizer for true (proper) lists of true lists

  True-list-listp is the function that checks whether its argument is a
  list that ends in, or equals, nil, and furthermore, all of its
  elements have that property. Also see [true-listp].

  Function: 

    (defun true-list-listp (x)
           (declare (xargs :guard t))
           (cond ((atom x) (eq x nil))
                 (t (and (true-listp (car x))
                         (true-list-listp (cdr x))))))")
 (TRUE-LISTP
  (LISTS ACL2-BUILT-INS)
  "Recognizer for proper (null-terminated) lists

  True-listp is the function that checks whether its argument is a list
  that ends in, or equals, nil.

For a discussion of whether requring lists to be nil-terminated is
right for you, see [std::strict-list-recognizers].
  Function: 

    (defun true-listp (x)
           (declare (xargs :guard t))
           (if (consp x)
               (true-listp (cdr x))
               (eq x nil)))


Subtopics

  [True-list-listp]
      Recognizer for true (proper) lists of true lists")
 (TRUNCATE
  (NUMBERS ACL2-BUILT-INS)
  "Division returning an integer by truncating toward 0

    Example Forms:
    ACL2 !>(truncate 14 3)
    4
    ACL2 !>(truncate -14 3)
    -4
    ACL2 !>(truncate 14 -3)
    -4
    ACL2 !>(truncate -14 -3)
    4
    ACL2 !>(truncate -15 -3)
    5
    ACL2 !>(truncate 10/4 3/4)
    3

  (Truncate i j) is the result of taking the quotient of i and j and
  dropping the fraction. For example, the quotient of -14 by 3 is -4
  2/3, so dropping the fraction 2/3, we obtain a result for (truncate
  -14 3) of -4.

  The [guard] for (truncate i j) requires that i and j are rational
  ([real], in ACL2(r)) numbers and j is non-zero.

  Truncate is a Common Lisp function. However, note that unlike Common
  Lisp, the ACL2 truncate function returns only a single value, Also
  see [nonnegative-integer-quotient], which is appropriate for
  integers and may simplify reasoning, unless a suitable arithmetic
  library is loaded, but be less efficient for evaluation on concrete
  objects.

  Function: 

    (defun truncate (i j)
           (declare (xargs :guard (and (real/rationalp i)
                                       (real/rationalp j)
                                       (not (eql j 0)))))
           (let* ((q (* i (/ j)))
                  (n (numerator q))
                  (d (denominator q)))
                 (cond ((= d 1) n)
                       ((>= n 0)
                        (nonnegative-integer-quotient n d))
                       (t (- (nonnegative-integer-quotient (- n)
                                                           d))))))")
 (TRUST-TAG (POINTERS) "See [defttag].")
 (TTAG (POINTERS) "See [defttag].")
 (TTAGS-SEEN
  (MISCELLANEOUS)
  "List some declared trust tags (ttags)

    General Forms:
    :ttags-seen
    (ttags-seen)

  Suppose the output is as follows.

    (T NIL)
    (FOO \"/home/bob/bar.lisp\"
         \"/home/cindy/bar.lisp\")
    Warning: This output is minimally trustworthy (see :DOC TTAGS-SEEN).

  This output indicates that the current logical [world] has seen the
  declaration of trust tag T at the top-level (see [defttag]) and the
  declaration of trust tag FOO in the two books included from the
  listed locations. The warning emphasizes that this command cannot
  be used to validate the ``purity'' of an ACL2 session, because
  using a ttag renders enough power to hide from this or any other
  command the fact that the ttag was ever declared.

  As discussed elsewhere (see [defttag]), the only reliable way to
  validate the ``purity'' of a session is to watch for ``TTAG NOTE''
  output.

  Another shortcoming of this command is that it only checks the
  current logical [world] for ttag declarations. For example, one
  could execute a [defttag] event; then use [progn!] and
  [set-raw-mode] to replace system functions with corrupt definitions
  or to introduce inconsistent axioms in the [ground-zero] [world];
  and finally, execute :[ubt!] 1 to remove all evidence of the ttag
  in the [world] while leaving in place the corrupt definitions or
  axioms. The base world is now tainted, meaning we could prove nil
  or certify a book that proves nil, but the resulting session or
  book would contain no trace of the ttag that tainted it!

  Despite shortcomings, this command might be useful to system hackers.
  It also serves to illustrate the inherent flaw in asking a session
  whether or how it is ``tainted'', justifying the ``TTAG NOTE''
  approach (see [defttag]).")
 (TTREE
  (MISCELLANEOUS)
  "Tag-trees

  Many low-level ACL2 functions take and return ``tag trees'' or
  ``ttrees'' (pronounced ``tee-trees'') which contain various useful
  bits of information such as the lemmas used, the linearize
  assumptions made, etc.

  Abstractly a tag-tree represents a list of sets, each member set
  having a name given by one of the ``tags'' (which are symbols) of
  the ttree. The elements of the set named tag are all of the objects
  tagged tag in the tree. You are invited to browse the source code.
  Definitions of primitives are labeled with the comment ``; Note:
  Tag-tree primitive''.

  The rewriter, for example, takes a term and a ttree (among other
  things), and returns a new term, term', and new ttree, ttree'.
  Term' is equivalent to term (under the current assumptions) and the
  ttree' is an extension of ttree. If we focus just on the set
  associated with the tag LEMMA in the ttrees, then the set for
  ttree' is the extension of that for ttree obtained by unioning into
  it all the [rune]s used by the rewrite. The set associated with
  LEMMA can be obtained by (tagged-objects 'LEMMA ttree).")
 (TUTORIAL1-TOWERS-OF-HANOI
  (ANNOTATED-ACL2-SCRIPTS)
  "The Towers of Hanoi Example

  This example was written almost entirely by Bill Young of
  Computational Logic, Inc.

  We will formalize and prove a small theorem about the famous ``Towers
  of Hanoi'' problem. This problem is illustrated by the following
  picture.

       |        |        |
       |        |        |
      ---       |        |
     -----      |        |
    -------     |        |

       A        B        C

  We have three pegs --- a, b, and c --- and n disks of different
  sizes. The disks are all initially on peg a. The goal is to move
  all disks to peg c while observing the following two rules.

  1. Only one disk may be moved at a time, and it must start and finish
  the move as the topmost disk on some peg;

  2. A disk can never be placed on top of a smaller disk.

  Let's consider some simple instances of this problem. If n = 1, i.e.,
  only one disk is to be moved, simply move it from a to c. If n = 2,
  i.e., two disks are to be moved, the following sequence of moves
  suffices: move from a to b, move from a to c, move from b to c.

  In this doc topic we will show an ACL2 function that generates a
  suitable list of moves for a tower of n disks. Then we will use
  ACL2 to prove that the number of moves is (- (expt 2 n) 1). For an
  ACL2 script that proves the correctness of (a version of) this
  function, see the community book \"misc/hanoi.lisp\" in the books
  directory of your ACL2 sources.

  In general, this problem has a straightforward recursive solution.
  Suppose that we desire to move n disks from a to c, using b as the
  intermediate peg. For the basis, we saw above that we can always
  move a single disk from a to c. Now if we have n disks and assume
  that we can solve the problem for n-1 disks, we can move n disks as
  follows. First, move n-1 disks from a to b using c as the
  intermediate peg; move the single disk from a to c; then move n-1
  disks from b to c using a as the intermediate peg.

  In ACL2, we can write a function that will return the sequence of
  moves. One such function is as follows. Notice that we have two
  base cases. If (zp n) then n is not a positive integer; we treat
  that case as if n were 0 and return an empty list of moves. If n is
  1, then we return a list containing the single appropriate move.
  Otherwise, we return the list containing exactly the moves dictated
  by our recursive analysis above.

    (defun move (a b)
      (list 'move a 'to b))

    (defun hanoi (a b c n)
      (if (zp n)
          nil
        (if (equal n 1)
            (list (move a c))
          (append (hanoi a c b (1- n))
                  (cons (move a c)
                        (hanoi b a c (1- n)))))))

  Notice that we give hanoi four arguments: the three pegs, and the
  number of disks to move. It is necessary to supply the pegs
  because, in recursive calls, the roles of the pegs differ. In any
  execution of the algorithm, a given peg will sometimes be the
  source of a move, sometimes the destination, and sometimes the
  intermediate peg.

  After submitting these functions to ACL2, we can execute the hanoi
  function on various specific arguments. For example:

    ACL2 !>(hanoi 'a 'b 'c 1)
    ((MOVE A TO C))

    ACL2 !>(hanoi 'a 'b 'c 2)
    ((MOVE A TO B)
     (MOVE A TO C)
     (MOVE B TO C))

    ACL2 !>(hanoi 'a 'b 'c 3)
    ((MOVE A TO C)
     (MOVE A TO B)
     (MOVE C TO B)
     (MOVE A TO C)
     (MOVE B TO A)
     (MOVE B TO C)
     (MOVE A TO C))

  From the algorithm it is clear that if it takes m moves to transfer n
  disks, it will take (m + 1 + m) = 2m + 1 moves for n+1 disks. From
  some simple calculations, we see that we need the following number
  of moves in specific cases:

    Disks   0   1   2   3   4   5   6   7  ...
    Moves   0   1   3   7  15  31  63  127 ...

  The pattern is fairly clear. To move n disks requires (2^n - 1)
  moves. Let's attempt to use ACL2 to prove that fact.

  First of all, how do we state our conjecture? Recall that hanoi
  returns a list of moves. The length of the list (given by the
  function len) is the number of moves required. Thus, we can state
  the following conjecture.

    (defthm hanoi-moves-required-first-try
      (equal (len (hanoi a b c n))
             (1- (expt 2 n))))

  When we submit this to ACL2, the proof attempt fails. Along the way
  we notice subgoals such as:

    Subgoal *1/1'
    (IMPLIES (NOT (< 0 N))
             (EQUAL 0 (+ -1 (EXPT 2 N)))).

  This tells us that the prover is considering cases that are
  uninteresting to us, namely, cases in which n might be negative.
  The only cases that are really of interest are those in which n is
  a non-negative natural number. Therefore, we revise our theorem as
  follows:

    (defthm hanoi-moves-required
      (implies (and (integerp n)
                    (<= 0 n))    ;; n is at least 0
               (equal (len (hanoi a b c n))
                      (1- (expt 2 n)))))

  and submit it to ACL2 again.

  Again the proof fails. Examining the proof script we encounter the
  following text. (How did we decide to focus on this goal? Some
  information is provided in ACLH, and the ACL2 documentation on
  [tips] may be helpful. But the simplest answer is: this was the
  first goal suggested by the ``[proof-tree]'' tool below the start
  of the proof by induction. See [proof-tree].)

    Subgoal *1/5''
    (IMPLIES (AND (INTEGERP N)
                  (< 0 N)
                  (NOT (EQUAL N 1))
                  (EQUAL (LEN (HANOI A C B (+ -1 N)))
                         (+ -1 (EXPT 2 (+ -1 N))))
                  (EQUAL (LEN (HANOI B A C (+ -1 N)))
                         (+ -1 (EXPT 2 (+ -1 N)))))
             (EQUAL (LEN (APPEND (HANOI A C B (+ -1 N))
                                 (CONS (LIST 'MOVE A 'TO C)
                                       (HANOI B A C (+ -1 N)))))
                    (+ -1 (* 2 (EXPT 2 (+ -1 N))))))

  It is difficult to make much sense of such a complicated goal.
  However, we do notice something interesting. In the conclusion is a
  [term] of the following shape.

    (LEN (APPEND ... ...))

  We conjecture that the length of the [append] of two lists should be
  the sum of the lengths of the lists. If the prover knew that, it
  could possibly have simplified this [term] earlier and made more
  progress in the proof. Therefore, we need a [rewrite] rule that
  will suggest such a simplification to the prover. The appropriate
  rule is:

    (defthm len-append
      (equal (len (append x y))
             (+ (len x) (len y))))

  We submit this to the prover, which proves it by a straightforward
  induction. The prover stores this lemma as a [rewrite] rule and
  will subsequently (unless we [disable] the rule) replace [term]s
  matching the left hand side of the rule with the appropriate
  instance of the [term] on the right hand side.

  We now resubmit our lemma hanoi-moves-required to ACL2. On this
  attempt, the proof succeeds and we are done.

  One bit of cleaning up is useful. We needed the hypotheses that:

    (and (integerp n) (<= 0 n)).

  This is an awkward way of saying that n is a natural number; natural
  is not a primitive data type in ACL2. We could define a function
  naturalp, but it is somewhat more convenient to define a macro as
  follows:

    (defmacro naturalp (x)
      (list 'and (list 'integerp x)
                    (list '<= 0 x)))

  Subsequently, we can use (naturalp n) wherever we need to note that a
  quantity is a natural number. See [defmacro] for more information
  about ACL2 macros. With this macro, we can reformulate our theorem
  as follows:

    (defthm hanoi-moves-required
      (implies (naturalp n)
               (equal (len (hanoi a b c n))
                      (1- (expt 2 n))))).

  Another interesting (but much harder) theorem asserts that the list
  of moves generated by our hanoi function actually accomplishes the
  desired goal while following the rules. When you can state and
  prove that theorem, you'll be a very competent ACL2 user.

  By the way, the name ``Towers of Hanoi'' derives from a legend that a
  group of Vietnamese monks works day and night to move a stack of 64
  gold disks from one diamond peg to another, following the rules set
  out above. We're told that the world will end when they complete
  this task. From the theorem above, we know that this requires
  18,446,744,073,709,551,615 moves:

    ACL2 !>(1- (expt 2 64))
    18446744073709551615
    ACL2 !>

  We're guessing they won't finish any time soon.")
 (TUTORIAL2-EIGHTS-PROBLEM
  (ANNOTATED-ACL2-SCRIPTS)
  "The Eights Problem Example

  This example was written almost entirely by Bill Young of
  Computational Logic, Inc.

  This simple example was brought to our attention as one that Paul
  Jackson has solved using the NuPrl system. The challenge is to
  prove the theorem:

    for all n > 7, there exist naturals i and j such that: n = 3i + 5j.

  In ACL2, we could phrase this theorem using quantification. However
  we will start with a constructive approach, i.e., we will show that
  values of i and j exist by writing a function that will construct
  such values for given n. Suppose we had a function (split n) that
  returns an appropriate pair (i . j). Our theorem would be as
  follows:

    (defthm split-splits
      (let ((i (car (split n)))
            (j (cdr (split n))))
        (implies (and (integerp n)
                      (< 7 n))
                 (and (integerp i)
                      (<= 0 i)
                      (integerp j)
                      (<= 0 j)
                      (equal (+ (* 3 i) (* 5 j))
                             n)))))

  That is, assuming that n is a natural number greater than 7, (split
  n) returns values i and j that are in the appropriate relation to
  n.

  Let's look at a few cases:

     8 = 3x1 + 5x1;    11 = 3x2 + 5x1;     14 = 3x3 + 5x1;   ...
     9 = 3x3 + 5x0;    12 = 3x4 + 5x0;     15 = 3x5 + 5x0;   ...
    10 = 3x0 + 5x2;    13 = 3x1 + 5x2;     16 = 3x2 + 5x2;   ...

  Maybe you will have observed a pattern here; any natural number
  larger than 10 can be obtained by adding some multiple of 3 to 8,
  9, or 10. This gives us the clue to constructing a proof. It is
  clear that we can write split as follows:

    (defun bump-i (x)
      ;; Bump the i component of the pair
      ;; (i . j) by 1.
      (cons (1+ (car x)) (cdr x)))

    (defun split (n)
      ;; Find a pair (i . j) such that
      ;; n = 3i + 5j.
      (if (or (zp n) (< n 8))
          nil ;; any value is really reasonable here
        (if (equal n 8)
            (cons 1 1)
          (if (equal n 9)
              (cons 3 0)
            (if (equal n 10)
                (cons 0 2)
              (bump-i (split (- n 3))))))))

  Notice that we explicitly compute the values of i and j for the cases
  of 8, 9, and 10, and for the degenerate case when n is not a
  natural or is less than 8. For all naturals greater than n, we
  decrement n by 3 and bump the number of 3's (the value of i) by 1.
  We know that the recursion must terminate because any integer value
  greater than 10 can eventually be reduced to 8, 9, or 10 by
  successively subtracting 3.

  Let's try it on some examples:

    ACL2 !>(split 28)
    (6 . 2)

    ACL2 !>(split 45)
    (15 . 0)

    ACL2 !>(split 335)
    (110 . 1)

  Finally, we submit our theorem split-splits, and the proof succeeds.
  In this case, the prover is ``smart'' enough to induct according to
  the pattern indicated by the function split.

  For completeness, we'll note that we can state and prove a quantified
  version of this theorem. We introduce the notion split-able to mean
  that appropriate i and j exist for n.

    (defun-sk split-able (n)
      (exists (i j)
              (equal n (+ (* 3 i) (* 5 j)))))

  Then our theorem is given below. Notice that we prove it by observing
  that our previous function split delivers just such an i and j (as
  we proved above).

    (defthm split-splits2
      (implies (and (integerp n)
                    (< 7 n))
               (split-able n))
      :hints ((\"Goal\" :use (:instance split-able-suff
                                      (i (car (split n)))
                                      (j (cdr (split n)))))))

  Unfortunately, understanding the mechanics of the proof requires
  knowing something about the way [defun-sk] works. See [defun-sk] or
  see [Tutorial4-Defun-Sk-Example] for more on that subject.")
 (TUTORIAL3-PHONEBOOK-EXAMPLE
  (ANNOTATED-ACL2-SCRIPTS)
  "A Phonebook Specification

  The other tutorial examples are rather small and entirely self
  contained. The present example is rather more elaborate, and makes
  use of a feature that really adds great power and versatility to
  ACL2, namely: the use of previously defined collections of lemmas,
  in the form of ``[books].''

  This example was written almost entirely by Bill Young of
  Computational Logic, Inc.

  This example is based on one developed by Ricky Butler and Sally
  Johnson of NASA Langley for the PVS system, and subsequently
  revised by Judy Crow, et al, at SRI. It is a simple phone book
  specification. We will not bother to follow their versions closely,
  but will instead present a style of specification natural for ACL2.

  The idea is to model an electronic phone book with the following
  properties.

      Our phone book will store the phone numbers of a city.

      It must be possible to retrieve a phone number, given a name.

      It must be possible to add and delete entries.

  Of course, there are numerous ways to construct such a model. A
  natural approach within the Lisp/ACL2 context is to use
  ``association lists'' or ``alists.'' Briefly, an alist is a list of
  pairs (key . value) associating a value with a key. A phone book
  could be an alist of pairs (name . pnum). To find the phone number
  associated with a given name, we merely search the alist until we
  find the appropriate pair. For a large city, such a linear list
  would not be efficient, but at this point we are interested only in
  modeling the problem, not in deriving an efficient implementation.
  We could address that question later by proving our alist model
  equivalent, in some desired sense, to a more efficient data
  structure.

  We could build a theory of alists from scratch, or we can use a
  previously constructed theory (book) of alist definitions and
  facts. By using an existing book, we build upon the work of others,
  start our specification and proof effort from a much richer
  foundation, and hopefully devote more of our time to the problem at
  hand. Unfortunately, it is not completely simple for the new user
  to know what [books] are available and what they contain. We hope
  later to improve the documentation of the growing collection of
  [community-books] that are typically downloaded with ACL2; for now,
  the reader is encouraged to look in the README.html file in the
  books' top-level directory. For present purposes, the beginning
  user can simply take our word that a book exists containing useful
  alist definitions and facts. These definitions and lemmas can be
  introduced into the current theory using the [command]:

    (include-book \"data-structures/alist-defthms\" :dir :system)

  This book has been ``certified,'' which means that the definitions
  and lemmas have been mechanically checked and stored in a safe
  manner. (See [books] and see [include-book] for details.)

  Including this book makes available a collection of functions
  including the following:

    (ALISTP A)    ; is A an alist (actually a primitive ACL2 function)

    (BIND X V A)  ; associate the key X with value V in alist A

    (BINDING X A) ; return the value associated with key X in alist A

    (BOUND? X A)  ; is key X associated with any value in alist A

    (DOMAIN A)    ; return the list of keys bound in alist A

    (RANGE A)     ; return the list of values bound to keys in alist A

    (REMBIND X A) ; remove the binding of key X in alist A

  Along with these function definitions, the book also provides a
  number of proved lemmas that aid in simplifying expressions
  involving these functions. (See [rule-classes] for the way in which
  lemmas are used in simplification and rewriting.) For example,

    (defthm bound?-bind
      (equal (bound? x (bind y v a))
             (or (equal x y)
                 (bound? x a))))

  asserts that x will be bound in (bind y v a) if and only if: either x
  = y or x was already bound in a. Also,

    (defthm binding-bind
      (equal (binding x (bind y v a))
             (if (equal x y)
                 v
               (binding x a))))

  asserts that the resulting binding will be v, if x = y, or the
  binding that x had in a already, if not.

  Thus, the inclusion of this book essentially extends our
  specification and reasoning capabilities by the addition of new
  operations and facts about these operations that allow us to build
  further specifications on a richer and possibly more intuitive
  foundation.

  However, it must be admitted that the use of a book such as this has
  two potential limitations:

      the definitions available in a book may not be ideal for your
      particular problem;

      it is (extremely) likely that some useful facts (especially,
      [rewrite] rules) are not available in the book and will have to
      be proved.

  For example, what is the value of binding when given a key that is
  not bound in the alist? We can find out by examining the function
  definition. Look at the definition of the binding function (or any
  other defined function), using the :[pe] command:

    ACL2 !>:pe binding
       d     33  (INCLUDE-BOOK
                      \"/slocal/src/acl2/v1-9/books/public/alist-defthms\")

    >V d          (DEFUN BINDING (X A)
                         \"The value bound to X in alist A.\"
                         (DECLARE (XARGS :GUARD (ALISTP A)))
                         (CDR (ASSOC-EQUAL X A)))

  This tells us that binding was introduced by the given [include-book]
  form, is currently [disable]d in the current theory, and has the
  definition given by the displayed [defun] form. We see that binding
  is actually defined in terms of the primitive [assoc-equal]
  function. If we look at the definition of [assoc-equal]:

    ACL2 !>:pe assoc-equal
     V     -489  (DEFUN ASSOC-EQUAL (X ALIST)
                        (DECLARE (XARGS :GUARD (ALISTP ALIST)))
                        (COND ((ENDP ALIST) NIL)
                              ((EQUAL X (CAR (CAR ALIST)))
                               (CAR ALIST))
                              (T (ASSOC-EQUAL X (CDR ALIST)))))

  we can see that [assoc-equal] returns nil upon reaching the end of an
  unsuccessful search down the alist. So binding returns (cdr nil) in
  that case, which is nil. Notice that we could also have
  investigated this question by trying some simple examples.

    ACL2 !>(binding 'a nil)
    NIL

    ACL2 !>(binding 'a (list (cons 'b 2)))
    NIL

  These definitions aren't ideal for all purposes. For one thing,
  there's nothing that keeps us from having nil as a value bound to
  some key in the alist. Thus, if binding returns nil we don't always
  know if that is the value associated with the key in the alist, or
  if that key is not bound. We'll have to keep that ambiguity in mind
  whenever we use binding in our specification. Suppose instead that
  we wanted binding to return some error string on unbound keys.
  Well, then we'd just have to write our own version of binding. But
  then we'd lose much of the value of using a previously defined
  book. As with any specification technique, certain tradeoffs are
  necessary.

  Why not take a look at the definitions of other alist functions and
  see how they work together to provide the ability to construct and
  search alists? We'll be using them rather heavily in what follows
  so it will be good if you understand basically how they work.
  Simply start up ACL2 and execute the form shown earlier, but
  substituting our directory name for the top-level ACL2 directory
  with yours. Alternatively, just

    (include-book \"data-structures/alist-defthms\" :dir :system)

  Then, you can use :[pe] to look at function definitions. You'll soon
  discover that almost all of the definitions are built on
  definitions of other, more primitive functions, as binding is built
  on [assoc-equal]. You can look at those as well, of course, or in
  many cases visit their documentation.

  The other problem with using a predefined book is that it will seldom
  be ``sufficiently complete,'' in the sense that the collection of
  [rewrite] rules supplied won't be adequate to prove everything we'd
  like to know about the interactions of the various functions. If it
  were, there'd be no real reason to know that binding is built on
  top of [assoc-equal], because everything we'd need to know about
  binding would be nicely expressed in the collection of theorems
  supplied with the book. However, that's very seldom the case.
  Developing such a collection of rules is currently more art than
  science and requires considerable experience. We'll encounter
  examples later of ``missing'' facts about binding and our other
  alist functions. So, let's get on with the example.

  Notice that alists are mappings of keys to values; but, there is no
  notion of a ``type'' associated with the keys or with the values.
  Our phone book example, however, does have such a notion of types;
  we map names to phone numbers. We can introduce these ``types'' by
  explicitly defining them, e.g., names are strings and phone numbers
  are integers. Alternatively, we can partially define or axiomatize
  a recognizer for names without giving a full definition. A way to
  safely introduce such ``constrained'' function symbols in ACL2 is
  with the [encapsulate] form. For example, consider the following
  form.

    (encapsulate
      ;; Introduce a recognizer for names and give a ``type'' lemma.
      (((namep *) => *))
      ;;
      (local (defun namep (x)
               ;; This declare is needed to tell
               ;; ACL2 that we're aware that the
               ;; argument x is not used in the body
               ;; of the function.
               (declare (ignore x))
               t))
      ;;
      (defthm namep-booleanp
        (booleanp (namep x))))

  This [encapsulate] form introduces the new function namep of one
  argument and one result and constrains (namep x) to be Boolean, for
  all inputs x. More generally, an encapsulation establishes an
  environment in which functions can be defined and theorems and
  rules added without necessarily introducing those functions,
  theorems, and rules into the environment outside the encapsulation.
  To be admissible, all the events in the body of an encapsulate must
  be admissible. But the effect of an encapsulate is to assume only
  the non-local events.

  The first ``argument'' to encapsulate, ((namep (x) t)) above,
  declares the intended [signature]s of new function symbols that
  will be ``exported'' from the encapsulation without definition. The
  [local] [defun] of name defines name within the encapsulation
  always to return t. The defthm event establishes that namep is
  Boolean. By making the defun local but the defthm non-local this
  encapsulate constrains the undefined function namep to be Boolean;
  the admissibility of the encapsulation establishes that there
  exists a Boolean function (namely the constant function returning
  t).

  We can subsequently use namep as we use any other Boolean function,
  with the proviso that we know nothing about it except that it
  always returns either t or nil. We use namep to ``recognize'' legal
  keys for our phonebook alist.

  We wish to do something similar to define what it means to be a legal
  phone number. We submit the following form to ACL2:

    (encapsulate
      ;; Introduce a recognizer for phone numbers.
      (((pnump *) => *))
      ;;
      (local (defun pnump (x)
               (not (equal x nil))))
      ;;
      (defthm pnump-booleanp
        (booleanp (pnump x)))
      ;;
      (defthm nil-not-pnump
        (not (pnump nil)))).

  This introduces a Boolean-valued recognizer pnump, with the
  additional proviso that the constant nil is not a pnump. We impose
  this restriction to guarantee that we'll never bind a name to nil
  in our phone book and thereby introduce the kind of ambiguity
  described above regarding the use of binding.

  Now a legal phone book is an alist mapping from nameps to pnumps. We
  can define this as follows:

    (defun name-phonenum-pairp (x)
      ;; Recognizes a pair of (name . pnum).
      (and (consp x)
           (namep (car x))
           (pnump (cdr x))))

    (defun phonebookp (l)
      ;; Recognizes a list of such pairs.
      (if (not (consp l))
          (null l)
        (and (name-phonenum-pairp (car l))
             (phonebookp (cdr l)))))

  Thus, a phone book is really a list of pairs (name . pnum). Notice
  that we have not assumed that the keys of the phone book are
  distinct. We'll worry about that question later. (It is not always
  desirable to insist that the keys of an alist be distinct. But it
  may be a useful requirement for our specific example.)

  Now we are ready to define some of the functions necessary for our
  phonebook example. The functions we need are:

    (IN-BOOK? NM BK)          ; does NM have a phone number in BK

    (FIND-PHONE NM BK)        ; find NM's phone number in phonebook BK

    (ADD-PHONE NM PNUM BK)    ; give NM the phone number PNUM in BK

    (CHANGE-PHONE NM PNUM BK) ; change NM's phone number to PNUM in BK

    (DEL-PHONE NM PNUM)       ; remove NM's phone number from BK

  Given our underlying theory of alists, it is easy to write these
  functions. But we must take care to specify appropriate
  ``boundary'' behavior. Thus, what behavior do we want when, say, we
  try to change the phone number of a client who is not currently in
  the book? As usual, there are numerous possibilities; here we'll
  assume that we return the phone book unchanged if we try anything
  ``illegal.''

  Possible definitions of our phone book functions are as follows.
  (Remember, an include-book form such as the ones shown earlier must
  be executed in order to provide definitions for functions such as
  bound?.)

    (defun in-book? (nm bk)
      (bound? nm bk))

    (defun find-phone (nm bk)
      (binding nm bk))

    (defun add-phone (nm pnum bk)
      ;; If nm already in-book?, make no change.
      (if (in-book? nm bk)
          bk
        (bind nm pnum bk)))

    (defun change-phone (nm pnum bk)
      ;; Make a change only if nm already has a phone number.
      (if (in-book? nm bk)
          (bind nm pnum bk)
        bk))

    (defun del-phone (nm bk)
      ;; Remove the binding from bk, if there is one.
      (rembind nm bk))

  Notice that we don't have to check whether a name is in the book
  before deleting, because rembind is essentially a no-op if nm is
  not bound in bk.

  In some sense, this completes our specification. But we can't have
  any real confidence in its correctness without validating our
  specification in some way. One way to do so is by proving some
  properties of our specification. Some candidate properties are:

      1. A name will be in the book after we add it.

      2. We will find the most recently added phone number for a client.

      3. If we change a number, we'll find the change.

      4. Changing and then deleting a number is the same as just deleting.

      5. A name will not be in the book after we delete it.

  Let's formulate some of these properties. The first one, for example,
  is:

    (defthm add-in-book
      (in-book? nm (add-phone nm pnum bk))).

  You may wonder why we didn't need any hypotheses about the ``types''
  of the arguments. In fact, add-in-book is really expressing a
  property that is true of alists in general, not just of the
  particular variety of alists we are dealing with. Of course, we
  could have added some extraneous hypotheses and proved:

    (defthm add-in-book
      (implies (and (namep nm)
                    (pnump pnum)
                    (phonebookp bk))
               (in-book? nm (add-phone nm pnum bk)))),

  but that would have yielded a weaker and less useful lemma because it
  would apply to fewer situations. In general, it is best to state
  lemmas in the most general form possible and to eliminate
  unnecessary hypotheses whenever possible. The reason for that is
  simple: lemmas are usually stored as rules and used in later
  proofs. For a lemma to be used, its hypotheses must be relieved
  (proved to hold in that instance); extra hypotheses require extra
  work. So we avoid them whenever possible.

  There is another, more important observation to make about our lemma.
  Even in its simpler form (without the extraneous hypotheses), the
  lemma add-in-book may be useless as a [rewrite] rule. Notice that
  it is stated in terms of the non-recursive functions in-book? and
  add-phone. If such functions appear in the left hand side of the
  conclusion of a lemma, the lemma may not ever be used. Suppose in a
  later proof, the theorem prover encountered a [term] of the form:

    (in-book? nm (add-phone nm pnum bk)).

  Since we've already proved add-in-book, you'd expect that this would
  be immediately reduced to true. However, the theorem prover will
  often ``expand'' the non-recursive definitions of in-book? and
  add-phone using their definitions before it attempts rewriting with
  lemmas. After this expansion, lemma add-in-book won't ``match'' the
  [term] and so won't be applied. Look back at the proof script for
  add-in-proof and you'll notice that at the very end the prover
  warned you of this potential difficulty when it printed:

    Warnings:  Non-rec
    Time:  0.18 seconds (prove: 0.05, print: 0.00, other: 0.13)
    ADD-IN-BOOK

  The ``Warnings'' line notifies you that there are non-recursive
  function calls in the left hand side of the conclusion and that
  this problem might arise. Of course, it may be that you don't ever
  plan to use the lemma for rewriting or that your intention is to
  [disable] these functions. [Disable]d functions are not expanded
  and the lemma should apply. However, you should always take note of
  such warnings and consider an appropriate response. By the way, we
  noted above that binding is [disable]d. If it were not, none of the
  lemmas about binding in the book we included would likely be of
  much use for exactly the reason we just gave.

  For our current example, let's assume that we're just investigating
  the properties of our specifications and not concerned about using
  our lemmas for rewriting. So let's go on. If we really want to
  avoid the warnings, we can add :rule-classes nil to each defthm
  event; see [rule-classes].

  Property 2 is: we always find the most recently added phone number
  for a client. Try the following formalization:

    (defthm find-add-first-cut
      (equal (find-phone nm (add-phone nm pnum bk))
             pnum))

  and you'll find that the proof attempt fails. Examining the proof
  attempt and our function definitions, we see that the lemma is
  false if nm is already in the book. We can remedy this situation by
  reformulating our lemma in at least two different ways:

    (defthm find-add1
      (implies (not (in-book? nm bk))
               (equal (find-phone nm (add-phone nm pnum bk))
                      pnum)))

    (defthm find-add2
      (equal (find-phone nm (add-phone nm pnum bk))
             (if (in-book? nm bk)
                 (find-phone nm bk)
                 pnum)))

  For technical reasons, lemmas such as find-add2, i.e., which do not
  have hypotheses, are usually slightly preferable. This lemma is
  stored as an ``unconditional'' [rewrite] rule (i.e., has no
  hypotheses) and, therefore, will apply more often than find-add1.
  However, for our current purposes either version is all right.

  Property 3 says: If we change a number, we'll find the change. This
  is very similar to the previous example. The formalization is as
  follows.

    (defthm find-change
      (equal (find-phone nm (change-phone nm pnum bk))
             (if (in-book? nm bk)
                 pnum
               (find-phone nm bk))))

  Property 4 says: changing and then deleting a number is the same as
  just deleting. We can model this as follows.

    (defthm del-change
      (equal (del-phone nm (change-phone nm pnum bk))
             (del-phone nm bk)))

  Unfortunately, when we try to prove this, we encounter subgoals that
  seem to be true, but for which the prover is stumped. For example,
  consider the following goal. (Note: endp holds of lists that are
  empty.)

    Subgoal *1/4
    (IMPLIES (AND (NOT (ENDP BK))
                  (NOT (EQUAL NM (CAAR BK)))
                  (NOT (BOUND? NM (CDR BK)))
                  (BOUND? NM BK))
             (EQUAL (REMBIND NM (BIND NM PNUM BK))
                    (REMBIND NM BK))).

  Our intuition about rembind and bind tells us that this goal should
  be true even without the hypotheses. We attempt to prove the
  following lemma.

    (defthm rembind-bind
      (equal (rembind nm (bind nm pnum bk))
             (rembind nm bk)))

  The prover proves this by induction, and stores it as a rewrite rule.
  After that, the prover has no difficulty in proving del-change.

  The need to prove lemma rembind-bind illustrates a point we made
  early in this example: the collection of [rewrite] rules supplied
  by a previously certified book will almost never be everything
  you'll need. It would be nice if we could operate purely in the
  realm of names, phone numbers, and phone books without ever having
  to prove any new facts about alists. Unfortunately, we needed a
  fact about the relation between rembind and bind that wasn't
  supplied with the alists theory. Hopefully, such omissions will be
  rare.

  Finally, let's consider our property 5 above: a name will not be in
  the book after we delete it. We formalize this as follows:

    (defthm in-book-del
      (not (in-book? nm (del-phone nm bk))))

  This proves easily. But notice that it's only true because del-phone
  (actually rembind) removes all occurrences of a name from the phone
  book. If it only removed, say, the first one it encountered, we'd
  need a hypothesis that said that nm occurs at most once in bk. Ah,
  maybe that's a property you hadn't considered. Maybe you want to
  ensure that any name occurs at most once in any valid phonebook.

  To complete this example, let's consider adding an invariant to our
  specification. In particular, suppose we want to assure that no
  client has more than one associated phone number. One way to ensure
  this is to require that the domain of the alist is a ``set'' (has
  no duplicates).

    (defun setp (l)
      (if (atom l)
          (null l)
        (and (not (member-equal (car l) (cdr l)))
             (setp (cdr l)))))

    (defun valid-phonebookp (bk)
      (and (phonebookp bk)
           (setp (domain bk))))

  Now, we want to show under what conditions our operations preserve
  the property of being a valid-phonebookp. The operations in-book?
  and find-phone don't return a phone book, so we don't really need
  to worry about them. Since we're really interested in the ``types''
  of values preserved by our phonebook functions, let's look at the
  types of those operations as well.

    (defthm in-book-booleanp
      (booleanp (in-book? nm bk)))

    (defthm in-book-namep
      (implies (and (phonebookp bk)
                    (in-book? nm bk))
               (namep nm))
      :hints ((\"Goal\" :in-theory (enable bound?))))

    (defthm find-phone-pnump
      (implies (and (phonebookp bk)
                    (in-book? nm bk))
               (pnump (find-phone nm bk)))
      :hints ((\"Goal\" :in-theory (enable bound? binding))))

  Note the ``:[hints]'' on the last two lemmas. Neither of these would
  prove without these [hints], because once again there are some
  facts about bound? and binding not available in our current
  context. Now, we could figure out what those facts are and try to
  prove them. Alternatively, we can [enable] bound? and binding and
  hope that by opening up these functions, the conjectures will
  reduce to versions that the prover does know enough about or can
  prove by induction. In this case, this strategy works. The hints
  tell the prover to [enable] the functions in question when
  considering the designated goal.

  Below we develop the theorems showing that add-phone, change-phone,
  and del-phone preserve our proposed invariant. Notice that along
  the way we have to prove some subsidiary facts, some of which are
  pretty ugly. It would be a good idea for you to try, say,
  add-phone-preserves-invariant without introducing the following
  four lemmas first. See if you can develop the proof and only add
  these lemmas as you need assistance. Then try
  change-phone-preserves-invariant and del-phone-preserves-invariant.
  They will be easier. It is illuminating to think about why
  del-phone-preserves-invariant does not need any ``type''
  hypotheses.

    (defthm bind-preserves-phonebookp
      (implies (and (phonebookp bk)
                    (namep nm)
                    (pnump num))
               (phonebookp (bind nm num bk))))

    (defthm member-equal-strip-cars-bind
      (implies (and (not (equal x y))
                    (not (member-equal x (strip-cars a))))
               (not (member-equal x (strip-cars (bind y z a))))))

    (defthm bind-preserves-domain-setp
      (implies (and (alistp bk)
                    (setp (domain bk)))
               (setp (domain (bind nm num bk))))
      :hints ((\"Goal\" :in-theory (enable domain))))

    (defthm phonebookp-alistp
      (implies (phonebookp bk)
               (alistp bk)))

    (defthm ADD-PHONE-PRESERVES-INVARIANT
      (implies (and (valid-phonebookp bk)
                    (namep nm)
                    (pnump num))
               (valid-phonebookp (add-phone nm num bk)))
      :hints ((\"Goal\" :in-theory (disable domain-bind))))

    (defthm CHANGE-PHONE-PRESERVES-INVARIANT
      (implies (and (valid-phonebookp bk)
                    (namep nm)
                    (pnump num))
               (valid-phonebookp (change-phone nm num bk)))
      :hints ((\"Goal\" :in-theory (disable domain-bind))))

    (defthm remove-equal-preserves-setp
      (implies (setp l)
               (setp (remove-equal x l))))

    (defthm rembind-preserves-phonebookp
      (implies (phonebookp bk)
               (phonebookp (rembind nm bk))))

    (defthm DEL-PHONE-PRESERVES-INVARIANT
      (implies (valid-phonebookp bk)
               (valid-phonebookp (del-phone nm bk))))

  As a final test of your understanding, try to formulate and prove an
  invariant that says that no phone number is assigned to more than
  one name. The following hints may help.

      1. Define the appropriate invariant. (Hint: remember the function
      range.)

      2. Do our current definitions of add-phone and change-phone
      necessarily preserve this property? If not, consider what
      hypotheses are necessary in order to guarantee that they do
      preserve this property.

      3. Study the definition of the function range and notice that it is
      defined in terms of the function [strip-cdrs]. Understand how
      this defines the range of an alist.

      4. Formulate the correctness theorems and attempt to prove them.
      You'll probably benefit from studying the invariant proof
      above. In particular, you may need some fact about the function
      [strip-cdrs] analogous to the lemma
      member-equal-strip-cars-bind above.

  Below is one solution to this exercise. Don't look at the solution,
  however, until you've struggled a bit with it. Notice that we
  didn't actually change the definitions of add-phone and
  change-phone, but added a hypothesis saying that the number is
  ``new.'' We could have changed the definitions to check this and
  return the phonebook unchanged if the number was already in use.

    (defun pnums-in-use (bk)
      (range bk))

    (defun phonenums-unique (bk)
      (setp (pnums-in-use bk)))

    (defun new-pnump (pnum bk)
      (not (member-equal pnum (pnums-in-use bk))))

    (defthm member-equal-strip-cdrs-rembind
      (implies (not (member-equal x (strip-cdrs y)))
               (not (member-equal x (strip-cdrs (rembind z y))))))

    (defthm DEL-PHONE-PRESERVES-PHONENUMS-UNIQUE
      (implies (phonenums-unique bk)
               (phonenums-unique (del-phone nm bk)))
      :hints ((\"Goal\" :in-theory (enable range))))

    (defthm strip-cdrs-bind-non-member
      (implies (and (not (bound? x a))
                    (alistp a))
               (equal (strip-cdrs (bind x y a))
                      (append (strip-cdrs a) (list y))))
      :hints ((\"Goal\" :in-theory (enable bound?))))

    (defthm setp-append-list
      (implies (setp l)
               (equal (setp (append l (list x)))
                      (not (member-equal x l)))))

    (defthm ADD-PHONE-PRESERVES-PHONENUMS-UNIQUE
      (implies (and (phonenums-unique bk)
                    (new-pnump pnum bk)
                    (alistp bk))
               (phonenums-unique (add-phone nm pnum bk)))
      :hints ((\"Goal\" :in-theory (enable range))))

    (defthm member-equal-strip-cdrs-bind
      (implies (and (not (member-equal z (strip-cdrs a)))
                    (not (equal z y)))
               (not (member-equal z (strip-cdrs (bind x y a))))))

    (defthm CHANGE-PHONE-PRESERVES-PHONENUMS-UNIQUE
      (implies (and (phonenums-unique bk)
                    (new-pnump pnum bk)
                    (alistp bk))
               (phonenums-unique (change-phone nm pnum bk)))
      :hints ((\"Goal\" :in-theory (enable range))))")
 (TUTORIAL4-DEFUN-SK-EXAMPLE
  (ANNOTATED-ACL2-SCRIPTS)
  "Example of quantified notions

  This example illustrates the use of [defun-sk] and [defthm] [events]
  to reason about quantifiers. See [defun-sk]. For a more through,
  systematic beginner's introduction to quantification in ACL2, see
  [quantifier-tutorial].

  Many users prefer to avoid the use of quantifiers, since ACL2
  provides only very limited support for reasoning about quantifiers.

  Here is a list of [events] that proves that if there are arbitrarily
  large numbers satisfying the disjunction (OR P R), then either
  there are arbitrarily large numbers satisfying P or there are
  arbitrarily large numbers satisfying R.

    ; Introduce undefined predicates p and r.
    (defstub p (x) t)
    (defstub r (x) t)

    ; Define the notion that something bigger than x satisfies p.
    (defun-sk some-bigger-p (x)
      (exists y (and (< x y) (p y))))

    ; Define the notion that something bigger than x satisfies r.
    (defun-sk some-bigger-r (x)
      (exists y (and (< x y) (r y))))

    ; Define the notion that arbitrarily large x satisfy p.
    (defun-sk arb-lg-p ()
      (forall x (some-bigger-p x)))

    ; Define the notion that arbitrarily large x satisfy r.
    (defun-sk arb-lg-r ()
      (forall x (some-bigger-r x)))

    ; Define the notion that something bigger than x satisfies p or r.
    (defun-sk some-bigger-p-or-r (x)
      (exists y (and (< x y) (or (p y) (r y)))))

    ; Define the notion that arbitrarily large x satisfy p or r.
    (defun-sk arb-lg-p-or-r ()
      (forall x (some-bigger-p-or-r x)))

    ; Prove the theorem promised above.  Notice that the functions open
    ; automatically, but that we have to provide help for some rewrite
    ; rules because they have free variables in the hypotheses.  The
    ; ``witness functions'' mentioned below were introduced by DEFUN-SK.

    (thm
     (implies (arb-lg-p-or-r)
              (or (arb-lg-p)
                  (arb-lg-r)))
     :hints ((\"Goal\"
              :use
              ((:instance some-bigger-p-suff
                          (x (arb-lg-p-witness))
                          (y (some-bigger-p-or-r-witness
                              (max (arb-lg-p-witness)
                                   (arb-lg-r-witness)))))
               (:instance some-bigger-r-suff
                          (x (arb-lg-r-witness))
                          (y (some-bigger-p-or-r-witness
                              (max (arb-lg-p-witness)
                                   (arb-lg-r-witness)))))
               (:instance arb-lg-p-or-r-necc
                          (x (max (arb-lg-p-witness)
                                  (arb-lg-r-witness))))))))

    ; And finally, here's a cute little example.  We have already
    ; defined above the notion (some-bigger-p x), which says that
    ; something bigger than x satisfies p.  Let us introduce a notion
    ; that asserts that there exists both y and z bigger than x which
    ; satisfy p.  On first glance this new notion may appear to be
    ; stronger than the old one, but careful inspection shows that y and
    ; z do not have to be distinct.  In fact ACL2 realizes this, and
    ; proves the theorem below automatically.

    (defun-sk two-bigger-p (x)
      (exists (y z) (and (< x y) (p y) (< x z) (p z))))

    (thm (implies (some-bigger-p x) (two-bigger-p x)))

    ; A technical point:  ACL2 fails to prove the theorem above
    ; automatically if we take its contrapositive, unless we disable
    ; two-bigger-p as shown below.  That is because ACL2 needs to expand
    ; some-bigger-p before applying the rewrite rule introduced for
    ; two-bigger-p, which contains free variables.  The moral of the
    ; story is:  Don't expect too much automatic support from ACL2 for
    ; reasoning about quantified notions.

    (thm (implies (not (two-bigger-p x)) (not (some-bigger-p x)))
         :hints ((\"Goal\" :in-theory (disable two-bigger-p))))")
 (TUTORIAL5-MISCELLANEOUS-EXAMPLES
  (ANNOTATED-ACL2-SCRIPTS)
  "Miscellaneous ACL2 examples

  The following examples are more advanced examples of usage of ACL2.
  They are included largely for reference, in case someone finds them
  useful.


Subtopics

  [File-reading-example]
      Example of reading files in ACL2

  [Functional-instantiation-example]
      A small proof demonstrating functional instantiation

  [Guard-example]
      A brief transcript illustrating [guard]s in ACL2

  [Mutual-recursion-proof-example]
      A small proof about mutually recursive functions")
 (TYPE
  (POINTERS)
  "Disambiguation page for type-related concepts.

  The word type might mean many things in ACL2.

    Built-in Types
      ACL2 can reason about and compute with certain different kinds of
      objects, such as [numbers], [strings], [characters], and
      [conses]. See [About_Types] for basic background on the
      different kinds of ACL2 objects.
    User-Defined Types
      When modeling systems with ACL2, you may often want to introduce
      certain concepts as new data types. For instance, if you are
      modeling a network, you might want host and connection objects.
      ACL2 does not directly support introducing new types. Instead,
      such types are usually ``emulated'' by introducing a new
      recognizer function, say hostp, and perhaps some related
      constructor and accessor functions, say make-host and
      host->name. Macro libraries can help to assist with introducing
      common types. See for instance [std/util], [defdata], or
      [fty::fty].
    Type Declarations
      For more efficient Common Lisp execution, ACL2 functions can be
      annotated with Common Lisp type specifiers (see [type-spec])
      that may boost performance by reducing run-time type checking.
      This mechanism is integrated with ACL2's [guard] mechanism, so
      you can prove your type declarations are correct. See also
      [declare] and [the], and also [patbind-the].
    Type Prescriptions
      ACL2 includes a limited but efficient ``[type-set] reasoning engine
      for determining whether objects are of certain built-in types.
      This engine can be extended with [type-prescription] rules.
      Such rules are often inferred automatically when new functions
      are introduced with [defun]. Type-set reasoning can assist
      other reasoning engines like [forward-chaining],
      [linear-arithmetic], and rewriting. Type-set information is
      stored in a [type-alist] data structure.
    Tau
      ACL2 includes another reasoning engine, the [tau-system], for
      reasoning about type-like predicates. Unlike [type-set], Tau
      can also be used for reasoning about user-defined types, and
      can also carry out certain interval arithmetic reasoning. See
      the [introduction-to-the-tau-system] for more information about
      Tau.")
 (TYPE-ALIST
  (TYPE-SET)
  "An ACL2 representation of contextual knowledge

  The ACL2 prover maintains many structures that need not be understood
  by the user. One of these, the type-alist structure, is usually in
  this category. But some utilities refer to the type-alist, so we
  summarize it here.

  A type-alist is is an association list, each element of which is of
  the form (u ts . ttree), where u is a [term] (in internal,
  ``translated'' form), ts is a [type-set], and ttree is a tag-tree
  (see [ttree]). Such an element means that the term u has the
  type-set ts, which is a number. While you are welcome to see the
  [documentation] of [type-set] for details, this is not necessary,
  since user-level utilities generally display a type-alist without
  displaying numeric type-sets. Instead, they often use a symbol of
  the form *TS-typ* to denote the type described by typ, and for
  complements they use (TS-COMPLEMENT *TS-typ*). For example, a
  context in which the terms (p x y), (no-duplicatesp-equal y), and
  (natp x) are assumed to be true (i.e., non-nil) may be displayed
  using the following lines.

    -----
    Terms with type *TS-T*:
    (NO-DUPLICATESP-EQUAL Y)
    -----
    Terms with type (TS-COMPLEMENT *TS-NIL*):
    (P X Y)
    -----
    Terms with type *TS-NON-NEGATIVE-INTEGER*:
    X
    -----

  These lines says that (no-duplicatesp-equal y) is the symbol t, (p x
  y) is not the symbol nil, and x is a non-negative integer (i.e., a
  [natp]).

  ACL2 computes a type-alist based on contextual information including
  the hypotheses of the current goal (technically: the negations of
  the literals in the goal that are not currently being rewritten),
  [forward-chaining] from those literals, and the surrounding tests
  in calls of if. The type-alist is of course not all that is known,
  since an entire logical [world] of facts is also known; and
  additional known information may be recorded in the current
  database of [linear] rules.")
 (TYPE-PRESCRIPTION
  (RULE-CLASSES)
  "Make a rule that specifies the type of a term

  See [rule-classes] for a general discussion of rule classes,
  including how they are used to build rules from formulas and a
  discussion of the various keywords in a rule class description.

    Examples:
    (defthm integerp-foo                       ; Assumes that foo has been
      (integerp (foo x y))                     ; defined; then, states that
      :rule-classes :type-prescription)        ; (foo x y) is of type integer.

    (defthm characterp-nth-type-prescription   ; (Nth n lst) is of type character
      (implies                                 ; provided the hypotheses can be
       (and (character-listp lst)              ; established by type reasoning.
            (<= 0 n)
            (< n (len lst)))
       (characterp (nth n lst)))
      :rule-classes :type-prescription)

    (defthm characterp-nth-type-prescription-alt ; equivalent to the above
      (implies
       (and (character-listp lst)
            (<= 0 n)
            (< n (len lst)))
       (characterp (nth n lst)))
      :rule-classes ((:type-prescription :typed-term (nth n lst))))

    (defthm demodulize-type-for-quote-value  ; (Demodulize a lst 'value ans) is
      (implies                               ; either a nonnegative integer or
       (and (atom a)                         ; of the same type as ans, provided
            (true-listp lst)                 ; the hyps can be established by type
            (member-equal a lst))            ; reasoning
       (or (and (integerp (demodulize a lst 'value ans))
                (>= (demodulize a lst 'value ans) 0))
         (equal (demodulize a lst 'value ans) ans)))
      :rule-classes :type-prescription)

  To specify the term whose type (see [type-set]) is described by the
  rule, provide that term as the value of the :typed-term field of
  the rule class object.

    General Form (after preprocessing; see below):
    (implies hyps
             (or type-restriction1-on-pat
                 ...
                 type-restrictionk-on-pat
                 (equal pat var1)
                 ...
                 (equal pat varj)))

  where pat is the application of some function symbol to some
  arguments, each type-restrictioni-on-pat is a term involving pat
  and containing no variables outside of the occurrences of pat, and
  each vari is one of the variables of pat. Generally speaking, the
  type-restriction terms ought to be terms that inform us as to the
  type of pat. Ideally, they should be ``primitive recognizing
  expressions'' about pat; see [compound-recognizer]. We describe
  preprocessing at the end of this topic.

  If the :typed-term is not provided in the rule class object, it is
  computed heuristically by looking for a term in the conclusion
  whose type is being restricted. An error is caused if no such term
  is found.

  Roughly speaking, the effect of adding such a rule is to inform the
  ACL2 typing mechanism that pat has the type described by the
  conclusion, when the hypotheses are true. In particular, the type
  of pat is within the union of the types described by the several
  disjuncts. The ``type described by'' (equal pat vari) is the type
  of vari.

  More operationally, when asked to determine the type of a term that
  is an instance of pat, ACL2 will first attempt to establish the
  hypotheses. This is done by type reasoning alone, not rewriting!
  However, if some hypothesis is a call of [force], then forcing may
  occur, which may ultimately invoke the rewriter; see [force] and
  see [case-split]. So-called free variables in hypotheses are
  treated specially; see [free-variables]. Provided the hypotheses
  are established by type reasoning, ACL2 then unions the types
  described by the type-restrictioni-on-pat terms together with the
  types of those subexpressions of pat identified by the vari. The
  final type computed for a term is the intersection of the types
  implied by each applicable rule. Type prescription rules may be
  disabled.

  You can limit the recursive establishment of hypotheses of rules; see
  [set-backchain-limit].

  Because only type reasoning is used to establish the hypotheses of
  :type-prescription rules, some care must be taken with the
  hypotheses. Suppose, for example, that the non-recursive function
  my-statep is defined as

    (defun my-statep (x)
      (and (true-listp x)
           (equal (len x) 2)))

  and suppose (my-statep s) occurs as a hypothesis of a
  :type-prescription rule that is being considered for use in the
  proof attempt for a conjecture with the hypothesis (my-statep s).
  Since the hypothesis in the conjecture is rewritten, it will become
  the conjunction of (true-listp s) and (equal (len s) 2). Those two
  terms will be assumed to have type t in the context in which the
  :type-prescription rule is tried. But type reasoning will be unable
  to deduce that (my-statep s) has type t in this context. Thus,
  either my-statep should be disabled (see [disable]) during the
  proof attempt or else the occurrence of (my-statep s) in the
  :type-prescription rule should be replaced by the conjunction into
  which it rewrites.

  While this example makes it clear how non-recursive predicates can
  cause problems, non-recursive functions in general can cause
  problems. For example, if (mitigate x) is defined to be (if
  (rationalp x) (1- x) x) then the hypothesis (pred (mitigate s)) in
  the conjecture will rewrite, opening mitigate and splitting the
  conjecture into two subgoals, one in which (rationalp s) and (pred
  (1- x)) are assumed and the other in which (not (rationalp s)) and
  (pred x) are assumed. But (pred (mitigate s)) will not be typed as
  t in either of these contexts. The moral is: beware of
  non-recursive functions occuring in the hypotheses of
  :type-prescription rules.

  Because of the freedom one has in forming the conclusion of a
  type-prescription, we have to use heuristics to recover the
  pattern, pat, whose type is being specified. In some cases our
  heuristics may not identify the intended term and the
  :type-prescription rule will be rejected as illegal because the
  conclusion is not of the correct form. When this happens you may
  wish to specify the pat directly. This may be done by using a
  suitable rule class token. In particular, when the token
  :type-prescription is used it means ACL2 is to compute pat with its
  heuristics; otherwise the token should be of the form
  (:type-prescription :typed-term pat), where pat is the term whose
  type is being specified.

  The defun event may generate a :type-prescription rule. Suppose fn is
  the name of the function concerned. Then (:type-prescription fn) is
  the rune given to the type-prescription, if any, generated for fn
  by [defun]. (The trivial rule, saying fn has unknown type, is not
  stored, but [defun] still allocates the rune and the corollary of
  this rune is known to be t.)

  We close with a discussion of how, before a term is parsed into a
  :type-prescription rule, it is preprocessed. We describe this
  preprocessing in some detail below, but first consider the
  following (contrived) example.

    (defthm append-tp-example
      (let ((result (append x y)))
        (implies (nat-listp x)
                 (implies (let ((second-hyp (integer-listp y)))
                            second-hyp)
                          (true-listp result))))
      :rule-classes :type-prescription)

  This theorem is parsed into a type-prescription rule with the
  following hypotheses and conclusion.

    (nat-listp x) ; first hypothesis
    ((lambda (second-hyp) second-hyp) (integer-listp y)) ; second hypothesis
    (true-listp (binary-append x y)) ; conclusion

  Notice that the top-level [let] was expanded, i.e., (append x y) was
  substituted for result --- more accurately, (binary-append x y) was
  substituted for result, since [append] is a macro that abbreviates
  [binary-append]. Also notice that the two hypotheses were
  ``flattened'' in the sense that they were gathered up into a list.
  Finally, notice that the [let] in the second hypothesis was not
  expanded (it was merely translated to internal form, using LAMBDA).
  If you actually submit the theorem above, you will get warnings,
  which you may choose to ignore; the application of
  type-prescription rules is somewhat subtle, so if you use them then
  you may wish to experiment to see which forms work best for you.

  Here is the detail promised above, for parsing a term into a
  :type-prescription rule. There are two steps. (1) ACL2 first
  translates the term, expanding all macros (see [trans]) and also
  removing [guard-holders]. (2) Then the the translated term is
  traversed top-down, expanding away lambdas ([let], [let*], and
  [mv-let] expressions) and flattening the [implies] structure, until
  the conclusion is exposed; then the conclusion's lambdas are also
  expanded away. The simplest way to understand (2) may be to look at
  the definition of ACL2 source function unprettyify-tp, which
  implements Step (2), say by evaluating :[pe] unprettyify-tp.


Subtopics

  [Backchain-limit]
      Limiting the effort expended on relieving hypotheses

  [Case-split]
      Like force but immediately splits the top-level goal on the
      hypothesis

  [Force]
      Identity function used to force a hypothesis")
 (TYPE-SET
  (MISCELLANEOUS)
  "How type information is encoded in ACL2

  To help you experiment with type-sets we briefly note the following
  utility functions.

  (type-set-quote x) will return the type-set of the object x. For
  example, (type-set-quote \"test\") is 2048 and (type-set-quote '(a b
  c)) is 512.

  (type-set 'term nil nil nil (ens state) (w state) nil nil nil) will
  return the type-set of term. For example,

    (type-set '(integerp x) nil nil nil (ens state) (w state) nil nil nil)

  will return (mv 192 nil). 192, otherwise known as *ts-boolean*, is
  the type-set containing t and nil. The second result may be ignored
  in these experiments. Term must be in the translated, internal form
  shown by :[trans]. See [trans] and see [term].

  (type-set-implied-by-term 'x nil 'term (ens state)(w state) nil) will
  return the type-set deduced for the variable symbol x assuming the
  translated term, term, true. The second result may be ignored in
  these experiments. For example,

    (type-set-implied-by-term 'v nil '(integerp v)
                              (ens state) (w state) nil)

  returns 11.

  (convert-type-set-to-term 'x ts (ens state) (w state) nil) will
  return a term whose truth is equivalent to the assertion that the
  term x has type-set ts. The second result may be ignored in these
  experiments. For example

    (convert-type-set-to-term 'v 523 (ens state) (w state) nil)

  returns a term expressing the claim that v is either an integer or a
  non-nil true-list. 523 is the logical-or of 11 (which denotes the
  integers) with 512 (which denotes the non-nil true-lists).

  The ``actual primitive types'' of ACL2 are listed in
  *actual-primitive-types*, whose elements are shown below. Each
  actual primitive type denotes a set --- sometimes finite and
  sometimes not --- of ACL2 objects and these sets are pairwise
  disjoint. For example, *ts-zero* denotes the set containing 0 while
  *ts-positive-integer* denotes the set containing all of the
  positive integers.

    *TS-ZERO*                  ;;; {0}
    *TS-POSITIVE-INTEGER*      ;;; positive integers
    *TS-POSITIVE-RATIO*        ;;; positive non-integer rationals
    *TS-NEGATIVE-INTEGER*      ;;; negative integers
    *TS-NEGATIVE-RATIO*        ;;; negative non-integer rationals
    *TS-COMPLEX-RATIONAL*      ;;; complex rationals
    *TS-NIL*                   ;;; {nil}
    *TS-T*                     ;;; {t}
    *TS-NON-T-NON-NIL-SYMBOL*  ;;; symbols other than nil, t
    *TS-PROPER-CONS*           ;;; null-terminated non-empty lists
    *TS-IMPROPER-CONS*         ;;; conses that are not proper
    *TS-STRING*                ;;; strings
    *TS-CHARACTER*             ;;; characters

  The actual primitive types were chosen by us to make theorem proving
  convenient. Thus, for example, the actual primitive type *ts-nil*
  contains just nil so that we can encode the hypothesis ``x is nil''
  by saying ``x has type *ts-nil*'' and the hypothesis ``x is
  non-nil'' by saying ``x has type complement of *ts-nil*.'' We
  similarly devote a primitive type to t, *ts-t*, and to a third
  type, *ts-non-t-non-nil-symbol*, to contain all the other ACL2
  symbols.

  Let *ts-other* denote the set of all Common Lisp objects other than
  those in the actual primitive types. Thus, *ts-other* includes such
  things as floating point numbers and CLTL array objects. The actual
  primitive types together with *ts-other* constitute what we call
  *universe*. Note that *universe* is a finite set containing one
  more object than there are actual primitive types; that is, here we
  are using *universe* to mean the finite set of primitive types, not
  the infinite set of all objects in all of those primitive types.
  *Universe* is a partitioning of the set of all Common Lisp objects:
  every object belongs to exactly one of the sets in *universe*.

  Abstractly, a ``type-set'' is a subset of *universe*. To say that a
  term, x, ``has type-set ts'' means that under all possible
  assignments to the variables in x, the value of x is a member of
  some member of ts. Thus, (cons x y) has type-set {*ts-proper-cons*
  *ts-improper-cons*}. A term can have more than one type-set. For
  example, (cons x y) also has the type-set {*ts-proper-cons*
  *ts-improper-cons* *ts-nil*}. Extraneous types can be added to a
  type-set without invalidating the claim that a term ``has'' that
  type-set. Generally we are interested in the smallest type-set a
  term has, but because the entire theorem-proving problem for ACL2
  can be encoded as a type-set question, namely, ``Does p have
  type-set complement of *ts-nil*?,'' finding the smallest type-set
  for a term is an undecidable problem. When we speak informally of
  ``the'' type-set we generally mean ``the type-set found by our
  heuristics'' or ``the type-set assumed in the current context.''

  Note that if a type-set, ts, does not contain *ts-other* as an
  element then it is just a subset of the actual primitive types. If
  it does contain *ts-other* it can be obtained by subtracting from
  *universe* the complement of ts. Thus, every type-set can be
  written as a (possibly complemented) subset of the actual primitive
  types.

  By assigning a unique bit position to each actual primitive type we
  can encode every subset, s, of the actual primitive types by the
  nonnegative integer whose ith bit is on precisely if s contains the
  ith actual primitive type. The type-sets written as the complement
  of s are encoded as the twos-complement of the encoding of s. Those
  type-sets are thus negative integers. The bit positions assigned to
  the actual primitive types are enumerated from 0 in the same order
  as the types are listed in *actual-primitive-types*. At the
  concrete level, a type-set is an integer between *min-type-set* and
  *max-type-set*, inclusive.

  For example, *ts-nil* has bit position 6. The type-set containing
  just *ts-nil* is thus represented by 64. If a term has type-set 64
  then the term is always equal to nil. The type-set containing
  everything but *ts-nil* is the twos-complement of 64, which is -65.
  If a term has type-set -65, it is never equal to nil. By ``always''
  and ``never'' we mean under all, or under no, assignments to the
  variables, respectively.

  Here is a more complicated example. Let s be the type-set containing
  all of the symbols and the natural numbers. The relevant actual
  primitive types, their bit positions and their encodings are:

    actual primitive type       bit    value

    *ts-zero*                    0       1
    *ts-positive-integer*        1       2
    *ts-nil*                     6      64
    *ts-t*                       7     128
    *ts-non-t-non-nil-symbol*    8     256

  Thus, the type-set s is represented by (+ 1 2 64 128 256) = 451. The
  complement of s, i.e., the set of all objects other than the
  natural numbers and the symbols, is -452.


Subtopics

  [Type-alist]
      An ACL2 representation of contextual knowledge")
 (TYPE-SET-INVERTER
  (RULE-CLASSES)
  "Exhibit a new decoding for an ACL2 type-set

  See [rule-classes] for a general discussion of rule classes,
  including how they are used to build rules from formulas and a
  discussion of the various keywords in a rule class description.

    Example Rule Class:
    (:type-set-inverter
      :corollary (equal (and (counting-number x) (not (equal x 0)))
                        (and (integerp x) (< 0 x)))
      :type-set 2)

    General Forms of Rule Class:
    :type-set-inverter, or
    (:type-set-inverter :type-set n)

    General Form of Theorem or Corollary:
    (EQUAL new-expr old-expr)

  where n is a [type-set] (see [type-set]) and old-expr is the term
  containing x as a free variable that ACL2 currently uses to
  recognize [type-set] n. For a given n, the exact form of old-expr
  is generated by

    (convert-type-set-to-term 'x n (ens state) (w state) nil)].

  If the :[type-set] field of the rule-class is omitted, we attempt to
  compute it from the right-hand side, old-expr, of the corollary.
  That computation is done by type-set-implied-by-term (see
  [type-set]). However, it is possible that the type-set we compute
  from lhs does not have the required property that when inverted
  with convert-type-set-to-term the result is lhs. If you omit
  :[type-set] and an error is caused because lhs has the incorrect
  form, you should manually specify both :[type-set] and the lhs
  generated by convert-type-set-to-term.

  The rule generated will henceforth make new-expr be the term used by
  ACL2 to recognize type-set n. If this rule is created by a [defthm]
  event named name then the rune of the rule is (:type-set-inverter
  name) and by disabling that rune you can prevent its being used to
  decode type-sets.

  Type-sets are inverted when forced assumptions are turned into
  formulas to be proved. In their internal form, assumptions are
  essentially pairs consisting of a context and a goal term, which
  was forced. Abstractly a context is just a list of hypotheses which
  may be assumed while proving the goal term. But actually contexts
  are alists which pair terms with type-sets, encoding the current
  hypotheses. For example, if the original conjecture contained the
  hypothesis (integerp x) then the context used while working on that
  conjecture will include the assignment to x of the type-set
  *ts-integer*.")
 (TYPE-SPEC
  (DECLARE THE)
  "Type specifiers can be used in Common Lisp type declarations and
  [the] forms, and may result in improved efficiency of execution.

  ACL2 permits the use of type declarations in certain contexts; see
  [declare] for background. Here is an example of a type declaration;
  here the symbol, integer, is what we refer to as a ``type-spec'':

    (let ((x (+ a b)))
      (declare (type integer x))   ;; <-- type declaration
      (+ 1 x))

  A Common Lisp compiler might be able to use the above declaration to
  improve the execution efficiency of the resulting code. In
  particular, the Common Lisp [+] operation is rather elaborate: it
  must be capable of adding together integers, rationals, floats,
  etc. When we tell the compiler that this x is surely an integer, it
  may be able to use a more efficient version of (+ 1 x) that only
  deals with the integer case.

  Type declarations can be added to functions, [let] bindings, and
  other places as described in [declare], and interact with the
  ACL2's [guard] mechanism. For instance, during guard verification,
  the above type declaration will result in a guard obligation: we
  will need to prove that (+ a b) is always an integer. Type
  declarations about the formals of a function generally become part
  of the guard of the function, but see also [split-types] for a way
  to gain more control over this.

  Whether or not a particular type declaration will actually improve
  the efficiency of your functions depends on the Lisp compiler. For
  instance, many Lisp compilers will not benefit much from a plain
  integer declaration. If you are trying to optimize code by adding
  type declarations, it may be useful to use [disassemble$] to
  inspect the impact that your declarations have on the resulting
  code.


Type Specs

  The syntax that Common Lisp compilers use for these type
  declarations---e.g., the symbol integer above---is different than
  the usual syntax of ACL2.

  We use the name type-spec to refer to the supported types that can be
  mentioned in declarations. For instance:

    Declaration	|  Type-Spec	|
    (type string x y z)	|  string	|
    (type (integer 0 7) x)	|  (integer 0 7)	|
    (type rational x)	|  rational	|
    (type (rational 1 *) x)	|  (rational 1 *)	|

  The supported type-specs and their meanings (when applied to the
  variable x as in (declare (type type-spec x)) are given below.

    type-spec              meaning
    ----------------------------------------------------------------------
    (AND type1 ... typek)  (AND (p1 X) ... (pk X))
                           where (pj x) is the meaning for type-spec typej
    ATOM                   (ATOM X)
    BIT                    (OR (EQUAL X 1) (EQUAL X 0))
    CHARACTER              (CHARACTERP X)
    COMPLEX                (AND (COMPLEX-RATIONALP X)
                                (RATIONALP (REALPART X))
                                (RATIONALP (IMAGPART X)))
    (COMPLEX RATIONAL)     same as COMPLEX, above
    (COMPLEX type)         (AND (COMPLEX-RATIONALP X)
                                (p (REALPART X))
                                (p (IMAGPART X)))
                           where (p x) is the meaning for type-spec type
    CONS                   (CONSP X)
    INTEGER                (INTEGERP X)
    (INTEGER i j)          (AND (INTEGERP X)   ; See notes below
                                (<= i X)
                                (<= X j))
    (MEMBER x1 ... xn)     (MEMBER X '(x1 ... xn))
    (MOD i)                same as (INTEGER 0 i-1)
    NIL                    NIL
    (NOT type)             (NOT (p X))
                           where (p x) is the meaning for type-spec type
    NULL                   (EQ X NIL)
    (OR type1 ... typek)   (OR (p1 X) ... (pk X))
                           where (pj x) is the meaning for type-spec typej
    RATIO                  (AND (RATIONALP X) (NOT (INTEGERP X)))
    RATIONAL               (RATIONALP X)
    (RATIONAL i j)         (AND (RATIONALP X)  ; See notes below
                                (<= i X)
                                (<= X j))
    REAL                   (RATIONALP X)       ; (REALP X) in ACL2(r)
    (REAL i j)             (AND (RATIONALP X)  ; See notes below
                                (<= i X)
                                (<= X j))
    (SATISFIES pred)       (pred X) ; Lisp requires a unary function, not a macro
    SIGNED-BYTE            (INTEGERP X)
    (SIGNED-BYTE i)        same as (INTEGER k m) where k=-2^(i-1), m=2^(i-1)-1
    STANDARD-CHAR          (STANDARD-CHARP X)
    STRING                 (STRINGP X)
    (STRING max)           (AND (STRINGP X) (EQUAL (LENGTH X) max))
    SYMBOL                 (SYMBOLP X)
    T                      T
    UNSIGNED-BYTE          same as (INTEGER 0 *)
    (UNSIGNED-BYTE i)      same as (INTEGER 0 (2^i)-1)
    ----------------------------------------------------------------------

  Notes

  In general, (integer i j) means

    (AND (INTEGERP X)
         (<= i X)
         (<= X j)).

  But if i is the symbol *, the first inequality is omitted. If j is
  the symbol *, the second inequality is omitted. If instead of being
  an integer, the second element of the type specification is a list
  containing an integer, (i), then the first inequality is made
  strict. An analogous remark holds for the (j) case. The rational
  and real type specifiers are similarly generalized.

  Common Lisp itself supports richer type specifiers than ACL2. Some
  resources:

    * A {nice picture of the Common Lisp Type Hierarchy |
      http://sellout.github.io/2012/03/03/common-lisp-type-hierarchy/}
      by Greg Pfeil.")
 (TYPESPEC-CHECK (POINTERS)
                 "See [meta-extract].")
 (U
  (HISTORY)
  "Undo last [command], without a query

    Example:
    :u

  The keyword [command] :u is the same as :[ubt] :[max], but with
  related queries suppressed appropriately. :[Oops] will undo the
  last :u. See [ubt], see [ubu], see [ubt!], and see [ubu!].")
 (UBT
  (HISTORY)
  "Undo the [command]s back through a [command] descriptor

    Examples:
    :ubt :max      ; undo back through the most recent command
                   ; (which just means undo the most recent command)
    :ubt :x        ; same as :ubt :max
    :u             ; same as :ubt :max with no questions asked
    :ubt fn        ; undo back through the introduction of fn
                   ; (including all the other events in fn's block)
    :ubt 5         ; undo back through the fifth command executed
    :ubt (:max -4) ; undo back through the most recent five commands
    :ubt (:x -4)   ; undo back through the most recent five commands

  See [command-descriptor].

  Ubt takes one argument, a [command] descriptor, and undoes the
  [command]s from :[max] (aka :x) through the one described. See
  [command-descriptor]. [Pbt] will print the [command]s that ubt will
  undo. :[Oops] will undo the undo. See [oops].

  Ubt can cause errors or queries. To avoid these, see [ubt!].

  It is important to remember that a [command] may create several
  [events]. That is, the [command] that introduces fn1 may also
  introduce fn2. Undoing the [command] that created either of these
  will undo them both. The [events] created by a [command] constitute
  the [command]'s ``block'' and we can only undo entire blocks. Use
  [pcb] to print the [command] block of a [command] if you wish to
  see what will be lost by undoing the [command].

  Ubt will not undo into ``prehistory''. :Ubt 1 will undo all of your
  [command]s. But :ubt -5 will cause an error, warning you that :ubt
  cannot undo system initialization.

  See [u] for how to undo just the latest command, and see [ubu] and
  see [ubu!] for how to undo back up to, but not including, the
  current command.")
 (UBT!
  (HISTORY)
  "Undo [command]s, without a query or an error

    Example:
    :ubt! :x-4

  The keyword [command] :ubt! is the same as :[ubt], but with related
  queries suppressed appropriately, and with a guarantee that it is
  ``error-free.'' More precisely, the value returned by :ubt! will
  always be of the form (mv nil val state). :[Oops] will undo the
  last :ubt!. See [ubt], see [ubu], and see [u].")
 (UBT-PREHISTORY
  (HISTORY)
  "Undo the [command]s back through the last [reset-prehistory] event

  This command is only used to eliminate a [reset-prehistory] event. If
  your most recent reset-prehistory event does not have a flag
  argument of t, then :ubt-prehistory undoes all command back
  through, and including, that reset-prehistory event.")
 (UBU
  (HISTORY)
  "Undo the [command]s back up to (not including) a [command] descriptor

    Examples:
    :ubu :x-3      ; undo the last three commands (same as :ubt :x-2)
    :ubu (:x -3)   ; same as above
    :ubu fn        ; undo back up to, but not including the introduction of fn
                   ; (so fn will continue to be defined)
    :ubu 5         ; undo back up to, but not including, the fifth command
                   ; executed (leaving the first five commands in place)

  See [command-descriptor].

  Ubu takes one argument, a [command] descriptor, and undoes the
  [command]s from :[max] (aka :x) up to, but not including, the
  indicated command. See [command-descriptor].

  Ubu can cause errors or queries. To avoid these, see [ubu!].

  Also see [ubt], which is similar but also undoes the indicated
  command. As for :[ubt], :[oops] will undo the undo (see [oops]) and
  [ubu] will not undo into ``prehistory''.

  See [u] for how to undo just the latest command, and see [ubt] and
  see [ubt!] for how to undo back through (that is, including) the
  current command.")
 (UBU!
  (HISTORY)
  "Undo [command]s, without a query or an error

    Example:
    :ubu! :x-4

  The keyword [command] :ubu! is the same as :[ubu], but with related
  queries suppressed appropriately, and with a guarantee that it is
  ``error-free.'' More precisely, the error triple (see
  [error-triples]) returned by :ubu! will always be of the form (mv
  nil val state). :[Oops] will undo the last :ubu!. Also see [ubu],
  see [ubt], and see [u].")
 (UNARY--
  (NUMBERS ACL2-BUILT-INS)
  "Arithmetic negation function

  Completion Axiom (completion-of-unary-minus):

    (equal (unary-- x)
           (if (acl2-numberp x)
               (unary-- x)
             0))

  [Guard] for (unary-- x):

    (acl2-numberp x)

  Notice that like all arithmetic functions, unary-- treats non-numeric
  inputs as 0.

  Calls of the macro [-] on one argument expand to calls of unary--;
  see [-].")
 (UNARY-/
  (NUMBERS ACL2-BUILT-INS)
  "Reciprocal function

  Completion Axiom (completion-of-unary-/):

    (equal (unary-/ x)
           (if (and (acl2-numberp x)
                    (not (equal x 0)))
               (unary-/ x)
             0))

  [Guard] for (unary-/ x):

    (and (acl2-numberp x)
         (not (equal x 0)))

  Notice that like all arithmetic functions, unary-/ treats non-numeric
  inputs as 0.

  Calls of the macro [/] on one argument expand to calls of unary-/;
  see [/].")
 (UNCERTIFIED-BOOKS
  (BOOKS)
  "Invalid [certificate]s and uncertified [books]

  For relevant background see [books], see [certificate], and see
  [portcullis].

  [Include-book] has a special provision for dealing with an
  uncertified book, i.e., a file with no [certificate] or an invalid
  [certificate] (i.e., one whose check sums describe files other than
  the ones actually read). In this case, a warning is printed and the
  book is otherwise processed much as though it were certified and
  had an open [portcullis].

  If a book B.lisp is uncertified and a file B.port exists, then the
  forms in B.port are evaluated before the forms in B.lisp. Such a
  file B.port is typically created calling [certify-book] on book \"B\"
  with argument :write-port t, so that B.port contains the
  [portcullis] [command]s for B (the commands present in the [world]
  when that certification was attempted). To avoid loading .port
  files, see [compilation].

  Inclusion of uncertified books can be handy, but it can have
  disastrous consequences.

  The provision allowing uncertified [books] to be included can have
  disastrous consequences, ranging from hard lisp errors, to damaged
  memory, to quiet logical inconsistency.

  It is possible for the inclusion of an uncertified book to render the
  logic inconsistent. For example, one of its non-[local] [events]
  might be (defthm t-is-nil (equal t nil)). It is also possible for
  the inclusion of an uncertified book to cause hard errors or
  [breaks] into raw Common Lisp. For example, if the file has been
  edited since it was certified, it may contain too many open
  parentheses, causing Lisp to read past ``end of file.'' Similarly,
  it might contain non-ACL2 objects such as 3.1415 or ill-formed
  event forms that cause ACL2 code to break.

  Even if a book is perfectly well formed and could be certified (in a
  suitable extension of ACL2's initial [world]), its uncertified
  inclusion might cause Lisp errors or inconsistencies! For example,
  it might mention packages that do not exist in the host [world],
  especially if the .port file (discussed above) does not exist from
  an earlier certification attempt. The [portcullis] of a certified
  book ensures that the correct [defpkg]s have been admitted, but if
  a book is read without actually raising its [portcullis], symbols
  in the file, e.g., acl2-arithmetic::fn, could cause ``unknown
  package'' errors in Common Lisp. Perhaps the most subtle disaster
  occurs if the host [world] does have a [defpkg] for each package
  used in the book but the host [defpkg] imports different symbols
  than those required by the [portcullis]. In this case, it is
  possible that formulas which were theorems in the certified book
  are non-theorems in the host [world], but those formulas can be
  read without error and will then be quietly assumed.

  In short, if you include an uncertified book, all bets are off
  regarding the validity of the future behavior of ACL2.

  That said, it should be noted that ACL2 is pretty tough and if errors
  don't occur, the chances are that deductions after the inclusion of
  an uncertified book are probably justified in the (possibly
  inconsistent) logical extension obtained by assuming the
  admissibility and validity of the definitions and conjectures in
  the book.")
 (UNDOCUMENTED_TOPIC
      (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
      "Undocumented Topic

  This topic has not yet been documented. Sorry")
 (UNION$
  (LISTS ACL2-BUILT-INS)
  "Elements of one list that are not elements of another

    General Forms:
    (union$ l1 l2 ... lk)
    (union$ l1 l2 ... lk :test 'eql) ; same as above
    (union$ l1 l2 ... lk :test 'eq)    ; same, but eq is equality test
    (union$ l1 l2 ... lk :test 'equal) ; same, but equal is equality test

  (Union$ x y) equals a list that contains both the members of x and
  the members of y. More precisely, the resulting list is the same as
  one would get by first deleting the members of y from x, and then
  concatenating the result to the front of y. The optional keyword,
  :TEST, has no effect logically, but provides the test (default
  [eql]) used for comparing members of the two lists.

  Union$ need not take exactly two arguments: (union$) is nil, (union$
  x) is x, (union$ x y z ... :test test) is (union$ x (union$ y z ...
  :test test) :test test), and if :TEST is not supplied, then (union$
  x y z ...) is (union$ x (union$ y z ...)). For the discussion below
  we restrict ourselves, then, to the cases (union$ x y) and (union$
  x y :test test).

  The [guard] for a call of union$ (in the two cases just above)
  depends on the test. In all cases, both arguments must satisfy
  [true-listp]. If the test is [eql], then one of the arguments must
  satisfy [eqlable-listp]. If the test is [eq], then one of the
  arguments must satisfy [symbol-listp].

  See [equality-variants] for a discussion of the relation between
  union$ and its variants:

      (union-eq x lst) is equivalent to (union$ x lst :test 'eq);

      (union-equal x lst) is equivalent to (union$ x lst :test 'equal).

  In particular, reasoning about any of these primitives reduces to
  reasoning about the function union-equal.

  Function: 

    (defun
         union-equal (l1 l2)
         (declare (xargs :guard (and (true-listp l1) (true-listp l2))))
         (cond ((endp l1) l2)
               ((member-equal (car l1) l2)
                (union-equal (cdr l1) l2))
               (t (cons (car l1)
                        (union-equal (cdr l1) l2)))))

  Note that union-eq can take any number of arguments, in analogy to
  union$; indeed, (union-eq ...) expands to (union$ ... :test 'eq).
  However, union-equal is a function, not a macro, and takes exactly
  two arguments.

  Union$ is similar to the Common Lisp primitive union. However, Common
  Lisp does not specify the order of elements in the result of a call
  of union.")
 (UNION-EQ (POINTERS) "See [union$].")
 (UNION-EQUAL (POINTERS) "See [union$].")
 (UNION-THEORIES
  (THEORIES THEORY-FUNCTIONS)
  "Union two [theories]

    Example:
    (union-theories (current-theory 'lemma3)
                    (theory 'arith-patch))

    General Form:
    (union-theories th1 th2)

  where th1 and th2 are theories (see [theories]). To each of the
  arguments there corresponds a runic theory. This function returns
  the union of those two runic [theories], represented as a list and
  ordered chronologically.

  This ``function'' is actually a macro that expands to a term
  mentioning the single free variable [world]. When theory
  expressions are evaluated by [in-theory] or the :[in-theory] hint,
  [world] is bound to the current ACL2 [world].")
 (UNIVERSAL-THEORY
  (THEORIES THEORY-FUNCTIONS)
  "All rules as of logical name

    Examples:
    (universal-theory :here)
    (universal-theory 'lemma3)

  See [logical-name].

    General Form:
    (universal-theory logical-name)

  Returns the theory consisting of all the [rune]s that existed
  immediately after [logical-name] was introduced. See [theories] and
  see [logical-name]. The theory includes [logical-name] itself (if
  there is a rule by that name). (Note that since some [events] do
  not introduce rules (e.g., [defmacro], [defconst] or [defthm] with
  :[rule-classes] nil), the universal-theory does not necessarily
  include a [rune] for every event name.) The universal-theory is
  very long and you will probably regret printing it.

  You may experience a fencepost problem in deciding which
  [logical-name] to use. [Deflabel] can always be used to mark
  unambiguously for future reference a particular point in the
  development of your theory. This is convenient because [deflabel]
  does not introduce any rules and hence it doesn't matter if you
  count it as being in the interval or not. The order of [events] in
  the vicinity of an [encapsulate] is confusing. See [encapsulate].

  This ``function'' is actually a macro that expands to a term
  mentioning the single free variable [world]. When theory
  expressions are evaluated by [in-theory] or the :[in-theory] hint,
  [world] is bound to the current ACL2 [world].

  Also see [current-theory]. Current-theory is much more commonly used
  than universal-theory. The former includes only the [enable]d
  [rune]s as of the given [logical-name], which is probably what you
  want, while the latter includes [disable]d ones as well.")
 (UNMEMOIZE
  (MEMOIZE PROGRAMMING HONS-AND-MEMOIZATION EVENTS)
  "Turn off memoization for the specified function

    Example:
    (unmemoize 'foo) ; turn off memoization of foo

    General Form:
    (unmemoize fn)

  where fn evaluates to a function symbol that is currently memoized;
  see [memoize]. An exception is that as with [memoize], fn may
  evaluate to the name of a macro that is associated with such a
  function symbol; see [macro-aliases-table].

  Calls of this macro generate events of the form (table memoize-table
  fn nil). When successful, the returned value is of the form (mv nil
  function-symbol state).

  To remove the effects of all [memoize] [events], evaluate:
  (clear-memo-table). To save and restore memoization, see
  [save-and-clear-memoization-settings] and see
  [restore-memoization-settings].")
 (UNMONITOR
  (BREAK-REWRITE)
  "To stop monitoring a rule name

    Examples:
    (unmonitor '(:rewrite assoc-of-app))
    :unmonitor (:rewrite assoc-of-app)
    :unmonitor :all

    General Forms:
    (unmonitor rune)
    (unmonitor :all)

  Here, rune is a [rune] that is currently among those with break
  points installed. This function removes the break.

  Subtle point: Because you may want to unmonitor a ``[rune]'' that is
  no longer a [rune] in the current ACL2 [world], we don't actually
  check this about [rune]. Instead, we simply check that [rune] is a
  consp beginning with a keywordp. That way, you'll know you've made
  a mistake if you try to :unmonitor binary-append instead of
  :unmonitor (:definition binary-append), for example.")
 (UNQUOTE
  'ACL2-BUILT-INS
  "Obtain the object being quoted

  Unquote is just an abbrevation for [cadr]. Its intended use is to
  obtain an object being quoted. For example, if x is (quote (3 4))
  then (unquote x) is (3 4):

    ACL2 !>(let ((x '(quote (3 4))))
             (unquote x))
    (3 4)
    ACL2 !>")
 (UNSAVE
  (PROOF-CHECKER)
  "Remove a [proof-checker] state

    Example:
    (unsave assoc-of-append)

    General Form:
    (unsave name)

  Eliminates the association of a [proof-checker] state with name. See
  [unsave] or see [ACL2-pc::unsave].

  Also see [ACL2-pc::save] and see [retrieve].")
 (UNSIGNED-BYTE-P
  (NUMBERS ACL2-BUILT-INS)
  "Recognizer for natural numbers that fit in a specified bit width

  (Unsigned-byte-p bits x) is T when bits is a positive integer and x
  is a nonnegative integer that fits into a bit-width of bits, i.e.,
  0 <= x < 2^bits.

  Note that a [type-spec] of (unsigned-byte i) for a variable x in a
  function's [declare] form translates to a [guard] condition of
  (unsigned-byte-p i x).

  The [guard] for unsigned-byte-p is T.

  Function: 

    (defun unsigned-byte-p (bits x)
           (declare (xargs :guard t))
           (and (integerp bits)
                (<= 0 bits)
                (integer-range-p 0 (expt 2 bits) x)))")
 (UNSUPPORTED-PARALLELISM-FEATURES
  (PARALLELISM)
  "ACL2 features not supported in ACL2(p)

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].
  See [parallelism-tutorial] for an introduction to parallel
  programming in ACL2.

  For proof features of ACL2 that are not yet supported when parallel
  execution is enabled for the primary ACL2 proof process, generally
  known as ``the waterfall'', see
  [unsupported-waterfall-parallelism-features].

  Please note that this topic discusses ACL2 features that are disabled
  when using ACL2(p) (see [compiling-ACL2p]). These features are
  disabled regardless of whether waterfall parallelism is enabled.

  Calls of [observation-cw] simply convert to calls of [cw], so
  suppressing [observation]s (see [set-inhibit-output-lst]) will not
  suppress these messages.

  Memoization is not supported when executing in parallel. See
  [Unsupported-waterfall-parallelism-features] for memoization
  details related to waterfall parallelism.

  Since, as of April 2012, garbage collection is inherently sequential,
  ACL2(p) minimizes the use of garbage collection by setting a high
  garbage collection threshold. As a result, ACL2(p) is not expected
  to perform well on machines with less memory than this threshold (1
  gigabyte, as of April 2012).

  In CCL, the underlying parallel execution engine is tuned for the
  number of CPU cores (or hardware threads) actually available in the
  machine. SBCL and LispWorks are tuned for a machine with 16 CPU
  cores.

  CCL is considered to be the ``flagship Lisp'' for parallel execution
  in ACL2. The SBCL and LispWorks implementations are thought to be
  generally stable. However, due to their relatively less common use,
  the SBCL and LispWorks implementations are likely less robust than
  the CCL implementation.

  The [time-tracker] utility is a no-op for ACL2(p).")
 (UNSUPPORTED-WATERFALL-PARALLELISM-FEATURES
  (PARALLEL-PROOF)
  "Proof features not supported with waterfall-parallelism enabled

  For a general introduction to ACL2(p), an experimental extension of
  ACL2 that supports parallel execution and proof, see [parallelism].
  Please note that although this extension is usable and, we hope,
  robust in its behavior, there are still known issues to address
  beyond those listed explicitly below. While we expect ACL2(p) to
  perform correctly, it may never have the same level of attention to
  correctness as is given to ACL2; see [parallelism], specifically
  the ``IMPORTANT NOTE'' there.

  Below we list proof features of ACL2 that are not yet supported when
  parallel execution is enabled for the primary ACL2 proof process,
  generally known as ``the waterfall'', typically by calling
  [set-waterfall-parallelism].

  Please note that this topic is limited to the case that such
  waterfall parallelism is enabled. We believe that all ACL2 proof
  procedures are supported when waterfall parallelism is disabled,
  even in executables that support parallelism (see
  [compiling-ACL2p]).

  Without a trust tag (see [defttag]): We support [clause-processor]s,
  [computed-hints], and [custom-keyword-hints] that do not modify
  [state], but we do not permit [override-hints], regardless of
  whether they modify state. With a trust tag, the user can use
  [clause-processor]s that modify state and can also use
  [override-hints] (see [set-waterfall-parallelism-hacks-enabled] for
  a convenient mechanism for adding a trust tag). See
  [error-triples-and-parallelism] for a discussion of how to avoid
  modifying state in such situations. Regardless of whether a trust
  tag is active: We do not support checkers of [custom-keyword-hints]
  to be anything but the default checker.

  GNU Make versions 3.81 and 3.82 formerly caused a lot of problems
  (version 3.80 somewhat less so), at least on Linux, when certifying
  books with ACL2 built on a host Lisp of CCL using `make'. CCL was
  updated around March 23, 2011 to fix this problem, so if you get
  segfaults (for example) with CCL, try updating your CCL
  installation.

  Book certification should generally work but may present some issues,
  including the following.

    * The standard `make'-based process for book certification will not use
      [waterfall-parallelism], which is disabled by default (even
      when [compiling-ACL2p] by using the ACL2_PAR flag). See
      [books-certification] and see [books-certification-classic],
      which explain that [ACL2-customization] files are ignored
      during that process unless specified explicitly on the command
      line or in the environment.
    * A book certified with ACL2(p) might subsequently cause an error when
      included with ACL2. As of this writing, however, we have only
      seen this for a book in which [deftheory-static] is used.
    * In general, ACL2(p) is primarily intended to support more rapid
      interactive development. While we are unaware of an unsoundness
      likely to affect an ACL2(p) user, we suggest using ACL2 for
      final book certification, rather than ACL2(p), to lower the
      risk of unsound book certification.

  Proof output can contain repeated printing of the same subgoal name.

  [Gag-mode] isn't officially supported, although it has proved helpful
  to use ACL2(p) in conjunction with (set-gag-mode t) (because this
  setting suppresses the output that occurs outside the waterfall).
  This being said, ACL2(p) also prints key checkpoints (for example
  see [introduction-to-key-checkpoints]), but with a notion of ``key
  checkpoint'' that does not take into account whether the goal is
  later proved by induction. See [ACL2p-key-checkpoints] for further
  explanation of these key checkpoints. Note that [pso] is also not
  supported.

  The :[brr] utility is not supported.

  The [accumulated-persistence] utility is not supported.

  Tracking for [forward-chaining-reports] is not supported (see
  [set-fc-criteria]).

  Time limits (see [with-prover-time-limit]) aren't supported.

  The timing information printed at the end of a proof attempt, which
  is intended to represent cpu time (not wall-clock time), may be
  somewhat inaccurate when [waterfall-parallelism] is non-nil.
  Consider using [time$] to obtain timing information.

  The use of [wormhole]s is not recommended, as there may be race
  conditions.

  Output specific to :OR [hints] is disabled.

  Proof trees are likely not to work as originally designed.

  The use of [set-inhibit-output-lst] may not fully inhibit proof
  output.

  Reporting of [splitter] rules is currently unsupported when
  waterfall-parallelism is on.

  Interrupting a proof attempt is not yet properly supported. At a
  minimum, interrupts are trickier with waterfall parallelism
  enabled. For one, the user typically needs to issue the interrupt
  twice before the proof attempt is actually interrupted.
  Additionally, on rare occasions the theorem is registered as
  proved, even though the prover did not finish the proof. If this
  occurs, issue a :u (see [ubt]) and you will likely be at a stable
  state.

  Also with regards to interrupting a proof attempt, sometimes the user
  may need to issue a :q and lp to reset properly the parallelism
  implementation to a stable state. The primary symptom that the user
  is experiencing this issue is that threads will continue to compute
  in the background, even though there should be no proof attempt in
  progress. The user can observe this symptom by examining the CPU
  utilization of their ACL2 process, for example on Linux/Unix with
  the shell process top. Lisp usage greater than a few percent is
  indicative of this problem.

  Because of how ACL2 [arrays] are designed, the user may find that, in
  practice, ACL2 arrays work (but perhaps with some
  [slow-array-warning] messages). However, we are aware of race
  conditions that can cause problems.

  Instead of dynamically monitoring rewrites, [dmr] instead dynamically
  outputs information helpful for debugging the performance of proof
  parallelism. The instructions concerning how to see this debugging
  information are the same as the instructions for enabling [dmr]
  mode.

  If you are working with LispWorks 6.0 or 6.0.1, then you may see
  messages about misaligned conses. The state of the system may be
  corrupted after such a message has been printed. This LispWorks bug
  is fixed in LispWorks 6.1.

  The waterfall parallelism mode :resource-and-timing-based is not
  fully supported when the host Lisp is other than CCL. It may work,
  but we have not attempted to address a potential race condition.

  Proof output for splitter rules (see [splitter]) is currently
  unsupported when waterfall-parallelism is enabled.

  Memoization may not work as intended when executing in parallel
  (including the waterfall). In an effort to be helpful to the user,
  the functions automatically memoized by ACL2 are unmemoized when
  setting waterfall parallelism to anything but nil. Those exact
  functions are again memoized once waterfall parallelism is
  disabled. Additionally, any functions memoized within the ACL2 loop
  (by a call of [memoize]) are also unmemoized when enabling
  waterfall parallelism and once again memoized when disabling
  waterfall parallelism. This is implemented by returning the
  memoization state to what it was before enabling waterfall
  parallelism. As such, the user should be aware that any changes
  made to the memoization state while waterfall parallelism is
  enabled will be lost once waterfall parallelism is disabled.")
 (UNTRACE$
  (TRACE)
  "Untrace functions

    Examples:
    (untrace$)         ; untrace all functions previously
                       ; traced (e.g. with trace$ or trace!)
    (untrace$ foo bar) ; as above, except only untrace foo and bar

    General Forms:
    (untrace$)                 ; untrace all (as noted above)
    (untrace$ fn1 fn2 ... fnk) ; untrace the indicated functions

  where the fni were previously traced (e.g. with [trace$] or
  [trace!]).

  Untrace$ undoes the effect of [trace$]. See [trace$]. The value
  returned by untrace$ gives the list of functions for which tracing
  is being removed.")
 (UNTRANS-TABLE
  (MACROS)
  "Associates a function symbol with a macro for printing user-level
  terms

    Examples:
    ACL2 !>(untrans-table (w state))
    ((BINARY-+ + . T)
     (BINARY-* * . T)
     (BINARY-APPEND APPEND . T)
     (BINARY-LOGAND LOGAND . T)
     (BINARY-LOGIOR LOGIOR . T)
     (BINARY-LOGXOR LOGXOR . T)
     (BINARY-LOGEQV LOGEQV . T)
     (BINARY-POR POR . T)
     (BINARY-PAND PAND . T))

  See [table] for a general discussion of tables.

  See [add-macro-fn] for a more general discussion of this [table] and
  for a way to associate a macro name with a function name in theory
  events.")
 (UNTRANSLATE (POINTERS)
              "See [user-defined-functions-table].")
 (UNTRANSLATE-PREPROCESS (POINTERS)
                         "See [user-defined-functions-table].")
 (UPDATE-NTH
  (LISTS ACL2-BUILT-INS)
  "Modify a list by putting the given value at the given position

  (Update-nth key val l) returns a list that is the same as the list l,
  except that the value at the 0-based position key (a natural
  number) is val.

  If key is an integer at least as large as the length of l, then l
  will be padded with the appropriate number of nil elements, as
  illustrated by the following example.

    ACL2 !>(update-nth 8 'z '(a b c d e))
    (A B C D E NIL NIL NIL Z)

  We have the following theorem.

    (implies (and (true-listp l)
                  (integerp key)
                  (<= 0 key))
             (equal (length (update-nth key val l))
                    (if (< key (length l))
                        (length l)
                      (+ 1 key))))

  The [guard] of update-nth requires that its first (position) argument
  is a natural number and its last (list) argument is a true list.

  Function: 

    (defun update-nth (key val l)
           (declare (xargs :guard (true-listp l))
                    (type (integer 0 *) key))
           (cond ((zp key) (cons val (cdr l)))
                 (t (cons (car l)
                          (update-nth (1- key) val (cdr l))))))


Subtopics

  [Nth-aliases-table]
      A [table] used to associate names for nth/update-nth printing")
 (UPDATE-NTH-ARRAY
  (STOBJ ACL2-BUILT-INS)
  "Update a stobj array

  Update-nth-array is called by [stobj] updaters to modify stobj array
  fields. See [stobj-example-3] for a discussion of this function and
  how it plays that role.

  Function: 

    (defun update-nth-array (j key val l)
           (declare (xargs :guard (and (integerp j)
                                       (integerp key)
                                       (<= 0 j)
                                       (<= 0 key)
                                       (true-listp l)
                                       (true-listp (nth j l)))))
           (update-nth j (update-nth key val (nth j l))
                       l))")
 (UPPER-CASE-P
  (CHARACTERS ACL2-BUILT-INS)
  "Recognizer for upper case characters

  (Upper-case-p x) is true if and only if x is an upper case character,
  i.e., a member of the list #\\A, #\\B, ..., #\\Z.

  The [guard] for upper-case-p requires its argument to be a standard
  character (see [standard-char-p]).

  Upper-case-p is a Common Lisp function. See any Common Lisp
  documentation for more information.

  Function: 

    (defun upper-case-p (x)
           (declare (xargs :guard (and (characterp x)
                                       (standard-char-p x))))
           (and (member x
                        '(#\\A #\\B #\\C #\\D #\\E #\\F #\\G
                              #\\H #\\I #\\J #\\K #\\L #\\M #\\N #\\O #\\P #\\Q
                              #\\R #\\S #\\T #\\U #\\V #\\W #\\X #\\Y #\\Z))
                t))")
 (USE (POINTERS)
      "See [hints] for keyword :use.")
 (USER-DEFINED-FUNCTIONS-TABLE
  (MACROS)
  "An advanced [table] used to replace certain system functions

    Examples:
    (table user-defined-functions-table 'untranslate-preprocess 'my-preprocess)
    (table user-defined-functions-table 'untranslate 'my-untranslate)

  This feature should perhaps only be used by advanced users who have a
  thorough understanding of the system functions being replaced.
  There are currently two ways a user can affect the way ACL2 prints
  terms.

  The first example associates the user-defined function symbol
  my-preprocess with untranslate-preprocess. As a result, when ACL2
  prints a term, say during a proof, using its so-called
  ``untranslate'' process the first thing it does is to call
  my-preprocess on two arguments: that term and the current ACL2
  logical [world]. If the call produces a non-nil result, then that
  result is passed to the untranslate process.

  The second example associates the user-defined function symbol
  my-untranslate with the built-in function symbol untranslate. As a
  result, the code for my-untranslate will be run whenever the
  untranslate process is run. The formals of the two functions must
  agree and must not contain any [stobj] names. Note that these
  overrides fail to occur upon guard violations and some other
  evaluation errors.

  The untranslate-preprocess approach may suffice for most cases in
  which a user wants to modify the way output is produced by the
  theorem prover. We present an example immediately below, but see
  [untranslate-patterns] for a more elaborate example. If the
  untranslate-preprocess approach does not seem sufficient for your
  purposes, you are invited to look at community book
  books/misc/rtl-untranslate.lisp or the source code for [define] for
  an example of user-defined untranslate (i.e., following the second
  example displayed above).

  Suppose you have a large constant that you would prefer not to see in
  proofs. For example, you may have submitted the following
  definition (but imagine a much larger constant, say, a list of
  length 1,000,000).

    (defconst *a* '(a b c d))

  If you submit the following (silly) theorem

    (thm (equal (cons x *a*) (car (cons yyy zzz))))

  then you will see the following output:

    (EQUAL (CONS X '(A B C D)) YYY).

  If *a* had represented a much larger structure, we would wish we
  could see the following instead.

    (EQUAL (CONS X *A*) YYY)

  That can be accomplished as follows. First we make the following
  definition.

    (defun my-preprocess (term wrld)
      (declare (ignore wrld))
      (if (equal term (list 'quote *a*))
          '*a*
        nil))

  Now we submit the following [table] event.

    (table user-defined-functions-table
           'untranslate-preprocess
           'my-preprocess)

  This will install my-preprocess as a preprocessor before the normal
  untranslation routine is applied to printing a term. When the
  untranslation routine encounters the constant (QUOTE (A B C D)), it
  will replace it with *a*, and the usual untranlation routine will
  print this as *A*.")
 (USING-COMPUTED-HINTS
  (HINTS)
  "How to use computed hints

  Computed hints (see [computed-hints]) are extraordinarily powerful.
  We show a few examples here to illustrate their use. We recommend
  that the using-computed-hints-n topics be read in the order
  using-computed-hints-1, using-computed-hints-2, and so on.


Subtopics

  [Using-computed-hints-1]
      Driving Home the Basics

  [Using-computed-hints-2]
      One Hint to Every Top-Level Goal in a Forcing Round

  [Using-computed-hints-3]
      Hints as a Function of the Goal (not its Name)

  [Using-computed-hints-4]
      Computing the Hints

  [Using-computed-hints-5]
      Debugging Computed Hints

  [Using-computed-hints-6]
      Using the computed-hint-replacement feature

  [Using-computed-hints-7]
      Using the stable-under-simplificationp flag

  [Using-computed-hints-8]
      Some Final Comments")
 (USING-COMPUTED-HINTS-1
  (USING-COMPUTED-HINTS)
  "Driving Home the Basics

  The common hint

    (\"Subgoal 3.2.1''\" :use lemma42)

  has the same effect as the computed hint

    (if (equal id '((0) (3 2 1) . 2))
        '(:use lemma42)
        nil)

  which, of course, is equivalent to

    (and (equal id '((0) (3 2 1) . 2))
         '(:use lemma42))

  which is also equivalent to the computed hint

    my-special-hint

  provided the following defun has first been executed

    (defun my-special-hint (id clause world)
      (declare (xargs :mode :program)
               (ignore clause world))
      (if (equal id '((0) (3 2 1) . 2))
          '(:use lemma42)
          nil))

  It is permitted for the defun to be in :LOGIC mode (see [defun-mode])
  also.

  Just to be concrete, the following three events all behave the same
  way (if my-special-hint is as above):

    (defthm main (big-thm a b c)
      :hints ((\"Subgoal 3.2.1''\" :use lemma42)))

    (defthm main (big-thm a b c)
      :hints ((and (equal id '((0) (3 2 1) . 2)) '(:use lemma42))))

    (defthm main (big-thm a b c)
      :hints (my-special-hint))")
 (USING-COMPUTED-HINTS-2
  (USING-COMPUTED-HINTS)
  "One Hint to Every Top-Level Goal in a Forcing Round

  Suppose the main proof completes with a forcing round on three
  subgoals, \"[1]Subgoal 3\", \"[1]Subgoal 2\", and \"[1]Subgoal 1\".
  Suppose you wish to :use lemma42 in all top-level goals of the
  first forcing round. This can be done supplying the hint

    (if test '(:use lemma42) nil),

  where test is an expression that returns t when ID is one of the
  clause ids in question.

        goal-spec     (parse-clause-id goal-spec)

    \"[1]Subgoal 3\"        ((1) (3) . 0)
    \"[1]Subgoal 2\"        ((1) (2) . 0)
    \"[1]Subgoal 1\"        ((1) (1) . 0)

  Recall (see [clause-identifier]) that parse-clause-id maps from a
  goal spec to a clause id, so you can use that function on the goal
  specs printed in the failed proof attempt to determine the clause
  ids in question.

  So one acceptable test is

    (member-equal id '(((1) (3) . 0)
                       ((1) (2) . 0)
                       ((1) (1) . 0)))

  or you could use parse-clause-id in your computed hint if you don't
  want to see clause ids in your script:

    (or (equal id (parse-clause-id \"[1]Subgoal 3\"))
        (equal id (parse-clause-id \"[1]Subgoal 2\"))
        (equal id (parse-clause-id \"[1]Subgoal 1\")))

  or you could use the inverse function (see [clause-identifier]):

    (member-equal (string-for-tilde-@-clause-id-phrase id)
                  '(\"[1]Subgoal 3\"
                    \"[1]Subgoal 2\"
                    \"[1]Subgoal 1\"))

  Recall that what we've shown above are the tests to use in the
  computed hint. The hint itself is (if test '(:use lemma42) nil) or
  something equivalent like (and test '(:use lemma42)).

  The three tests above are all equivalent. They suffer from the
  problem of requiring the explicit enumeration of all the goal specs
  in the first forcing round. A change in the script might cause more
  forced subgoals and the ones other than those enumerated would not
  be given the hint.

  You could write a test that recognizes all first round top-level
  subgoals no matter how many there are. Just think of the
  programming problem: how do I recognize all the clause id's of the
  form ((1) (n) . 0)? Often you can come to this formulation of the
  problem by using parse-clause-id on a few of the candidate
  goal-specs to see the common structure. A suitable test in this
  case is:

    (and (equal (car id) '(1))     ; forcing round 1, top-level (pre-induction)
         (equal (len (cadr id)) 1) ; Subgoal n (not Subgoal n.i ...)
         (equal (cddr id) 0))      ; no primes

  The test above is ``overkill'' because it recognizes precisely the
  clause ids in question. But recall that once a computed hint is
  used, it is (by default) removed from the hints available to the
  children of the clause. Thus, we can widen the set of clause ids
  recognized to include all the children without worrying that the
  hint will be applied to those children.

  In particular, the following test supplies the hint to every
  top-level goal of the first forcing round:

    (equal (car id) '(1))

  You might worry that it would also supply the hint to the subgoal
  produced by the hint -- the cases we ruled out by the ``overkill''
  above. But that doesn't happen since the hint is unavailable to the
  children. You could even write:

    (equal (car (car id)) 1)

  which would supply the hint to every goal of the form \"[1]Subgoal
  ...\" and again, because we see and fire on the top-level goals
  first, we will not fire on, say, \"[1]Subgoal *1.3/2\", i.e., the id
  '((1 1 3) (2) . 0) even though the test recognizes that id.

  Finally, the following test supplies the hint to every top-level goal
  of every forcing round (except the 0th, which is the ``gist'' of
  the proof, not ``really'' a forcing round):

    (not (equal (car (car id)) 0))

  Recall again that in all the examples above we have exhibited the
  test in a computed hint of the form (if test '(:key1 val1 ...)
  nil).")
 (USING-COMPUTED-HINTS-3
  (USING-COMPUTED-HINTS)
  "Hints as a Function of the Goal (not its Name)

  Sometimes it is desirable to supply a hint whenever a certain term
  arises in a conjecture. For example, suppose we have proved

    (defthm all-swaps-have-the-property
       (the-property (swap x))
       :rule-classes nil)

  and suppose that whenever (SWAP A) occurs in a goal, we wish to add
  the additional hypothesis that (THE-PROPERTY (SWAP A)). Note that
  this is equivalent supplying the hint

    (if test
        '(:use (:instance all-swaps-have-the-property (x A)))
        nil)

  where test answers the question ``does the clause contain (SWAP A)?''
  That question can be asked with (occur-lst '(SWAP A) clause).
  Briefly, occur-lst takes the representation of a translated term,
  x, and a list of translated terms, y, and determines whether x
  occurs as a subterm of any term in y. (By ``subterm'' here we mean
  proper or improper, e.g., the subterms of (CAR X) are X and (CAR
  X).)

  Thus, the computed hint:

    (if (occur-lst '(swap a) clause)
        '(:use (:instance all-swaps-have-the-property (x A)))
        nil)

  will add the hypothesis (THE-PROPERTY (SWAP A)) to every goal
  containing (SWAP A) -- except the children of goals to which the
  hypothesis was added.

  A COMMON MISTAKE users are likely to make is to forget that they are
  dealing with translated terms. For example, suppose we wished to
  look for (SWAP (LIST 1 A)) with occur-lst. We would never find it
  with

    (occur-lst '(SWAP (LIST 1 A)) clause)

  because that presentation of the term contains macros and other
  abbreviations. By using :trans (see [trans]) we can obtain the
  translation of the target term. Then we can look for it with:

    (occur-lst '(SWAP (CONS '1 (CONS A 'NIL))) clause)

  Note in particular that you must

    * eliminate all macros and
    * explicitly quote all constants.

  We recommend using :trans to obtain the translated form of the terms
  in which you are interested, before programming your hints.

  An alternative is to use the expression (prettyify-clause clause nil
  nil) in your hint to convert the current goal clause into the
  s-expression that is actually printed. For example, the clause

    ((NOT (CONSP X)) (SYMBOLP Y) (EQUAL (CONS '1 (CAR X)) Y))

  ``prettyifies'' to

    (IMPLIES (AND (CONSP X)
                  (NOT (SYMBOLP Y)))
             (EQUAL (CONS 1 (CAR X)) Y))

  which is what you would see printed by ACL2 when the goal clause is
  that shown.

  However, if you choose to convert your clauses to prettyified form,
  you will have to write your own explorers (like our occur-lst),
  because all of the ACL2 term processing utilities work on
  translated and/or clausal forms. This should not be taken as a
  terrible burden. You will, at least, gain the benefit of knowing
  what you are really looking for, because your explorers will be
  looking at exactly the s-expressions you see at your terminal. And
  you won't have to wade through our still undocumented term/clause
  utilities. The approach will slow things down a little, since you
  will be paying the price of independently consing up the
  prettyified term.

  We make one more note on this example. We said above that the
  computed hint:

    (if (occur-lst '(swap a) clause)
        '(:use (:instance all-swaps-have-the-property (x A)))
        nil)

  will add the hypothesis (THE-PROPERTY (SWAP A)) to every goal
  containing (SWAP A) -- except the children of goals to which the
  hypothesis was added.

  It bears noting that the subgoals produced by induction and top-level
  forcing round goals are not children. For example, suppose the hint
  above fires on \"Subgoal 3\" and produces, say, \"Subgoal 3'\". Then
  the hint will not fire on \"Subgoal 3'\" even though it (still)
  contains (SWAP A) because \"Subgoal 3'\" is a child of a goal on
  which the hint fired.

  But now suppose that \"Subgoal 3'\" is pushed for induction. Then the
  goals created by that induction, i.e., the base case and induction
  step, are not considered children of \"Subgoal 3'\". All of the
  original hints are available.

  Alternatively, suppose that \"Subgoal 3' is proved but forces some
  other subgoal, \"[1]Subgoal 1\" which is attacked in Forcing Round 1.
  That top-level forced subgoal is not a child. All the original
  hints are available to it. Thus, if it contains (SWAP A), the hint
  will fire and supply the hypothesis, producing \"[1]Subgoal 1'\".
  This may be unnecessary, as the hypothesis might already be present
  in \"[1]Subgoal 1\". In this case, no harm is done. The hint won't
  fire on \"[1]Subgoal 1\" because it is a child of \"[1]Subgoal 1\" and
  the hint fired on that.")
 (USING-COMPUTED-HINTS-4
  (USING-COMPUTED-HINTS)
  "Computing the Hints

  So far we have used computed hints only to compute when a fixed set
  of keys and values are to be used as a hint. But computed hints
  can, of course, compute the set of keys and values. You might, for
  example, write a hint that recognizes when a clause ``ought'' to be
  provable by a :BDD hint and generate the appropriate hint. You
  might build in a set of useful lemmas and check to see if the
  clause is provable :BY one of them. You can keep all function
  symbols disabled and use computed hints to compute which ones you
  want to :EXPAND. In general, you can write a theorem prover for use
  in your hints, provided you can get it to do its job by directing
  our theorem prover.

  Suppose for example we wish to find every occurrence of an instance
  of (SWAP x) and provide the corresponding instance of
  ALL-SWAPS-HAVE-THE-PROPERTY. Obviously, we must explore the clause
  looking for instances of (SWAP x) and build the appropriate
  instances of the lemma. We could do this in many different ways,
  but below we show a general purpose set of utilities for doing it.
  The functions are not defined in ACL2 but could be defined as
  shown.

  Our plan is: (1) Find all instances of a given pattern (term) in a
  clause, obtaining a set of substitutions. (2) Build a set of
  :instance expressions for a given lemma name and set of
  substitutions. (3) Generate a :use hint for those instances when
  instances are found.

  The pair of functions below find all instances of a given pattern
  term in either a term or a list of terms. The functions each return
  a list of substitutions, each substitution accounting for one of
  the matches of pat to a subterm. At this level in ACL2
  substitutions are lists of pairs of the form (var . term). All
  terms mentioned here are presumed to be in translated form.

  The functions take as their third argument a list of substitutions
  accumulated to date and add to it the substitutions produced by
  matching pat to the subterms of the term. We intend this
  accumulator to be nil initially. If the returned value is nil, then
  no instances of pat occurred.

    (mutual-recursion

    (defun find-all-instances (pat term alists)
     (declare (xargs :mode :program))
     (mv-let
      (instancep alist)
      (one-way-unify pat term)
      (let ((alists (if instancep (add-to-set-equal alist alists) alists)))
        (cond
         ((variablep term) alists)
         ((fquotep term) alists)
         (t (find-all-instances-list pat (fargs term) alists))))))

    (defun find-all-instances-list (pat list-of-terms alists)
     (declare (xargs :mode :program))
     (cond
      ((null list-of-terms) alists)
      (t (find-all-instances pat
                             (car list-of-terms)
                             (find-all-instances-list pat
                                                      (cdr list-of-terms)
                                                      alists))))))

  Caveat: The following aside has nothing to do with computed hints.
  Does an instance of (CAR (CDR x)) occur in ((LAMBDA (V) (CAR V))
  (CDR A))? It does if one beta-reduces the lambda-expression to (CAR
  (CDR A)); the appropriate substitution is to replace x by A. But
  the definition of find-all-instances above does not find this
  instance because it does not do beta-reduction.

  We now turn our attention to converting a list of substitutions into
  a list of lemma instances, each of the form

    (:INSTANCE name (var1 term1) ... (vark termk))

  as written in :use hints. In the code shown above, substitutions are
  lists of pairs of the form (var . term), but in lemma instances we
  must write ``doublets.'' So here we show how to convert from one to
  the other:

    (defun pairs-to-doublets (alist)
      (declare (xargs :mode :program))
      (cond ((null alist) nil)
            (t (cons (list (caar alist) (cdar alist))
                     (pairs-to-doublets (cdr alist))))))

  Now we can make a list of lemma instances:

    (defun make-lemma-instances (name alists)
      (declare (xargs :mode :program))
      (cond
       ((null alists) nil)
       (t (cons (list* :instance name (pairs-to-doublets (car alists)))
                (make-lemma-instances name (cdr alists))))))

  Finally, we can package it all together into a hint function. The
  function takes a pattern, pat, which must be a translated term, the
  name of a lemma, name, and a clause. If some instances of pat occur
  in clause, then the corresponding instances of name are :USEd in
  the computed hint. Otherwise, the hint does not apply.

    (defun add-corresponding-instances (pat name clause)
      (declare (xargs :mode :program))
      (let ((alists (find-all-instances-list pat clause nil)))
        (cond
         ((null alists) nil)
         (t (list :use (make-lemma-instances name alists))))))

  The design of this particular hint function makes it important that
  the variables of the pattern be the variables of the named lemma
  and that all of the variables we wish to instantiate occur in the
  pattern. We could, of course, redesign it to allow ``free
  variables'' or some sort of renaming.

  We could now use this hint as shown below:

    (defthm ... ...
      :hints ((add-corresponding-instances
               '(SWAP x)
               'ALL-SWAPS-HAVE-THE-PROPERTY
               clause)))

  The effect of the hint above is that any time a clause arises in
  which any instance of (SWAP x) appears, we add the corresponding
  instance of ALL-SWAPS-HAVE-THE-PROPERTY. So for example, if Subgoal
  *1/3.5 contains the subterm (SWAP (SWAP A)) then this hint fires
  and makes the system behave as though the hint:

    (\"Subgoal *1/3.5\"
     :USE ((:INSTANCE ALL-SWAPS-HAVE-THE-PROPERTY (X A))
           (:INSTANCE ALL-SWAPS-HAVE-THE-PROPERTY (X (SWAP A)))))

  had been present.")
 (USING-COMPUTED-HINTS-5
  (USING-COMPUTED-HINTS)
  "Debugging Computed Hints

  We have found that it is sometimes helpful to define hints so that
  they print out messages to the terminal when they fire, so you can
  see what hint was generated and which of your computed hints did
  it.

  To that end we have defined a macro we sometimes use. Suppose you
  have a :hints specification such as:

    :hints (computed-hint-fn (hint-expr id))

  If you defmacro the macro below you could then write instead:

    :hints ((show-hint computed-hint-fn 1)
            (show-hint (hint-expr id) 2))

  with the effect that whenever either hint is fired (i.e., returns
  non-nil), a message identifying the hint by the marker (1 or 2,
  above) and the non-nil value is printed.

    (defmacro show-hint (hint &optional marker)
      (cond
       ((and (consp hint)
             (stringp (car hint)))
        hint)
       (t
        `(let ((marker ,marker)
               (ans ,(if (symbolp hint)
                         `(,hint id clause world stable-under-simplificationp)
                       hint)))
           (if ans
               (prog2$
                (cw \"~%***** Computed Hint~#0~[~/ (from hint ~x1)~]~%~x2~%~%\"
                    (if (null marker) 0 1)
                    marker
                    (cons (string-for-tilde-@-clause-id-phrase id)
                          ans))
                ans)
             nil)))))

  Note that when show-hint is applied to a hint that is a symbol, e.g.,
  computed-hint-fn, it applies the symbol to the four computed-hint
  arguments: id, clause, world, and stable-under-simplificationp. If
  computed-hint-fn is of arity 3 the code above would cause an error.
  One way to avoid it is to write

    :hints ((show-hints (computed-hint-fn id clause world) 1)
            (show-hint (hint-expr id) 2)).

  If you only use computed hints of arity 3, you might eliminate the
  occurrence of stable-under-simplificationp in the definition of
  show-hint above.

  Putting a show-hint around a common hint has no effect. If you find
  yourself using this utility let us know and we'll consider putting
  it into the system itself. But it does illustrate that you can use
  computed hints to do unusual things.")
 (USING-COMPUTED-HINTS-6
  (USING-COMPUTED-HINTS)
  "Using the computed-hint-replacement feature

  So far none of our computed hints have used the
  :COMPUTED-HINT-REPLACEMENT feature. We now illustrate that.

  The :computed-hint-replacement feature can easily lead to loops. So
  as you experiment with the examples in this section and your own
  hints using this feature, be ready to interrupt the theorem prover
  and abort!

  A non-looping use of the :computed-hint-replacement feature would be
  a hint like this:

    (if (certain-terms-present clause)
        '(:computed-hint-replacement t
          :in-theory (enable lemma25))
        '(:computed-hint-replacement t
          :in-theory (disable lemma25)))

  In this hint, if certain terms are present in clause, as determined
  by the function with the obvious name (here undefined), then this
  hint enables lemma25 and otherwise disables it. Lemma25 might be a
  very expensive lemma, e.g., one that matches frequently and has an
  expensive and rarely established hypothesis. One might wish it
  enabled only under certain conditions. Recall that theories are
  inherited by children. So once lemma25 is enabled it ``stays''
  enabled for the children, until disabled; and vice versa. If the
  :computed-hint-replacement feature were not present and computed
  hints were always deleted after they had been used, then lemma25
  would be left enabled (or disabled) for all the childen produced by
  the first firing of the hint. But with the arrangement here, every
  subgoal gets a theory deemed suitable by the hint, and the hint
  persists.

  Now we will set up a toy to allow us to play with computed hints to
  understand them more deeply. To follow the discussion it is best to
  execute the following events.

    (defstub wrapper (x) t)
    (defaxiom wrapper-axiom (wrapper x) :rule-classes nil)

  Now submit the following event and watch what happens.

    (thm (equal u v)
      :hints (`(:use (:instance wrapper-axiom (x a)))))

  The theorem prover adds (wrapper a) to the goal and then abandons the
  proof attempt because it cannot prove the subgoal. Since the
  computed hint is deleted upon use, the hint is not applied to the
  subgoal (i.e., the child of the goal).

  What happens if we do the following?

    (thm (equal u v)
      :hints (`(:computed-hint-replacement t
                :use (:instance wrapper-axiom (x a)))))

  As one might expect, this loops forever: The hint is applied to the
  child and adds the hypothesis again. When the hint fires, nothing
  is actually changed, since (wrapper a) is already in the subgoal.

  So let's change the experiment a little. Let's make the hint add the
  hypothesis (wrapper p) where p is the first literal of the clause.
  This is silly but it allows us to explore the behavior of computed
  hints a little more.

    (thm (equal u v)
      :hints (`(:use (:instance wrapper-axiom (x ,(car clause))))))

  So in this case, the theorem prover changes the goal to

    (IMPLIES (WRAPPER (EQUAL U V)) (EQUAL U V))

  which then simplifies to

    (IMPLIES (WRAPPER NIL) (EQUAL U V))

  because the concluding equality can be assumed false in the
  hypothesis (e.g., think of the contrapositive version). Nothing
  else happens because the hint has been removed and so is not
  applicable to the child.

  Now consider the following -- and be ready to interrupt it and abort!

    (thm (equal u v)
      :hints (`(:computed-hint-replacement t
                :use (:instance wrapper-axiom (x ,(car clause))))))

  This time the hint is not removed and so is applied to the child. So
  from Goal we get

    Goal'
    (IMPLIES (WRAPPER (EQUAL U V))
             (EQUAL U V))

  and then

    Goal''
    (IMPLIES (AND (WRAPPER (NOT (WRAPPER (EQUAL U V))))
                  (WRAPPER (EQUAL U V)))
             (EQUAL U V))

  etc.

  First, note that the hint is repeatedly applied to its children. That
  is because we wrote :computed-hint-replacement t. But second, note
  that Goal' is not even being simplified before Goal'' is produced
  from it. If it were being simplified, the (equal u v)'s in the
  hypotheses would be replaced by nil. This is a feature. It means
  after a computed hint has fired, other hints are given a chance at
  the result, even the hint itself unless it is removed from the list
  of hints.

  As an exercise, let's arrange for the hint to stay around and be
  applied indefinitely but with a simplification between each use of
  the the hint. To do this we need to pass information from one
  application of the hint to the next, essentially to say ``stay
  around but don't fire.''

  First, we will define a function to use in the hint. This is more
  than a mere convenience; it allows the hint to ``reproduce itself''
  in the replacement.

    (defun wrapper-challenge (clause parity)
      (if parity
          `(:computed-hint-replacement ((wrapper-challenge clause nil))
            :use (:instance wrapper-axiom (x ,(car clause))))
          `(:computed-hint-replacement ((wrapper-challenge clause t)))))

  Note that this function is not recursive, even though it uses its own
  name. That is because the occurrence of its name is in a quoted
  constant.

  Now consider the following. What will it do?

    (thm (equal u v)
      :hints ((wrapper-challenge clause t)))

  First, observe that this is a legal hint because it is a term that
  mentions only the free variable CLAUSE. When defining hint
  functions you may sometimes think their only arguments are the four
  variables id, clause, world, and stable-under-simplificationp. That
  is not so. But in your hints you must call those functions so that
  those are the only free variables. Note also that the occurrence of
  clause inside the :computed-hint-replacement is not an occurrence
  of the variable clause but just a constant. Just store this note
  away for a moment. We'll return to it momentarily.

  Second, the basic cleverness of this hint is that every time it fires
  it reproduces itself with the opposite parity. When the parity is t
  it actually changes the goal by adding a hypothesis. When the
  parity is nil it doesn't change the goal and so allows
  simplification to proceed -- but it swaps the parity back to t.
  What you can see with this simple toy is that we can use the
  computed hints to pass information from parent to child.

  Ok, so what happens when the event above is executed? Try it. You
  will see that ACL2 applied the hint the first time. It doesn't get
  around to printing the output because an error is caused before it
  can print. But here is a blow-by-blow description of what happens.
  The hint is evaluated on Goal with the clause ((equal u v)). It
  produces a hint exactly as though we had typed:

    (\"Goal\" :use (:instance wrapper-axiom (x (equal u v))))

  which is applied to this goal. In addition, it produces the new hints
  argument

    :hints ((wrapper-challenge clause nil)).

  By applying the \"Goal\" hint we get the new subgoal

    Goal'
    (implies (wrapper (equal u v))
             (equal u v))

  but this is not printed because, before printing it, the theorem
  prover looks for hints to apply to it and finds

    (wrapper-challenge clause nil)

  That is evaluated and produces a hint exactly as though we had typed:

    (\"Goal'\" )

  and the new hints argument:

    :hints ((wrapper-challenge clause nil)).

  But if you supply the hint (\"Goal'\" ), ACL2 will signal an error
  because it does not allow you to specify an empty hint!

  So the definition of wrapper-challenge above is almost correct but
  fatally flawed. We need a non-empty ``no-op'' hint. One such hint
  is to tell the system to expand a term that will always be expanded
  anyway. So undo wrapper-challenge, redefine it, and try the proof
  again. Now remember the observation about clause that we asked you
  to ``store'' above. The new definition of wrapper-challenge
  illustrates what we meant. Note that the first formal parameter of
  wrapper-challenge, below, is no longer named clause but is called
  cl instead. But the ``call'' of wrapper-challenge in the
  replacements is on clause. This may seem to violate the rule that a
  function definition cannot use variables other than the formals.
  But the occurrences of clause below are not variables but constants
  in an object that will eventually be treated as hint term.

    :ubt wrapper-challenge

    (defun wrapper-challenge (cl parity)
      (if parity
          `(:computed-hint-replacement ((wrapper-challenge clause nil))
            :use (:instance wrapper-axiom (x ,(car cl))))
          `(:computed-hint-replacement ((wrapper-challenge clause t))
            :expand ((atom zzz)))))

    (thm (equal u v)
      :hints ((wrapper-challenge clause t)))

  This time, things go as you might have expected! Goal' is produced
  and simplified, to

    Goal''
    (implies (wrapper nil)
             (equal u v)).

  Simplification gets a chance because when the new hint
  (wrapper-challenge clause nil) is fired it does not change the
  goal. But it does change the parity in the hints argument so that
  before Goal'' is simplified again, the hint fires and adds the
  hypothesis:

    Goal'''
    (IMPLIES (AND (WRAPPER (NOT (WRAPPER NIL)))
                  (WRAPPER NIL))
             (EQUAL U V)).

  This simplifies, replacing the first (NOT (WRAPPER NIL)) by NIL,
  since (WRAPPER NIL) is known to be true here. Thus the goal
  simplifies to

    Goal'4'
    (IMPLIES (WRAPPER NIL) (EQUAL U V)).

  The process repeats indefinitely.

  So we succeeded in getting a hint to fire indefinitely but allow a
  full simplification between rounds.")
 (USING-COMPUTED-HINTS-7
  (USING-COMPUTED-HINTS)
  "Using the stable-under-simplificationp flag

  A problem with the example in [using-computed-hints-6] is that
  exactly one simplification occurs between each (effective) firing
  of the hint. Much more commonly we wish to fire a hint once a
  subgoal has become stable under simplification.

  A classic example of this is when we are dealing with an interpreter
  for some state machine. We typically do not want the ``step''
  function to open up on the symbolic representation of a state until
  that state has been maximally simplified. We will illustrate with a
  simple state machine.

  Let us start by defining the step function, stp, and the
  corresponding run function that applies it a given number of times.

    (defun stp (s)
      (+ 1 s))

    (defun run (s n)
      (if (zp n)
          s
          (run (stp s) (- n 1))))

  The step function here is trivial: a state is just a number and the
  step function increments it. In this example we will not be
  interested in the theorems we prove but in how we prove them. The
  formula we will focus on is

    (thm (equal (run s 7) xxx))

  This is not a theorem, of course. But we want to test our advice on
  non-theorems because we do not want the advice to work only for
  proofs that succeed. (In the past, we gave advice about using
  computed hints and that advice caused the theorem prover to run
  forever when given formulas that it couldn't prove -- but most of
  the time the system is presented with formulas it cannot prove!)

  Furthermore, without some kind of additional rules, the (run s 7)
  expression in the conjecture above will not expand at all, because
  ACL2's heuristics do not approve.

  In fact, we do not want to take chances that run will be expanded --
  we want to control its expansion completely. Therefore, disable
  run.

    (in-theory (disable run))

  Now, what do we want? (That is always a good question to ask!) We
  want (run s 7) to expand ``slowly.'' In particular, we want it to
  expand once, to (run (stp s) 6). Then we want the stp to be
  expanded and fully simplified before the run expression is expanded
  again. That is, we want to force the expansion of run whenever the
  goal is stable under simplification. This is sometimes called
  ``staged simplification.''

  We can achieve staged simplification for any given function symbol by
  defining the functions shown below and then using a simple computed
  hint:

    (thm (equal (run s 7) xxx)
         :hints ((stage run)))

  By inspecting how stage is defined you can see how to extend it, but
  we explain as we go. To experiment, you can just paste the
  definitions (and defmacro) below into your ACL2 shell and then try
  the thm command.

  First, define this pair of mutually recursive functions.
  Find-first-call finds the first call of the function symbol fn in a
  given term.

    (mutual-recursion
     (defun find-first-call (fn term)
     ; Find the first call of fn in term.
      (cond ((variablep term) nil)
            ((fquotep term) nil)
            ((equal (ffn-symb term) fn)
             term)
            (t (find-first-call-lst fn (fargs term)))))
     (defun find-first-call-lst (fn lst)
     ; Find the first call of fn in a list of terms.
      (cond ((endp lst) nil)
            (t (or (find-first-call fn (car lst))
                   (find-first-call-lst fn (cdr lst)))))))

  We will arrange for the computed hint to generate an :EXPAND hint for
  the first call of fn, whenever the goal becomes stable under
  simplification. If no call is found, the hint will do nothing. To
  make sure the hint will not loop indefinitely (for example, by
  forcing fn to expand only to have the rewriter ``fold'' it back up
  again), we will provide the hint with a bound that stops it after
  some number of iterations. Here is the basic function that creates
  the expand hint and replaces itself to count down.

    (defun stage1 (fn max clause flg)
    ; If the clause is stable under simplification and there is a call of
    ; fn in it, expand it.  But don't do it more than max times.
     (let ((temp (and flg
                      (find-first-call-lst fn clause))))
       (if temp
           (if (zp max)
               (cw \"~%~%HINT PROBLEM:  The maximum repetition count of ~
                    your STAGE hint been reached without eliminating ~
                    all of the calls of ~x0.  You could supply a larger ~
                    count with the optional second argument to STAGE ~
                    (which defaults to 100).  But think about what is ~
                    happening! Is each stage permanently eliminating a ~
                    call of ~x0?~%~%\"
                   fn)
             `(:computed-hint-replacement
                ((stage1 ',fn ,(- max 1)
                         clause
                         stable-under-simplificationp))
               :expand (,temp)))
         nil)))

  Suppose that when stage1 is called, fn is the function we want to
  expand, max is the maximum number of iterations of this expansion,
  clause is the current goal clause, and flg is the value of the
  stable-under-simplificationp flag. Then if clause is stable and we
  can find a call of fn in it, we ask whether max is exhausted. If
  so, we print an ``error message'' to the comment window with [cw]
  and return nil (the value of cw). That nil means the hint does
  nothing. But if max is not yet exhausted, we return a new hint. As
  you can see above, the hint replaces itself with another stage1
  hint with the same fn and a decremented max to be applied to the
  new clause and the then-current value of
  stable-under-simplificationp. The hint also contains an :expand
  directive for the call of fn found.

  Thus, if the computed hint was:

    (stage1 'run 5 clause stable-under-simplificationp)

  and (run s 7) occurs in the clause, then it will generate

    (:computed-hint-replacement
      ((stage1 'run 4 clause stable-under-simplificationp))
     :expand ((run s 7)))

  which will in turn replace the old stage1 hint with the new one and
  will apply :expand ((run s 7)) to the current goal.

  We can make this more convenient by defining the macro:

    (defmacro stage (fn &optional (max '100))
     `(stage1 ',fn ,max clause stable-under-simplificationp))

  Note that the macro allows us to either provide the maximum bound or
  let it default to 100.

  Henceforth, we can type

    (thm (equal (run s 7) xxx)
         :hints ((stage run)))

  to stage the opening of run up to 100 times, or we can write

    (thm (equal (run s 7) xxx)
         :hints ((stage run 5)))

  to stage it only 5 times. In the latter example, the system with
  print a ``error message'' after the fifth expansion.

  Note that if we executed

    (set-default-hints '((stage run)))

  then we could attack all theorems (involving run) with staged
  simplification (up to bound 100), without typing an explicit hint.

    (thm (equal (run s 7) xxx))

  Using techniques similar to those above we have implemented
  ``priority phased simplification'' and provided it as a book. See
  community book books/misc/priorities.lisp. This is an idea
  suggested by Pete Manolios, by which priorities may be assigned to
  rules and then the simplifier simplifies each subgoal maximally
  under the rules of a given priority before enabling the rules of
  the next priority level. The book above documents both how we
  implement it with computed hints and how to use it.

  Here is another example of using the stable-under-simplificationp
  flag to delay certain actions. It defines a default hint, see
  [default-hints], which will enable [non-linear-arithmetic] on
  precisely those goals which are stable-under-simplificationp. It
  also uses the HISTORY and PSPV variables to determine when toggling
  [non-linear-arithmetic] is appropriate. These variables are
  documented only in the source code. If you start using these
  variables extensively, please contact the developers of ACL2 or
  Robert Krug (rkrug@cs.utexas.edu) and let us know how we can help.

    (defun nonlinearp-default-hint (stable-under-simplificationp hist pspv)
      (cond (stable-under-simplificationp
             (if (not (access rewrite-constant
                              (access prove-spec-var pspv :rewrite-constant)
                              :nonlinearp))
                 '(:computed-hint-replacement t
                   :nonlinearp t)
               nil))
            ((access rewrite-constant
                     (access prove-spec-var pspv :rewrite-constant)
                     :nonlinearp)
             (if (not (equal (caar hist) 'SETTLED-DOWN-CLAUSE))
                 '(:computed-hint-replacement t
                   :nonlinearp nil)
               nil))
            (t
             nil)))")
 (USING-COMPUTED-HINTS-8
  (USING-COMPUTED-HINTS)
  "Some Final Comments

  None of the examples show the use of the variable WORLD, which is
  allowed in computed hints. There are some (undocumented) ACL2
  utilities that might be useful in programming hints, but these
  utilities need access to the ACL2 logical world (see [world]).

  A very useful fact to know is that (table-alist name world) returns
  an alist representation of the current value of the [table] named
  name.

  The ACL2 source code is littered with :[program] mode functions for
  manipulating world. In our source code, the world is usually bound
  a variable named wrld; so searching our code for that name might be
  helpful.

  Using these utilities to look at the WORLD one can, for example,
  determine whether a symbol is defined recursively or not, get the
  body and formals of a defined function, or fetch the statement of a
  given lemma. Because these utilities are not yet documented, we do
  not expect users to employ WORLD in computed hints. But experts
  might and it might lead to the formulation of a more convenient
  language for computed hints.

  None of our examples illustrated the 7 argument form of a computed
  hint, (fn ID CLAUSE WORLD STABLE-UNDER-SIMPLIFICATIONP HIST PSPV
  CTX). When used, the variables HIST, PSPV, and CTX, are bound to
  the clause history, the package of ``special variables'' governing
  the clause, and the ``error message context.'' These variables are
  commonly used throughout our source code but are, unfortunately,
  undocumented. Again, we expect a few experts will find them useful
  in developing computed hints.

  If you start using computed hints extensively, please contact the
  developers of ACL2 and let us know what you are doing with them and
  how we can help.")
 (USING-ENABLED-RULES
  (THEORIES)
  "Avoiding :use [hints] for [enable]d :[rewrite] rules

  Consider the following (admittedly silly) example.

    (thm (equal (append (append x y) z) (append x y z))
         :hints ((\"Subgoal *1/1\" :use cdr-cons)))

  ACL2's output includes the following warning.

    ACL2 Warning [Use] in ( THM ...):  It is unusual to :USE an enabled
    :REWRITE or :DEFINITION rule, so you may want to consider disabling
    (:REWRITE CDR-CONS) in the hint provided for Subgoal *1/1.

  The warning is saying that if you leave the rewrite rule enabled,
  ACL2 may simplify away the hypothesis added by the :use hint. We
  now explain this danger in more detail and show how disabling the
  rule can solve this problem.

  Recall (see [hints]) how :use [hints] work. Such a hint specifies a
  formula, F, which is based on an existing lemma. Then the indicated
  goal, G, is replaced by the implication (implies F G). The
  intention is that the truth of F will help in the simplification of
  G to T (true). The ``[Use]'' warning shown above is telling us of
  the danger that F may be rewritten to T, reducing the implication
  above to (implies T G) --- thus, sadly, F has disappeared and is
  not available to help with the simplification of G.

  Consider the following tiny example.

    (defun p (x) (cons x x))
    (defthm car-p
       (equal (car (p x)) x))
    (in-theory (disable p (:type-prescription p)))
    (thm (implies (equal (p x1) (p x2))
                  (equal x1 x2))
         :hints ((\"Goal\"
                  :use ((:instance car-p (x x1))
                        (:instance car-p (x x2))))))

  The proof of the final [thm] form fails, because the new hypotheses
  are rewritten to t using the :[rewrite] rule CAR-P, in the manner
  described above. The following proof log shows the new hypotheses
  and their disappearance via rewriting.

    We augment the goal with the hypotheses provided by the :USE hint.
    These hypotheses can be derived from CAR-P via instantiation.  We are
    left with the following subgoal.

    Goal'
    (IMPLIES (AND (EQUAL (CAR (P X1)) X1)
                  (EQUAL (CAR (P X2)) X2))
             (IMPLIES (EQUAL (P X1) (P X2))
                      (EQUAL X1 X2))).

    By the simple :rewrite rule CAR-P we reduce the conjecture to

    Goal''
    (IMPLIES (EQUAL (P X1) (P X2))
             (EQUAL X1 X2)).

  When we disable the rule CAR-P as follows, the proof succeeds.

    (thm (implies (equal (p x1) (p x2))
                  (equal x1 x2))
         :hints ((\"Goal\"
                  :use ((:instance car-p (x x1))
                        (:instance car-p (x x2)))
                  :in-theory (disable car-p))))

  In general, then, a solution is to disable the rewrite rule that you
  are supplying in a :use hint.")
 (USING-TABLES-EFFICIENTLY
  (TABLE)
  "Notes on how to use tables efficiently

  (Thanks to Jared Davis for contributing this [documentation] topic,
  to which we have made only minor modifications.)

  Suppose your book contains [table] [events], or macros that expand
  into table events, of the following form:

    (table my-table 'my-field )

  Then  will be evaluated twice during [certify-book] and
  again every time you include the book with [include-book]. In some
  cases this overhead can be avoided using [make-event].

  See also [defconsts] for an analogous trick involving [defconst].

  As an example, suppose we want to store numbers in a table only if
  they satisfy some computationally expensive predicate. We'll
  introduce a new book, number-table.lisp, and create a table to
  store these numbers:

    (table number-table 'data nil)

  Instead of implementing a ``computationally expensive predicate,''
  we'll write a function that just prints a message when it is called
  and accepts even numbers:

    (defun expensive-computation (n)
      (prog2$ (cw \"Expensive computation on ~x0.~%\" n)
              (evenp n)))

  Now we'll implement a macro, add-number, which will add its argument
  to the table only if it satisfies the expensive predicate:

    (defmacro add-number (n)
      `(table number-table 'data
              (let ((current-data
                     (cdr (assoc-eq 'data (table-alist 'number-table world)))))
                (if (expensive-computation ,n)
                    (cons ,n current-data)
                  current-data))))

  Finally, we'll call add-number a few times to finish the book.

    (add-number 1)
    (add-number 2)
    (add-number 3)

  When we now invoke (certify-book \"number-table\"), we see the
  expensive predicate being called twice for each number: once in
  Step 2, the main pass, then again in Step 3, the admissibility
  check. Worse, the computation is performed again for each number
  when we use [include-book] to load number-table, e.g.,

    ACL2 !>(include-book \"number-table\")
    Expensive computation on 1.
    Expensive computation on 2.
    Expensive computation on 3.

  To avoid these repeated executions, we can pull the test out of the
  table event using [make-event]. Here's an alternate implementation
  of add-number that won't repeat the computation:

    (defmacro add-number (n)
      `(make-event
        (if (expensive-computation ,n)
            '(table number-table 'data
                    (cons ,n (cdr (assoc 'data
                                         (table-alist 'number-table world)))))
          '(value-triple :expensive-computation-failed))))

  When we recertify number-table.lisp, we'll see the expensive
  computation is still called once for each number in Step 2, but is
  no longer called during Step 3. Similarly, the [include-book] no
  longer shows any calls of the expensive computation.")
 (USING_THE_ASSOCIATIVITY_OF_APP_TO_PROVE_A_TRIVIAL_CONSEQUENCE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "Using the Associativity of App to Prove a Trivial Consequence

  [{IMAGE}]

  If we have proved the associativity-of-app rule, then the following
  theorem is trivial:

    (defthm trivial-consequence
      (equal (app (app (app (app x1 x2) (app x3 x4)) (app x5 x6)) x7)
             (app x1 (app (app x2 x3) (app (app x4 x5) (app x6 x7))))))

  Below we show the proof

  [{IMAGE}]")
 (VALUE-TRIPLE
  (EVENTS ACL2-BUILT-INS)
  "Compute a value, optionally checking that it is not nil

    Examples:
    (value-triple (+ 3 4))
    (value-triple (cw \"hi\") :on-skip-proofs t)
    (value-triple (@ ld-pre-eval-print))
    (value-triple (@ ld-pre-eval-print) :check t)

    General Form:
    (value-triple form
                  :on-skip-proofs sp ; optional; nil by default
                  :check chk         ; optional; nil by default
                  )

  Value-triple provides a convenient way to evaluate a form in an event
  context, including [progn] and [encapsulate] and in [books]; see
  [events]. The form should evaluate to a single, non-[stobj] value.

  Calls of value-triple are generally skipped when proofs are being
  skipped, in particular when ACL2 is performing the second pass
  through the [events] of an [encapsulate] form or during an
  [include-book], or indeed any time [ld-skip-proofsp] is non-nil. If
  you want the call evaluated during those times as well, use a
  non-nil value for :on-skip-proofs. Note that the argument to
  :on-skip-proofs is not evaluated.

  If you expect the form to evaluate to a non-nil value and you want an
  error to occur when that is not the case, you can use :check t.
  More generally, the argument of :check can be a form that evaluates
  to a single, non-[stobj] value. If this value is not nil, then the
  aforementioned test is made (that the given form is not nil). If an
  error occurs and the value of :check is a string or indeed any
  ``message'' suitable for printing by [fmt] when supplied as a value
  for tilde-directive ~@, then that string or message is printed.")
 (VERBOSE-PSTACK
  (PSTACK)
  "Seeing what the prover is up to (for system hackers)

  NOTE: This utility is a low-level debugging utility, which may not be
  useful except to those familiar with ACL2 source code.

    General Forms:
    (verbose-pstack t)   ; get trace-like information on prover during proofs
    (verbose-pstack '(fn1 fn2 ...))
                         ; as above, but omit calls of the indicated functions
    (verbose-pstack nil) ; turn off trace-like information on prover

  For example, (verbose-pstack '(ev-fncall)) will provide a trace of
  various prover functions during proofs, except for the function
  ev-fncall.

  By evaluating (verbose-pstack t) one can get trace-like information
  during subsequent proofs about prover functions, including time
  summaries, printed to the screen during a proof. To turn off this
  feature, evaluate (verbose-pstack nil). Also see [pstack].")
 (VERIFY
  (PROOF-CHECKER)
  "Enter the interactive proof checker

  For proof-checker command summaries, see [proof-checker].

    Examples:
    (VERIFY (implies (and (true-listp x) (true-listp y))
                          (equal (append (append x y) z)
                                 (append x (append y z)))))
       -- Attempt to prove the given term interactively.

    (VERIFY (p x)
            :event-name p-always-holds
            :rule-classes (:rewrite :generalize)
            :instructions ((rewrite p-always-holds-lemma)
                           change-goal))
       -- Attempt to prove (p x), where the intention is to call the
          resulting DEFTHM event by the name p-always-holds, with
          rule-classes as indicated.  The two indicated instructions
          will be run immediately to start the proof.

    (VERIFY)
       -- Re-enter the proof-checker in the state at which is was last
          left.

    General Form:
    (VERIFY &OPTIONAL raw-term
            &KEY
            event-name
            rule-classes
            instructions)

  Verify is the function used for entering the [proof-checker]'s
  interactive loop.")
 (VERIFY-GUARDS
  (EVENTS GUARD)
  "Verify the [guard]s of a function

  See [guard] for a general discussion of guards.

  Before discussing the verify-guards event, we first discuss guard
  verification, which can take place at definition time or, later,
  using verify-guards. Typically, guard verification takes place at
  definition time if a guard (or type, or [stobjs]) has been supplied
  explicitly unless :verify-guards nil has been specified; see
  [defun] and see [xargs], and see [set-verify-guards-eagerness] for
  how to change this default. The point of guard verification is to
  ensure that during evaluation of an expression without free
  variables, no guard violation takes place.

  Technical note: the first argument of verify-guards must be a
  function symbol or the name of a [defthm] or [defaxiom] event, not
  a macro-alias for a function symbol (see [macro-aliases-table]).
  See [verify-guards+] for a utility that does not have this
  restriction.

  Guard verification is intended to guarantee that for any call of a
  given function, if its [guard] holds for that call then the [guard]
  will hold for every function call in the body of that function.
  Moreover, in order to avoid guard violations during evaluation of
  the function's guard itself, guard verification also is intended to
  guarantee that the guards are satisfied for all calls in the guard
  itself. Consider the following simple example.

    (defun f (x)
      (declare (xargs :guard (and (consp x)
                                  (integerp (car x)))))
      (if (rationalp (cdr x))
          (+ (car x) (cdr x))
        17))

  If you evaluate (f t), for example, in the top-level loop, you will
  (by default) get a guard error. The point of guard verification is
  to guarantee the absence of guard errors, and we start by using
  this example to illustrate the proof obligations that guarantee
  such absence.

  The body of the above definition has the following function calls,
  where the first is the entire body.

    (if (rationalp (cdr x))
        (< (car x) (cdr x))
      17)
    (rationalp (cdr x)) ; the test of the top-level IF call
    (cdr x)             ; from (rationalp (cdr x))
    (< (car x) (cdr x)) ; the true branch of the top-level IF call
    (car x)             ; from (< (car x) (cdr x))
    (cdr x)             ; from (< (car x) (cdr x))

  We thus see potentially six conditions to prove, one for each call.
  The guards of the function symbols of those calls are t for [if]
  and [rationalp], (or (consp x) (equal x nil)) for both (car x) and
  (cdr x), and finally that both arguments are rationals for <.
  Moreover, we can take advantage of ``contextual assumptions'': the
  if-test conditions and the top-level :guard. Thus, for
  verify-guards the proof obligation from the body of f is as
  follows.

    (implies
     (and (consp x) (integerp (car x))) ; from the :guard
     (and t ; from the top-level IF call
          t ; from (rationalp (cdr x))
          (or (consp x) (equal x nil)) ; from the first (cdr x)
          (implies
           (rationalp (cdr x)) ; IF-test for calls in the true branch
           (and (or (consp x) (equal x nil)) ; from (car x)
                (or (consp x) (equal x nil)) ; from the second (cdr x)
                (and (rationalp (car x)) (rationalp (cdr x))) ; from the < call
                ))))

  But the :guard itself generates a similar sort of proof obligation.
  Note that the guard (and (consp x) (integerp (car x))) is really an
  abbreviation (i.e. via the macro [and]) for the term (if (consp x)
  (integerp (car x)) nil). The guard proof obligation for the guard
  itself is thus as follows.

    (and t ; from (consp x)
         (implies (consp x)
                  (and t         ; from (integerp (car x)) ;
                       (consp x) ; from (car x) ;
                       )))

  All of the above proof obligations are indeed theorems, and guard
  verification succeeds for the above definition of f.

  The example above illustrates the general procedure for generating
  the guard proof obligation. Each function call is considered in the
  body or guard of the function, and it is required that the guard is
  met for that call, under certain ``contextual assumptions'', which
  are as follows. In the case of the body of the named function, it
  is assumed that the guard holds for that function on its formal
  parameters. And in both cases --- the body of the named function
  and also its guard --- the governing tests from superior calls of
  [if] are also assumed.

  As mentioned above, if the guard on a function is not t, then guard
  verification requires not only consideration of the body under the
  assumption that the guard is true, but also consideration of the
  guard itself. Thus, for example, guard verification fails in the
  following example, even though there are no proof obligations
  arising from the body, because the guard itself can cause a guard
  violation when evaluated for an arbitrary value of x:

    (defun foo (x)
      (declare (xargs :guard (car x)))
      x)

  We turn now to the verify-guards event as a way of verifying the
  [guard]s for a function or theorem.

    Examples:
    (verify-guards flatten)
    (verify-guards flatten
                   :hints ((\"Goal\" :use (:instance assoc-of-app)))
                   :otf-flg t
                   :guard-debug t ; default = nil
                   :doc \"string\")

    General Form:
    (verify-guards name
            :hints        hints
            :otf-flg      otf-flg
            :guard-debug  t ; typically t, but any value is legal
            :doc          doc-string)

  In the General Form above, name is the name of a :[logic] function
  (see [defun-mode]) or of a theorem or axiom. In the most common
  case name is the name of a function that has not yet had its
  [guard]s verified, each subroutine of which has had its [guard]s
  verified. The values [hints], [otf-flg], and [guard-debug] are as
  described in the corresponding [documentation] entries; and
  doc-string, if non-nil, is an optional string that can provide
  documentation but is essentially ignored by ACL2. The four keyword
  arguments above are all optional. To admit this event, the
  conjunction of the guard proof obligations must be proved. If that
  proof is successful, name is considered to have had its [guard]s
  verified.

  See [verify-guards-formula] for a utility that lets you view the
  formula to be proved by verify-guards, but without creating an
  event.

  If name is one of several functions in a mutually recursive clique,
  verify-guards will attempt to verify the [guard]s of all of the
  functions.

  If name is a theorem or axiom name, verify-guards verifies the guards
  of the associated formula. When a theorem has had its guards
  verified then you know that the theorem will evaluate to non-nil in
  all Common Lisps, without causing a runtime error (other than
  possibly a resource error). In particular, you know that the
  theorem's validity does not depend upon ACL2's arbitrary completion
  of the domains of partial Common Lisp functions.

  For example, if app is defined as

    (defun app (x y)
      (declare (xargs :guard (true-listp x)))
      (if (endp x)
          y
          (cons (car x) (app (cdr x) y))))

  then we can verify the guards of app and we can prove the theorem:

    (defthm assoc-of-app
      (equal (app (app a b) c) (app a (app b c))))

  However, if you go into almost any Common Lisp in which app is
  defined as shown and evaluate

    (equal (app (app 1 2) 3) (app 1 (app 2 3)))

  we get an error or, perhaps, something worse like nil! How can this
  happen since the formula is an instance of a theorem? It is
  supposed to be true!

  It happens because the theorem exploits the fact that ACL2 has
  completed the domains of the partially defined Common Lisp
  functions like [car] and [cdr], defining them to be nil on all
  non-conses. The formula above violates the guards on app. It is
  therefore ``unreasonable'' to expect it to be valid in Common Lisp.

  But the following formula is valid in Common Lisp:

    (if (and (true-listp a)
             (true-listp b))
        (equal (app (app a b) c) (app a (app b c)))
        t)

  That is, no matter what the values of a, b and c the formula above
  evaluates to t in all Common Lisps (unless the Lisp engine runs out
  of memory or stack computing it). Furthermore the above formula is
  a theorem:

    (defthm guarded-assoc-of-app
      (if (and (true-listp a)
               (true-listp b))
          (equal (app (app a b) c) (app a (app b c)))
          t))

  This formula, guarded-assoc-of-app, is very easy to prove from
  assoc-of-app. So why prove it? The interesting thing about
  guarded-assoc-of-app is that we can verify the guards of the
  formula. That is, (verify-guards guarded-assoc-of-app) succeeds.
  Note that it has to prove that if a and b are true lists then so is
  (app a b) to establish that the guard on the outermost app on the
  left is satisfied. By verifying the guards of the theorem we know
  it will evaluate to true in all Common Lisps. Put another way, we
  know that the validity of the formula does not depend on ACL2's
  completion of the partial functions or that the formula is
  ``well-typed.''

  One last complication: The careful reader might have thought we could
  state guarded-assoc-of-app as

    (implies (and (true-listp a)
                  (true-listp b))
             (equal (app (app a b) c)
                    (app a (app b c))))

  rather than using the if form of the theorem. We cannot! The reason
  is technical: [implies] is defined as a function in ACL2. When it
  is called, both arguments are evaluated and then the obvious truth
  table is checked. That is, implies is not ``lazy.'' Hence, when we
  write the guarded theorem in the implies form we have to prove the
  guards on the conclusion without knowing that the hypothesis is
  true. It would have been better had we defined implies as a macro
  that expanded to the if form, making it lazy. But we did not and
  after we introduced guards we did not want to make such a basic
  change.

  Recall however that verify-guards is almost always used to verify the
  guards on a function definition rather than a theorem. We now
  return to that discussion.

  Verify-guards must often be used when the value of a recursive call
  of a defined function is given as an argument to a subroutine that
  is [guard]ed. An example of such a situation is given below.
  Suppose app (read ``append'') has a [guard] requiring its first
  argument to be a [true-listp]. Consider

    (defun rev (x)
      (declare (xargs :guard (true-listp x)))
      (cond ((endp x) nil)
            (t (app (rev (cdr x)) (list (car x))))))

  Observe that the value of a recursive call of rev is being passed
  into a [guard]ed subroutine, app. In order to verify the [guard]s
  of this definition we must show that (rev (cdr x)) produces a
  [true-listp], since that is what the [guard] of app requires. How
  do we know that (rev (cdr x)) is a [true-listp]? The most elegant
  argument is a two-step one, appealing to the following two lemmas:
  (1) When x is a [true-listp], (cdr x) is a [true-listp]. (2) When z
  is a [true-listp], (rev z) is a [true-listp]. But the second lemma
  is a generalized property of rev, the function we are defining.
  This property could not be stated before rev is defined and so is
  not known to the theorem prover when rev is defined.

  Therefore, we might break the admission of rev into three steps:
  define rev without addressing its [guard] verification, prove some
  general properties about rev, and then verify the [guard]s. This
  can be done as follows:

    (defun rev (x)
      (declare (xargs :guard (true-listp x)
                      :verify-guards nil))    ; Note this additional xarg.
      (cond ((endp x) nil)
            (t (app (rev (cdr x)) (list (car x))))))

    (defthm true-listp-rev
      (implies (true-listp x2)
               (true-listp (rev x2))))

    (verify-guards rev)

  The ACL2 system can actually admit the original definition of rev,
  verifying the [guard]s as part of the [defun] event. The reason is
  that, in this particular case, the system's heuristics just happen
  to hit upon the lemma true-listp-rev. But in many more complicated
  functions it is necessary for the user to formulate the inductively
  provable properties before [guard] verification is attempted.

  Remark on computation of guard conjectures and evaluation. When ACL2
  computes the [guard] conjecture for the body of a function, it
  evaluates any ground subexpressions (those with no free variables),
  for calls of functions whose :[executable-counterpart] [rune]s are
  [enable]d. Note that here, ``enabled'' refers to the current global
  [theory], not to any :[hints] given to the guard verification
  process; after all, the guard conjecture is computed even before
  its initial goal is produced. Also note that this evaluation is
  done in an environment as though :set-guard-checking :all had been
  executed, so that we can trust that this evaluation takes place
  without guard violations; see [set-guard-checking].

  If you want to verify the [guard]s on functions that are built into
  ACL2, you will first need to put them into :[logic] mode. See
  [verify-termination], specifically the ``Remark on system
  functions'' in that [documentation].")
 (VERIFY-GUARDS+
  (EVENTS)
  "Verify the [guard]s of a function

  We assume familiarity with [guard] verification; see [verify-guards].
  Unlike verify-guards, the macro call (verify-guards+ mac ...) will
  verify guards for a function, fn, such that the macro mac is
  associated with the function symbol fn in [macro-aliases-table]
  (also see [add-macro-alias]). For example, if you define a macro
  app and list append function binary-app, and you associate macro
  app with function symbol binary-app in [macro-aliases-table], then
  evaluation of the form (verify-guards+ app) will have the effect of
  evaluating (verify-guards fn). Note that in this setting,
  evaluation of (verify-guards app) would cause an error, because app
  is a macro and verify-guards, unlike verify-guards+, cannot handle
  macros.

  The rest of this [documentation] topic discusses why we do not simply
  arrange that verify-guards be permitted to take a macro alias. The
  following example shows a soundness issue in doing so.

    (encapsulate
     ()
     (defun f1 (x)
       (declare (xargs :guard (consp x)
                       :verify-guards nil))
       (car x))
     (defun f2 (x)
       (declare (xargs :guard t
                       :verify-guards nil))
       (cdr x))
     (defmacro mac (x)
       x)
     (add-macro-alias mac f2) ; silly macro alias ;
     (local (add-macro-alias mac f1)) ; alternate silly macro alias ;
     (verify-guards mac))

  If we were to allow macro aliases in [verify-guards], this event
  would be admitted, because on the first pass we are verifying
  guards of f1. But after the [encapsulate] form completes
  evaluation, it would appear that f2 is guard-verified. That could
  of course cause a raw Lisp error.

  The enhanced functionality provided by verify-guards+ does not have
  the above problem, because it takes advantage of [make-event] to
  avoid taking advantage of the contradictory results produced by the
  two calls of add-macro-alias. See [make-event]. If the specific
  example above is modified by replacing verify-guards with
  verify-guards+, then the first pass through the [encapsulate] form
  will expand the form (verify-guards+ mac) to (verify-guards f1).
  That same expansion will be used for the verify-guards+ call during
  the second pass through the encapsulate form, which is evaluated
  successfully and leaves us in a [world] where f1 is guard-verified
  and f2 is not.")
 (VERIFY-GUARDS-EAGERNESS (POINTERS)
                          "See [set-verify-guards-eagerness].")
 (VERIFY-GUARDS-FORMULA
  (GUARD)
  "View the guard proof obligation, without proving it

  See [verify-guards] and see [guard] for a discussion of guards. This
  utility is provided for viewing a guard proof obligation, without
  doing a proof.

    Example Forms:
    (verify-guards-formula foo)
    (verify-guards-formula foo :guard-debug t)
    (verify-guards-formula foo :otf-flg dont-care :xyz whatever)
    (verify-guards-formula (+ (foo x) (bar y)) :guard-debug t)

  Verify-guards-formula allows all keywords, but only pays attention to
  :guard-debug, which has the same effect as in [verify-guards] (see
  [guard-debug]). Apply verify-guards-formula to a name just as you
  would use [verify-guards], but when you only want to view the
  formula rather than creating an event. If the first argument is not
  a symbol, then it is treated as the body of a [defthm] event for
  which you want the guard proof obligation.

  See [guard-obligation] if you want to obtain guard proof obligations
  for use in a program.")
 (VERIFY-TERMINATION
  (EVENTS)
  "Convert a function from :program mode to :logic mode

    Example:
    (verify-termination fact)

    General Forms:
    (verify-termination fn dcl ... dcl)
    (verify-termination (fn1 dcl ... dcl)
                        (fn2 dcl ... dcl)
                        ...)

  where fn and the fni are function symbols having :[program] mode (see
  [defun-mode]) and all of the dcls are either [declare] forms or
  [documentation] strings. The first form above is an abbreviation
  for

    (verify-termination (fn dcl ... dcl))

  so we limit our discussion to the second form. Each of the fni must
  be in the same clique of mutually recursively defined functions,
  but not every function in the clique need be among the fni.

  Verify-termination attempts to establish the admissibility of the
  fni. Verify-termination retrieves their definitions, creates
  modified definitions using the dcls supplied above, and resubmits
  these definitions. You could avoid using verify-termination by
  typing the new definitions yourself. So in that sense,
  verify-termination adds no new functionality. But if you have
  prototyped your system in :[program] mode and tested it, you can
  use verify-termination to resubmit your definitions and change
  their [defun-mode]s to :[logic], addings [hints] without having to
  retype or recopy the code.

  The [defun] [command] executed by verify-termination is obtained by
  retrieving the [defun] (or [mutual-recursion]) [command] that
  introduced the clique in question and then possibly modifying each
  definition as follows. Consider a function, fn, in the clique. If
  fn is not among the fni above, its definition is left unmodified
  other than to add (declare (xargs :mode :logic)). Otherwise, fn is
  some fni and we modify its definition by inserting into it the
  corresponding dcls listed with fni in the arguments to
  verify-termination, as well as (declare (xargs :mode :logic)). In
  addition, we throw out from the old declarations in fn the :mode
  specification and anything that is specified in the new dcls.

  For example, suppose that fact was introduced with:

    (defun fact (n)
      (declare (type integer n)
               (xargs :mode :program))
      (if (zp n) 1 (* n (fact (1- n))))).

  Suppose later we do (verify-termination fact). Then the following
  definition is submitted.

    (defun fact (n)
      (declare (type integer n))
      (if (zp n) 1 (* n (fact (1- n))))).

  Observe that this is the same definition as the original one, except
  the old specification of the :mode has been deleted so that the
  [defun-mode] now defaults to :[logic]. Although the termination
  proof succeeds, ACL2 also tries to verify the [guard], because we
  have (implicitly) provided a [guard], namely (integerp n), for this
  function. (See [guard] for a general discussion of guards, and see
  [type-spec] for a discussion of how type declarations are used in
  guards.) Unfortunately, the [guard] verification fails, because the
  subterm (zp n) requires that n be nonnegative, as can be seen by
  invoking :args zp. (For a discussion of termination issues relating
  to recursion on the naturals, see [zero-test-idioms].) So we might
  be tempted to submit the following:

    (verify-termination
     fact
     (declare (xargs :guard (and (integerp n) (<= 0 n))))).

  However, this is considered a changing of the guard (from (integerp
  n)), which is illegal. If we instead change the guard in the
  earlier defun after undoing that earlier definition with :[ubt]
  fact, then (verify-termination fact) will succeed.

  Remark on system functions. There may be times when you want to apply
  verify-termination (and also, perhaps, [verify-guards]) to
  functions that are predefined in ACL2. It may be necessary in such
  cases to modify the system code first. See Part II of the {open
  architecture page for ACL2 |
  http://www.cs.utexas.edu/users/moore/acl2/open-architecture/} for a
  discussion of the process for contributing updates to the system
  code and [books] with such verify-termination or [verify-guards]
  [events], perhaps resulting in more system functions being built-in
  as [guard]-verified. To see which built-in functions have already
  received such treatment, see community books directory
  books/system/; or, evaluate the constant
  *system-verify-guards-alist*, each of whose entries associates the
  name of a community book with a list of functions whose
  guard-verification is proved by including that book. See the above
  URL for more details.

  Note that if fn1 is already in :[logic] mode, then the
  verify-termination call has no effect. It is generally considered
  to be redundant, in the sense that it returns without error; but if
  the fn1 is a constrained function (i.e., introduced in the
  signature of an [encapsulate], or by [defchoose]), then an error
  occurs. This error is intended to highlight unintended uses of
  verify-termination; but if you do not want to see an error in this
  case, you can write and use your own macro in place of
  verify-termination. The following explanation of the implementation
  of verify-termination may help with such a task.

  We conclude with a discussion of the use of [make-event] to implement
  verify-termination. This discussion can be skipped; we include it
  only for those who want to create variants of verify-termination,
  or who are interested in seeing an application of [make-event].

  Consider the following proof of nil, which succeeded up through
  Version_3.4 of ACL2.

    (encapsulate
     ()
     (defun foo (x y)
       (declare (xargs :mode :program))
       (if (or (zp x) (zp y))
           (list x y)
         (foo (1+ x) (1- y))))
     (local (defun foo (x y)
              (declare (xargs :measure (acl2-count y)))
              (if (or (zp x) (zp y))
                  (list x y)
                (foo (1+ x) (1- y)))))
     (verify-termination foo))

    (defthm bad-lemma
      (zp x)
      :hints ((\"Goal\" :induct (foo x 1)))
      :rule-classes nil)

  How did this work? In the first pass of the [encapsulate], the second
  [defun] of foo promoted foo from :program to :logic mode, with y as
  the unique measured variable. The following call to
  verify-termination was then redundant. However, on the second pass
  of the [encapsulate], the second ([local]) definition of foo was
  skipped, and the verify-termination event then used the first
  definition of foo to guess the measure, based (as with all guesses
  of measures) on a purely syntactic criterion. ACL2 incorrectly
  chose (acl2-count x) as the measure, installing x as the unique
  measured variable, which in turn led to an unsound induction scheme
  subsequently used to prove nil (lemma bad-lemma, above)

  Now, verify-termination is a macro whose calls expand to [make-event]
  calls. So in the first pass above, the verify-termination call
  generated a defun event identical to the [local] [defun] of foo,
  which was correctly identified as redundant. That expansion was
  recorded, and on the second pass of the [encapsulate], the
  expansion was recalled and used in place of the verify-termination
  call (that is how [make-event] works). So instead of a measure
  being guessed for the verify-termination call on the second pass,
  the same measure was used as was used on the first pass, and a
  sound induction scheme was stored. The attempt to prove nil (lemma
  bad-lemma) then failed.")
 (VERSION
  (ABOUT-ACL2)
  "ACL2 Version Number

  To determine the version number of your copy of ACL2, evaluate the
  form (@ acl2-version). The value will be a string. For example,

    ACL2 !>(@ acl2-version)
    \"ACL2 Version 3.4\"

  The part of the string after \"ACL2 Version \" is of the form x.y or
  x.y.z, optionally followed by a succession of values in
  parentheses, where x, y, and z are natural numbers. If z is omitted
  then it is implicitly 0. We refer to X, y, and z as the ``major'',
  ``minor'', and ``incrl'' fields, respectively. The incrl field is
  used for incremental releases. The discussion just below assumes
  that incremental releases are not employed at the user's site,
  i.e., the incrl fields are always 0. We remove this assumption when
  we discuss incremental releases at the end of this documenttation
  topic.

  [Books] are considered certified only in the same version of ACL2 in
  which the certification was done. The [certificate] file records
  the version number of the certifying ACL2 and [include-book]
  considers the book uncertified if that does not match the current
  version number. Thus, each time we release a new version of ACL2,
  previously certified books should be recertified.

  Note that there are over 150 constants in the system, most having to
  do with the fact that ACL2 is coded in ACL2. Many of these, for
  example *common-lisp-specials-and-constants* and *acl2-exports*,
  may change from version to version, and this can cause unsoundness.
  For example, the symbol 'set-difference-eq was added to
  *acl2-exports* in Version_2.9, so we can certify a book in
  Version_2.8 containing the following theorem, which is false in
  Version_2.9.

    (null (member 'set-difference-eq *acl2-exports*))

  Therefore, we need to disallow inclusion of such a book in a
  Version_2.9 session, which otherwise would allow us to prove nil.
  Furthermore, it is possible that from one version of the system to
  another we might change, say, the default values on some system
  function or otherwise make ``intentional'' changes to the axioms.
  It is even possible one version of the system is discovered to be
  unsound and we release a new version to correct our error.

  Therefore we adopted the draconian policy that books are certified by
  a given version of ACL2 and ``must'' be recertified to be used in
  other versions. We put ``must'' in quotes because in fact, ACL2
  allows a book that was certified in one ACL2 version to be included
  in a later version, using [include-book]. But ACL2 does not allow
  [certify-book] to succeed when such an [include-book] is executed
  on its behalf. Also, you may experience undesirable behavior if you
  avoid recertification when moving to a different version. Hence we
  recommend that you stick to the draconion policy of recertifying
  books when updating to a new ACL2 version.

  Furthermore, all bets are off if you certify a book using ACL2 built
  on one host Lisp implementation and include the book using ACL2
  built on a different host Lisp implementation. For example, for
  most host Lisp implementations, the Lisp reader will interpret the
  token 2f as a symbol; however, Common Lisp allows for the
  possibility that 2f is read as a number. In such a case, one could
  use the former ACL2 executable to certify a book containing the
  form

    (defthm my-thm
      (symbolp '2f)
      :rule-classes nil)

  but then use the latter ACL2 executable to include the book, even
  though for the latter ACL2 executable, 2f is a number, not a
  symbol. Of course, one would expect a checksum error in that case;
  but checksums do not provide guaranteed protection against
  including uncertified books.

  Incremental releases.

  From time to time, so-called ``incremental releases'' of ACL2 are
  made available. These releases are thoroughly tested on at least
  two platforms; ``normal'' releases, on the other hand, are
  thoroughly tested on many more platforms (perhaps a dozen or so)
  and are accompanied by updates to the ACL2 home page. We provide
  incremental releases in order to provide timely updates for ACL2
  users who want them, without imposing unnecessary burdens on either
  on the ACL2 implementors or on ACL2 users who prefer to update less
  frequently. The implementors expect users to update their copies of
  ACL2 when normal releases are made available, but not necessarily
  when incremental releases are made available.

  Incremental releases are accompanied by a bump in the incrl field of
  the version field, while normal releases are accompanied by a bump
  in the minor or (much less frequently) major field and zeroing out
  of the incrl field. Note that incremental releases are full-fledged
  releases.")
 (WALKABOUT
  (DEBUGGING)
  "Explore an ACL2 cons tree

  By typing (walkabout x state) for an ACL2 term x whose value is a
  [cons] tree, you can walk around that tree. For example, ACL2
  developers often use this utility to explore the ACL2 logical
  [world].

  When you issue a walkabout command, a summary of commands will be
  printed before you enter an interactive loop.

    Commands:
    0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.

  In the interactive walkabout loop, a positive integer n takes you to
  the nth position, while 0 takes you up a level. The commands nx and
  bk take you to the next and previous position, respectively, at the
  same level. The command pp prints the current object in full, while
  (pp level length) hides sub-objects below the indicated level and
  past the indicated length, if non-nil; see [evisc-tuple]. The
  command (pp n) abbreviates (pp n n), so in particular (pp nil) is
  equivalent to pp.

  Note that the commands above work in any package: nx, bk, pp, =, and
  q are converted to the \"ACL2\" package if the current package is not
  \"ACL2\".

  The following example illustrates the commands described above.

    ACL2 !>(walkabout (append '(a (b1 b2 b3)) '(c d e f)) state)

    Commands:
    0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.

    (A (B1 B2 B3) C ...)
    :2
    (B1 B2 B3)
    :3
    B3
    :0
    (B1 B2 B3)
    :nx
    C
    :nx
    D
    :0
    (A (B1 B2 B3) C ...)
    :pp
    (A (B1 B2 B3) C D E F)
    :(pp 4)
    (A (B1 B2 B3) C D ...)
    :(pp 1 4)
    (A # C D ...)
    :(pp nil 2)
    (A (B1 B2 ...) ...)
    :q
    ACL2 !>

  Finally we describe the commands q, =, and (= symb), where symb is a
  symbol. The command q simply causes an exit from the walkabout
  loop. The command = also exits, but causes the current object to be
  printed in full. The command (= symb) saves an association of symb
  with the current object, which can be retrieved outside the
  walkabout loop using the macro walkabout=, as illustrated below.

    :2
    (B1 B2 B3)
    :(= my-list)
    (walkabout= MY-LIST) is
    (B1 B2 B3)
    :q
    ACL2 !>(walkabout= MY-LIST)
    (B1 B2 B3)
    ACL2 !>

  Finally, we remark that for trees that are not true-lists, walkabout
  treats the dot as an object that can be ``walked about''. The
  following example illustrates this point.

    ACL2 !>(walkabout '(c d e . f) state)

    Commands:
    0, 1, 2, ..., nx, bk, pp, (pp n), (pp lev len), =, (= symb), and q.

    (C D E . F)
    :3
    E
    :nx
    .
    :nx
    F
    :0
    (C D E . F)
    :4
    .
    :0
    (C D E . F)
    :5
    F
    :")
 (WARNINGS
  (PROVER-OUTPUT)
  "Warnings emitted by the ACL2 proof process

  The prover can emit many warnings when processing [events]. See
  [set-inhibit-warnings] and see [set-inhibit-output-lst] for how to
  disable and enable them.")
 (WATERFALL (POINTERS)
            "See [hints-and-the-waterfall].")
 (WATERFALL-PARALLELISM
  (PARALLEL-PROOF)
  "For ACL2(p): configuring the parallel execution of the waterfall

  See [set-waterfall-parallelism].")
 (WATERFALL-PARALLELISM-FOR-BOOK-CERTIFICATION
  (PARALLELISM)
  "For ACL2(p): using waterfall parallelism during book certification

  This [documentation] topic relates to the experimental extension of
  ACL2 supporting parallel execution and proof; see [parallelism].

  There are books whose certification can be sped up significantly by
  using waterfall parallelism. (See [parallelism], including the
  caveat in its \"IMPORTANT NOTE\".) One such example in the ACL2
  community books is models/jvm/m5/apprentice.lisp, which is
  typically excluded from regressions because of how long it takes to
  certify. In order to use waterfall parallelism during certification
  of a book .lisp using `make' (see [books-certification]
  and see [books-certification-classic]), we recommend creating a
  file .acl2 that includes the following forms.

    #+acl2-par
    (set-waterfall-parallelism t)

    (certify-book  ? t) ; other arguments may be preferable

  Note that there are books that will not certify when
  waterfall-parallelism is enabled. See file
  acl2-customization-files/README for more information, including how
  to certify essentially all books using waterfall parallelism.")
 (WATERFALL-PRINTING
  (PARALLEL-PROOF)
  "For ACL2(p): configuring the printing within the parallelized
  waterfall

  See [set-waterfall-printing].")
 (WELL-FOUNDED-RELATION
  (RULE-CLASSES)
  "Show that a relation is well-founded on a set

  See [rule-classes] for a general discussion of rule classes,
  including how they are used to build rules from formulas and a
  discussion of the various keywords in a rule class description.

    Example:
    (defthm lex2p-is-well-founded-relation
      (and (implies (pairp x) (o-p (ordinate x)))
           (implies (and (pairp x)
                         (pairp y)
                         (lex2p x y))
                    (o< (ordinate x) (ordinate y))))
      :rule-classes :well-founded-relation)

  The example above creates a :well-founded-relation rule, where of
  course the functions pairp, lex2p, and ordinate would have to be
  defined first. It establishes that lex2p is a well-founded relation
  on pairps. We explain and give details below.

  Exactly two general forms are recognized:

    General Forms
    (AND (IMPLIES (mp x) (O-P (fn x)))              ; Property 1
         (IMPLIES (AND (mp x)                       ; Property 2
                       (mp y)
                       (rel x y))
                  (O< (fn x) (fn y)))),

  or

    (AND (O-P (fn x))                               ; Property 1
         (IMPLIES (rel x y)                         ; Property 2
                  (O< (fn x) (fn y))))

  where mp, fn, and rel are function symbols, x and y are distinct
  variable symbols, and no other :well-founded-relation theorem about
  fn has been proved. When the second general form is used, we act as
  though the first form were used with mp being the function that
  ignores its argument and returns t. The discussion below therefore
  considers only the first general form.

  Note: We are very rigid when checking that the submitted formula is
  of one of these forms. For example, in the first form, we insist
  that all the conjuncts appear in the order shown above. Thus,
  interchanging the two properties in the top-level conjunct or
  rearranging the hyptheses in the second conjunct both produce
  unrecognized forms. The requirement that each fn be proved
  well-founded at most once ensures that for each well-founded
  relation, fn, there is a unique mp that recognizes the domain on
  which rel is well-founded. We impose this requirement simply so
  that rel can be used as a short-hand when specifying the
  well-founded relations to be used in definitions; otherwise the
  specification would have to indicate which mp was to be used.

  We also insist that the new ordering be embedded into the ordinals as
  handled by [o-p] and [o<] and not some into previously admitted
  user-defined well-founded set and relation. This restriction should
  pose no hardship. If mp and rel were previously shown to be
  well-founded via the embedding fn, and you know how to embed some
  new set and relation into mp and rel, then by composing fn with
  your new embedding and using the previously proved well-founded
  relation lemma you can embed the new set and relation into the
  ordinals.

  Mp is a predicate that recognizes the objects that are supposedly
  ordered in a well-founded way by rel. We call such an object an
  ``mp-measure'' or simply a ``measure'' when mp is understood.
  Property 1 tells us that every measure can be mapped into an ACL2
  ordinal. (See [o-p].) This mapping is performed by fn. Property 2
  tells us that if the measure x is smaller than the measure y
  according to rel then the image of x under fn is a smaller than
  that of y, according to the well-founded relation [o<]. (See [o<].)
  Thus, the general form of a :well-founded-relation formula
  establishes that there exists a rel-order preserving embedding
  (namely via fn) of the mp-measures into the ordinals. We can thus
  conclude that rel is well-founded on mp-measures.

  Such well-founded relations are used in the admissibility test for
  recursive functions, in particular, to show that the recursion
  terminates. To illustrate how such information may be used,
  consider a generic function definition

    (defun g (x) (if (test x) (g (step x)) (base x))).

  If rel has been shown to be well-founded on mp-measures, then g's
  termination can be ensured by finding a measure, (m x), with the
  property that m produces a measure:

    (mp (m x)),                                     ; Defun-goal-1

  and that the argument to g gets smaller (when measured by m and
  compared by rel) in the recursion,

    (implies (test x) (rel (m (step x)) (m x))).    ; Defun-goal-2

  If rel is selected as the :well-founded-relation to be used in the
  definition of g, the definitional principal will generate and
  attempt to prove defun-goal-1 and defun-goal-2 to justify g. We
  show later why these two goals are sufficient to establish the
  termination of g. Observe that neither the ordinals nor the
  embedding, fn, of the mp-measures into the ordinals is involved in
  the goals generated by the definitional principal.

  Suppose now that a :well-founded-relation theorem has been proved for
  mp and rel. How can rel be ``selected as the
  :well-founded-relation'' by [defun]? There are two ways. First, an
  [xargs] keyword to the [defun] event allows the specification of a
  :well-founded-relation. Thus, the definition of g above might be
  written

    (defun g (x)
     (declare (xargs :well-founded-relation (mp . rel)))
     (if (test x) (g (step x)) (base x)))

  Alternatively, rel may be specified as the
  :default-well-founded-relation in [ACL2-defaults-table] by
  executing the event

    (set-well-founded-relation rel).

  When a [defun] event does not explicitly specify the relation in its
  [xargs] the default relation is used. When ACL2 is initialized, the
  default relation is [o<].

  Finally, though it is probably obvious, we now show that defun-goal-1
  and defun-goal-2 are sufficient to ensure the termination of g
  provided property-1 and property-2 of mp and rel have been proved.
  To this end, assume we have proved defun-goal-1 and defun-goal-2 as
  well as property-1 and property-2 and we show how to admit g under
  the primitive ACL2 definitional principal (i.e., using only the
  ordinals). In particular, consider the definition event

    (defun g (x)
     (declare (xargs :well-founded-relation o<
                     :measure (fn (m x))))
     (if (test x) (g (step x)) (base x)))

  Proof that g is admissible: To admit the definition of g above we
  must prove

    (o-p (fn (m x)))                        ; *1

  and

    (implies (test x)                               ; *2
             (o< (fn (m (step x))) (fn (m x)))).

  But *1 can be proved by instantiating property-1 to get

    (implies (mp (m x)) (o-p (fn (m x)))),

  and then relieving the hypothesis with defun-goal-1, (mp (m x)).

  Similarly, *2 can be proved by instantiating property-2 to get

    (implies (and (mp (m (step x)))
                  (mp (m x))
                  (rel (m (step x)) (m x)))
             (o< (fn (m (step x))) (fn (m x))))

  and relieving the first two hypotheses by appealing to two instances
  of defun-goal-1, thus obtaining

    (implies (rel (m (step x)) (m x))
             (o< (fn (m (step x))) (fn (m x)))).

  By chaining this together with defun-goal-2,

    (implies (test x)
             (rel (m (step x)) (m x)))

  we obtain *2. Q.E.D.")
 (WET
  (TRACE)
  "Evaluate a form and print subsequent error trace

  The acronym ``wet'' stands for ``with-error-trace''. Wet provides a
  convenient way to obtain a backtrace when evaluation causes a guard
  violation or other error.

  The basic idea is that (wet form) evaluates form and, if there is an
  error, shows a backtrace of calls that led to that error. Note
  however that by default only calls of user-defined (not built-in)
  functions ``supporting'' form in the following sense will show up
  in the backtrace: those that occur in the macroexpansion of form or
  (recursively) support any of those functions. So for example, since
  (make-event form) macroexpands to (make-event-fn (quote form) ...),
  calls of functions occurring in form will likely not show up in the
  backtrace by default. The option :fns all overrides this default,
  with potential loss of speed; more on this below.

  The following example explains the use of wet. First, submit the
  following three definitions:

    (defun foo (x) (declare (xargs :guard (consp x))) (car x))
    (defun bar (x) (foo (cdr x)))
    (defun g (x) (bar (cdr x)))

  Now imagine you have obtained the following guard violation:

    ACL2 !>(g '(3 4))

    ACL2 Error in TOP-LEVEL:  The guard for the function call (FOO X),
    which is (CONSP X), is violated by the arguments in the call (FOO NIL).
    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 !>

  With wet, you can get a backtrace of user-defined functions. The
  package prefixes shown below, ACL2_*1*_, indicate that the
  executable (logical) counterparts of the corresponding raw Lisp
  functions are being called; see [guard]. Don't forget to start with
  (include-book \"misc/wet\" :dir :system).

    ACL2 !>(wet (g '(3 4)))
    ; Fast loading /projects/acl2/devel/books/misc/wet.fasl

    TTAG NOTE: Adding ttag :TRACE! from the top level loop.

    ACL2 Error in WET:  The guard for the function call (FOO X), which
    is (CONSP X), is violated by the arguments in the call (FOO NIL).
    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.

    Backtrace stack:
    ----------------
    1. (ACL2_*1*_ACL2::FOO NIL)
    2. (ACL2_*1*_ACL2::BAR (4))
    3. (ACL2_*1*_ACL2::G (3 4))

    ACL2 !>

  By default, large structures are hidden during the printing of the
  backtrace stack. But you can supply a value for keyword argument
  :evisc-tuple to modify the printing: nil to avoid hiding, else a
  suitable evisc-tuple, as shown below (see [evisc-tuple]).

    ACL2 !>(wet (g '(3 4)) :evisc-tuple (evisc-tuple 1 1 nil nil))
    ; Fast loading /projects/acl2/devel/books/misc/wet.fasl

    TTAG NOTE: Adding ttag :TRACE! from the top level loop.

    ACL2 Error in WET:  The guard for the function call (FOO X), which
    is (CONSP X), is violated by the arguments in the call (FOO NIL).
    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.

    Backtrace stack:
    ----------------
    1. (ACL2_*1*_ACL2::FOO ...)
    2. (ACL2_*1*_ACL2::BAR ...)
    3. (ACL2_*1*_ACL2::G ...)

    ACL2 !>

  For a backtrace as a data object, evaluate the form (@ wet-stack).
  But note that this object may not be a legal ACL2 value, for
  example because of the ``*1*'' symbols shown above.

    General Form:
    (wet form           ; an arbitrary form
         :book bk-form  ; optional, not evaluated
         ;;; the rest are optional and evaluated:
         :evisc-tuple e ; an evisc-tuple
         :fns fns       ; :all, or a list of functions to show in a backtrace
         :compile c     ; :same, t, or nil; default :same (nil if :fns supplied)

  Form is evaluated. If there is an error, a backtrace stack is printed
  to the standard output ([*standard-co*]), containing (by default)
  the user-defined function calls made before the error. Such
  printing is controlled by the :evisc-tuple if supplied; otherwise,
  hiding of large structures will occur. (Technical detail: by
  default the global abbrev-evisc-tuple is used, if bound; see
  [set-evisc-tuple].

  The :fns option. As mentioned above, by default the wet backtrace
  shows user-defined functions that syntactically ``support'' the
  form being evaluated. This default can be overridden by supplying
  an explicit list, fns, of functions, using option :fns fns; these
  will then be the functions whose calls are eligible for inclusion
  in the backtrace. The special value :fns :all will allow all
  user-defined function calls in the backtrace. This value can be
  useful when using [oracle-apply], for example, since the function
  being applied isn't typically included as a syntactic supporter of
  the form being evaluated.

  The :compile option. Wet uses the [trace$] utility to modify the
  definitions of affected functions so that they can record
  information for the backtrace. As described above, these affected
  functions are those that syntactically ``support'' the form unless
  specified by the :fns option. As is the case for trace$ --- see
  [trace$] --- the new definitions of these affected functions may or
  may not be compiled. For trace$ and for wet, the default is to
  compile the new definition if and only if the original definition
  was compiled, except: For wet, if option :fns :all is provided,
  then the default is not to compile the affected definitions. And
  for trace$ and wet, the :compile option overrides the default, to
  specify what will be compiled: value :same to compile each affected
  function if and only if its original definition was compiled, value
  t to compile all affected functions, and value nil to skip
  compilation.

  The :book option. Wet actually works by temporarily including a
  community book,

    (include-book \"misc/wet\" :dir :system)

  and then passing its arguments to macro wet!, defined in that book.
  The keyword argument :book allows you to specify a different book
  that defines a macro wet! to which to pass its arguments. If the
  value of :book is a string, then the book named by that string is
  temporarily included using [include-book]: (include-book \"bk\").
  Otherwise :book should be a list of arguments, to be provided
  (unevaluated) to [include-book], for example (\"my-wet\" :dir
  :my-utils). Thus you can experiment by copying community book
  books/misc/wet.lisp to your own directory and making modifications
  to the copy. If you make changes, we invite you to share them with
  the ACL2 community (see [books]). Note that you can also supply
  :book nil, in which case the definition of wet! in your current
  session will be used without including a book.

  Also see [trace$] for a general tracing utility. As mentioned above,
  wet is implemented using trace$. Wet actually first applies
  [untrace$]; upon completion, wet then applies [trace$] to re-trace
  any functions that it had untraced, using their original trace
  specs.")
 (WHAT_IS_ACL2{Q}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "What Is ACL2?

  [{IMAGE}]

  ACL2 is a mathematical logic together with a mechanical theorem
  prover to help you reason in the logic.

  The logic is just a subset of applicative [Common Lisp]. (This link
  takes you off the main route of the tour. You'll see some Common
  Lisp on the tour, so visit this later!)

  The theorem prover is an ``industrial strength'' version of the
  Boyer-Moore theorem prover, Nqthm.

  Models of all kinds of computing systems can be built in ACL2, just
  as in Nqthm, even though the formal logic is Lisp.

  Once you've built an ACL2 model of a system, you can run it.

  You can also use ACL2 to prove theorems about the model.

  [{IMAGE}]")
 (WHAT_IS_A_MATHEMATICAL_LOGIC{Q}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "What is a Mathematical Logic?

  [{IMAGE}]

  {IMAGE}

  A mathematical logic is a formal system of formulas (axioms) and
  rules for deriving other formulas, called theorems.

  A proof is a derivation of a theorem. To see a concrete proof tree,
  click [here].

  Why should you care? The neat thing about Theorems is that they are
  ``true.'' More precisely, if all the axioms are valid and the rules
  are validity preserving, then anything derived from the axioms via
  the rules is valid.

  So, if you want to determine if some formula is true, prove it.

  [{IMAGE}]")
 (WHAT_IS_A_MECHANICAL_THEOREM_PROVER{Q}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "What is a Mechanical Theorem Prover?

  [{IMAGE}]

  A mechanical theorem prover is a computer program that finds proofs
  of theorems.

  {IMAGE}

  The ideal mechanical theorem prover is automatic: you give it a
  formula and it gives you a proof of that formula or tells you there
  is no proof.

  Unfortunately, automatic theorem provers can be built only for very
  simple logics (e.g., propositional calculus) and even then
  practical considerations (e.g., how many centuries you are willing
  to wait) limit the problems they can solve.

  [{IMAGE}]")
 (WHAT_IS_A_MECHANICAL_THEOREM_PROVER{Q}_{CONT}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "What is a Mechanical Theorem Prover? (cont)

  [{IMAGE}] To get around this, mechanical theorem provers often
  require help from the user.

  {IMAGE}

  Click [here] to continue downward.

  [{IMAGE}]")
 (WHAT_IS_REQUIRED_OF_THE_USER{Q}
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "What is Required of the User?

  [{IMAGE}]

  It is not easy to build ACL2 models of complex systems. To do so, the
  user must understand

    * the system being modeled, and

    * ACL2, at least as a programming language.

  It is not easy to get ACL2 to prove hard theorems. To do so, the user
  must understand

    * the model,

    * ACL2 as a mathematical logic, and

    * be able to construct a proof (in interaction with ACL2).

  ACL2 will help construct the proof but its primary role is to prevent
  logical mistakes. The creative burden --- the mathematical insight
  into why the model has the desired property --- is the user's
  responsibility.

  [{IMAGE}]")
 (WHY-BRR
  (BREAK-REWRITE)
  "An explanation of why ACL2 has an explicit [brr] mode

  Why isn't [brr] mode automatically disabled when there are no
  monitored runes? The reason is that the list of monitored runes is
  kept in a wormhole state.

  See [wormhole] for more information on wormholes in general. But the
  fundamental property of the wormhole function is that it is a
  logical no-op, a constant function that does not take state as an
  argument. When entering a wormhole, arbitrary information can be
  passed in (including the external state). That information is used
  to construct a near copy of the external state and that ``wormhole
  state'' is the one with respect to which interactions occur during
  breaks. But no information is carried by ACL2 out of a wormhole ---
  if that were allowed wormholes would not be logical no-ops. The
  only information carried out of a wormhole is in the user's head.

  [Break-rewrite] interacts with the user in a wormhole state because
  the signature of the ACL2 rewrite function does not permit it to
  modify [state]. Hence, only wormhole interaction is possible. (This
  has the additional desirable property that the correctness of the
  rewriter does not depend on what the user does during interactive
  breaks within it; indeed, it is logically impossible for the user
  to affect the course of [rewrite].)

  Now consider the list of monitored runes. Is that kept in the
  external state as a normal state global or is it kept in the
  wormhole state? If it is in the external state then it can be
  inspected within the wormhole but not changed. This is
  unacceptable; it is common to change the [monitor]ed rules as the
  proof attempt progresses, installing monitors when certain rules
  are about to be used in certain contexts. Thus, the list of
  monitored runes must be kept as a wormhole variable. Hence, its
  value cannot be determined outside the wormhole, where the proof
  attempt is ongoing.

  This raises another question: If the list of monitored runes is
  unknown to the rewriter operating on the external state, how does
  the rewriter know when to break? The answer is simple: it breaks
  every time, for every rune, if [brr] mode is enabled. The wormhole
  is entered (silently), computations are done within the wormhole
  state to determine if the user wants to see the break, and if so,
  interactions begin. For unmonitored runes and runes with false
  break conditions, the silent wormhole entry is followed by a silent
  wormhole exit and the user perceives no break.

  Thus, the penalty for running with [brr] mode enabled when there are
  no monitored runes is high: a wormhole is entered on every
  application of every rune and the user is simply unware of it. The
  user who has finally unmonitored all runes is therefore strongly
  advised to carry this information out of the wormhole and to do
  :[brr] nil in the external state when the next opportunity arises.")
 (WITH-FAST-ALIST
  (FAST-ALISTS ACL2-BUILT-INS)
  "(with-fast-alist name form) causes name to be a fast alist for the
  execution of form.

  Logically, with-fast-alist just returns form.

  Under the hood, we cause alist to become a fast alist before
  executing form. If doing so caused us to introduce a new hash
  table, the hash table is automatically freed after form completes.

  More accurately, under the hood (with-fast-alist name form)
  essentially expands to something like:

    (if (already-fast-alist-p name)
        form
      (let (( (make-fast-alist name)))
        (prog1 form
               (fast-alist-free ))))

  Practically speaking, with-fast-alist is frequently a better choice
  then just using [make-fast-alist], and is particularly useful for
  writing functions that can take either fast or slow alists as
  arguments. That is, consider the difference between:

    (defun bad (alist ...)
      (let* ((fast-alist (make-fast-alist alist))
             (answer     (expensive-computation fast-alist ...)))
       (prog2$ (fast-alist-free fast-alist)
               answer)))

    (defun good (alist ...)
       (with-fast-alist alist
         (expensive-computation alist ...)))

  Either approach is fine if the caller provides a slow alist. But if
  the input alist is already fast, bad will (perhaps unexpectedly)
  free it! On the other hand, good is able to take advantage of an
  already-fast argument and will not cause it to be inadvertently
  freed.

  See also the macro with-fast-alists defined in the community book
  \"books/centaur/misc/hons-extra.lisp\", which allows you to call
  [with-fast-alist] on several alists simultaneously.

  The community book \"books/centaur/misc/hons-extra.lisp\" extends the
  [b*] macro with the with-fast pattern binder. That is, after
  executing (include-book \"centaur/misc/hons-extra.lisp\" :dir
  :system) you may write something like this:

    (b* (...
         ((with-fast a b c ...))
         ...)
      ...)

  which causes a, b, and c to become fast alists until the completion
  of the b* form.

  Note that with-fast-alist will cause logically tail-recursive
  functions not to execute tail-recursively if its cleanup phase
  happens after the tail-recursive call returns.")
 (WITH-GUARD-CHECKING
  (GUARD ACL2-BUILT-INS)
  "Suppressing or enable guard-checking for a form

    Example:

    ; Turn off all guard-checking for the indicated calls of append and car:
    (with-guard-checking :none
                         (car (append 3 4)))

    General Form:
    (with-guard-checking val form)

  where val evaluates to a legal guard-checking value (see
  [set-guard-checking], or evaluate *guard-checking-values* to see
  the list of such values), and form is a form to be evaluated as
  though we had first executed (set-guard-checking val). Of course,
  this gaurd-checking setting is active only during evaluation of
  form, and is ignored once evaluation passes into raw Lisp functions
  (see [guards-and-evaluation]).")
 (WITH-LIVE-STATE
  (PROGRAMMING-WITH-STATE ACL2-BUILT-INS)
  "Allow a reference to state in raw Lisp

  The macro with-live-state is an advanced feature that very few users
  will need (basically, only system hackers). Indeed, it is
  untouchable; see [remove-untouchable] for how to enable calling
  with-live-state in the ACL2 loop.

    Example Form:
    (with-live-state (assign y 3))

    General form:
    (with-live-state form)

  where form is an arbitrary form with a free reference to the variable
  [state].

  Logically, (with-live-state FORM) macroexpands to FORM. However, in
  raw Lisp it expands to:

    (let ((state *the-live-state*))
      FORM)

  If a form that mentions the variable [state] might be executed in raw
  Lisp --- that is, either outside the ACL2 loop or in raw mode (see
  [set-raw-mode]) --- then the surrounding the form with
  with-live-state as shown above can avoid potential warnings or
  (much less likely) errors. Note however that if state is lexically
  bound to a state other than the usual ``live'' state, surprising
  behavior may occur when evaluating a call of with-live-state in raw
  Lisp or raw mode (either directly by evaluation or at compile
  time), because with-live-state will override that lexical binding
  of [state] by a lexical binding of state to the usual ``live''
  state.")
 (WITH-LOCAL-STATE
  (STOBJ ACL2-BUILT-INS)
  "Locally bind state

  This is an advanced topic, probably of interest only to system
  developers.

  Consider the following example form:

    (with-local-state
     (mv-let (result state)
             (compute-with-state x state)
             result))

  This is equivalent to the following form.

    (with-local-stobj
     state
     (mv-let (result state)
             (compute-with-state x state)
             result))

  By default, this form is illegal, because ACL2 does not have a way to
  unwind all changes to the ACL2 [state]; we say more on this issue
  below. There may however be situations where you are willing to
  manage or overlook this issue. In that case you may execute the
  following form to enable the use of with-local-state, by enabling
  the use of [with-local-stobj] on state; but note that it requires
  an active trust tag (see [defttag]).

    (remove-untouchable create-state t)

  Please be aware that no local [state] is actually created, however!
  In particular, users of with-local-state need either to ensure that
  channels are closed and state global variables are returned to
  their original values, or else be willing to live with changes made
  to state that are not justified by the code that has been
  evaluated. You are welcome to look in the the ACL2 source code at
  the definition of macro channel-to-string, which employs
  with-local-state to create a local [state] for the purpose of
  creating a string.

  Here is an example use of with-local-state. Notice the use of
  [defttag] --- and indeed, please understand that we are just
  hacking here, and in general it takes significant effort to be sure
  that one is using with-local-state correctly!

    (defttag t)

    (remove-untouchable create-state t)

    (set-state-ok t)

    (defun foo (state)
      (declare (xargs :mode :program))
      (mv-let
       (channel state)
       (open-input-channel \"my-file\" :object state)
       (mv-let (eofp obj state)
               (read-object channel state)
               (declare (ignore eofp))
               (let ((state (close-input-channel channel state)))
                 (mv obj state)))))

    (defun bar ()
      (declare (xargs :mode :program))
      (with-local-state (mv-let (result state)
                                (foo state)
                                result)))

    ; Multiple-value return version:

    (defun foo2 (state)
      (declare (xargs :mode :program))
      (mv-let
       (channel state)
       (open-input-channel \"my-file\" :object state)
       (mv-let (eofp obj state)
               (read-object channel state)
               (let ((state (close-input-channel channel state)))
                 (mv eofp obj state)))))

    (defun bar2 ()
      (declare (xargs :mode :program))
      (with-local-state (mv-let (eofp result state)
                                (foo2 state)
                                (mv eofp result))))")
 (WITH-LOCAL-STOBJ
  (STOBJ ACL2-BUILT-INS)
  "Locally bind a single-threaded object

  See [stobj] for an introduction to single-threaded objects.

    Example Form:
    (with-local-stobj
     st
     (mv-let (result st)
             (compute-with-st x st)
             result))

  With-local-stobj can be thought of as a macro, where the example form
  above expands as follows.

    (mv-let (result st)
            (let ((st (create-st)))
              (compute-with-st x st))
            (declare (ignore st))
            result)

  However, ACL2 expects you to use with-local-stobj, not its expansion.
  More precisely, stobj creator functions are not allowed except
  (implicitly) via with-local-stobj and in logic-only situations
  (like theorems and hints). Moreover, neither with-local-stobj nor
  its expansions are legal when typed directly at the top-level loop.
  See [top-level] for a way to use with-local-stobj in the top-level
  loop.

    General Forms:
    (with-local-stobj stobj-name mv-let-form)
    (with-local-stobj stobj-name mv-let-form creator-name)

  where stobj-name is the name of a [stobj], mv-let-form is a call of
  [mv-let], and if creator-name is supplied then it should be the
  name of the creator function for stobj-name; see [defstobj]. For
  the example form above, its expansion would use creator-name, if
  supplied, in place of create-st. Note that stobj-name must not be
  [state] (the ACL2 state), except in special situations probably of
  interest only to system developers; see [with-local-state].

  With-local-stobj can be useful when a stobj is used to memoize
  intermediate results during a computation, yet it is desired not to
  make the stobj a formal parameter for the function and its callers.

  ACL2 can reason about these ``local stobjs,'' and in particular about
  stobj creator functions. For technical reasons, ACL2 will not allow
  you to enable the :EXECUTABLE-COUNTERPART [rune] of a stobj creator
  function.

  Finally, here is a small example concocted in order to illustrate
  that with-local-stobj calls can be nested.

    (defstobj st fld1)

    (defun foo ()
      (with-local-stobj
       st ; Let us call this the ``outer binding of st''.
       (mv-let (val10 val20 st)
         (let ((st (update-fld1 10 st)))
           ;; At this point the outer binding of st has fld1 = 10.
           (let ((result (with-local-stobj
                          st ; Let us call this the ``inner binding of st''.
                          (mv-let (val st)
                            (let ((st (update-fld1 20 st)))
                              ;; Now fld1 = 20 for the inner binding of st.
                              (mv (fld1 st) st))
                            val))))
             ;; So result has been bound to 20 above, but here we are once again
             ;; looking at the outer binding of st, where fld1 is still 10.
             (mv (fld1 st) result st)))
         (mv val10 val20))))

    (thm (equal (foo) (mv 10 20))) ; succeeds")
 (WITH-OUTPUT
  (PROVER-OUTPUT)
  "Suppressing or turning on specified output for an event

    Examples:

    ; Turn off all output during evaluation of the indicated thm form.
    (with-output
     :off :all
     :gag-mode nil
     (thm (equal (app (app x y) z) (app x (app y z)))))

    ; Prove the indicated theorem with the event summary turned off and
    ; using the :goals setting for gag-mode.
    (with-output
       :off summary
       :gag-mode :goals
       (defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))

    ; Same effect as just above:
    (with-output
       :on summary
       :summary nil
       :gag-mode :goals
       (defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))

    ; Turn on only the indicated parts of the summary.
    (with-output
       :on summary
       :summary (time rules)
       :gag-mode :goals  ; use gag-mode, with goal names printed
       (defthm app-assoc (equal (app (app x y) z) (app x (app y z)))))

    ; Same as specifying :off :all, but showing all output types
    ; (i.e., the value of constant *valid-output-names*):
    (with-output
     :off (error warning warning! observation prove proof-checker event history
                 summary proof-tree)
     :gag-mode nil
     (thm (equal (app (app x y) z) (app x (app y z)))))

    ; Same as above, but :stack :push says to save the current
    ; inhibit-output-lst, which can be restored in a subsidiary with-output call
    ; that specifies :stack :pop.
    (with-output
     :stack :push
     :off :all
     :gag-mode nil
     (thm (equal (app (app x y) z) (app x (app y z)))))

    ; Abbreviate printing in gag-mode for guard goals and induction schemes, but
    ; defeat abbreviated printing (if any) for terms.
    (with-output
     :evisc (:gag-mode (evisc-tuple 3 4 nil nil)
             :term nil)
     (defun h (x)
       (declare (xargs :guard t))
       (append (cons (make-list 10) x) x)))

    General Form:
    (with-output :key1 val1 ... :keyk valk form)

  where each :keyi is either :off, :on, :stack, :summary, :gag-mode, or
  :evisc; form evaluates to an error triple (see [error-triples]);
  and vali is as follows. If :keyi is :off or :on, then vali is
  either :all, or else a symbol or non-empty list of symbols
  representing output types that can be inhibited; see
  [set-inhibit-output-lst]. Note that vali is not evaluated if :keyi
  is :off or :on. If :keyi is :summary, then vali is either :all or a
  true-list of symbols each of which belongs to the list
  *summary-types*. Note that vali is not evaluated if :keyi is
  :summary. If :keyi is :gag-mode, then vali should evaluate to one
  of the legal values for :[set-gag-mode]. If :keyi is :evisc, then
  vali should be a [keyword-value-listp], where each key is a legal
  keyword for the :sites keyword argument of [set-evisc-tuple] other
  than :trace (that is, a member of the list (:term :ld :abbrev
  :gag-mode)), and each value evaluates to a legal [evisc-tuple] for
  that keyword. Otherwise :keyi is :stack, in which case :vali is
  :push or :pop; for now assume that :stack is not specified (we'll
  return to it below). The result of evaluating the General Form
  above is to evaluate form, but in an environment where output
  occurs as follows. If :on :all is specified, then every output type
  is turned on except as inhibited by :off; else if :off :all is
  specified, then every output type is inhibited except as specified
  by :on; and otherwise, the currently-inhibited output types are
  reduced as specified by :on and then extended as specified by :off.
  If :gag-mode and/or :evisc are specified, then before modifying how
  output is inhibited, [gag-mode] and/or the appropriate
  [evisc-tuple]s are set for the evaluation of form as specified by
  the values of those keywords; see [set-gag-mode] and
  [set-evisc-tuple]. If summary is among the output types that are
  turned on (not inhibited), then if :summary is specified, the only
  parts of the summary to be printed will be those specified by the
  value of :summary. The correspondence should be clear, except
  perhaps that header refers to the line containing only the word
  Summary, and value refers to the value of the form printed during
  evaluation of sequences of events as for [progn] and [encapsulate].

  Note that the handling of the :stack argument pays no attention to
  the :summary argument.

  Note: When the scope of with-output is exited, then all modifications
  are undone: that is, the states of each of [gag-mode], the
  [evisc-tuple]s, and output inhibition are all restored to those
  which were present before the with-output call was entered.

  The :stack keyword's effect is illustrated by the following example,
  where ``(encapsulate nil)'' may replaced by ``(progn'' without any
  change to the output that is printed.

    (with-output
     :stack :push :off :all
     (encapsulate ()
       (defun f1 (x) x)
       (with-output :stack :pop (defun f2 (x) x))
       (defun f3 (x) x)
       (with-output :stack :pop :off warning (in-theory nil))
       (defun f4 (x) x)))

  The outer with-output call saves the current output settings (as may
  have been modified by earlier calls of [set-inhibit-output-lst]),
  by pushing them onto a stack, and then turns off all output. Each
  inner with-output call temporarily pops that stack, restoring the
  starting output settings, until it completes and undoes the effects
  of that pop. Unless event output was inhibited at the top level
  (see [set-inhibit-output-lst]), the following output is shown:

    Since F2 is non-recursive, its admission is trivial.  We observe that
    the type of F2 is described by the theorem (EQUAL (F2 X) X).

  And then, if summary output was not inhibited at the top level, we
  get the rest of this output:

    Summary
    Form:  ( DEFUN F2 ...)
    Rules: NIL
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

    Summary
    Form:  ( IN-THEORY NIL)
    Rules: NIL
    Warnings:  None
    Time:  0.00 seconds (prove: 0.00, print: 0.00, other: 0.00)

  Note that the use of :off warning suppresses a \"Theory\" warning for
  the (in-theory nil) event, and that in no case will output be
  printed for definitions of f1, f3, or f4, or for the [encapsulate]
  event itself.

  The following more detailed explanation of :stack is intended only
  for advanced users. After :gag-mode and :evisc are handled (if
  present) but before :on or :off is handled, the value of :stack is
  handled as follows. If the value is :push, then [state] global
  inhibit-output-lst-stack is modified by pushing the value of
  [state] global inhibit-output-lst onto the value of [state] global
  inhibit-output-lst-stack, which is nil at the top level. If the
  value is :pop, then [state] global inhibit-output-lst-stack is
  modified only if non-nil, in which case its top element is popped
  and becomes the value of of [state] global inhibit-output-lst.

  Warning: With-output has no effect in raw Lisp (other than to expand
  to the provided form argument), and hence is disallowed in function
  bodies. However, you can probably get the effect you want as
  illustrated below, where  must return an error triple (mv erp
  val state); see [ld] and see [error-triples].

    Examples avoiding with-output, for use in function definitions:

    ; Inhibit all output:
    (state-global-let*
     ((inhibit-output-lst *valid-output-names*))
     )

    ; Inhibit all warning output:
    (state-global-let*
     ((inhibit-output-lst
       (union-eq (f-get-global 'inhibit-output-lst state)
                 '(warning warning!))))
     )

  Note that with-output is allowed in books. See [embedded-event-form].")
 (WITH-OUTPUT-LOCK
  (PARALLEL-PROGRAMMING ACL2-BUILT-INS)
  "Provides a mutual-exclusion mechanism for performing output in
  parallel

  This documentation topic relates to an experimental extension of
  ACL2, ACL2(p), created initially by David L. Rager. See
  [compiling-ACL2p] for how to build an executable image that
  supports parallel execution. Also see community books directory
  books/parallel/ for examples.

  One may wish to perform output while executing code in parallel. If
  threads are allowed to print concurrently, the output will be
  interleaved and often unreadable. To avoid this, the user can
  surround forms that perform output with the with-output-lock macro.

  Take the following definition of pfib as an example.

    (defun pfib (x)
      (declare (xargs :guard (natp x)))
      (cond ((mbe :logic (or (zp x) (<= x 0))
                  :exec (<= x 0))
             0)
            ((= x 1) 1)
            (t (plet (declare (granularity t))
                     ((a (prog2$ (cw \"Computing pfib ~x0~%\" (- x 1))
                                 (pfib (- x 1))))
                      (b (prog2$ (cw \"Computing pfib ~x0~%\" (- x 2))
                                 (pfib (- x 2)))))
                     (+ a b)))))

  With [parallel-execution] enabled, a call of (pfib 5)results in
  non-deterministically interleaved output, for example as follows.

    ACL2 !>(pfib 5)
    CComputing pfib 4
    omputing pfib 3
    ComCpuotmipnugt ipnfgi bp fib3
    2
    Computing pCfiobm put2i
    ng pfib 1
    Computing pfib Co1mp
    uting pfib 0
    CCoommppuuttiinngg  ppffiibb  12

    ComCpuotmipnugt ipnfgi bp fib1
    0
    CoCmopmuptuitnign gp fpifbi b 1
    0
    5
    ACL2 !>

  If the user instead surrounds the calls to [cw] with the macro
  with-output-lock, as in the following session, the output will no
  longer be interleaved.

    ACL2 !>
    (defun pfib (x)
      (declare (xargs :guard (natp x)))
      (cond ((mbe :logic (or (zp x) (<= x 0))
                  :exec (<= x 0))
             0)
            ((= x 1) 1)
            (t (plet (declare (granularity t))
                     ((a (prog2$ (with-output-lock
                                  (cw \"Computing pfib ~x0~%\" (- x 1)))
                                 (pfib (- x 1))))
                      (b (prog2$ (with-output-lock
                                  (cw \"Computing pfib ~x0~%\" (- x 2)))
                                 (pfib (- x 2)))))
                     (+ a b)))))

    

    ACL2 !>(pfib 5)
    Computing pfib 4
    Computing pfib 3
    Computing pfib 3
    Computing pfib 2
    Computing pfib 2
    Computing pfib 1
    Computing pfib 2
    Computing pfib 1
    Computing pfib 1
    Computing pfib 0
    Computing pfib 1
    Computing pfib 0
    Computing pfib 1
    Computing pfib 0
    5
    ACL2 !>")
 (WITH-PROVER-STEP-LIMIT
  (MISCELLANEOUS)
  "Limit the number of steps for proofs

  Logically, (with-prover-step-limit expr form) is equivalent to form,
  except that if the number of ``prover steps'' executed during
  evaluation of form exceeds a bound specified by the value of expr,
  then that proof will abort. See [set-prover-step-limit] for a
  related utility that sets the limit on prover steps globally
  instead of setting it for just one form, and for a discussion of
  the notion of ``prover steps'', which could change in future ACL2
  releases. For a related utility based on time instead of prover
  steps, see [with-prover-time-limit]; but as discussed in the
  [documentation] for [set-prover-step-limit], there is at best a
  loose connection between the counting of steps and
  [with-prover-time-limit].

  The arguments of (with-prover-step-limit expr form) are evaluated.
  However, the (optional) argument flg is not evaluated in
  (with-prover-step-limit expr flg form).

  Depending on the machine you are using, you may have less than a
  half-hour of time before the number of prover steps exceeds the
  maximum limit on prover steps that may be imposed, which is one
  less than the value of *default-step-limit*. But there is no limit
  unless you explicitly call with-prover-step-limit or
  [set-prover-step-limit].

  For examples of how step-limits work besides those presented below,
  see the community book books/misc/misc2/step-limits.lisp.

  For a utility that returns an indicator of the number of prover steps
  most recently taken, see [last-prover-steps].

  Note that with-prover-step-limit may not be called inside
  definitions, and that it is simply the identity macro in raw Lisp.
  However, with-prover-step-limit! may be called in place of
  with-prover-step-limit, with the effect described here even in raw
  Lisp.

    Examples:

    ; Limit (mini-proveall) to 100,000 prover steps (which happens to suffice)
    (with-prover-step-limit 100000 (mini-proveall))

    ; Same as above for the inner call of with-prover-step-limit; so the
    ; mini-proveall call completes, but then we get an error because the second
    ; argument of the outer with-prover-step-limit call took more than 200
    ; steps.
    (with-prover-step-limit
     200
     (with-prover-step-limit 100000 (mini-proveall)))

    ; Same as preceding form just above, except that this time there is no error,
    ; because the inner call of with-prover-step-limit has an extra argument
    ; of t inserted into the second argument position, which specifies that this
    ; entire inner call is treated as though it uses no prover steps.
    (with-prover-step-limit
     200
     (with-prover-step-limit 100000 t (mini-proveall)))

    ; The inner call limits (mini-proveall) to 200 prover steps, which fails
    ; almost immediately.
    (with-prover-step-limit 100000 (with-prover-step-limit 200 (mini-proveall)))

    ; Do not limit the number of prover steps, regardless of such a limit imposed
    ; globally or by the surrounding context.
    (with-prover-step-limit nil (mini-proveall))

    ; Same as just above (indeed, nil above is converted to
    ; *default-step-limit*):
    (with-prover-step-limit *default-step-limit* (mini-proveall))

    ; Advanced example: Limit the indicated theorem to 100 steps, and when the
    ; proof does not complete, then put down a label instead.
    (mv-let (erp val state)
            (with-prover-step-limit
             100
             (thm (equal (append (append x x) x)
                         (append x x x))))
            (if erp
                (deflabel foo :doc \"Attempt failed.\")
              (value (list :succeeded-with val))))

    ; Use extra argument of t to avoid ``charging'' steps for the indicated
    ; form.
    (with-prover-step-limit
     500
     (encapsulate
      ()
      (with-prover-step-limit
       500
       t ; Don't charge prover steps for this first defthm.
       (defthm test1
         (equal (append x (append y z))
                (append (append x y) z))
         :rule-classes nil))
      (defthm test2
        (equal (append x (append y z))
               (append (append x y) z))
        :rule-classes nil)))

    General Forms:
    (with-prover-step-limit expr form)
    (with-prover-step-limit expr flg form)

  where form is an arbitrary form to evaluate, and expr evaluates to
  one of the following: nil; a natural number not exceeding the value
  of *default-step-limit*; or the special value, :START. The optional
  extra argument in the second position, flg, must be Boolean if
  supplied.

  If the value of expr is a natural number less than the value of
  *default-step-limit*, then that value is the maximum number of
  prover steps permitted during evaluation of form before an error
  occurs. If however the value of expr is nil or is the value of
  *default-step-limit*, then no limit is placed on the number of
  prover steps during processing of form. Otherwise, the value of
  expr should be the keyword :START, which is intended for use by the
  ACL2 implementation and may have semantics that change with new
  ACL2 versions.

  Finally we describe the optional extra Boolean argument, flg. If flg
  is nil or omitted, then a running count of prover steps is
  maintained after form is evaluated; otherwise, that count is not
  affected by evaluation of form. To see how this works when flg is
  nil or omitted, consider an event of shape (progn form1 form2),
  where we are tracking prover steps (say, because of a superior call
  of with-prover-step-limit). If n is the number of prover steps
  available when the [progn] form is entered, and if s prover steps
  are executed while evaluating form1, then n-s steps are available
  for evaluation of form2 provided s does not exceed n; otherwise, an
  error occurs. In particular, this is the case if form1 is an event
  (with-prover-step-limit k form1'). However, if form1 is an event
  (with-prover-step-limit k t form1'), then because of the extra
  argument of t, no steps are ``charged'' to form; that is, all n
  steps, rather than n-s steps, are available for evaluation of
  form2.


Subtopics

  [Last-prover-steps]
      The number of prover steps most recently taken")
 (WITH-PROVER-TIME-LIMIT
  (MISCELLANEOUS)
  "Limit the time for proofs

    Examples:

    ; Limit (mini-proveall) to about 1/4 second:
    (with-prover-time-limit 1/4 (mini-proveall))

    ; Limit (mini-proveall) to about 1/4 second, even if surrounding call of
    ; with-prover-time-limit provides for a more restrictive bound:
    (with-prover-time-limit '(1/4) (mini-proveall))

    ; Limit the indicated theorem to about 1/50 second, and if the proof does not
    ; complete or it fails, then put down a label instead.
    (mv-let (erp val state)
            (with-prover-time-limit
             1/50
             (thm (equal (append (append x x) x)
                         (append x x x))))
            (if erp
                (deflabel foo :doc \"Attempt failed.\")
              (value (list :succeeded-with val))))

    General Form:
    (with-prover-time-limit time form)

  where time evaluates to a positive rational number or to a list
  containing such, and form is arbitrary. Logically,
  (with-prover-time-limit time form) is equivalent to form. However,
  if the time for evaluation of form exceeds the value specified by
  time, and if ACL2 notices this fact during a proof, then that proof
  will abort, for example like this:

    ACL2 Error in ( DEFTHM PERM-REFLEXIVE ...):  Out of time in the rewriter.

  If there is already a surrounding call of with-prover-time-limit that
  has set up an expiration time, the inner with-prover-time-limit
  call is not allowed to push that time further into the future
  unless the inner time is specified as a list containing a rational,
  rather than as a rational.

  Note that by default, the time used is runtime (cpu time); to switch
  to realtime (elapsed time), see [get-internal-time].

  For a related utility based on prover steps instead of time, see
  [with-prover-step-limit]; also see [set-prover-step-limit]. Those
  utilities have the advantage of having platform-independent
  behavior, unlike time limits, which of course are generally less
  restrictive for faster processors. But note that the prover steps
  counted need not correspond closely to prover time.

  Although with-prover-time-limit behaves like an ACL2 function in the
  sense that it evaluates both its arguments, it is however actually
  a macro that behaves as follows. (1) The value of its first (time
  limit) argument affects the evaluation of its second argument (by
  causing an error during that evaluation if the time for completion
  is insufficient). (2) The second argument can return multiple
  values (see [mv]), which are then returned by the call of
  with-prover-time-limit. (3) Thus, there is not a fixed number of
  values returned by with-prover-time-limit.

  If you find that the time limit appears to be implemented too
  loosely, it may be because the prover only checks the time elapsed
  at certain points during the proof process, for example at entry to
  the rewriter. For example, if you write your own [clause-processor]
  that does an expensive computation, the time is unlikely to be
  checked during its execution. If however you find the time limit
  seems to be ignored even during ordinary prover operation, you are
  encouraged to email an example to the ACL2 implementors with
  instructions on how to observe the undesirable behavior. This
  information can perhaps be used to improve ACL2 by the insertion of
  more checks for expiration of the time limit.

  The rest of this documentation topic explains the rather subtle
  logical story, and is not necessary for understanding how to use
  with-prover-time-limit. The ACL2 [state] object logically contains
  a field called the acl2-oracle, which is an arbitrary true list of
  objects; see [read-ACL2-oracle]. Our claim is that every ACL2
  session makes sense for some value of acl2-oracle in the initial
  state for that session. Logically, with-prover-time-limit is a
  no-op, just returning its second value. But under the hood, it
  provides a ``hint'' for the acl2-oracle, so that (logically
  speaking) when its first element ([car]) is consulted by ACL2's
  prover to see if the time limit has expired, it gets the ``right''
  answer (specifically, either nil if all is well or else a message
  to print if the time limit has expired). Logically, the acl2-oracle
  is then [cdr]'ed --- that is, its first element is popped off ---
  so that future results from read-acl2-oracle are independent of the
  one just obtained.")
 (WITH-SERIALIZE-CHARACTER
  (SERIALIZE ACL2-BUILT-INS)
  "Control output mode for print-object$

  This documentation topic relates to [hons-enabled] ACL2 executables,
  which are built by default. See [serialize] for a discussion of
  ``serialization'' routines, contributed by Jared Davis for saving
  ACL2 objects in files for later loading.

  The expression (with-serialize-character char form) evaluates to the
  value of form, but with the serialize-character of the [state]
  assigned to char, which should be one of nil, #\\Y, or #\\Z. We
  describe the effect of that assignment below. But note that if you
  are doing this because of one or more specific calls of
  print-object$, such as (print-object$ x channel state), then you
  may wish instead to evaluate (print-object$-ser x
  serialize-character channel state), in which case you will not need
  to use with-serialize-character. (Note however that
  serialize-character is treated as nil by ACL2 executables that are
  not [hons-enabled].)

    General forms:
    (with-serialize-character nil form)
    (with-serialize-character #Y form)
    (with-serialize-character #Z form)

  where form should evaluate to an error triple (see [error-triples]).

  Note that if you prefer to obtain the same behavior (as described
  below) globally, rather than only within the scope of
  with-serialize-character, then use set-serialize-character in a
  corresponding manner:

    (set-serialize-character nil state)
    (set-serialize-character #\\Y state)
    (set-serialize-character #\\Z state)

  In each case above, calls of print-object$ (see [io]) in form will
  produce an object that can be read by a [hons-enabled] ACL2
  executable. In the first case, that object is printed as one might
  expect at the terminal, as an ordinary Lisp s-expression. But in
  the other cases, the object is printed by first laying down either
  #Y or #Z (respectively) and then calling [serialize-write] (or more
  precisely, the underlying function called by serialize-write that
  prints to a stream).

  Consider what happens when the ACL2 reader encounters an object
  produced as described above (in the #Y or #Z case). When the object
  was written, information was recorded on whether that object was a
  [hons]. In the case of #Z, the object will be read as a hons if and
  only if it was originally written as a hons. But in the case of #Y,
  it will never be read as a hons. Thus, #Y and #Z will behave the
  same if the original written object was not a hons, creating an
  object that is not a hons. For an equivalent explanation and a bit
  more discussion, see [serialize-read], in particular the discussion
  of the hons-mode. The value :smart described there corresponds to
  #Z, while :never corresponds to #Y.")
 (WITH-STOLEN-ALIST
  (HONS-AND-MEMOIZATION ACL2-BUILT-INS)
  "(with-stolen-alist name form) ensures that name is a fast alist at
  the start of the execution of form. At the end of execution, it
  ensures that name is a fast alist if and only if it was originally.
  That is, if name was not a fast alist originally, its hash table
  link is freed, and if it was a fast alist originally but its table
  was modified during the execution of form, that table is restored.
  Note that any extended table created from the original fast alist
  during form must be manually freed.

  Logically, with-stolen-alist just returns form.

  Under the hood, we cause alist to become a fast alist before
  executing form, and we check the various conditions outlined above
  before returning the final value.

  Note that with-stolen-alist will cause logically tail-recursive
  functions not to execute tail-recursively if its cleanup phase
  happens after the tail-recursive call returns.")
 (WITHOUT-EVISC
  (IO ACL2-BUILT-INS)
  "Print output in full

    General Form:
    (without-evisc form)

  where form is any expression to evaluate. The effect is to evaluate
  form as though the without-evisc wrapper were absent, except that
  expressions are printed in full for the ensuing output, regardless
  of the current evisc-tuples (see [set-evisc-tuple]). See
  [set-iprint] for an example.

  More precisely, without-evisc binds each of the term-evisc-tuple,
  ld-evisc-tuple, abbrev-evisc-tuple and gag-mode-evisc-tuple to nil
  (see [set-evisc-tuple]). It does not modify the trace evisc-tuple,
  so trace output is not modified by without-evisc. Also note that
  calls of printing functions such as [fmt] that include explicit
  evisc-tuples will not have those evisc-tuples overridden. The
  following example illustrates this point.

    ACL2 !>(without-evisc
            (fms \"~x0~%\"
                 (list (cons #0 '((a b ((c d)) e f g) u v w x y)))
                 *standard-co*
                 state
                 (evisc-tuple 2 3 nil nil)))

    ((A B # ...) U V ...)
    
    ACL2 !>

  We conclude with two remarks. (1) A call of without-evisc on
  expression exp actually invokes a specialized call of [ld] on a
  one-element list containing exp, which prints the value returned by
  evaluation of exp but actually returns the useless value (mv nil
  :invisible state). So do not use without-evisc in programs; just
  use it at the top level of the ACL2 read-eval-print loop, or at
  least the top level of ld. (2) Even when using without-evisc, if
  the ACL2 logical [world] is part of the value returned, it will be
  printed in abbreviated form because the ACL2 read-eval-print loop
  always arranges for this to be the case, regardless of the
  ld-evisc-tuple. For example:

    ACL2 !>(without-evisc (w state))
    
    ACL2 !>

  An alternative to the use of without-evisc is to explore large
  objects using the ACL2 function (walkabout object state). Some
  brief documentation is printed when you enter an interactive loop
  upon evaluating a call of walkabout. We may add documentation for
  walkabout if that is requested.")
 (WOF
  (IO)
  "Direct standard output and proofs output to a file

    Example Form:
    (wof \"tmp\" (pso)) ; same as (psof \"tmp\")

    General Form:
    (wof filename form)

  where filename is a writable filename and form is any form that
  evaluates to an error triple (see [programming-with-state]), that
  is, a multiple value of the form (mv erp val state). All output to
  channels [standard-co] and [proofs-co] will be directed to the
  indicated file. It is acceptable to replace filename with (quote
  filename).

  Note that so-called comment-window output (see [cw] and see
  [observation-cw]) is not redirected by wof to a file, nor is
  printing from a [wormhole].")
 (WORLD
  (STATE)
  "ACL2 property lists and the ACL2 logical database

  The ACL2 logical world is a data structure that includes all logical
  content resulting from the [command]s evaluated, back through and
  including initialization, but not including commands that have been
  undone (see [ubt]). Thus in particular, the world includes a
  represention of the current logical theory, as well as some
  extra-logical information such as the values of ACL2 [table]s. The
  rest of this topic focuses on the structure of the the ACL2 world
  and, more generally, the ``world'' data structure.

  A ``world'' is a list of triples, each of the form (sym prop . val),
  implementing the ACL2 notion of property lists. ACL2 permits the
  simultaneous existence of many property list worlds. ``The world''
  is often used as a shorthand for ``the ACL2 logical world'' which
  is the particular property list world used within the ACL2 system
  to maintain a database that contiains rules, [table]s, and so on.

  Common Lisp provides the notion of ``property lists'' by which one
  can attach ``properties'' and their corresponding ``values'' to
  symbols. For example, one can arrange for the 'color property of
  the symbol 'box-14 to be 'purple and the 'color property of the
  symbol 'triangle-7 to be 'yellow. Access to property lists is given
  via the Common Lisp function get. Thus, (get 'box-14 'color) might
  return 'purple. Property lists can be changed via the special form
  setf. Thus, (setf (get 'box-14 'color) 'blue) changes the Common
  Lisp property list configuration so that (get 'box-14 'color)
  returns 'blue. It should be obvious that ACL2 cannot provide this
  facility, because Common Lisp's get ``function'' is not a function
  of its argument, but instead a function of some implicit state
  object representing the property list settings for all symbols.

  ACL2 provides the functions getprop and putprop which allow one to
  mimic the Common Lisp property list facility. However, ACL2's
  getprop takes as one of its arguments a list that is a direct
  encoding of what was above called the ``state object representing
  the property list settings for all symbols.'' Because ACL2 already
  has a notion of ``[state]'' that is quite distinct from that used
  here, we call this property list object a ``world.'' A world is
  just a true list of triples. Each triple is of the form (sym prop .
  val). This world can be thought of as a slightly elaborated form of
  association list and getprop is a slightly elaborated form of
  [assoc] that takes two keys. When getprop is called on a symbol, s,
  property p, and world, w, it scans w for the first triple whose sym
  is s and prop is p and returns the corresponding val. Getprop has
  two additional arguments: one controls what it returns if no such
  sym and prop exist in w, and the other allows an extremely
  efficient implementation. To set some property's value for some
  symbol, ACL2 provides putprop. (putprop sym prop val w) merely
  returns a new world, w', in which (sym prop . val) has been
  [cons]ed onto the front of w, thus ``overwriting'' the prop value
  of sym in w to val and leaving all other properties in w unchanged.

  One aspect of ACL2's property list arrangement is that it is possible
  to have many different property list worlds. For example, 'box-14
  can have 'color 'purple in one world and can have 'color 'yes in
  another, and these two worlds can exist simultaneously because
  getprop is explicitly provided the world from which the property
  value is to be extracted.

  The efficiency alluded to above stems from the fact that Common Lisp
  provides property lists. Using Common Lisp's provisions behind the
  scenes, ACL2 can ``install'' the properties of a given world into
  the Common Lisp property list state so as to make retrieval via
  getprop very fast in the special case that the world provided to
  getprop has been installed. To permit more than one installed
  world, each of which is permitted to be changed via putprop, ACL2
  requires that worlds be named and these names are used to
  distinquish installed versions of the various worlds. At the moment
  we do not further document getprop and putprop.

  However, the ACL2 system uses a property list world, named
  'current-acl2-world, in which to store the succession of user
  [command]s and their effects on the logic. This world is often
  referred to in our [documentation] as ``the world'' though it
  should be stressed that the user is permitted to have worlds and
  ACL2's is in no way distinguished except that the user is not
  permitted to modify it except via event [command]s. The ACL2 world
  is part of the ACL2 [state] and may be obtained via (w state).

  Warning: The ACL2 world is very large. Its length as of this writing
  (Version 2.5) is over 40,000 and it grows with each release.
  Furthermore, some of the values stored in it are pointers to old
  versions of itself. Printing (w state) is something you should
  avoid because you likely will not have the patience to await its
  completion. For these practical reasons, the only thing you should
  do with (w state) is provide it to getprop, as in the form

    (getprop sym prop default 'current-acl2-world (w state))

  to inspect properties within it, or to pass it to ACL2 primitives,
  such as theory functions, where it is expected.

  Some ACL2 [command] forms, such as theory expressions (see
  [theories]) and the values to be stored in tables (see [table]),
  are permitted to use the variable symbol world freely with the
  understanding that when these forms are evaluated that variable is
  bound to (w state). Theoretically, this gives those forms complete
  knowledge of the current logical configuration of ACL2. However, at
  the moment, few world scanning functions have been documented for
  the ACL2 user. Instead, supposedly convenient macro forms have been
  created and documented. For example, (current-theory :here), which
  is the theory expression which returns the currently [enable]d
  theory, actually macroexpands to (current-theory-fn :here world).
  When evaluated with world bound to (w state), current-theory-fn
  scans the current ACL2 world and computes the set of [rune]s
  currently [enable]d in it.


Subtopics

  [Formula]
      The formula of a name or [rune]

  [Getprop]
      Access fast property lists

  [Logical-name]
      A name created by a logical event

  [Props]
      Print the ACL2 properties on a symbol

  [Putprop]
      Update fast property lists

  [Redefined-names]
      To collect the names that have been redefined")
 (WORMHOLE
  (STATE LD)
  "[ld] without [state] --- a short-cut to a parallel universe

    Example Form:
    ; The following form enters a recursive read-eval-print loop on a
    ; copy of the current state, allowing you to interact with that loop.
    ; Note that the form does not mention the ACL2 state variable!
    ; Evaluate the form below. Inside the resulting loop, define some function,
    ; e.g., with (defun foo (x) x).  Then exit with :q and observe,
    ; e.g., with :pe foo, that the external state did not change.

    (wormhole 'foo
              '(lambda (whs) (set-wormhole-entry-code whs :ENTER))
              nil
              '(list 'hello 'there))

    General Form:
    (wormhole name entry-lambda input form
      :current-package    ...  ; known package name
      :ld-skip-proofsp    ...  ; nil, t or 'include-book
      :ld-redefinition-action  ; nil or '(:a . :b)
      :ld-prompt          ...  ; nil, t, or some prompt printer fn
      :ld-missing-input-ok ... ; nil, t, :warn, or warning message
      :ld-pre-eval-filter ...  ; :all, :query, or some new name
      :ld-pre-eval-print  ...  ; nil, t, or :never
      :ld-post-eval-print ...  ; nil, t, or :command-conventions
      :ld-evisc-tuple     ...  ; nil or '(alist level length hiding-cars)
      :ld-error-triples   ...  ; nil or t
      :ld-error-action    ...  ; :return!, :return, :continue, :error,
                               ;   or (:exit N)
      :ld-query-control-alist  ; alist supplying default responses
      :ld-verbose         ...) ; nil or t

  The keyword arguments above are exactly those of [ld] (see [ld])
  except that three of [ld]'s keyword arguments are missing: the
  three that specify the channels [standard-oi], [standard-co] and
  [proofs-co], which default in wormhole to ACL2's comment window.

  There are two ways to create and enter a wormhole: wormhole as
  described here and the simpler [wormhole-eval]. We recommend you
  read this full account of wormholes before using wormhole-eval.

  Ignoring the use of entry-lambda, wormhole manufactures a named
  ``wormhole [state]'' and calls the general-purpose ACL2
  read-eval-print loop [ld] on it. However, when ld exits, the
  wormhole evaporates and the function wormhole returns nil. The
  manufactured state is like the ``current'' ACL2 [state] except for
  two things. First, some information from the last wormhole state of
  this name is transferred into the new state; this allows a wormhole
  to maintain some state from one call to the next. Second, some
  information from the wormhole call itself is transferred into the
  new state; this allows the wormhole to be sensitive to context.
  These two changes to the current state are reflected in the
  settings (@ wormhole-status) and (@ wormhole-input) discussed in
  detail below.

  Note that wormhole may be called from environments in which [state]
  is not bound. It is still applicative because it always returns
  nil.

  There are some restrictions about what can be done inside a wormhole.
  As you may imagine, we really do not ``copy the current state'' but
  rather just keep track of how we modified it and undo those
  modifications upon exit. An error is signalled if you try to modify
  state in an unsupported way. For this same reason, wormholes do not
  allow updating of any user-defined single-threaded objects. See
  [stobj].

  One example wormhole is the implementation of the ACL2
  [accumulated-persistence] facility for tracking the frequency with
  which rules are tried. To implement this feature directly the
  theorem prover would have to take the tracking data as an argument
  and pass it around so that updates could be accumulated. This would
  greatly clutter the code. Instead, the tracking data is maintained
  in a wormhole. The theorem prover enters the wormhole to update the
  data as rules are tried. When you request a display of the data,
  [show-accumulated-persistence] enters the wormhole and prints the
  data. But the data is never available outside that wormhole. The
  ACL2 system uses a second wormhole to implement the [brr] facility,
  allowing the user to interact with the rewriter as rules are
  applied.

  We now specify the arguments and behavior of wormhole.

  The name argument must be a quoted constant and is typically a
  symbol. It will be the ``name'' of the wormhole. A wormhole of that
  name will be created the first time either wormhole or
  [wormhole-eval] is called.

  Every wormhole name has a ``status.'' The status of a wormhole is
  stored outside of ACL2; it is inaccessible to the ACL2 user except
  when in the named wormhole. But the status of a wormhole may be set
  by the user from within the wormhole.

  Upon the first call of wormhole or wormhole-eval on a name, the
  status of that name is nil. But in general you should arrange for
  the status to be a cons. The status is set by the quoted lambda
  every time wormhole is called; but it may also be set in the form
  argument (the first form evaluated in the interactive loop) by
  assigning to the state global variable wormhole-status, as with

    (assign wormhole-status ...)

  or even by the user interacting with the loop if you do not exit the
  loop with the first form. The car of the cons should be either
  :ENTER or :SKIP and is called the wormhole's ``entry code.'' The
  entry code of nil or an unexpectedly shaped status is :ENTER. The
  cdr of the cons is arbitrary data maintained by you.

  When wormhole is invoked, the status of the specified name is
  incorporated into the manufactured wormhole state. In particular,
  inside the wormhole, the status is the value of the state global
  variable wormhole-status. That is, inside the wormhole, the status
  may be accessed by (@ wormhole-status) and set by (assign
  wormhole-status ...), f-get-global and f-put-global. When ld exits
  -- typically because the form :q was read by ld -- the then-current
  value of wormhole-status is hidden away so that it can be restored
  when this wormhole is entered again. The rest of the wormhole state
  is lost.

  This allows a sequence of entries and exits to a wormhole to maintain
  some history in the status and this information can be manipulated
  by ACL2 functions executing inside the wormhole.

  The second argument to wormhole must be a quoted lambda expression.
  We explain it later.

  The third argument, input, may be any term. The value of the term is
  passed into the manufactured wormhole state, allowing you to pass
  in information about the calling context. Inside the wormhole, the
  input is available via (@ wormhole-input). It could be reassigned
  via (assign wormhole-input ...), but there is no reason to do that.

  The fourth argument, form, may be any term; when [ld] is called on
  the manufactured wormhole state, the first form evaluated by ld
  will be the value of form. Note that form will be translated by ld.
  Errors, including guard violations, in the translation or execution
  of that first form will leave you in the interactive loop of the
  wormhole state.

  When used properly, the first form allows you to greet your user
  before reading the first interactive command or simply to do
  whatever computation you want to do inside the wormhole and exit
  silently. We give examples below.

  Manufacturing a wormhole state is relatively expensive; in addition,
  the forms executed by ld must be read, translated, and interpreted
  as with any user type-in. The entry-lambda offers a way to avoid
  this or, at least, to decide whether to incur that expense.

  Before the wormhole state is manufactured and entered, the
  entry-lambda is applied to the current wormhole status with
  [wormhole-eval]. That lambda application must produce a new
  wormhole status, which is stored as the wormhole's status. The
  entry code for the new status determines whether wormhole actually
  manufactures a wormhole state and calls ld.

  If the entry code for that new status is :ENTER the wormhole state is
  manufactured and entered; otherwise, the new status is simply saved
  as the most recent status but the wormhole state is not
  manufactured or entered. Note therefore that the entry-lambda may
  be used to perform two functions: (a) to determine if it is really
  necessary to manufacture a state and (b) to update the data in the
  wormhole status as a function of the old status without invoking
  ld.

  The entry-lambda must be a quoted lambda expression of at most one
  argument. Thus, the argument must be either

    '(lambda (whs) )

  or

    '(lambda () )

  Note the quote. If a formal, e.g., whs, is provided, it must be used
  as a variable in the lambda body. The lambda-expression may contain
  free variables, that is, the body may mention variables other than
  the lambda formal. These free variables are understood in the
  caller's environment. These conventions allow us to compile the
  entry-lambda application very efficiently when the guard has been
  verified.

  The guard on a call of wormhole is the conjunction of the guards on
  the arguments conjoined with the guard on the body of the
  entry-lambda. See [wormhole-eval] for a discussion of the guard on
  the lambda-expression.

  The functions [wormhole-statusp], [wormhole-entry-code],
  [wormhole-data], [set-wormhole-entry-code], [set-wormhole-data],
  and [make-wormhole-status] may be useful in manipulating entry
  codes and data in the entry-lambda.

  Note that you access and manipulate the wormhole's status in two
  different ways depending on whether you're ``outside'' of the
  wormhole applying the quoted lambda or ``inside'' the
  read-eval-print loop of the wormhole.

  OUTSIDE (wormhole-eval): access via the value of the lambda formal
  and set by returning the new status as the value of the lambda
  body.

  INSIDE (ld phase of wormhole): access via (@ wormhole-status), and
  set via (assign wormhole-status ...).

  Pragmatic Advice on Designing a Wormhole: Suppose you are using
  wormholes to implement some extra-logical utility. You must
  contemplate how you will use your wormhole's status to store hidden
  information. You might be tempted to exploit the entry code as part
  of the status. For example, you may think of :ENTER as indicating
  that your utility is ``turned on'' and :SKIP as indicating that
  your utility is ``turned off.'' We advise against such a design. We
  recommend you base your decisions on the wormhole data. We
  recommend that you set but not read the wormhole entry code to
  signal whether you wish to enter a full-fledged wormhole. To use
  the entry code as a flag overloads it and invites confusion when
  your facility is ``turned off'' but you have to enter the wormhole
  for some reason.

  For a behind-the-scenes description of how wormholes work, See
  [wormhole-implementation].

  Here are some sample situations handled by wormhole-eval and
  wormhole. Let the wormhole in question be named DEMO. Initially its
  status is NIL. The functions below all maintain the convention that
  the status is either nil or of the form (:key . lst), where :key is
  either :SKIP or :ENTER and lst is a true-list of arbitrary objects.
  But since there is no way to prevent the user from entering the
  DEMO wormhole interactively and doing something to the status, this
  convention cannot be enforced. Thus, the functions below do what we
  say they do, e.g., remember all the values of x ever seen, only if
  they're the only functions messing with the DEMO status. On the
  other hand, the guards of all the functions below can be verified.
  We have explicitly declared that the guards on the functions below
  are to be verified, to confirm that they can be. Guard verification
  is optional but wormholes (and wormhole-eval in particular) are
  more efficient when guards have been verified. All of the functions
  defined below return nil.

  The examples below build on each other. If you really want to
  understand wormholes we recommend that you evaluate each of the
  forms below, in the order they are discussed.

  Q. How do I create a wormhole that prints its status to the comment
  window?

    (defun demo-status ()
      (declare (xargs :verify-guards t))
      (wormhole-eval 'demo
                     '(lambda (whs)
                        (prog2$ (cw \"DEMO status:~%~x0~%\" whs)
                                whs))
                     nil))

  Note above that after printing the status to the comment window we
  return the new (unchanged) status whs. Had we just written the call
  of cw, which returns nil, the function would print the status and
  then set it to nil!

  Q. How do I use a wormhole to collect every symbol, x, passed to the
  function?

    (defun demo-collect (x)
      (declare (xargs :verify-guards t))
      (wormhole-eval 'demo
                     '(lambda (whs)
                        (make-wormhole-status whs
                                              (wormhole-entry-code whs)
                                              (if (symbolp x)
                                                  (cons x (wormhole-data whs))
                                                  (wormhole-data whs))))
                     nil))

  We could have also defined this function this way:

    (defun demo-collect (x)
      (declare (xargs :verify-guards t))
      (if (symbolp x)
          (wormhole-eval 'demo
                         '(lambda (whs)
                            (set-wormhole-data whs
                                               (cons x (wormhole-data whs))))
                         nil)
          nil))

  Both versions always return nil and both versions collect into the
  wormhole data field just the symbols x upon which demo-collect is
  called.

  Q. How do I use demo-collect? Below is a function that maps over a
  list and computes its length. But it has been annotated with a call
  to demo-collect on every element.

    (defun my-len (lst)
      (if (endp lst)
          0
          (+ 1
             (prog2$ (demo-collect (car lst))
                     (my-len (cdr lst))))))

  Thus, for example:

    ACL2 !>(my-len '(4 temp car \"Hi\" rfix))
    5
    ACL2 !>(demo-status)
    DEMO status:
    (:ENTER RFIX CAR TEMP)
    NIL
    ACL2 !>

  Q. How do I set the entry code to :ENTER or :SKIP according to
  whether name is a member-equal of the list of things seen so far?
  Note that we cannot check this condition outside the wormhole,
  because it depends on the list of things collected so far. We make
  the decision inside the lambda-expression. Note that we explicitly
  check that the guard of member-equal is satisfied by the current
  wormhole status, since we cannot rely on the invariant that no
  other function interferes with the status of the DEMO wormhole. In
  the case that the status is ``unexpected'' we act like the status
  is nil and set it to (:SKIP . NIL).

    (defun demo-set-entry-code (name)
      (declare (xargs :verify-guards t))
      (wormhole-eval 'demo
                     '(lambda (whs)
                        (if (true-listp (wormhole-data whs))
                            (set-wormhole-entry-code
                             whs
                             (if (member-equal name (wormhole-data whs))
                                 :ENTER
                                 :SKIP))
                            '(:SKIP . NIL)))
                     nil))

  Thus

    ACL2 !>(demo-set-entry-code 'monday)
    NIL
    ACL2 !>(demo-status)
    DEMO status:
    (:SKIP RFIX CAR TEMP)
    NIL
    ACL2 !>(demo-set-entry-code 'rfix)
    NIL
    ACL2 !>(demo-status)
    DEMO status:
    (:ENTER RFIX CAR TEMP)
    NIL
    ACL2 !>

  Q. Suppose I want to collect every symbol and then, if the symbol has
  an ABSOLUTE-EVENT-NUMBER property in the ACL2 logical world, print
  the defining event with :pe and then enter an interactive loop; but
  if the symbol does not have an ABSOLUTE-EVENT-NUMBER, don't print
  anything and don't enter an interactive loop.

  Here it is not important to know what ABSOLUTE-EVENT-NUMBER is; this
  example just shows that we can use a wormhole to access the ACL2
  logical world, even in a function that does not take the state as
  an argument.

  In the code below, we use wormhole instead of wormhole-eval, because
  we might have to access the logical world and enter an interactive
  loop. But for efficiency we do as much as we can inside the entry
  lambda, where we can check whether x is symbol and collect it into
  the data field of the wormhole status. Note that if we collect x,
  we also set the entry code to :ENTER. If we don't collect x, we set
  the entry code to :SKIP.

    (defun collect-symbols-and-print-events (x)
      (declare (xargs :guard t))
      (wormhole 'demo
                '(lambda (whs)
                   (if (symbolp x)
                       (make-wormhole-status whs
                                             :ENTER
                                             (cons x (wormhole-data whs)))
                       (set-wormhole-entry-code whs :SKIP)))

    ; The wormhole will not get past here is unless the entry code is
    ; :ENTER.  If we get past here, we manufacture a state, put
    ; x into (@ wormhole-input) and call ld in such a way that the
    ; first form executed is the quoted if-expression below.

                x
                '(if (getprop (@ wormhole-input)
                              'absolute-event-number
                              nil
                              'CURRENT-ACL2-WORLD (w state))
                     (er-progn
                      (mv-let (col state)
                              (fmt \"~%Entering a wormhole on the event name ~x0~%\"
                                   (list (cons #\\0 (@ wormhole-input)))
                                   *standard-co* state nil)
                              (declare (ignore col))
                              (value nil))
                      (pe (@ wormhole-input))
                      (set-ld-prompt 'wormhole-prompt state)
                      (value :invisible))
                     (value :q))
                :ld-verbose nil
                :ld-prompt nil))

  The ``first form'' (the if) asks whether the wormhole-input (i.e., x)
  has an ABSOLUTE-EVENT-NUMBER property. If so, it enters an
  [er-progn] to perform a sequence of commands, each of which returns
  an ACL2 error triple (see [programming-with-state]). The first form
  uses [fmt] to print a greeting. Since fmt returns (mv col state)
  and we must return an error triple, we embed the fmt term in an
  (mv-let (col state) ... (value nil)). The macro value takes an
  object and returns a ``normal return'' error triple. The second
  form in the er-progn uses the ACL2 history macro pe (see [pe]) to
  print the defining event for a name. The third form sets the prompt
  of this read-eval-print loop to the standard function for printing
  the wormhole prompt. We silenced the printing of the prompt when we
  called ld, thanks to the :ld-prompt nil keyword option. More on
  this below. The fourth form returns the error triple value
  :invisible as the value of the first form. This prevents ld from
  printing the value of the first form. Since we have not exited ld,
  that function just continues by reading the next form from the
  comment window. The user perceives this as entering a
  read-eval-print loop. We continue in the loop until the user types
  :q.

  On the other branch of the if, if the symbol has no
  ABSOLUTE-EVENT-NUMBER property, we execute the form (value :q),
  which is the programming equivalent of typing :q. That causes the
  ld to exit.

  The ld special variables set in the call to wormhole and further
  manipulated inside the first form to ld may require explanation. By
  setting :[ld-verbose] to nil, we prevent ld from printing the
  familiar ACL2 banner when ld is called. If :ld-verbose nil is
  deleted, then you would see something like

    ACL2 Version  4.0.  Level 2.
    ...
    Type (good-bye) to quit completely out of ACL2.

  before the first form is read and evaluated.

  By setting :[ld-prompt] to nil we prevent ld from printing the prompt
  before reading and evaluating the first form.

  As this example shows, to use full-blown wormholes you must
  understand the protocol for using wormhole status to control
  whether a wormhole state is manufactured for ld and you must also
  understand programming with [state] and the effects of the various
  [ld] ``special variables.''

  From the discussion above we see that wormholes can be used to create
  formatted output without passing in the ACL2 [state]. For examples
  see [cw], in particular the discussion at the end of that
  documentation topic.


Subtopics

  [Get-wormhole-status]
      Make a wormhole's status visible outside the wormhole

  [Make-wormhole-status]
      Creates a wormhole status object from given status, entry code, and
      data

  [Set-wormhole-data]
      Sets the wormhole data object in a wormhole status object

  [Set-wormhole-entry-code]
      Sets the wormhole entry code in a wormhole status object

  [Wormhole-data]
      Determines the wormhole data object from a wormhole status object

  [Wormhole-entry-code]
      Determines the wormhole entry code from a wormhole status object

  [Wormhole-eval]
      State-saving without state --- a short-cut to a parallel universe

  [Wormhole-implementation]
      Notes on how wormholes are implemented

  [Wormhole-p]
      Predicate to determine if you are inside a [wormhole]

  [Wormhole-statusp]
      Predicate recognizing well-formed wormhole status object")
 (WORMHOLE-DATA
  (WORMHOLE)
  "Determines the wormhole data object from a wormhole status object

    General Form:  (wormhole-data whs)

  See [wormhole]. Returns the wormhole data from a well-formed wormhole
  status whs. If whs is nil or not well-formed, the data is nil.")
 (WORMHOLE-ENTRY-CODE
  (WORMHOLE)
  "Determines the wormhole entry code from a wormhole status object

    General Form:  (wormhole-entry-code whs)

  See [wormhole]. Returns :ENTER or :SKIP given a well-formed wormhole
  status whs. If whs is nil or not well-formed, the entry code is
  :ENTER.")
 (WORMHOLE-EVAL
  (WORMHOLE)
  "State-saving without state --- a short-cut to a parallel universe

    Example Form:
    (wormhole-eval 'demo
       '(lambda (whs)
          (set-wormhole-data whs
                             (cons (cons name info)
                                   (wormhole-data whs))))
       (prog2$ info name))

    General Form:
    (wormhole-eval name lambda varterm)

  where name must be a quoted wormhole name and lambda must be a quoted
  lambda-expression. The lambda-expression must have at most one
  formal parameter but the body of the lambda-expression may contain
  other variables. Note that in the example form given above, the
  lambda has one formal, whs, and uses name and info freely. Note
  that the lambda is quoted. The third argument of wormhole-eval,
  varterm, is an arbitrary term that should mention all of the free
  variables in the lambda-expression. That term establishes your
  ``right'' to refer to those free variables in the environment in
  which the wormhole-eval expression occurs. The value of varterm is
  irrelevant and if you provide nil ACL2 will automatically provide a
  suitable term, namely a prog2$ form like the one shown in the
  example above.

  Aside: Exception for ACL2(p) (see [parallelism]) to the irrelevance
  of varterm. By default, calls of wormhole-eval employ a lock,
  *wormhole-lock*. To avoid such a lock, include the symbol
  :NO-WORMHOLE-LOCK in varterm; for example, you might replace a last
  argument of nil in wormhole-eval by :NO-WORMHOLE-LOCK. End of
  Aside.

  See [wormhole] for a full explanation of wormholes. Most relevant
  here is that every wormhole has a name and a status. The status is
  generally a cons pair whose car is the keyword :ENTER or the
  keyword :SKIP and whose cdr is an arbitrary object used to store
  information from one wormhole call to the next.

  Here is a succinct summary of wormhole-eval. If the lambda-expression
  has a local variable, wormhole-eval applies the lambda-expression
  to the wormhole status of the named wormhole and remembers the
  value as the new wormhole status. If the lambda has no formal
  parameter, the lambda is applied to no arguments and the value is
  the new status. Wormhole-eval returns nil. Thus, the formal
  parameter of the lambda-expression, if provided, denotes the
  wormhole's hidden status information; the value of the lambda is
  the new status and is hidden away.

  The guard of a wormhole-eval call is the guard of the body of the
  lambda-expression, with a fresh variable symbol used in place of
  the formal so that no assumptions are possible about the hidden
  wormhole status. If the guard of a wormhole-eval is verified, the
  call is macroexpanded inline to the evaluation of the body in a
  suitable environment. Thus, it can be a very fast way to access and
  change hidden state information, but the results must remain
  hidden. To do arbitrary computations on the hidden state (i.e., to
  access the ACL2 [state] or logical [world] or to interact with the
  user) see [wormhole].

  Functions that are probably useful in the body of the [lambda] or the
  guard of a function using wormhole-eval include the following:
  [wormhole-statusp], [wormhole-entry-code], [wormhole-data],
  [set-wormhole-entry-code], [set-wormhole-data], and
  [make-wormhole-status].

  See [wormhole] for a series of example uses of wormhole-eval and
  wormhole.

  For a behind-the-scenes description of how wormholes work, See
  [wormhole-implementation].")
 (WORMHOLE-IMPLEMENTATION
  (WORMHOLE)
  "Notes on how wormholes are implemented

  What happens when you call [wormhole]? Recall that a typical call of
  the function looks like this:

    (wormhole 'name
              '(lambda (whs) ...)
              input
              form
              :ld-verbose ...
              ...)

  A brief recap of the advertised semantics for wormhole establishes
  our terminology: When the above wormhole is evaluated, the
  lambda-expression is applied to the wormhole's status and the
  result is stored as the new status. Then, if the entry-code of the
  new status is :ENTER, [ld] is invoked on a copy of the ``current
  state'' with the specified ld- ``special variables;'' output is
  directed to the comment window. In that copy of the state, the
  state-global variable wormhole-input is set to the value of input
  and the state-global variable wormhole-status is set to the (new)
  status computed by the lambda-expression. Thus, inside the
  wormhole, (@ wormhole-input) returns the list of inputs, (@
  wormhole-status) returns the current status, and (assign
  wormhole-status ...) sets the wormhole's status. The first form
  executed by the ld is the value of form and unless that form
  returns (value :q), causing the ld to quit, the ld proceeds to take
  subsequent input from the comment window. Upon exiting from ld, the
  wormhole state ``evaporates.'' The wormhole's status upon exit is
  remembered and restored the next time the wormhole is entered.

  Here is what really happens.

  Each wormhole's status is recorded in an alist stored in a Common
  Lisp global variable named *wormhole-status-alist*. This variable
  is not part of the ACL2 state. If you exit the ACL2 loop with :q
  you can inspect the value of *wormhole-status-alist*. When the
  lambda-expression is evaluated it is applied to the value
  associated with name in the alist and the result is stored back
  into that alist. This step is performed by [wormhole-eval]. To make
  things more efficient, wormhole-eval is just a macro that expands
  into a let that binds the lambda formal to the current status and
  whose body is the lambda body. Guard clauses are generated from the
  body, with one exception: the lambda formal is replaced by a new
  variable so that no prior assumptions are available about the value
  of the the wormhole status.

  If the newly computed status has an entry code of :ENTER [ld] will be
  invoked. But we don't really copy state, of course. Instead we will
  invoke ld on the live state, which is always available in the von
  Neumann world in which ACL2 is implemented. To give the illusion of
  copying state, we will undo changes to the state upon exiting. To
  support this, we do two things just before invoking ld: we bind a
  Common Lisp special variable is to t to record that ACL2 is in a
  wormhole, and we initialize an accumulator that will be used to
  record state changes made while in the wormhole.

  Then ld is invoked, with first argument, standard-oi, being set to
  (cons form *standard-oi*). According to the standard semantics of
  ld, this reads and evaluates form and then the forms in the
  specified channel. The standard channels are directed to and from
  the terminal, which is the physical realization of the comment
  window.

  All state modifying functions of ACL2 are sensitive to the special
  variable that indicates that evaluation is in a wormhole. Some ACL2
  state-modifying functions (e.g., those that modify the file system
  like [write-byte$]) are made to cause an error if invoked inside a
  wormhole on a file other than the terminal. Others, like
  f-put-global (the function behind such features as assign and
  maintenance of the ACL2 logical world by such events as [defun] and
  [defthm]) are made to record the old value of the state component
  being changed; these records are kept in the accumulator
  initialized above.

  Upon exit from ld for any reason, the final value of (@
  wormhole-status) is stored in *wormhole-status-alist* and then the
  accumulator is used to ``undo'' all the state changes.

  Wormhole always returns nil.")
 (WORMHOLE-P
  (WORMHOLE)
  "Predicate to determine if you are inside a [wormhole]

  See [wormhole] for a discussion of wormholes. (Wormhole-p state)
  returns (mv nil t state) when evaluated inside a wormhole, else (mv
  nil nil state).")
 (WORMHOLE-STATUSP
  (WORMHOLE)
  "Predicate recognizing well-formed wormhole status object

    General Form:  (wormhole-statusp whs)

  See [wormhole]. This predicate is useful in guards for wormholes. It
  checks whether whs is either nil or a cons whose car is :ENTER or
  :SKIP.")
 (WRITE-BYTE$ (POINTERS) "See [io].")
 (XARGS
  (DEFUN DECLARE)
  "Extra arguments, for example to give [hints] to [defun]

  Common Lisp's [defun] function does not easily allow one to pass
  extra arguments such as ``[hints]''. ACL2 therefore supports a
  peculiar new declaration (see [declare]) designed explicitly for
  passing additional arguments to [defun] via a keyword-like syntax.
  This declaration can also be used with [defmacro], but only for
  xargs keyword :GUARD; so we restrict attention below to use of
  xargs in [defun] [events].

  The following declaration is nonsensical but does illustrate all of
  the xargs keywords for [defun] (which are the members of the list
  *xargs-keywords*).

    (declare (xargs :guard (symbolp x)
                    :guard-hints ((\"Goal\" :in-theory (theory batch1)))
                    :guard-debug t
                    :measure-debug t
                    :hints ((\"Goal\" :in-theory (theory batch1)))
                    :measure (- i j)
                    :ruler-extenders :basic
                    :mode :logic
                    :non-executable t
                    :normalize nil
                    :otf-flg t
                    :stobjs ($s)
                    :verify-guards t
                    :split-types t
                    :well-founded-relation my-wfr))

    General Form:
    (xargs :key1 val1 ... :keyn valn)

  where the keywords and their respective values are as shown below.
  Note that once ``inside'' the xargs form, the ``extra arguments''
  to [defun] are passed exactly as though they were keyword
  arguments.

  :[guard]
  :GUARD
  :GUARD
  Value is a term involving only the formals of the function being
  defined. The actual [guard] used for the definition is the
  conjunction of all the [guard]s and types (see [declare])
  [declare]d.

  :GUARD-HINTS
  Value: hints (see [hints]), to be used during the [guard]
  verification proofs as opposed to the termination proofs of the
  [defun].

  :GUARD-DEBUG
  Value: nil by default, else directs ACL2 to decorate each guard
  proof obligation with hypotheses indicating its sources. See
  [guard-debug].

  :MEASURE-DEBUG
  Value: nil by default, else directs ACL2 to decorate each measure
  proof obligation with hypotheses indicating its sources. See
  [measure-debug].

  :[hints]
  Value: hints (see [hints]), to be used during the termination proofs
  as opposed to the [guard] verification proofs of the [defun].

  :MEASURE
  Value is a term involving only the formals of the function being
  defined. This term is indicates what is getting smaller in the
  recursion. The well-founded relation with which successive measures
  are compared is [o<]. Also allowed is a special case, (:? v1 ...
  vk), where (v1 ... vk) enumerates a subset of the formal parameters
  such that some valid measure involves only those formal parameters.
  However, this special case is only allowed for definitions that are
  redundant (see [redundant-events]) or are executed when skipping
  proofs (see [skip-proofs]). Another special case is :MEASURE nil,
  which is treated the same as if :MEASURE is omitted.

  :RULER-EXTENDERS
  For recursive definitions (possibly mutually recursive), value
  controls termination analysis and the resulting stored induction
  scheme. See [ruler-extenders] for a discussion of legal values and
  their effects.

  :MODE
  Value is :[program] or :[logic], indicating the [defun] mode of the
  function introduced. See [defun-mode]. If unspecified, the [defun]
  mode defaults to the default [defun] mode of the current [world].
  To convert a function from :[program] mode to :[logic] mode, see
  [verify-termination].

  :NON-EXECUTABLE
  Value is normally t or nil (the default). Rather than stating
  :non-executable t directly, which requires :[logic] mode and that
  the definitional body has a certain form, we suggest using the
  macro defun-nx or defund-nx; see [defun-nx]. A third value of
  :non-executable for advanced users is :program, which is generated
  by expansion of defproxy forms; see [defproxy]. For another way to
  deal with non-executability, see [non-exec].

  :NORMALIZE
  Value is a flag telling [defun] whether to propagate [if] tests
  upward. Since the default is to do so, the value supplied is only
  of interest when it is nil. (See [defun]).

  :[otf-flg]
  Value is a flag indicating ``onward through the fog'' (see
  [otf-flg]).

  :STOBJS
  Value is either a single [stobj] name or a true list of stobj names
  (see [stobj] and see [defstobj], and perhaps see [defabsstobj]).
  Every stobj name among the formals of the function must be listed,
  if the corresponding actual is to be treated as a stobj. That is,
  if a function uses a stobj name as a formal parameter but the name
  is not declared among the :stobjs then the corresponding argument
  is treated as ordinary. The only exception to this rule is [state]:
  whether you include it or not, state is always treated as a
  single-threaded object. This declaration has two effects. One is to
  enforce the syntactic restrictions on single-threaded objects. The
  other is to strengthen the [guard] of the function being defined so
  that it includes conjuncts specifying that each declared
  single-threaded object argument satisfies the recognizer for the
  corresponding single-threaded object.

  :[verify-guards]
  Value is t or nil, indicating whether or not [guard]s are to be
  verified upon completion of the termination proof. This flag should
  only be t if the :mode is unspecified but the default [defun] mode
  is :[logic], or else the :mode is :[logic].

  :SPLIT-TYPES
  Value is t or nil, indicating whether or not [type]s are to be
  proved from the [guard]s. The default is nil, indicating that type
  declarations (see [declare]) contribute to the [guard]s. If the
  value is t, then instead, the expressions corresponding to the type
  declarations (see [type-spec]) are conjoined into a ``split-type
  expression,'' and guard verification insists that this term is
  implied by the specified :guard. Suppose for example that a
  definition has the following [declare] form.

    (declare (xargs :guard (p x y) :split-types t)
             (type integer x)
             (type (satisfies good-bar-p) y))

  Then for guard verification, (p x y) is assumed, and in addition to
  the usual proof obligations derived from the body of the
  definition, guard verification requires a proof that (p x y)
  implies both (integerp x) and (good-bar-p y). See community book
  demos/split-types-examples.lisp for small examples.

  :[well-founded-relation]
  Value is a function symbol that is known to be a well-founded
  relation in the sense that a rule of class :[well-founded-relation]
  has been proved about it. See [well-founded-relation].


Subtopics

  [Guard]
      Restricting the domain of a function

  [Otf-flg]
      Allow more than one initial subgoal to be pushed for induction")
 (XOR
  (BASICS ACL2-BUILT-INS)
  "Logical ``exclusive or''

  Xor is the ACL2 exclusive-or function. (xor P Q) means that either P
  or Q, but not both, is false (i.e., nil).

  Function: 

    (defun xor (p q)
           (declare (xargs :guard t))
           (if p (if q nil t) (if q t nil)))")
 (YOU_MUST_THINK_ABOUT_THE_USE_OF_A_FORMULA_AS_A_RULE
  (PAGES_WRITTEN_ESPECIALLY_FOR_THE_TOURS)
  "You Must Think about the Use of a Formula as a Rule

  [{IMAGE}]

  This is good and bad.

  The good news is that you can program ACL2's simplifier.

  The bad news is that when you command ACL2 to prove a theorem you
  must give some thought to how that theorem is to be used as a rule!

  For example, if after proving associativity-of-app as previously
  shown, you engaged in the mathematically trivial act of proving it
  again but with the equality reversed, you would have programmed
  ACL2's rewriter to loop forever.

  You can avoid adding any rule by using the command:

    (defthm associativity-of-app
      (equal (app (app a b) c)
             (app a (app b c)))
      :rule-classes nil)

  [{IMAGE}]")
 (ZERO-TEST-IDIOMS
  (NUMBERS)
  "How to test for 0

  Below are six commonly used idioms for testing whether x is 0. [Zip]
  and [zp] are the preferred termination tests for recursions down
  the integers and naturals, respectively.

    idiom       logical              guard                 primary
                meaning                                 compiled code*

    (equal x 0) (equal x 0)          t                   (equal x 0)

    (eql x 0)   (equal x 0)          t                   (eql x 0)

    (zerop x)   (equal x 0)          x is a number       (= x 0)

    (= x 0)     (equal x 0)          x is a number       (= x 0)

    (zip x)     (equal (ifix x) 0)   x is an integer     (= x 0)

    (zp x)      (equal (nfix x) 0)   x is a natural      (int= x 0)

    (zpf x)     (equal (nfix x) 0)   x is a fixnum >= 0  (eql (the-fixnum x) 0)

  *See [guards-and-evaluation], especially the subsection titled
  ``Guards and evaluation V: efficiency issues''. Primary code is
  relevant only if [guard]s are verified. The ``compiled code'' shown
  is only suggestive.

  The first four idioms all have the same logical meaning and differ
  only with respect to their executability and efficiency. In the
  absence of compiler optimizing, (= x 0) is probably the most
  efficient, (equal x 0) is probably the least efficient, and (eql x
  0) is in between. However, an optimizing compiler could always
  choose to compile (equal x 0) as (eql x 0) and, in situations where
  x is known at compile-time to be numeric, (eql x 0) as (= x 0). So
  efficiency considerations must, of course, be made in the context
  of the host compiler.

  Note also that (zerop x) and (= x 0) are indistinguishable. They have
  the same meaning and the same [guard], and can reasonably be
  expected to generate equally efficient code.

  Note that (zip x) and (zp x) do not have the same logical meanings as
  the others or each other. They are not simple tests for equality to
  0. They each coerce x into a restricted domain, [zip] to the
  integers and [zp] to the natural numbers, choosing 0 for x when x
  is outside the domain. Thus, 1/2, #c(1 3), and 'abc, for example,
  are all ``recognized'' as zero by both [zip] and [zp]. But [zip]
  reports that -1 is different from 0 while [zp] reports that -1
  ``is'' 0. More precisely, (zip -1) is nil while (zp -1) is t.

  Note that the last five idioms all have [guard]s that restrict their
  Common Lisp executability. If these last five are used in
  situations in which [guard]s are to be verified, then proof
  obligations are incurred as the price of using them. If guard
  verification is not involved in your project, then the first five
  can be thought of as synonymous.

  [Zip] and [zp] are not provided by Common Lisp but are ACL2-specific
  functions. Why does ACL2 provide these functions? The answer has to
  do with the admission of recursively defined functions and
  efficiency. [Zp] is provided as the zero-test in situations where
  the controlling formal parameter is understood to be a natural
  number. [Zip] is analogously provided for the integer case. We
  illustrate below.

  Here is an admissible definition of factorial

    (defun fact (n) (if (zp n) 1 (* n (fact (1- n)))))

  Observe the classic recursion scheme: a test against 0 and recursion
  by [1-]. Note however that the test against 0 is expressed with the
  [zp] idiom. Note also the absence of a [guard] making explicit our
  intention that n is a natural number.

  This definition of factorial is readily admitted because when (zp n)

  is false (i.e., nil) then n is a natural number other than 0 and so
  (1- n) is less than n. The base case, where (zp n) is true, handles
  all the ``unexpected'' inputs, such as arise with (fact -1) and
  (fact 'abc). When calls of fact are evaluated, (zp n) checks
  (integerp n) and (> n 0). [Guard] verification is unsuccessful for
  this definition of fact because [zp] requires its argument to be a
  natural number and there is no [guard] on fact, above. Thus the
  primary raw lisp for fact is inaccessible and only the :[logic]
  definition (which does runtime ``type'' checking) is used in
  computation. In summary, this definition of factorial is easily
  admitted and easily manipulated by the prover but is not executed
  as efficiently as it could be.

  Runtime efficiency can be improved by adding a [guard] to the
  definition.

    (defun fact (n)
      (declare (xargs :guard (and (integerp n) (>= n 0))))
      (if (zp n) 1 (* n (fact (1- n)))))

  This [guard]ed definition has the same termination conditions as
  before -- termination is not sensitive to the [guard]. But the
  [guard]s can be verified. This makes the primary raw lisp
  definition accessible during execution. In that definition, the (zp
  n) above is compiled as (= n 0), because n will always be a natural
  number when the primary code is executed. Thus, by adding a [guard]
  and verifying it, the elegant and easily used definition of
  factorial is also efficiently executed on natural numbers.

  Now let us consider an alternative definition of factorial in which
  (= n 0) is used in place of (zp n).

    (defun fact (n) (if (= n 0) 1 (* n (fact (1- n)))))

  This definition does not terminate. For example (fact -1) gives rise
  to a call of (fact -2), etc. Hence, this alternative is
  inadmissible. A plausible response is the addition of a [guard]
  restricting n to the naturals:

    (defun fact (n)
     (declare (xargs :guard (and (integerp n) (>= n 0))))
     (if (= n 0) 1 (* n (fact (1- n)))))

  But because the termination argument is not sensitive to the [guard],
  it is still impossible to admit this definition. To influence the
  termination argument one must change the conditions tested. Adding
  a runtime test that n is a natural number would suffice and allow
  both admission and [guard] verification. But such a test would slow
  down the execution of the compiled function.

  The use of (zp n) as the test avoids this dilemma. [Zp] provides the
  logical equivalent of a runtime test that n is a natural number but
  the execution efficiency of a direct [=] comparison with 0, at the
  expense of a [guard] conjecture to prove. In addition, if [guard]
  verification and most-efficient execution are not needed, then the
  use of (zp n) allows the admission of the function without a
  [guard] or other extraneous verbiage.

  While general rules are made to be broken, it is probably a good idea
  to get into the habit of using (zp n) as your terminating ``0
  test'' idiom when recursing down the natural numbers. It provides
  the logical power of testing that n is a non-0 natural number and
  allows efficient execution.

  We now turn to the analogous function, [zip]. [Zip] is the preferred
  0-test idiom when recursing through the integers toward 0. [Zip]
  considers any non-integer to be 0 and otherwise just recognizes 0.
  A typical use of [zip] is in the definition of [integer-length],
  shown below. (ACL2 can actually accept this definition, but only
  after appropriate lemmas have been proved.)

    (defun integer-length (i)
      (declare (xargs :guard (integerp i)))
      (if (zip i)
          0
        (if (= i -1)
          0
          (+ 1 (integer-length (floor i 2))))))

  Observe that the function recurses by (floor i 2). Hence, calling the
  function on 25 causes calls on 12, 6, 3, 1, and 0, while calling it
  on -25 generates calls on -13, -7, -4, -2, and -1. By making (zip
  i) the first test, we terminate the recursion immediately on
  non-integers. The [guard], if present, can be verified and allows
  the primary raw lisp definition to check (= i 0) as the first
  terminating condition (because the primary code is executed only on
  integers).")
 (ZEROP
  (NUMBERS ACL2-BUILT-INS)
  "Test an acl2-number against 0

  (zerop x) is t if x is 0 and is nil otherwise. Thus, it is logically
  equivalent to (equal x 0).

  (Zerop x) has a [guard] requiring x to be numeric and can be expected
  to execute more efficiently than (equal x 0) in properly [guard]ed
  compiled code.

  In recursions down the natural numbers, (zp x) is preferred over
  (zerop x) because the former coerces x to a natural and allows the
  termination proof. In recursions through the integers, (zip x) is
  preferred. See [zero-test-idioms].

  Zerop is a Common Lisp function. See any Common Lisp documentation
  for more information.

  Function: 

    (defun zerop (x)
           (declare (xargs :guard (acl2-numberp x)))
           (eql x 0))")
 (ZIP
  (NUMBERS ACL2-BUILT-INS)
  "Testing an ``integer'' against 0

  (Zip i) is logically equivalent to (equal (ifix i) 0) and is the
  preferred termination test for recursion through the integers. (Zip
  i) returns t if i is 0 or not an integer; it returns nil otherwise.
  Thus,

    i         (zip i)
    3         nil
    0         t
    -2        nil
    5/2       t
    #c(1 3)   t
    'abc      t

  (Zip i) has a [guard] requiring i to be an integer.

  For a discussion of the various idioms for testing against 0, see
  [zero-test-idioms].

  Zip is typically used as the termination test in recursions through
  the integers. It has the advantage of ``coercing'' its argument to
  an integer and hence allows the definition to be admitted without
  an explicit type check in the body. [Guard] verification allows zip
  to be compiled as a direct [=]-comparision with 0.

  Function: 

    (defun zip (x)
           (declare (xargs :guard (integerp x)))
           (if (integerp x) (= x 0) t))")
 (ZP
  (NUMBERS ACL2-BUILT-INS)
  "Testing a ``natural'' against 0

  (Zp n) is logically equivalent to (equal (nfix n) 0) and is the
  preferred termination test for recursion down the natural numbers.
  (Zp n) returns t if n is 0 or not a natural number; it returns nil
  otherwise. Thus, in the ACL2 logic (ignoring the issue of
  [guard]s):

     n       (zp n)
    3         nil
    0         t
    -1        t
    5/2       t
    #c(1 3)   t
    'abc      t

  (Zp n) has a [guard] requiring n to be a natural number.

  For a discussion of the various idioms for testing against 0, see
  [zero-test-idioms].

  Zp is typically used as the termination test in recursions down the
  natural numbers. It has the advantage of ``coercing'' its argument
  to a natural and hence allows the definition to be admitted without
  an explicit type check in the body. [Guard] verification allows zp
  to be compiled as a direct [=]-comparision with 0.

  Function: 

    (defun zp (x)
           (declare (xargs :guard (and (integerp x) (<= 0 x))))
           (if (integerp x) (<= x 0) t))")
 (ZPF
  (NUMBERS ACL2-BUILT-INS)
  "Testing a nonnegative fixnum against 0

  Zpf is exactly the same as [zp], except that zpf is intended for, and
  faster for, fixnum arguments. Its guard is specified with a type
  declaration, (type (unsigned-byte 29) x). (See [declare] and see
  [type-spec].) Also see [zp].

  Function: 

    (defun zpf (x)
           (declare (type (unsigned-byte 29) x))
           (if (integerp x) (<= x 0) t))")
 (ACL2-PC::=
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) attempt an equality (or equivalence) substitution

    Examples:
    =     -- replace the current subterm by a term equated to it in
             one of the hypotheses (if such a term exists)
    (= x) -- replace the current subterm by x, assuming that the prover
             can show that they are equal
    (= (+ x y) z)
          -- replace the term (+ x y) by the term z inside the current
             subterm, assuming that the prover can prove
             (equal (+ x y) z) from the current top-level hypotheses
             or that this term or (equal z (+ x y)) is among the
             current top-level hypotheses or the current governors
    (= & z)
          -- exactly the same as above, if (+ x y) is the current
             subterm
    (= (+ x y) z :hints :none)
          -- same as (= (+ x y) z), except that a new subgoal is
             created with the current goal's hypotheses and governors
             as its top-level hypotheses and (equal (+ x y) z) as its
             conclusion
    (= (+ x y) z 0)
          -- exactly the same as immediately above
    (= (p x)
       (p y)
       :equiv iff
       :otf-flg t
       :hints ((\"Subgoal 2\" :BY FOO) (\"Subgoal 1\" :use bar)))
          -- same as (= (+ x y) z), except that the prover uses
             the indicated values for otf-flg and hints, and only
             propositional (iff) equivalence is used (however, it
             must be that only propositional equivalence matters at
             the current subterm)

    General Form:
    (= &optional x y &rest keyword-args)

  If terms x and y are supplied, then replace x by y inside the current
  subterm if they are ``known'' to be ``equal''. Here ``known'' means
  the following: the prover is called as in the prove command (using
  keyword-args) to prove (equal x y), except that a keyword argument
  :equiv is allowed, in which case (equiv x y) is proved instead,
  where equiv is that argument. (See below for how governors are
  handled.)

  Actually, keyword-args is either a single non-keyword or is a list of
  the form ((kw-1 x-1) ... (kw-n x-n)), where each kw-i is one of the
  keywords :equiv, :otf-flg, :hints. Here :equiv defaults to equal if
  the argument is not supplied or is nil, and otherwise should be the
  name of an ACL2 equivalence relation. :Otf-flg and :hints give
  directives to the prover, as explained above; also see
  [ACL2-pc::prove]. However, no prover call is made if :hints is a
  non-nil atom or if keyword-args is a single non-keyword (more on
  this below).

  Remarks on defaults

  (1) If there is only one argument, say a, then x defaults to the
  current subterm, in the sense that x is taken to be the current
  subterm and y is taken to be a.

  (2) If there are at least two arguments, then x may be the symbol &,
  which then represents the current subterm. Thus, (= a) is
  equivalent to (= & a). (Obscure point: actually, & can be in any
  package, except the keyword package.)

  (3) If there are no arguments, then we look for a top-level
  hypothesis or a governor of the form (equal c u) or (equal u c),
  where c is the current subterm. In that case we replace the current
  subterm by u.

  As with the prove command, we allow goals to be given ``bye''s in the
  proof, which may be generated by a :hints keyword argument in
  keyword-args. These result in the creation of new subgoals.

  A proof is attempted unless the :hints argument is a non-nil atom
  other than :none, or unless there is one element of keyword-args
  and it is not a keyword. In that case, if there are any hypotheses
  in the current goal, then what is attempted is a proof of the
  implication whose antecedent is the conjunction of the current
  hypotheses and governors and whose conclusion is the appropriate
  equal term.

  Remarks: (1) It is allowed to use abbreviations in the hints. (2) The
  keyword :none has the special role as a value of :hints that is
  shown clearly in an example above. (3) If there are governors, then
  the new subgoal has as additional hypotheses the current governors.")
 (ACL2-PC::ACL2-WRAP
  (PROOF-CHECKER-COMMANDS)
  "(macro) same as (lisp x)

    Example:
    (acl2-wrap (pe :here))

    General Form:
    (acl2-wrap form)

  Same as (lisp form). This is provided for interface tools that want
  to be able to execute the same form in raw Lisp, in the
  proof-checker, or in the ACL2 top-level loop (lp).")
 (ACL2-PC::ADD-ABBREVIATION
  (PROOF-CHECKER-COMMANDS)
  "(primitive) add an abbreviation

  Example: (add-abbreviation v (* x y)) causes future occurrences of (*
  x y) to be printed as (? v), until (unless) a corresponding
  invocation of remove-abbreviations occurs. In this case we say that
  v ``abbreviates'' (* x y).

    General Form:
    (add-abbreviation var &optional raw-term)

  Let var be an abbreviation for raw-term, if raw-term is supplied,
  else for the current subterm. Note that var must be a variable that
  does not already abbreviate some term.

  A way to think of abbreviations is as follows. Imagine that whenever
  an abbreviation is added, say v abbreviates expr, an entry
  associating v to expr is made in an association list, which we will
  call ``*abbreviations-alist*''. Then simply imagine that ? is a
  function defined by something like:

    (defun ? (v)
      (let ((pair (assoc v *abbreviations-alist*)))
        (if pair (cdr pair)
          (error ...))))

  Of course the implementation isn't exactly like that, since the
  ``constant'' *abbreviations-alist* actually changes each time an
  add-abbreviation instruction is successfully invoked. Nevertheless,
  if one imagines an appropriate redefinition of the ``constant''
  *abbreviations-alist* each time an add-abbreviation is invoked,
  then one will have a clear model of the meaning of such an
  instruction.

  The effect of abbreviations on output is that before printing a term,
  each subterm that is abbreviated by a variable v is first replaced
  by (? v).

  The effect of abbreviations on input is that every built-in
  proof-checker command accepts abbreviations wherever a term is
  expected as an argument, i.e., accepts the syntax (? v) whenever v
  abbreviates a term. For example, the second argument of
  add-abbreviation may itself use abbreviations that have been
  defined by previous add-abbreviation instructions.

  See also [ACL2-pc::remove-abbreviations] and see
  [ACL2-pc::show-abbreviations].")
 (ACL2-PC::AL
  (PROOF-CHECKER-COMMANDS)
  "(macro) same as apply-linear

    Example:
    (al 3)

  See [ACL2-pc::apply-linear], as al and apply-linear are identical.")
 (ACL2-PC::APPLY-LINEAR
  (PROOF-CHECKER-COMMANDS)
  "(primitive) apply a linear rule

    Examples:
    (apply-linear foo)
       -- apply the linear rule `foo'
    (apply-linear (:linear foo))
       -- same as above
    (apply-linear 2)
       -- apply the second linear rule, as displayed by show-linears
    rewrite
       -- apply the first rewrite rule, as displayed by show-rewrites
    (apply-linear foo ((y 7)))
       -- apply the linear rule foo with the substitution
          that associates 7 to the ``free variable'' y
    (apply-linear foo ((x 2) (y 3)) t)
       -- apply the linear rule foo by substituting 2 and 3 for free
          variables x and y, respectively, and also binding all other
          free variables possible by using the current context
          (hypotheses and governors)

    General Form:
    (apply-linear &optional rule-id substitution instantiate-free)

  Add a new top-level hypothesis by applying a [linear] rule to the
  current subterm. The new hypothesis will be created according to
  the information provided by the show-linears (sls) command.

  A short name for this command is al.

  We assume familiarity with the [proof-checker]'s rewrite (r) command
  (see [ACL2-pc::rewrite]). In brief, the apply-linear command is an
  analogue of the rewrite command, but for [linear] rules in place of
  [rewrite] rules. There is a significant difference: for the
  apply-linear command, instead of rewriting the current subterm as
  is done by the rewrite command, the conclusion of the applicable
  linear rule, suitably instantiated, is added as a new (and last)
  top-level hypothesis of the goal. There is another significant
  difference: the automatic application of [linear] rules in the
  theorem prover is somewhat more complex than the automatic
  application of [rewrite] rules, so the apply-linear command may not
  correspond as closely to the prover's automatic use of a linear
  rule as the rewrite command corresponds to the prover's automatic
  use of a rewrite rule.

  Below, we refer freely to the [documentation] for the proof-checker's
  rewrite command (see [ACL2-pc::rewrite]).

  The rule-id is treated just as it is by the rewrite command. If
  rule-id is a positive integer n, then the nth rule as displayed by
  show-linears is the one that is applied. If rule-id is nil or is
  not supplied, then it is treated as the number 1. Otherwise,
  rule-id should be either a symbol or else a :linear [rune]. If a
  symbol is supplied, then any [linear] rule of that name may be
  used.

  Consider the following example. Suppose that the current subterm is
  (< (g (h y)) y) and that foo is the name of the following linear
  rule.

    (implies (true-listp x)
             (< (g x) 15))

  Then the instruction (apply-linear foo) applies foo by adding a new
  hypothesis (< (g (h y)) 15). In addition, a new goal with
  conclusion (true-listp y) is created unless the current context
  (top-level hypotheses and governors) implies (true-listp y) using
  only ``trivial reasoning'', just as for the rewrite command.

  If the rule-id argument is a number or is not supplied, then the
  system will store an instruction of the form (apply-linear name
  ...), where name is the name of a [linear] rule; this is in order
  to make it easier to replay instructions when there have been
  changes to the history. Except: instead of the name (whether the
  name is supplied or calculated), the system stores the [rune] if
  there is any chance of ambiguity. (Formally, ``ambiguity'' here
  means that the rune being applied is of the form (:rewrite name .
  index), where index is not nil.)

  Speaking in general, then, an apply-linear instruction works as
  follows.

  First, a [linear] rule is selected according to the arguments of the
  instruction. The selection is made as explained under ``General
  Form'' above.

  Next, a trigger term of the rule (see [linear]) is matched with the
  current subterm, i.e., a substitution unify-subst is found such
  that if one instantiates that trigger term of the rule with
  unify-subst, then one obtains the current subterm. If this match
  fails, then the instruction fails.

  Next, an attempt is made to relieve (discharge) the hypotheses,
  possibly handling free variables (see [free-variables]), exactly as
  is done with hypotheses when applying the [proof-checker] command,
  rewrite (r).

  Finally, the instruction is applied exactly as the rewrite
  instruction is applied, except instead of replacing the current
  subterm, the rule's instantiated conclusion is added to the end of
  the list of top-level hypotheses of the goal.

  Note that as for the rewrite command, the substitution argument
  should be a list whose elements have the form (variable term),
  where term may contain abbreviations.")
 (ACL2-PC::BASH
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) call the ACL2 theorem prover's simplifier

    Examples:
    bash -- attempt to prove the current goal by simplification alone
    (bash (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
         -- attempt to prove the current goal by simplification alone,
            with the indicated hints

    General Form:
    (bash &rest hints)

  Call the theorem prover's simplifier, creating a subgoal for each
  resulting goal.

  Notice that unlike prove, the arguments to bash are spread out, and
  are all hints.

  Bash is similar to reduce in that neither of these allows induction.
  But bash only allows simplification, while reduce allows processes
  eliminate-destructors, fertilize, generalize, and
  eliminate-irrelevance.

  Remark: All forcing rounds will be skipped (unless there are more
  than 15 subgoals generated in the first forcing round, an injustice
  that should be rectified, but might remain unless there is pressure
  to fix it).")
 (ACL2-PC::BDD
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) prove the current goal using bdds

    Examples:
    bdd
    (bdd :vars nil :bdd-constructors (cons) :prove t :literal :all)

  The general form is as shown in the latter example above, but with
  any keyword-value pairs omitted and with values as described for
  the :[bdd] hint; see [hints].

  This command simply calls the theorem prover with the indicated bdd
  hint for the top-level goal. Note that if :prove is t (the
  default), then the proof will succeed entirely using bdds or else
  it will fail immediately. See [bdd].")
 (ACL2-PC::BK
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) move backward one argument in the enclosing term

    Example and General Form:
    bk

  For example, if the conclusion is (= x (* (- y) z)) and the current
  subterm is (* (- y) z), then after executing bk, the current
  subterm will be x.

  Move to the previous argument of the enclosing term.

  This is the same as up followed by (dive n-1), where n is the
  position of the current subterm in its parent term in the
  conclusion. Thus in particular, the nx command fails if one is
  already at the top of the conclusion.

  Also see [ACL2-pc::up], [ACL2-pc::dive], [ACL2-pc::top], and
  [ACL2-pc::nx].")
 (ACL2-PC::BOOKMARK
  (PROOF-CHECKER-COMMANDS)
  "(macro) insert matching ``bookends'' comments

    Example:
    (bookmark final-goal)

    General Form:
    (bookmark name &rest instruction-list)

  Run the instructions in instruction-list (as though this were a call
  of do-all; see [ACL2-pc::do-all]), but first insert a begin bookend
  with the given name and then, when the instructions have been
  completed, insert an end bookend with that same name. See
  [ACL2-pc::comm] for an explanation of bookends and how they can
  affect the display of instructions.")
 (ACL2-PC::CASESPLIT
  (PROOF-CHECKER-COMMANDS)
  "(primitive) split into two cases

    Example:
    (casesplit (< x y)) -- assuming that we are at the top of the
                           conclusion, add (< x y) as a new top-level
                           hypothesis in the current goal, and create a
                           subgoal identical to the current goal except
                           that it has (not (< x y)) as a new top-level
                           hypothesis

    General Form:
    (casesplit expr &optional use-hyps-flag do-not-flatten-flag)

  When the current subterm is the entire conclusion, this instruction
  adds expr as a new top-level hypothesis, and create a subgoal
  identical to the existing current goal except that it has the
  negation of expr as a new top-level hypothesis. Also see
  [ACL2-pc::claim]. The optional arguments control the use of
  governors and the ``flattening'' of new hypotheses, as we now
  explain.

  The argument use-hyps-flag is only of interest when there are
  governors. (To read about governors, see [ACL2-pc::hyps]). In that
  case, if use-hyps-flag is not supplied or is nil, then the
  description above is correct; but otherwise, it is not expr but
  rather it is (implies govs expr) that is added as a new top-level
  hypothesis (and whose negation is added as a top-level hypothesis
  for the new goal), where govs is the conjunction of the governors.

  If do-not-flatten-flag is supplied and not nil, then that is all
  there is to this command. Otherwise (thus this is the default),
  when the claimed term (first argument) is a conjunction (and) of
  terms and the claim instruction succeeds, then each (nested)
  conjunct of the claimed term is added as a separate new top-level
  hypothesis. Consider the following example, assuming there are no
  governors.

    (casesplit (and (and (< x y) (integerp a)) (equal r s)) t)

  Three new top-level hypotheses are added to the current goal, namely
  (< x y), (integerp a), and (equal r s). In that case, only one
  hypothesis is added to create the new goal, namely the negation of
  (and (< x y) (integerp a) (equal r s)). If the negation of this
  term had been claimed, then it would be the other way around: the
  current goal would get a single new hypothesis while the new goal
  would be created by adding three hypotheses.

  Remark: It is allowed to use abbreviations in the hints.")
 (ACL2-PC::CG
  (PROOF-CHECKER-COMMANDS)
  "(macro) change to another goal.

    Examples:
    (cg (main . 1)) -- change to the goal (main . 1)
    cg              -- change to the next-to-top goal

    General Form:
    (CG &OPTIONAL goal-name)

  Same as (change-goal goal-name t), i.e. change to the indicated and
  move the current goal to the end of the goal stack.")
 (ACL2-PC::CHANGE-GOAL
  (PROOF-CHECKER-COMMANDS)
  "(primitive) change to another goal.

    Examples:
    (change-goal (main . 1)) -- change to the goal (main . 1)
    change-goal              -- change to the next-to-top goal

    General Form:
    (change-goal &optional goal-name end-flg)

  Change to the goal with the name goal-name, i.e. make it the current
  goal. However, if goal-name is nil or is not supplied, then it
  defaults to the next-to-top goal, i.e., the second goal in the
  stack of goals. If end-flg is supplied and not nil, then move the
  current goal to the end of the goal stack; else merely swap it with
  the next-to-top goal. Also see [ACL2-pc::cg].")
 (ACL2-PC::CL-PROC
  (PROOF-CHECKER-COMMANDS)
  "(macro) same as clause-processor

  This is simply an abbreviation for [ACL2-pc::clause-processor].")
 (ACL2-PC::CLAIM
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) add a new hypothesis

    Examples:
    (claim (< x y))   -- attempt to prove (< x y) from the current
                         top-level hypotheses and if successful, then
                         add (< x y) as a new top-level hypothesis in
                         the current goal
    (claim (< x y)
           :otf-flg t
           :hints ((\"Goal\" :induct t)))
                      -- as above, but call the prover using the
                         indicated values for the otf-flg and hints
    (claim (< x y) 0) -- as above, except instead of attempting to
                         prove (< x y), create a new subgoal with the
                         same top-level hypotheses as the current goal
                         that has (< x y) as its conclusion
    (claim (< x y) :hints :none)
                      -- same as immediately above

    General Form:
    (claim expr &rest rest-args)

  This command creates a new subgoal with the same top-level hypotheses
  as the current goal but with a conclusion of expr. If rest-args is
  a non-empty list headed by a non-keyword, then there will be no
  proof attempted for the new subgoal. With that possible exception,
  rest-args should consist of keyword arguments. The keyword argument
  :do-not-flatten controls the ``flattening'' of new hypotheses, just
  as with the casesplit command (see [ACL2-pc::casesplit]). The
  remaining rest-args are used with a call the prove command on the
  new subgoal, except that if :hints is a non-nil atom, then the
  prover is not called --- rather, this is the same as the situation
  described above, where rest-args is a non-empty list headed by a
  non-keyword.

  Remarks: (1) Unlike the casesplit command, the claim command is
  completely insensitive to governors. (2) It is allowed to use
  abbreviations in the hints. (3) The keyword :none has the special
  role as a value of :hints that is shown clearly in an example
  above.")
 (ACL2-PC::CLAUSE-PROCESSOR
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) use a clause-processor

    Example:
    (cl-proc :function
             note-fact-clause-processor
            :hint '(equal a a)) -- Invoke the indicated clause processor function
            with the indicated hint argument (see the beginning of community book
            books/clause-processors/basic-examples.lisp.

    General Form:
    (cl-proc &rest cl-proc-args)

  Invoke a clause-processor as indicated by cl-proc-args, which is a
  list of arguments that can serve as the value of a
  :[clause-processor] hint; see [hints].

  This command calls the prove command, and hence should only be used
  at the top of the conclusion.")
 (ACL2-PC::COMM
  (PROOF-CHECKER-COMMANDS)
  "(macro) display instructions from the current interactive session

    Examples:
    comm
    (comm 10)

    General Form:
    (comm &optional n)

  Prints out instructions in reverse order. This is actually the same
  as (commands n t) --- or, (commands nil t) if n is not supplied. As
  for commands (see [ACL2-pc::commands]), the final argument of t
  causes suppression of instructions occurring between so-called
  ``matching bookends,'' which we now explain.

  A ``begin bookend'' is an instruction of the form

    (COMMENT :BEGIN x . y).

  Similarly, an ``end bookend'' is an instruction of the form

    (COMMENT :END x' . y').

  The ``name'' of the first bookend is x and the ``name'' of the second
  bookend is x'. When such a pair of instructions occurs in the
  current state-stack, we call them ``matching bookends'' provided
  that they have the same name (i.e. x equals x') and if no other
  begin or end bookend with name x occurs between them. The idea now
  is that comm hides matching bookends together with the instructions
  they enclose. Here is a more precise explanation of this
  ``hiding''; probably there is no value in reading on!

  A comm instruction hides bookends in the following manner. (So does a
  comment instruction when its second optional argument is supplied
  and non-nil.) First, if the first argument n is supplied and not
  nil, then we consider only the last n instructions from the
  state-stack; otherwise, we consider them all. Now the resulting
  list of instructions is replaced by the result of applying the
  following process to each pair of matching bookends: the pair is
  removed, together with everything in between the begin and end
  bookend of the pair, and all this is replaced by the
  ``instruction''

    (\"***HIDING***\" :COMMENT :BEGIN name ...)

  where (comment begin name ...) is the begin bookend of the pair.
  Finally, after applying this process to each pair of matching
  bookends, each begin bookend of the form (comment begin name ...)
  that remains is replaced by

    (\"***UNFINISHED***\" :COMMENT :BEGIN name ...) .")
 (ACL2-PC::COMMANDS
  (PROOF-CHECKER-COMMANDS)
  "(macro) display instructions from the current interactive session

    Examples:
    commands
    (commands 10 t)

    General Forms:

    commands or (commands nil)
    Print out all the instructions (in the current state-stack) in
    reverse order, i.e. from the most recent instruction to the starting
    instruction.

    (commands n) [n a positive integer]
    Print out the most recent n instructions (in the current
    state-stack), in reverse order.

    (commands x abbreviate-flag)
    Same as above, but if abbreviate-flag is non-NIL, then do not
    display commands between ``matching bookends''.  See documentation
    for comm for an explanation of matching bookends.

  Remark: If there are more than n instructions in the state-stack,
  then (commands n) is the same as commands (and also, (commands n
  abb) is the same as (commands nil abb)).")
 (ACL2-PC::COMMENT
  (PROOF-CHECKER-COMMANDS)
  "(primitive) insert a comment

    Example:
    (comment now begin difficult final goal)

    General Form:
    (comment &rest x)

  This instruction makes no change in the state except to insert the
  comment instruction.

  Some comments can be used to improve the display of commands; see
  [ACL2-pc::comm].")
 (ACL2-PC::CONTRADICT
      (PROOF-CHECKER-COMMANDS)
      "(macro) same as contrapose

  See [ACL2-pc::contrapose].")
 (ACL2-PC::CONTRAPOSE
  (PROOF-CHECKER-COMMANDS)
  "(primitive) switch a hypothesis with the conclusion, negating both

    Example:
    (contrapose 3)

    General Form:
    (contrapose &optional n)

  The (optional) argument n should be a positive integer that does not
  exceed the number of hypotheses. Negate the current conclusion and
  make it the nth hypothesis, while negating the current nth
  hypothesis and making it the current conclusion. If no argument is
  supplied then the effect is the same as for (contrapose 1).

  Remark: By ``negate'' we mean an operation that replaces nil by t, x
  by nil for any other explicit value x, (not x) by x, and any other
  x by (not x).")
 (ACL2-PC::DEMOTE
  (PROOF-CHECKER-COMMANDS)
  "(primitive) move top-level hypotheses to the conclusion

    Examples:
    demote        -- demote all top-level hypotheses
    (demote 3 5)  -- demote hypotheses 3 and 5

  For example, if the top-level hypotheses are x and y and the
  conclusion is z, then after execution of demote, the conclusion
  will be (implies (and x y) z) and there will be no (top-level)
  hypotheses.

    General Form:
    (demote &rest hyps-indices)

  Eliminate the indicated (top-level) hypotheses, but replace the
  conclusion conc with (implies hyps conc) where hyps is the
  conjunction of the hypotheses that were eliminated. If no arguments
  are supplied, then all hypotheses are demoted, i.e. demote is the
  same as (demote 1 2 ... n) where n is the number of top-level
  hypotheses.

  Remark: You must be at the top of the conclusion in order to use this
  command. Otherwise, first invoke top. Also, demote fails if there
  are no top-level hypotheses or if indices are supplied that are out
  of range.")
 (ACL2-PC::DIVE
  (PROOF-CHECKER-COMMANDS)
  "(primitive) move to the indicated subterm

    Examples:
    (DIVE 1)    -- assign the new current subterm to be the first
                   argument of the existing current subterm
    (DIVE 1 2)  -- assign the new current subterm to be the result of
                   first taking the 1st argument of the existing
                   current subterm, and then the 2nd argument of that

  For example, if the current subterm is

    (* (+ a b) c),

  then after (dive 1) it is

    (+ a b).

  If after that, then (dive 2) is invoked, the new current subterm will
  be

    b.

  Instead of (dive 1) followed by (dive 2), the same current subterm
  could be obtained by instead submitting the single instruction
  (dive 1 2).

    General Form:
    (dive &rest naturals-list)

  If naturals-list is a non-empty list (n_1 ... n_k) of natural
  numbers, let the new current subterm be the result of selecting the
  n_1-st argument of the current subterm, and then the n_2-th subterm
  of that, ..., finally the n_k-th subterm.

  Remark: Dive is related to the command pp, in that the diving is done
  according to raw (translated, internal form) syntax. Use the
  command dv if you want to dive according to the syntax displayed by
  the command p. Note that (dv n) can be abbreviated by simply n.

  Remark: Emacs users who load (into Emacs) the file emacs/acl2-doc.el
  will have defined a command, Control-t Control-d, that avoids the
  need to type dive commands. After you print the current term using
  the pp command, you may position the cursor on a subterm and type
  Control-t Control-d. Emacs will respond by pasting the appropriate
  dive command immediately after the proof-checker's prompt. You can
  then simply type  in order to dive to the desired subterm.")
 (ACL2-PC::DO-ALL
  (PROOF-CHECKER-COMMANDS)
  "(macro) run the given instructions

    Example:
    (do-all induct p prove)

    General Form:
    (do-all &rest instruction-list)

  Run the indicated instructions until there is a hard ``failure''. The
  instruction ``succeeds'' if and only if each instruction in
  instruction-list does. (See [ACL2-pc::sequence] for an explanation
  of ``success'' and ``failure.'') As each instruction is executed,
  the system will print the usual prompt followed by that
  instruction, unless the global state variable
  pc-print-prompt-and-instr-flg is nil.

  Remark: If do-all ``fails'', then the failure is hard if and only if
  the last instruction it runs has a hard ``failure''.

  Obscure point: For the record, (do-all ins_1 ins_2 ... ins_k) is the
  same as (sequence (ins_1 ins_2 ... ins_k)).")
 (ACL2-PC::DO-ALL-NO-PROMPT
  (PROOF-CHECKER-COMMANDS)
  "(macro) run the given instructions, halting once there is a
  ``failure''

    Example:
    (do-all-no-prompt induct p prove)

    General Form:
    (do-all-no-prompt &rest instruction-list)

  Do-all-no-prompt is the same as do-all, except that the prompt and
  instruction are not printed each time, regardless of the value of
  pc-print-prompt-and-instr-flg. Also, restoring is disabled. See
  [ACL2-pc::do-all].")
 (ACL2-PC::DO-STRICT
  (PROOF-CHECKER-COMMANDS)
  "(macro) run the given instructions, halting once there is a
  ``failure''

    Example:
    (do-strict induct p prove)

    General Form:
    (do-strict &rest instruction-list)

  Run the indicated instructions until there is a (hard or soft)
  ``failure''. In fact do-strict is identical in effect to do-all,
  except that do-all only halts once there is a hard ``failure''. See
  [ACL2-pc::do-all].")
 (ACL2-PC::DOC
  (PROOF-CHECKER-COMMANDS)
  "(macro) access documentation inside the proof-checker

    Examples:

    (doc rewrite)          -- documentation on rewriting in ACL2
    (doc acl2-pc::rewrite) -- documentation on the proof-checker rewrite command
    (doc)                  -- same as (help doc) or (doc acl2-pc::doc)
    doc                    -- same as above

    General Forms:
    (doc) ; or, just: help
    (doc topic-name)

  For any [documentation] topic, A, (doc A) prints documentation on A
  to the terminal. You can read that documentation online or in the
  Emacs [ACL2-Doc] browser; see [documentation]. This [proof-checker]
  command provides a direct interface to the ACL2 :[doc] command at
  the terminal.

  Also see [ACL2-pc::help], which provides help for proof-checker
  commands. For example, submitting (help rewrite) to the
  proof-checker is equivalent to submitting (doc acl2-pc::rewrite) to
  the proof-checker, which corresponds to submitting :doc
  acl2-pc::rewrite directly to the ACL2 loop.")
 (ACL2-PC::DROP
  (PROOF-CHECKER-COMMANDS)
  "(primitive) drop top-level hypotheses

    Examples:
    (drop 2 3) -- drop the second and third hypotheses
    drop       -- drop all top-level hypotheses

    General Forms:
    (drop n1 n2 ...) -- Drop the hypotheses with the indicated indices.

    drop             -- Drop all the top-level hypotheses.

  Remark: If there are no top-level hypotheses, then the instruction
  drop will fail. If any of the indices is out of range, i.e. is not
  an integer between one and the number of top-level hypotheses
  (inclusive), then (drop n1 n2 ...) will fail.")
 (ACL2-PC::DV
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) move to the indicated subterm

    Examples:
    (dv 1)    -- assign the new current subterm to be the first argument
                 of the existing current subterm
    (dv 1 2)  -- assign the new current subterm to be the result of
                 first taking the 1st argument of the existing
                 current subterm, and then the 2nd argument of that

  For example, if the current subterm is

    (* (+ a b) c),

  then after (dv 1) it is

    (+ a b).

  If after that, then (dv 2) is invoked, the new current subterm will
  be

    b.

  Instead of (dv 1) followed by (dv 2), the same current subterm could
  be obtained by instead submitting the single instruction (dv 1 2).

    General Form:
    (dv &rest naturals-list)

  If naturals-list is a non-empty list (n_1 ... n_k) of natural
  numbers, let the new current subterm be the result of selecting the
  n_1-st argument of the current subterm, and then the n_2-th subterm
  of that, ..., finally the n_k-th subterm.

  Remark: (dv n) may be abbreviated by simply n, so we could have typed
  1 instead of (dv 1) in the first example above.

  Remark: Emacs users who load (into Emacs) the file emacs/acl2-doc.el
  will have defined a command, Control-t d, that avoids the need to
  type dv commands. After you print the current term using the p or
  th command, you may position the cursor on a subterm and type
  Control-t d. Emacs will respond by pasting the appropriate dv
  command immediately after the proof-checker's prompt. You can then
  simply type  in order to dive to the desired subterm.

  Remark: A similar command is dive, which is related to the command
  pp, in that the diving is done according to raw (translated,
  internal form) syntax. (See [ACL2-pc::dive].) Use the command dv if
  you want to dive according to the syntax displayed by the command
  p. Thus, the command ``up'' is the inverse of dive, not of dv. The
  following example illustrates this point.

    ACL2 !>(verify (equal (* a b c) x))
    ->: p ; print user-level term
    (EQUAL (* A B C) X)
    ->: pp ; print internal-form (translated) term
    (EQUAL (BINARY-* A (BINARY-* B C)) X)
    ->: exit
    Exiting....
     NIL
    ACL2 !>(verify (equal (* a b c) x))
    ->: p
    (EQUAL (* A B C) X)
    ->: 1 ; same as (dv 1)
    ->: p ; print user-level term
    (* A B C)
    ->: pp ; print internal-form (translated) term
    (BINARY-* A (BINARY-* B C))
    ->: 3 ; dive to third argument of (* A B C)
    ->: p
    C
    ->: up ; go up one level in (BINARY-* A (BINARY-* B C))
    ->: p
    (* B C)
    ->: pp
    (BINARY-* B C)
    ->:


Subtopics

  [Dive-into-macros-table]
      Right-associated function information for the [proof-checker]")
 (ACL2-PC::ELIM
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) call the ACL2 theorem prover's elimination process

    Example and General Form:
    elim

  Upon running the elim command, the system will create a subgoal will
  be created for each goal that would have been pushed for proof by
  induction in an ordinary proof, where only elimination is used; not
  even simplification is used!")
 (ACL2-PC::EQUIV
  (PROOF-CHECKER-COMMANDS)
  "(primitive) attempt an equality (or congruence-based) substitution

    Examples:
    (equiv (* x y) 3) -- replace (* x y) by 3 everywhere inside the
                         current subterm, if their equality is among the
                         top-level hypotheses or the governors
    (equiv x t iff)   -- replace x by t everywhere inside the current
                         subterm, where only propositional equivalence
                         needs to be maintained at each occurrence of x

    General form:
    (equiv old new &optional relation)

  Substitute new for old everywhere inside the current subterm,
  provided that either (relation old new) or (relation new old) is
  among the top-level hypotheses or the governors (possibly by way of
  backchaining and/or refinement; see below). If relation is nil or
  is not supplied, then it defaults to equal. Also see acl2-pc::= for
  a much more flexible command. Note that the equiv command fails if
  no substitution is actually made.

  Remark: No substitution takes place inside explicit values. So for
  example, the instruction (equiv 3 x) will cause 3 to be replaced by
  x if the current subterm is, say, (* 3 y), but not if the current
  subterm is (* 4 y) even though 4 = (1+ 3).

  The following remarks are quite technical and mostly describe a
  certain weak form of ``backchaining'' that has been implemented for
  equiv in order to support the = command. In fact neither the term
  (relation old new) nor the term (relation new old) needs to be
  explicitly among the current ``assumptions'', i.e., the top-level
  hypothesis or the governors. Rather, there need only be such an
  assumption that ``tells us'' (r old new) or (r new old), for some
  equivalence relation r that refines relation. Here, ``tells us''
  means that either one of the indicated terms is among those
  assumptions, or else there is an assumption that is an implication
  whose conclusion is one of the indicated terms and whose hypotheses
  (gathered up by appropriately flattening the first argument of the
  implies term) are all among the current assumptions.")
 (ACL2-PC::EX
  (PROOF-CHECKER-COMMANDS)
  "(macro) exit after possibly saving the state

    Example and General Form:
    ex

  Same as exit, except that first the instruction save is executed.

  If save queries the user and is answered negatively, then the exit is
  aborted.")
 (ACL2-PC::EXIT
  (PROOF-CHECKER-COMMANDS)
  "(meta) exit the interactive proof-checker

    Examples:
    exit                        -- exit the interactive proof-checker
    (exit t)                    -- exit after printing a bogus defthm event
    (exit append-associativity) -- exit and create a defthm
                                   event named append-associativity

    General Forms:

    exit --  Exit without storing an event.

    (exit t) -- Exit after printing a bogus defthm event, showing :INSTRUCTIONS.

    (exit event-name &optional rule-classes do-it-flg) --
    Exit, and perhaps store an event

  The command exit returns you to the ACL2 loop. At a later time,
  (acl2::verify) may be executed to get back into the same
  proof-checker state, as long as there hasn't been an intervening
  use of the proof-checker (otherwise see [ACL2-pc::save]).

  When given one or more arguments as shown above, exit still returns
  you to the ACL2 loop, but first, if the interactive proof is
  complete, then it attempts create a defthm event with the specified
  event-name and rule-classes (which defaults to (:rewrite) if not
  supplied). The event will be printed to the terminal, and then
  normally the user will be queried whether an event should really be
  created. However, if the final optional argument do-it-flg is
  supplied and not nil, then an event will be made without a query.

  For example, the form

    (exit top-pop-elim (:elim :rewrite) t)

  causes a defthm event named top-pop-elim to be created with
  rule-classes (:elim :rewrite), without a query to the user (because
  of the argument t).

  Remark: it is permitted for event-name to be nil. In that case, the
  name of the event will be the name supplied during the original
  call of verify. (See [verify] and [ACL2-pc::commands].) Also in
  that case, if rule-classes is not supplied then it defaults to the
  rule-classes supplied in the original call of verify.

  Comments on ``success'' and ``failure''. An exit instruction will
  always ``fail'', so for example, if it appears as an argument of a
  do-strict instruction then none of the later (instruction)
  arguments will be executed. Moreover, the ``failure'' will be
  ``hard'' if an event is successfully created or if the instruction
  is simply exit; otherwise it will be ``soft''. See
  [ACL2-pc::sequence] for an explanation of hard and soft
  ``failures''. An obscure but potentially important fact is that if
  the ``failure'' is hard, then the error signal is a special signal
  that the top-level interactive loop can interpret as a request to
  exit. Thus for example, a sequencing command that turns an error
  triple (mv erp val state) into (mv t val state) would never cause
  an exit from the interactive loop.

  If the proof is not complete, then (exit event-name ...) will not
  cause an exit from the interactive loop. However, in that case it
  will print out the original user-supplied goal (the one that was
  supplied with the call to verify) and the current list of
  instructions.")
 (ACL2-PC::EXPAND
  (PROOF-CHECKER-COMMANDS)
  "(primitive) expand the current function call without simplification

    Examples:
    expand -- expand and do not simplify.

  Also see [ACL2-pc::x], which performs simplification, and see
  [ACL2-pc::x-dumb], which provides a simple interface to
  acl2-pc::expand.

  For example, if the current subterm is (append a b), then after
  expand the current subterm will be the term:

    (if (consp a)
        (cons (car a) (append (cdr a) b))
      b)

  regardless of the top-level hypotheses and the governors.

    General Form:
    (expand &optional do-not-expand-lambda-flg)

  Expand the function call at the current subterm, and do not simplify.
  The options have the following meanings:

    do-not-expand-lambda-flg:   default is nil; otherwise, the result
                                should be a lambda expression")
 (ACL2-PC::FAIL
  (PROOF-CHECKER-COMMANDS)
  "(macro) cause a failure

    Examples:
    fail
    (fail t)

    General Form:
    (fail &optional hard)

  This is probably only of interest to writers of macro commands. The
  only function of fail is to fail to ``succeed''.

  The full story is that fail and (fail nil) simply return (mv nil nil
  state), while (fail hard) returns (mv hard nil state) if hard is
  not nil. Also see [ACL2-pc::do-strict], [ACL2-pc::do-all], and
  [ACL2-pc::sequence].")
 (ACL2-PC::FINISH
  (PROOF-CHECKER-COMMANDS)
  "(macro) require completion of instructions; save error if inside
  :[hints]

    Example:
    (finish induct prove bash)

    General Form:
    (finish &rest instructions)

  Run the indicated instructions, stopping at the first failure. If
  there is any failure, or if any new goals are created and remain at
  the end of the indicated instructions, then consider the call of
  finish to be a failure. See [proof-checker-commands] and see
  [ACL2-pc::sequence] for a discussion of the notion of ``failure''
  for [proof-checker] commands.")
 (ACL2-PC::FORWARDCHAIN
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) forward chain from an implication in the hyps

    Example:
    (forwardchain 2) ; Second hypothesis should be of the form
                     ; (IMPLIES hyp concl), and the result is to replace
                     ; that hypothesis with concl.

    General Forms:
    (forwardchain hypothesis-number)
    (forwardchain hypothesis-number hints)
    (forwardchain hypothesis-number hints quiet-flg)

  This command replaces the hypothesis corresponding to given index,
  which should be of the form (IMPLIES hyp concl), with its
  consequent concl. In fact, the given hypothesis is dropped, and the
  replacement hypothesis will appear as the final hypothesis after
  this command is executed.

  The prover must be able to prove the indicated hypothesis from the
  other hypotheses, or else the command will fail. The :hints
  argument is used in this prover call, and should have the usual
  syntax of hints to the prover.

  Output is suppressed if quiet-flg is supplied and not nil.")
 (ACL2-PC::FREE
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) create a ``free variable''

    Example:
    (free x)

    General Form:
    (free var)

  Mark var as a ``free variable''. Free variables are only of interest
  for the put command; see [ACL2-pc::put].")
 (ACL2-PC::GENEQV
  (PROOF-CHECKER-COMMANDS)
  "(macro) show the generated equivalence relation maintained at the
  current subterm

    General Forms:
    geneqv     ; show list of equivalence relations being maintained
    (geneqv t) ; as above, but pair each relation with a justifying rune

  This is an advanced command, whose effect is to print the so-called
  ``generated equivalence relation'' (or ``geneqv'') that is
  maintained at the current subterm of the conclusion. That structure
  is a list of equivalence relations, representing the transitive
  closure E of the union of those relations, such that it suffices to
  maintain E at the current subterm: if that subterm, u, is replaced
  in the goal's conclusion, G, by another term equivalent to u with
  respect to E, then the resulting conclusion is Boolean equivalent
  to G. Also see [defcong].

  The command `geneqv' prints the above list of equivalence relations,
  or more precisely, the list of function symbols for those
  relations. If however geneqv is given a non-nil argument, then a
  list is printed whose elements are each of the form (s r), where s
  is the symbol for an equivalence relation and r is a :[congruence]
  [rune] justifying the inclusion of s in the list of equivalence
  relations being maintained at the current subterm.")
 (ACL2-PC::GENERALIZE
  (PROOF-CHECKER-COMMANDS)
  "(primitive) perform a generalization

    Example:
    (generalize
     ((and (true-listp x) (true-listp y)) 0)
     ((append x y) w))

    General Form:
    (generalize &rest substitution)

  Generalize using the indicated substitution, which should be a
  non-empty list. Each element of that list should be a two-element
  list of the form (term variable), where term may use abbreviations.
  The effect of the instruction is to replace each such term in the
  current goal by the corresponding variable. This replacement is
  carried out by a parallel substitution, outside-in in each
  hypothesis and in the conclusion. More generally, actually, the
  ``variable'' (second) component of each pair may be nil or a
  number, which causes the system to generate a new name of the form
  _ or _n, with n a natural number; more on this below. However, when
  a variable is supplied, it must not occur in any goal of the
  current proof-checker state.

  When the ``variable'' above is nil, the system will treat it as the
  variable |_| if that variable does not occur in any goal of the
  current proof-checker state. Otherwise it treats it as |_0|, or
  |_1|, or |_2|, and so on, until one of these is not among the
  variables of the current proof-checker state. If the ``variable''
  is a non-negative integer n, then the system treats it as |_n|
  unless that variable already occurs among the current goals, in
  which case it increments n just as above until it obtains a new
  variable.

  Remark: The same variable may not occur as the variable component of
  two different arguments (though nil may occur arbitrarily many
  times, as may a positive integer).")
 (ACL2-PC::GOALS
  (PROOF-CHECKER-COMMANDS)
  "(macro) list the names of goals on the stack

    Example and General Form:
    goals

  Goals lists the names of all goals that remain to be proved. They are
  listed in the order in which they appear on the stack of remaining
  goals, which is relevant for example to the effect of a change-goal
  instruction.")
 (ACL2-PC::HELP
  (PROOF-CHECKER-COMMANDS)
  "(macro) proof-checker help facility

    Examples:

    (help rewrite)   -- documentation on the proof-checker rewrite command
    (help)           -- this help
    (help help)      -- same as (help) or simply, help
    (help all)       -- same as (doc proof-checker-commands)

    General Forms:
    (help) ; or, just: help
    (help command)
    (help all)

  For any proof-checker command, C, (help C) prints documentation on C
  to the terminal. You can read that documentation online or in the
  Emacs [ACL2-Doc] browser by viewing topic acl2-pc::C; see
  [documentation].

  To see a list of all proof-checker commands, you can submit (help
  all). This is actually equivalent to (doc proof-checker-commands),
  which prints the documentation for topic [proof-checker-commands]
  (which, as discussed above, you can view online or with
  [ACL2-Doc]).

  Also see [ACL2-pc::doc], which provides a direct interface to the
  ACL2 :[doc] command. For example, submitting (help rewrite) to the
  proof-checker is equivalent to submitting (doc acl2-pc::rewrite) to
  the proof-checker or submitting :doc acl2-pc::rewrite directly to
  the ACL2 loop.")
 (ACL2-PC::HYPS
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the hypotheses

    Examples:
    hyps               -- print all (top-level) hypotheses
    (hyps (1 3) (2 4)) -- print hypotheses 1 and 3 and governors 2 and 4
    (hyps (1 3) t)     -- print hypotheses 1 and 3 and all governors

    General Form:
    (hyps &optional hyps-indices govs-indices)

  Print the indicated top-level hypotheses and governors. (The notion
  of ``governors'' is defined below.) Here, hyps-indices and
  govs-indices should be lists of indices of hypotheses and governors
  (respectively), except that the atom t may be used to indicate that
  one wants all hypotheses or governors (respectively).

  The list of ``governors'' is defined as follows. Actually, we define
  here the notion of the governors for a pair of the form ]; we're interested in the special case where the term is
  the conclusion and the address is the current address. If the
  address is nil, then there are no governors, i.e., the list of
  governors is nil. If the term is of the form (if x y z) and the
  address is of the form (2 . rest) or (3 . rest), then the list of
  governors is the result of consing x or its negation (respectively)
  onto the list of governors for the pair  or the pair  (respectively). If the term is of the form (implies x y) and
  the address is of the form (2 . rest), then the list of governors
  is the result of consing x onto the list of governors for the pair
  . Otherwise, the list of governors for the pair  is exactly the list of governors for the pair 
  where argn is the nth argument of term.

  If all goals have been proved, a message saying so will be printed.
  (as there will be no current hypotheses or governors!).

  The hyps command never causes an error. It ``succeeds'' (in fact its
  value is t) if the arguments (when supplied) are appropriate, i.e.
  either t or lists of indices of hypotheses or governors,
  respectively. Otherwise it ``fails'' (its value is nil).")
 (ACL2-PC::ILLEGAL
  (PROOF-CHECKER-COMMANDS)
  "(macro) illegal instruction

    Example:
    (illegal -3)

    General Form:
    (illegal instruction)

  Probably not of interest to most users; always ``fails'' since it
  expands to the fail command.

  The illegal command is used mainly in the implementation. For
  example, the instruction 0 is ``read'' as (illegal 0), since dive
  expects positive integers.")
 (ACL2-PC::IN-THEORY
  (PROOF-CHECKER-COMMANDS)
  "(primitive) set the current proof-checker theory

    Example:
    (in-theory
       (union-theories (theory 'minimal-theory) '(true-listp binary-append)))

    General Form:
    (in-theory &optional atom-or-theory-expression)

  If the argument is not supplied, then this command sets the current
  proof-checker theory (see below for explanation) to agree with the
  current ACL2 theory. Otherwise, the argument should be a theory
  expression, and in that case the proof-checker theory is set to the
  value of that theory expression.

  The current proof-checker theory is used in all calls to the ACL2
  theorem prover and rewriter from inside the proof-checker. Thus,
  the most recent in-theory instruction in the current state-stack
  has an effect in the proof-checker totally analogous to the effect
  caused by an in-theory hint or event in ACL2. All in-theory
  instructions before the last are ignored, because they refer to the
  current theory in the ACL2 [state], not to the existing
  proof-checker theory. For example:

    ACL2 !>:trans1 (enable bar)
     (UNION-THEORIES (CURRENT-THEORY :HERE)
                     '(BAR))
    ACL2 !>:trans1 (CURRENT-THEORY :HERE)
     (CURRENT-THEORY-FN :HERE WORLD)
    ACL2 !>

  Thus (in-theory (enable bar)) modifies the current theory of the
  current ACL2 world. So for example, suppose that foo is disabled
  outside the proof checker and you execute the following
  instructions, in this order.

    (in-theory (enable foo))
    (in-theory (enable bar))

  Then after the second of these, bar will be enabled in the
  proof-checker, but foo will be disabled. The reason is that
  (in-theory (enable bar)) instructs the proof-checker to modify the
  current theory (from outside the proof-checker, not from inside the
  proof-checker) by enabling bar.

  Note that in-theory instructions in the proof-checker have no effect
  outside the proof-checker's interactive loop.

  If the most recent in-theory instruction in the current state of the
  proof-checker has no arguments, or if there is no in-theory
  instruction in the current state of the proof-checker, then the
  proof-checker will use the current ACL2 theory. This is true even
  if the user has interrupted the interactive loop by exiting and
  changing the global ACL2 theory. However, if the most recent
  in-theory instruction in the current state of the proof-checker had
  an argument, then global changes to the current theory will have no
  effect on the proof-checker state.")
 (ACL2-PC::INDUCT
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) generate subgoals using induction

    Examples:
    induct, (induct t)
       -- induct according to a heuristically-chosen scheme, creating
          a new subgoal for each base and induction step
    (induct (append (reverse x) y))
       -- as above, but choose an induction scheme based on the term
          (append (reverse x) y) rather than on the current goal

    General Form:
    (induct &optional term)

  Induct as in the corresponding :induct hint given to the theorem
  prover, creating new subgoals for the base and induction steps. If
  term is t or is not supplied, then use the current goal to
  determine the induction scheme; otherwise, use that term.

  Remark: As usual, abbreviations are allowed in the term.

  Remark: Induct actually calls the prove command with all processes
  turned off. Thus, you must be at top of the goal for an induct
  instruction.")
 (ACL2-PC::LEMMAS-USED
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the runes (definitions, lemmas, ...) used

  This is just an alias for runes.")
 (ACL2-PC::LISP
  (PROOF-CHECKER-COMMANDS)
  "(meta) evaluate the given form in Lisp

    Example:
    (lisp (assign xxx 3))

    General Form:
    (lisp form)

  Evaluate form. The lisp command is mainly of interest for side
  effects. Also see [ACL2-pc::print], [ACL2-pc::skip], and
  [ACL2-pc::fail].

  The rest of the documentation for lisp is of interest only to those
  who use it in macro commands. If the Lisp evaluation (by
  trans-eval) of form returns an error triple (see [error-triples])
  of the form (mv erp ((NIL NIL STATE) . (erp-1 val-1 &)) state),
  then the lisp command returns the appropriate error triple

    (mv (or erp erp-1)
        val-1
        state) .

  Otherwise, the trans-eval of form must return an error triple of the
  form (mv erp (cons stobjs-out val) &), and the lisp command returns
  the appropriate error triple

    (mv erp
        val
        state).

  Note that the output signature of the form has been lost. The user
  must know the signature in order to use the output of the lisp
  command. Trans-eval, which is undocumented except by comments in
  the ACL2 source code, has replaced, in val, any occurrence of the
  current state or the current values of stobjs by simple symbols
  such as REPLACED-STATE. The actual values of these objects may be
  recovered, in principle, from the state returned and the
  user-stobj-alist within that state. However, in practice, the
  stobjs cannot be recovered because the user is denied access to
  user-stobj-alist. The moral is: do not try to write macro commands
  that manipulate stobjs. Should the returned val contain
  REPLACED-STATE the value may simply be ignored and state used,
  since that is what REPLACED-STATE denotes.")
 (ACL2-PC::NEGATE
  (PROOF-CHECKER-COMMANDS)
  "(macro) run the given instructions, and ``succeed'' if and only if
  they ``fail''

  Example: (negate prove)

    General form:
    (negate &rest instruction-list)

  Run the indicated instructions exactly in the sense of do-all, and
  ``succeed'' if and only if they ``fail''.

  Remark: Negate instructions will never produce hard ``failures''.")
 (ACL2-PC::NIL
  (PROOF-CHECKER-COMMANDS)
  "(macro) used for interpreting control-d

    Example and General form:
    nil

  (or, control-d).

  The whole point of this command is that in some Lisps (including
  akcl), if you type control-d then it seems, on occasion, to get
  interpreted as nil. Without this command, one seems to get into an
  infinite loop.")
 (ACL2-PC::NOISE
  (PROOF-CHECKER-COMMANDS)
  "(meta) run instructions with output

    Example:
    (noise induct prove)

    General Form:
    (noise &rest instruction-list)

  Run the instruction-list through the top-level loop with output.

  In fact, having output is the default. Noise is useful inside a
  surrounding call of quiet, when one temporarily wants output. For
  example, if one wants to see output for a prove command immediately
  following an induct command but before an s command, one may want
  to submit an instruction like (quiet induct (noise prove) s). Also
  see [ACL2-pc::quiet].")
 (ACL2-PC::NX
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) move forward one argument in the enclosing term

    Example and General Form:
    nx

  For example, if the conclusion is (= x (* (- y) z)) and the current
  subterm is x, then after executing nx, the current subterm will be
  (* (- y) z).

  This is the same as up followed by (dive n+1), where n is the
  position of the current subterm in its parent term in the
  conclusion. Thus in particular, the nx command fails if one is
  already at the top of the conclusion.

  Also see [ACL2-pc::up], [ACL2-pc::dive], [ACL2-pc::top], and
  [ACL2-pc::bk].")
 (ACL2-PC::ORELSE
  (PROOF-CHECKER-COMMANDS)
  "(macro) run the first instruction; if (and only if) it ``fails'', run
  the second

    Example:
    (orelse top (print \"Couldn't move to the top\"))

    General form:
    (orelse instr1 instr2)

  Run the first instruction. Then if it ``fails'', run the second
  instruction also; otherwise, stop after the first.

  This instruction ``succeeds'' if and only if either instr1
  ``succeeds'', or else instr2 ``succeeds''. If it ``fails'', then
  the failure is soft.")
 (ACL2-PC::P
  (PROOF-CHECKER-COMMANDS)
  "(macro) prettyprint the current term

    Example and General Form:
    p

  Prettyprint the current term. The usual user syntax is used, so that
  for example one would see (and x y) rather than (if x y 'nil). (See
  also pp.) Also, abbreviations are inserted where appropriate; see
  [ACL2-pc::add-abbreviation].

  The ``current term'' is the entire conclusion unless dive commands
  have been given, in which case it may be a subterm of the
  conclusion.

  If all goals have been proved, a message saying so will be printed
  (as there will be no current term!).")
 (ACL2-PC::P-TOP
  (PROOF-CHECKER-COMMANDS)
  "(macro) prettyprint the conclusion, highlighting the current term

    Example and General Form:
    p-top

  For example, if the conclusion is (equal (and x (p y)) (foo z)) and
  the current subterm is (p y), then p-top will print (equal (and x
  (*** (p y) ***)) (foo z)).

  Prettyprint the the conclusion, highlighting the current term. The
  usual user syntax is used, as with the command p (as opposed to
  pp). This is illustrated in the example above, where one would*not*see (equal (if x (*** (p y) ***) 'nil) (foo z)).

  Remark (obscure): In some situations, a term of the form (if x t y)
  occurring inside the current subterm will not print as (or x y),
  when x isn't a call of a boolean primitive. There's nothing
  incorrect about this, however.")
 (ACL2-PC::PL
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the rules for a given name

    Examples:
    pl
    (pl foo)

    General Form:
    (pl &optional x)

  This command simply invokes the corresponding command of the
  top-level ACL2 loop; see [pl]. If no argument is given, or if the
  argument is nil, then the current subterm should be a call of a
  function symbol, and the argument is taken to be that symbol.

  If you want information about applying rewrite rules to the current
  subterm, consider the show-rewrites (or equivalently, sr) command.")
 (ACL2-PC::PP
  (PROOF-CHECKER-COMMANDS)
  "(macro) prettyprint the current term

    Example and General Form:
    pp

  This is the same as p (see its documentation), except that raw syntax
  (internal form) is used. So for example, one would see (if x y
  'nil) rather than (and x y). Abbreviations are however still
  inserted, as with p.")
 (ACL2-PC::PR
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the rules for a given name

    Examples:
    pr
    (pr foo)

    General Form:
    (pr &optional x)

  This command simply invokes the corresponding command of the
  top-level ACL2 loop; see [pr]. If no argument is given, or if the
  argument is nil, then the current subterm should be a call of a
  function symbol, and the argument is taken to be that symbol.

  If you want information about applying rewrite rules to the current
  subterm, consider the show-rewrites (or equivalently, sr) command.")
 (ACL2-PC::PRINT
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the result of evaluating the given form

    Example:
    (print (append '(a b) '(c d)))
    Print the list (a b c d) to the terminal

    General Forms:
    (print form)
    (print form t)

  Prettyprints the result of evaluating form. The evaluation of form
  should return a single value that is not [state] or a
  single-threaded object (see [stobj]). The optional second argument
  causes printing to be done without elision (so-called
  ``evisceration''; see [evisc-tuple]).

  If the form you want to evaluate does not satisfy the criterion
  above, you should create an appropriate call of the lisp command
  instead. Notice that this command always returns (mv nil nil state)
  where the second result will always be REPLACED-STATE.")
 (ACL2-PC::PRINT-ALL-CONCS
  (PROOF-CHECKER-COMMANDS)
  "(macro) print all the conclusions of (as yet unproved) goals

  Example and General Form: print-all-concs

  Prints all the conclusions of goals that remain to be proved, in a
  pleasant format. Also see [ACL2-pc::print-all-goals].")
 (ACL2-PC::PRINT-ALL-GOALS
  (PROOF-CHECKER-COMMANDS)
  "(macro) print all the (as yet unproved) goals

  Example and General Form: print-all-goals

  Prints all the goals that remain to be proved, in a pleasant format.
  Also see [ACL2-pc::print-all-concs].")
 (ACL2-PC::PRINT-MAIN
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the original goal

    Example and General Form:
    print-main

  Print the goal as originally entered.")
 (ACL2-PC::PRO
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) repeatedly apply promote

    Example and General Form:
    pro

  Apply the promote command until there is no change. This command
  ``succeeds'' exactly when at least one call of promote
  ``succeeds''. In that case, only a single new proof-checker state
  will be created.")
 (ACL2-PC::PROMOTE
  (PROOF-CHECKER-COMMANDS)
  "(primitive) move antecedents of conclusion's implies term to
  top-level hypotheses

    Examples:
    promote
    (promote t)

  For example, if the conclusion is (implies (and x y) z), then after
  execution of promote, the conclusion will be z and the terms x and
  y will be new top-level hypotheses.

    General Form:
    (promote &optional do-not-flatten-flag)

  Replace conclusion of (implies hyps exp) or (if hyps exp t) with
  simply exp, adding hyps to the list of top-level hypotheses.
  Moreover, if hyps is viewed as a conjunction then each conjunct
  will be added as a separate top-level hypothesis. An exception is
  that if do-not-flatten-flag is supplied and not nil, then only one
  top-level hypothesis will be added, namely hyps.

  Remark: You must be at the top of the conclusion in order to use this
  command. Otherwise, first invoke top.")
 (ACL2-PC::PROTECT
  (PROOF-CHECKER-COMMANDS)
  "(macro) run the given instructions, reverting to existing state upon
  failure

    Example:
    (protect induct p prove)

    General Form:
    (protect &rest instruction-list)

  Protect is the same as do-strict, except that as soon as an
  instruction ``fails'', the state-stack reverts to what it was
  before the protect instruction began, and restore is given the same
  meaning that it had before the protect instruction began. See
  [ACL2-pc::do-strict].")
 (ACL2-PC::PROVE
  (PROOF-CHECKER-COMMANDS)
  "(primitive) call the ACL2 theorem prover to prove the current goal

    Examples:
    prove -- attempt to prove the current goal
    (prove :otf-flg t
           :hints ((\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar)))
          -- attempt to prove the current goal, with the indicated hints
             and with OTF-FLG set

    General Form:
    (prove &rest rest-args)

  Attempt to prove the current goal, where rest-args is as in the
  keyword arguments to defthm except that only :hints and :otf-flg
  are allowed. The command succeeds exactly when the corresponding
  defthm would succeed, except that it is all right for some goals to
  be given ``bye''s. Each goal given a ``bye'' will be turned into a
  new subgoal. (See [hints] for an explanation of :by hints.)

  Remark: Use (= t) instead if you are not at the top of the
  conclusion. Also note that if there are any hypotheses in the
  current goal, then what is actually attempted is a proof of
  (implies hyps conc), where hyps is the conjunction of the top-level
  hypotheses and conc is the goal's conclusion.

  Remark: It is allowed to use abbreviations in the hints.")
 (ACL2-PC::PSO
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the most recent proof attempt from inside the
  proof-checker

    Example and General Form:
    pso

  Print the most recent proof attempt from inside the proof-checker
  assuming you are in [gag-mode] or have saved output (see
  [set-saved-output]). This includes all calls to the prover,
  including for example [proof-checker] commands induct, split, and
  bash, in addition to prove. So for example, you can follow (quiet
  prove) with pso to see the proof, including [proof-tree] output, if
  it failed.

  Related [proof-checker] commands are psog and pso!; see
  [ACL2-pc::psog] and [ACL2-pc::pso!].")
 (ACL2-PC::PSO!
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the most recent proof attempt from inside the
  proof-checker

    Example and General Form:
    pso!

  Print the most recent proof attempt from inside the proof-checker,
  including [proof-tree] output, assuming you are in [gag-mode] or
  have saved output (see [set-saved-output]). This includes all calls
  to the prover, including for example [proof-checker] commands
  induct, split, and bash, in addition to prove. So for example, you
  can follow (quiet prove) with pso! to see the proof, including
  [proof-tree] output, if it failed.

  Related [proof-checker] commands are pso and psog; see [ACL2-pc::pso]
  and [ACL2-pc::psog].")
 (ACL2-PC::PSOG
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the most recent proof attempt from inside the
  proof-checker

    Example and General Form:
    psog

  Print the most recent proof attempt from inside the proof-checker,
  including goal names, assuming you are in [gag-mode] or have saved
  output (see [set-saved-output]). This includes all calls to the
  prover, including for example [proof-checker] commands induct,
  split, and bash, in addition to prove. So for example, you can
  follow (quiet prove) with psog to see the proof, including
  [proof-tree] output, if it failed.

  Related [proof-checker] commands are pso and pso!; see [ACL2-pc::pso]
  and [ACL2-pc::pso!].")
 (ACL2-PC::PUT
  (PROOF-CHECKER-COMMANDS)
  "(macro) substitute for a ``free variable''

    Example:
    (put x 17)

    General Form:
    (put var expr)

  Substitute expr for the ``free variable'' var, as explained below.

  A ``free variable'' is, for our purposes, a variable var such that
  the instruction (free var) has been executed earlier in the
  state-stack. What (free var) really does is to let var be an
  abbreviation for the term (hide var) (see
  [ACL2-pc::add-abbreviation]). What (put var expr) really does is to
  unwind the state-stack, replacing that free instruction with the
  instruction (add-abbreviation var expr), so that future references
  to (? var) become reference to expr rather than to (hide var), and
  then to replay all the other instructions that were unwound.
  Because hide was used, the expectation is that in most cases, the
  instructions will replay successfully and put will ``succeed''.
  However, if any replayed instruction ``fails'', then the entire
  replay will abort and ``fail'', and the state-stack will revert to
  its value before the put instruction was executed.

  If (put var expr) ``succeeds'', then (remove-abbreviation var) will
  be executed at the end.

  Remark: The restore command will revert the state-stack to its value
  present before the put instruction was executed.")
 (ACL2-PC::QUIET
  (PROOF-CHECKER-COMMANDS)
  "(meta) run instructions without output

    Example:
    (quiet induct prove)

    General Form:
    (quiet &rest instruction-list)

  Run the instruction-list through the top-level loop with no output.

  Also see [ACL2-pc::noise].")
 (ACL2-PC::R
  (PROOF-CHECKER-COMMANDS)
  "(macro) same as rewrite

    Example:
    (r 3)

  See [ACL2-pc::rewrite].")
 (ACL2-PC::REDUCE
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) call the ACL2 theorem prover's simplifier

    Examples:
    reduce -- attempt to prove the current goal without using induction
    (reduce (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
           -- attempt to prove the current goal without using
              induction, with the indicated hints

    General Form:
    (reduce &rest hints)

  Attempt to prove the current goal without using induction, using the
  indicated hints (if any). A subgoal will be created for each goal
  that would have been pushed for proof by induction in an ordinary
  proof.

  Notice that unlike prove, the arguments to reduce are spread out, and
  are all hints.

  Reduce is similar to bash in that neither of these allows induction.
  But bash only allows simplification, while reduce allows processes
  eliminate-destructors, fertilize, generalize, and
  eliminate-irrelevance.

  Remark: Induction will be used to the extent that it is ordered
  explicitly in the hints.")
 (ACL2-PC::REDUCE-BY-INDUCTION
  (PROOF-CHECKER-COMMANDS)
  "(macro) call the ACL2 prover without induction, after going into
  induction

    Examples:
    reduce-by-induction
      -- attempt to prove the current goal after going into induction,
         with no further inductions

    (reduce-by-induction (\"Subgoal 2\" :by foo) (\"Subgoal 1\" :use bar))
      -- attempt to prove the current goal after going into induction,
         with no further inductions, using the indicated hints

    General Form:
    (reduce-by-induction &rest hints)

  A subgoal will be created for each goal that would have been pushed
  for proof by induction in an ordinary proof, except that the proof
  begins with a top-level induction.

  Notice that unlike prove, the arguments to reduce-by-induction are
  spread out, and are all hints. Also see [ACL2-pc::prove],
  [ACL2-pc::reduce], and [ACL2-pc::bash].

  Remark: Induction and the various processes will be used to the
  extent that they are specified explicitly in the :induct and
  :do-not [hints].")
 (ACL2-PC::REMOVE-ABBREVIATIONS
  (PROOF-CHECKER-COMMANDS)
  "(primitive) remove one or more abbreviations

    Examples:
    remove-abbreviations -- remove all abbreviations
    (remove-abbreviations v w)
                         -- assuming that V and W currently abbreviate
                            terms, then they are ``removed'' in the
                            sense that they are no longer considered to
                            abbreviate those terms

    General Forms:
    (remove-abbreviations &rest vars)

  If vars is not empty (i.e., not nil), remove the variables in vars
  from the current list of abbreviations, in the sense that each
  variable in vars will no longer abbreviate a term.

  Remark: The instruction fails if at least one of the arguments fails
  to be a variable that abbreviates a term.

  Also see [ACL2-pc::add-abbreviation] for a discussion of
  abbreviations in general, and see [ACL2-pc::show-abbreviations].")
 (ACL2-PC::REPEAT
  (PROOF-CHECKER-COMMANDS)
  "(macro) repeat the given instruction until it ``fails''

    Example:
    (repeat promote)

    General Form:
    (repeat instruction)

  The given instruction is run repeatedly until it ``fails''.

  Remark: There is nothing here in general to prevent the instruction
  from being run after all goals have been proved, though this is
  indeed the case for primitive instructions.")
 (ACL2-PC::REPEAT-REC
      (PROOF-CHECKER-COMMANDS)
      "(macro) auxiliary to repeat

  See [ACL2-pc::repeat].")
 (ACL2-PC::REPLAY
  (PROOF-CHECKER-COMMANDS)
  "(macro) replay one or more instructions

    Examples:
    REPLAY     -- replay all instructions in the current session
                  (i.e., state-stack)
    (REPLAY 5) -- replay the most recent 5 instructions
    (REPLAY 5
            (COMMENT deleted dive command here))
               -- replace the 5th most recent instruction with the
                  indicated comment instruction, and then replay it
                  followed by the remaining 4 instructions

    General Form:
    (REPLAY &OPTIONAL n replacement-instruction)

  Replay the last n instructions if n is a positive integer; else n
  should be nil or not supplied, and replay all instructions.
  However, if replacement-instruction is supplied and not nil, then
  before the replay, replace the nth instruction (from the most
  recent, as shown by commands) with replacement-instruction.

  If this command ``fails'', then the restore command will revert the
  state-stack to its value present before the replay instruction was
  executed.")
 (ACL2-PC::RESTORE
  (PROOF-CHECKER-COMMANDS)
  "(meta) remove the effect of an UNDO command

    Example and General Form:
    restore

  Restore removes the effect of an undo command. This always works as
  expected if restore is invoked immediately after undo, without
  intervening instructions. However, other commands may also interact
  with restore, notably ``sequencing'' commands such as do-all,
  do-strict, protect, and more generally, sequence.

  Remark: Another way to control the saving of proof-checker state is
  with the save command; see [ACL2-pc::save].

  The restore command always ``succeeds''; it returns (mv nil t state).")
 (ACL2-PC::RETAIN
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) drop all but the indicated top-level hypotheses

    Example:
    (RETAIN 2 3) -- keep the second and third hypotheses, and drop
                    the rest

    General Form:
    (retain &rest args)

  Drop all top-level hypotheses except those with the indicated
  indices.

  There must be at least one argument, and all must be in range (i.e.
  integers between one and the number of top-level hypotheses,
  inclusive).")
 (ACL2-PC::RETRIEVE
  (PROOF-CHECKER-COMMANDS)
  "(macro) re-enter the proof-checker

    Examples:
    (retrieve associativity-of-permutationp)
    retrieve

    General Form:
    (retrieve &optional name)

  Must be used from outside the interactive proof-checker loop. If name
  (which must be a symbol) is supplied and not nil, this causes
  re-entry to the interactive proof-checker loop in the state at
  which save was last executed for the indicated name. (See
  [ACL2-pc::save].) If name is nil or is not supplied, then the user
  is queried regarding which proof-checker state to re-enter. The
  query is omitted, however, if there only one proof-checker state is
  present that was saved with save, in which case that is the one
  that is used. Also see [ACL2-pc::unsave].")
 (ACL2-PC::REWRITE
  (PROOF-CHECKER-COMMANDS)
  "(primitive) apply a rewrite rule

    Examples:
    (rewrite reverse-reverse)
       -- apply the rewrite rule `reverse-reverse'
    (rewrite (:rewrite reverse-reverse))
       -- same as above
    (rewrite 2)
       -- apply the second rewrite rule, as displayed by show-rewrites
    rewrite
       -- apply the first rewrite rule, as displayed by show-rewrites
    (rewrite transitivity-of-< ((y 7)))
       -- apply the rewrite rule transitivity-of-< with the substitution
          that associates 7 to the ``free variable'' y
    (rewrite foo ((x 2) (y 3)) t)
       -- apply the rewrite rule foo by substituting 2 and 3 for free
          variables x and y, respectively, and also binding all other
          free variables possible by using the current context
          (hypotheses and governors)

    General Form:
    (rewrite &optional rule-id substitution instantiate-free)

  Replace the current subterm with a new term by applying a [rewrite]
  or [definition] rule. The replacement will be done according to the
  information provided by the show-rewrites (sr) command.

  If rule-id is a positive integer n, then the nth rule as displayed by
  show-rewrites is the one that is applied. If rule-id is nil or is
  not supplied, then it is treated as the number 1. Otherwise,
  rule-id should be either a symbol or else a :rewrite or :definition
  [rune]. If a symbol is supplied, then any (:rewrite or :definition)
  rule of that name may be used. We say more about this, and describe
  the other optional arguments, below.

  Consider first the following example. Suppose that the current
  subterm is (reverse (reverse y)) and that there is a [rewrite] rule
  called reverse-reverse of the form

    (implies (true-listp x)
             (equal (reverse (reverse x)) x)) .

  Then the instruction (rewrite reverse-reverse) causes the current
  subterm to be replaced by y and creates a new goal with conclusion
  (true-listp y). An exception is that if the top-level hypotheses
  imply (true-listp y) using only ``trivial reasoning'' (more on this
  below), then no new goal is created.

  If the rule-id argument is a number or is not supplied, then the
  system will store an instruction of the form (rewrite name ...),
  where name is the name of a rewrite rule; this is in order to make
  it easier to replay instructions when there have been changes to
  the history. Except: instead of the name (whether the name is
  supplied or calculated), the system stores the [rune] if there is
  any chance of ambiguity. (Formally, ``ambiguity'' here means that
  the rune being applied is of the form (:rewrite name . index),
  where index is not nil.)

  Speaking in general, then, a rewrite instruction works as follows:

  First, a [rewrite] or [definition] rule is selected according to the
  arguments of the rewrite instruction. The selection is made as
  explained under ``General Form'' above.

  Next, the left-hand side of the rule is matched with the current
  subterm, i.e., a substitution unify-subst is found such that if one
  instantiates the left-hand side of the rule with unify-subst, then
  one obtains the current subterm. If this match fails, then the
  instruction fails.

  Next, an attempt is made to relieve (discharge) the hypotheses, much
  as the theorem prover relieves hypotheses except that there is no
  call to the rewriter. First, the substitution unify-subst is
  extended with the substitution argument, which may bind free
  variables (see [free-variables]). Each hypothesis of the rule is
  then considered in turn, from first to last. For each hypothesis,
  first the current substitution is applied, and then the system
  checks whether the hypothesis is ``clearly'' true in the current
  context. If there are variables in the hypotheses of the rule that
  are not bound by the current substitution, then a weak attempt is
  made to extend that substitution so that the hypothesis is present
  in the current context (see [ACL2-pc::hyps]), much as would be done
  by the theorem prover's rewriter.

  If in the process above there are free variables (see
  [free-variables]), but the proof-checker can see how to bind them
  to relieve all hypotheses, then it will do so in both the
  show-rewrites (sr) and rewrite commands. But normally, if even one
  hypothesis remains unrelieved, then no automatic extension of the
  substitution is made. Except, if instantiate-free is not nil, then
  that extension to the substitution is kept. (Technical note: in the
  case of an unrelieved hypothesis and a non-nil value of
  instantiate-free, if a [bind-free] hypothesis produces a list of
  binding alists, then the last of those alists is the one that is
  used to extend the substitution.)

  Finally, the instruction is applied as follows. The current subterm
  is replaced by applying the final substitution described above to
  the right-hand side of the selected rule. And, one new subgoal is
  created for each unrelieved hypothesis of the rule, whose top-level
  hypotheses are the governors and top-level hypotheses of the
  current goal and whose conclusion and current subterm are the
  instance, by that same final substitution, of that unrelieved
  hypothesis.

  Remark: The substitution argument should be a list whose elements
  have the form (variable term), where term may contain
  abbreviations.")
 (ACL2-PC::RUN-INSTR-ON-GOAL
      (PROOF-CHECKER-COMMANDS)
      "(macro) auxiliary to THEN

  See [ACL2-pc::then].")
 (ACL2-PC::RUN-INSTR-ON-NEW-GOALS
      (PROOF-CHECKER-COMMANDS)
      "(macro) auxiliary to then

  See [ACL2-pc::then].")
 (ACL2-PC::RUNES
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the runes (definitions, lemmas, ...) used

    Examples and general forms:
    (runes t)   ; print all [rune]s used during this interactive proof
    (runes nil) ; print all [rune]s used by the most recent command
    (runes)     ; same as (runes nil)
    runes       ; same as (runes nil)

  This command does not change the [proof-checker] state. Rather, it
  simply reports runes (see [rune]) that have participated in the
  interactive proof.

  Note that (runes nil) will show the [rune]s used by the most recent
  primitive or macro command (as displayed by :comm).")
 (ACL2-PC::S
  (PROOF-CHECKER-COMMANDS)
  "(primitive) simplify the current subterm

    Examples:
    S  -- simplify the current subterm
    (S :backchain-limit 2 :normalize t :expand (append x z))
       -- simplify the current subterm, but during the rewriting
          process first ``normalize'' it by pushing IFs to the
          top-level, and also force the term (append x z) to be
          expanded during the rewriting process

    General Form:
    (s &key rewrite normalize backchain-limit repeat in-theory hands-off
            expand)

  Simplify the current subterm according to the keyword parameters
  supplied. First if-normalization is applied (unless the normalize
  argument is nil), i.e., each subterm of the form (f ... (if test x
  y) ...) is replaced by the term (if test (f ... x ...) (f ... y
  ...)) except, of course, when f is if and the indicated if subterm
  is in the second or third argument position. Then rewriting is
  applied (unless the rewrite argument is nil). Finally this pair of
  actions is repeated --- until the rewriting step causes no change
  in the term. A description of each parameter follows.

    :rewrite -- default t

  When non-nil, instructs the system to use ACL2's rewriter (or,
  something close to it) during simplification.

    :normalize -- default t

  When non-nil, instructs the system to use if-normalization (as
  described above) during simplification.

    :backchain-limit -- default 0

  Sets the number of recursive calls to the rewriter that are allowed
  for backchaining. Even with the default of 0, some reasoning is
  allowed (technically speaking, type-set reasoning is allowed) in
  the relieving of hypotheses. The value should be nil or a
  non-negative integer, and limits backchaining only for rewriting,
  not for type-set reasoning.

    :repeat -- default 0

  Sets the number of times the current term is to be rewritten. If this
  value is t, then the default is used (as specified by the constant
  *default-s-repeat-limit*).

    :in-theory, :hands-off, :expand

  These have their usual meaning; see [hints].

  Remark: if conditional rewrite rules are used that cause case splits
  because of the use of force, then appropriate new subgoals will be
  created, i.e., with the same current subterm (and address) but with
  each new (forced) hypothesis being negated and then used to create
  a corresponding new subgoal. In that case, the current goal will
  have all such new hypotheses added to the list of top-level
  hypotheses.")
 (ACL2-PC::S-PROP
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) simplify propositionally

    Example:
    s-prop

    General Form:
    (s-prop &rest names)

  Simplify, using the default settings for s (which include
  if-normalization and rewriting without real backchaining), but with
  respect to a theory in which only basic functions and rules (the
  ones in (theory 'minimal-theory)), together with the names (or
  parenthesized names) in the &rest argument names, are enabled.

  Also see [ACL2-pc::s].")
 (ACL2-PC::SAVE
  (PROOF-CHECKER-COMMANDS)
  "(macro) save the proof-checker state (state-stack)

    Example:
    (save lemma3-attempt)

    General Form:
    (save &optional name do-it-flg)

  Saves the current proof-checker state by ``associating'' it with the
  given name, which must be a symbol. Submit (retrieve name) to Lisp
  to get back to this proof-checker state. If verify was originally
  supplied with an event name, then the argument can be omitted in
  favor of that name as the default.

  Remark that if a save has already been done with the indicated name
  (or the default event name), then the user will be queried
  regarding whether to go ahead with the save --- except, if
  do-it-flg is supplied and not nil, then there will be no query and
  the save will be effected.

  Also see [ACL2-pc::retrieve] and [ACL2-pc::unsave].")
 (ACL2-PC::SEQUENCE
  (PROOF-CHECKER-COMMANDS)
  "(meta) run the given list of instructions according to a multitude of
  options

    Example:
    (sequence (induct p prove) t)

  This is a very general command that is used to define other
  sequencing commands; see [ACL2-pc::do-all], [ACL2-pc::do-strict],
  [ACL2-pc::protect], and [ACL2-pc::succeed].

    General Form:
    (sequence
     instruction-list
     &optional
     strict-flg protect-flg success-expr no-prompt-flg no-restore-flg)

  Each instruction in the list instruction-list is run, and the
  instruction ``succeeds'' if every instruction in instruction-list
  ``succeeds''. However, it might ``succeed'' even if some
  instructions in the list ``fail''; more generally, the various
  arguments control a number of aspects of the running of the
  instructions. All this is explained in the paragraphs below. First
  we embark on a general discussion of the instruction interpreter,
  including the notions of ``succeed'' and ``fail''.

  Remark: The arguments are not evaluated, except (in a sense) for
  success-expr, as described below.

  Each primitive and meta instruction can be thought of as returning an
  error triple, say (erp val state); see [error-triples]. An
  instruction (primitive or meta) ``succeeds'' if erp is nil and val
  is not nil; otherwise it ``fails''. (When we use the words
  ``succeed'' or ``fail'' in this technical sense, we'll always
  include them in double quotes.) If an instruction ``fails,'' we say
  that that the failure is ``soft'' if erp is nil; otherwise the
  failure is ``hard''. The sequence command gives the user control
  over how to treat ``success'' and ``failure'' when sequencing
  instructions, though we have created a number of handy macro
  commands for this purpose, notably do-all, do-strict and protect.

  Here is precisely what happens when a sequence instruction is run.
  The instruction interpreter is run on the instructions supplied in
  the argument instruction-list (in order). The interpreter halts the
  first time there is a hard ``failure.'' except that if strict-flg
  is supplied and not nil, then the interpreter halts the first time
  there is any ``failure.'' The error triple (erp val state) returned
  by the sequence instruction is the triple returned by the last
  instruction executed (or, the triple (nil t state) if
  instruction-list is nil), except for the following provision. If
  success-expr is supplied and not nil, then it is evaluated with the
  state global variables pc-erp and pc-val (in the \"ACL2\" package)
  bound to the corresponding components of the error triple returned
  (as described above). At least two values should be returned, and
  the first two of these will be substituted for erp and val in the
  triple finally returned by sequence. For example, if success-expr
  is (mv erp val), then no change will be made to the error triple,
  and if instead it is (mv nil t), then the sequence instruction will
  ``succeed''.

  That concludes the description of the error triple returned by a
  sequence instruction, but it remains to explain the effects of the
  arguments protect-flg and no-prompt-flg.

  If protect-flg is supplied and not nil and if also the instruction
  ``fails'' (i.e., the error component of the triple is not nil or
  the value component is nil), then the state is reverted so that the
  proof-checker's state (including the behavior of restore) is set
  back to what it was before the sequence instruction was executed.
  Otherwise, unless no-restore-flg is set, the state is changed so
  that the restore command will now undo the effect of this sequence
  instruction (even if there were nested calls to sequence).

  Finally, as each instruction in instruction-list is executed, the
  prompt and that instruction will be printed, unless the global
  state variable pc-print-prompt-and-instr-flg is unbound or nil and
  the parameter no-prompt-flg is supplied and not nil.")
 (ACL2-PC::SHOW-ABBREVIATIONS
  (PROOF-CHECKER-COMMANDS)
  "(macro) display the current abbreviations

    Examples:
    (show-abbreviations v w)
       -- assuming that v and w currently abbreviate terms,
          then this instruction displays them together with
          the terms they abbreviate
    show-abbreviations
       -- display all abbreviations

  Also see [ACL2-pc::add-abbreviation] for a general discussion of
  abbreviations and see [ACL2-pc::remove-abbreviations].

    General Form:
    (show-abbreviations &rest vars)

  Display each argument in vars together with the term it abbreviates
  (if any). If there are no arguments, i.e. the instruction is simply
  show-abbreviations, then display all abbreviations together with
  the terms they abbreviate.

  If the term abbreviated by a variable, say v, contains a proper
  subterm that is also abbreviate by (another) variable, then both
  the unabbreviated term and the abbreviated term (but not using (?
  v) to abbreviate the term) are displayed with together with v.")
 (ACL2-PC::SHOW-LINEARS
  (PROOF-CHECKER-COMMANDS)
  "(macro) display the applicable [linear] rules

    Example:
    show-linears

    General Form:
    (show-linears &optional rule-id enabled-only-flg)

  This command displays [linear] rules with a trigger term that matches
  the current subterm, and shows how they can be applied. This
  command is analogous to the show-rewrites [proof-checker] command;
  see [ACL2-pc::show-rewrites]. Also see [ACL2-pc::apply-linear] for
  how to apply [linear] rules.")
 (ACL2-PC::SHOW-REWRITES
  (PROOF-CHECKER-COMMANDS)
  "(macro) display the applicable [rewrite] rules

    Example:
    show-rewrites

    General Form:
    (show-rewrites &optional rule-id enabled-only-flg)

  This command displays [rewrite] rules whose left-hand side matches
  the current subterm, and shows how that command can be applied. For
  each rule displayed, hypotheses are shown that would need to be
  proved after the rule is applied. Note that hypotheses are omitted
  from the display when the system can trivially verify that they
  hold; to see all hypotheses for each rule in a display that is
  independent of the arguments of the current subterm, use the pl or
  pr command.

  Here are details on the arguments and the output. If rule-id is
  supplied and is a name (non-nil symbol) or a :[rewrite] or
  :[definition] [rune], then only the corresponding rewrite rule(s)
  will be displayed, while if rule-id is a positive integer n, then
  only the nth rule that would be in the list is displayed. In each
  case, the display will point out when a rule is currently disabled
  (in the interactive environment), except that if enabled-only-flg
  is supplied and not nil, then disabled rules will not be displayed
  at all. Finally, among the free variables of any rule (see
  [free-variables]), those that would remain free if the rule were
  applied will be displayed. Also see [rewrite].")
 (ACL2-PC::SHOW-TYPE-PRESCRIPTIONS
  (PROOF-CHECKER-COMMANDS)
  "(macro) display the applicable [type-prescription] rules

    Example:
    show-type-prescriptions

    General Form:
    (show-type-prescriptions &optional rule-id)

  Display [type-prescription] rules that apply to the current subterm.
  If rule-id is supplied and is a name (non-nil symbol) or a
  :[rewrite] or :[definition] [rune], then only the corresponding
  rewrite rule(s) will be displayed. In each case, the display will
  point out when a rule is currently disabled (in the interactive
  environment). Also see [type-prescription].")
 (ACL2-PC::SKIP
  (PROOF-CHECKER-COMMANDS)
  "(macro) ``succeed'' without doing anything

    Example and General Form:
    skip

  Make no change in the state-stack, but ``succeed''. Same as (sequence
  nil).")
 (ACL2-PC::SL
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) simplify with lemmas

    Examples:
    sl
    (sl 3)

    General Form:
    (sl &optional backchain-limit)

  Simplify, but with all function definitions disabled (see
  [function-theory] in the top-level ACL2 loop), except for a few
  basic functions (the ones in (theory 'minimal-theory)). The
  backchain-limit has a default of 0, but if is supplied and not nil,
  then it should be a nonnegative integer; see [ACL2-pc::s].

  WARNING: This command completely ignores in-theory commands that are
  executed inside the [proof-checker].")
 (ACL2-PC::SLS
  (PROOF-CHECKER-COMMANDS)
  "(macro) same as SHOW-LINEARS

    Example:
    sls

    General Form:
    (sls &optional rule-id enabled-only-flg)

  See show-linears. NOTE: In analogy to the sr abbreviation for
  show-rewrites, one might expect this command to be sl; but that
  name was taken (``simplify with lemmas'') before sls was
  implemented.")
 (ACL2-PC::SPLIT
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) split the current goal into cases

    Example:
    split

  For example, if the current goal has one hypothesis (or x y) and a
  conclusion of (and a b), then split will create four new goals:

    one with hypothesis X and conclusion A
    one with hypothesis X and conclusion B
    one with hypothesis Y and conclusion A
    one with hypothesis Y and conclusion B.

    General Form:
    SPLIT

  Replace the current goal by subgoals whose conjunction is equivalent
  (primarily by propositional reasoning) to the original goal, where
  each such goal cannot be similarly split.

  Remark: The new goals will all have their hypotheses promoted; in
  particular, no conclusion will have a top function symbol of
  implies. Also note that split will fail if there is exactly one new
  goal created and it is the same as the existing current goal.

  The way split really works is to call the ACL2 theorem prover with
  only simplification (and preprocessing) turned on, and with only a
  few built-in functions (especially, propositional ones) enabled,
  namely, the ones in the list (theory 'minimal-theory). However,
  because the prover is called, type-set reasoning can be used to
  eliminate some cases. For example, if (true-listp x) is in the
  hypotheses, then probably (true-listp (cdr x)) will be reduced to
  t.")
 (ACL2-PC::SR
  (PROOF-CHECKER-COMMANDS)
  "(macro) same as SHOW-REWRITES

    Example:
    sr

    General Form:
    (sr &optional rule-id enabled-only-flg)

  See [ACL2-pc::show-rewrites].")
 (ACL2-PC::ST
  (PROOF-CHECKER-COMMANDS)
  "(macro) same as SHOW-TYPE-PRESCRIPTIONS

    Example:
    sr

    General Form:
    (st &optional rule-id)

  See [ACL2-pc::show-type-prescriptions].")
 (ACL2-PC::SUCCEED
  (PROOF-CHECKER-COMMANDS)
  "(macro) run the given instructions, and ``succeed''

    Example:
    (succeed induct p prove)

    General Form:
    (succeed &rest instruction-list)

  Run the indicated instructions until there is a hard ``failure'', and
  ``succeed''. (See [ACL2-pc::sequence] for an explanation of
  ``success'' and ``failure''.)")
 (ACL2-PC::TH
  (PROOF-CHECKER-COMMANDS)
  "(macro) print the top-level hypotheses and the current subterm

    Examples:
    th               -- print all (top-level) hypotheses and the current
                        subterm
    (th (1 3) (2 4)) -- print hypotheses 1 and 3 and governors 2 and 4,
                        and the current subterm
    (th (1 3) t)     -- print hypotheses 1 and 3 and all governors, and
                        the current subterm

    General Form:
    (th &optional hyps-indices govs-indices)

  Print hypotheses and the current subterm. The printing of hypotheses
  (and perhaps governors) are controlled as in the hyps command; see
  [ACL2-pc::hyps].

  Historical note: The name th is adapted from the Gypsy Verification
  Environment, where th abbreviates the command theorem, which says
  to print information on the current goal.")
 (ACL2-PC::THEN
  (PROOF-CHECKER-COMMANDS)
  "(macro) apply one instruction to current goal and another to new
  subgoals

    Example:
    (then induct prove)

    General Form:
    (then first-instruction &optional completion must-succeed-flg)

  Run first-instruction, and then run completion (another instruction)
  on each subgoal created by first-instruction. If must-succeed-flg
  is supplied and not nil, then halt at the first ``failure'' and
  remove the effects of the invocation of completion that ``failed''.

  The default for completion is reduce.")
 (ACL2-PC::TOP
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) move to the top of the goal

    Example and General Form:
    top

  For example, if the conclusion is (= x (* (- y) z)) and the current
  subterm is y, then after executing top, the current subterm will be
  the same as the conclusion, i.e., (= x (* (- y) z)).

  Top is the same as (up n), where n is the number of times one needs
  to execute up in order to get to the top of the conclusion. The top
  command fails if one is already at the top of the conclusion.

  Also see [ACL2-pc::up], [ACL2-pc::dive], [ACL2-pc::nx], and
  [ACL2-pc::bk].")
 (ACL2-PC::TYPE-ALIST
  (PROOF-CHECKER-COMMANDS)
  "(macro) display the [type-alist] from the current context

    Examples:
    (type-alist t t)     ; display type-alist based on conclusion and governors
    (type-alist t t t)   ; as above, but also display forward-chaining report
    type-alist           ; same as (type-alist nil t) -- governors only
    (type-alist nil)     ; same as (type-alist nil t) -- governors only
    (type-alist t)       ; same as (type-alist t nil) -- conclusion only
    (type-alist nil nil) ; display type-alist without considering
                         ; conclusion or governors

    General Form:
    (type-alist &optional concl-flg govs-flg fc-report-flg)

  where if govs-flg is omitted then it defaults to (not concl-flg), and
  concl-flg and fc-report-flg default to nil.

  Display the current assumptions as a [type-alist]. Note that this
  display includes the result of forward chaining. When fc-report-flg
  is supplied a non-nil value, the display also includes a
  forward-chaining report; otherwise,the presence or absence of such
  a report is controlled by the usual global settings (see
  [forward-chaining-reports]).

  There are two basic reasons contemplated for using this command.

  1. The theorem prover has failed (either outside the proof-checker or
  using a proof-checker command such as bash or reduce and you want
  to debug by getting an idea of what the prover knows about the
  context.

      a. You really are interested in the context for the current term.
      Include hypotheses and governors (i.e., accounting for tests of
      surrounding if-expressions that must be true or false) but not
      the current conclusion (which the theorem prover's heuristics
      would generally ignore for contextual information). Command:
      (type-alist nil t) ; equivalently, type-alist or (type-alist nil)

      b. You are not thinking in particular about the current term; you
      just want to get an idea of the context that the prover would
      build at the top-level, for forward-chaining. Incorporate the
      conclusion but not the governors. Command:
      (type-alist t nil) ; equivalently, (type-alist t)

  2. You intend to use one of the [proof-checker-commands] that does
  simplification, such as s or x, and you want to see the context.
  Then include the surrounding if-term governors but not the goal's
  conclusion. Command:
  (type-alist nil t) ; equivalently, type-alist or (type-alist nil)

  See [type-set] (also see [type-prescription]) for information about
  ACL2's type system, which can assist in understanding the output of
  the type-alist command.")
 (ACL2-PC::UNDO
  (PROOF-CHECKER-COMMANDS)
  "(meta) undo some instructions

    Examples:
    (undo 7)
    undo

    General Forms:

    (undo n) -- Undo the last n instructions.  The argument n should be
                a positive integer.

    undo     -- Same as (undo 1).

  Remark: To remove the effect of an undo command, use restore; see
  [ACL2-pc::restore].

  Remark: If the argument n is greater than the total number of
  interactive instructions in the current session, then (undo n) will
  simply take you back to the start of the session.

  The undo meta command always ``succeeds''; it returns (mv nil t
  state) unless its optional argument is supplied and of the wrong
  type (i.e. not a positive integer) or there are no instructions to
  undo.")
 (ACL2-PC::UNSAVE
  (PROOF-CHECKER-COMMANDS)
  "(macro) remove a proof-checker state

    Example:
    (unsave assoc-of-append)

    General Form:
    (unsave &optional name)

  Eliminates the association of a proof-checker state with name, if
  name is supplied and not nil. The name may be nil or not supplied,
  in which case it defaults to the event name supplied with the
  original call to verify (if there is one --- otherwise, the
  instruction ``fails'' and there is no change). The ACL2 function
  unsave may also be executed outside the interactive loop, with the
  same syntax.

  Also see [ACL2-pc::save] and [ACL2-pc::retrieve].")
 (ACL2-PC::UP
  (PROOF-CHECKER-COMMANDS)
  "(primitive) move to the parent (or some ancestor) of the current
  subterm

    Examples:  if the conclusion is (= x (* (- y) z)) and the
               current subterm is y, then we have:
    up or (up 1) -- the current subterm becomes (- y)
    (up 2)       -- the current subterm becomes (* (- y) z)
    (up 3)       -- the current subterm becomes the entire conclusion
    (up 4)       -- no change; can't go up that many levels

    General Form:
    (up &optional n)

  Move up n levels in the conclusion from the current subterm, where n
  is a positive integer. If n is not supplied or is nil, then move up
  one level, i.e., treat the instruction as (up 1).

  Also see [ACL2-pc::dive], [ACL2-pc::top], [ACL2-pc::nx], and
  [ACL2-pc::bk].")
 (ACL2-PC::USE
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) use a lemma instance

    Example:
    (USE true-listp-append
         (:instance assoc-of-append (x a) (y b) (z c)))
    -- Add two top-level hypotheses, one the lemma called
       true-listp-append, and the other an instance of the lemma called
       assoc-of-append by the substitution in which x is assigned a, y
       is assigned b, and z is assigned c.

    General Form:
    (use &rest args)

  Add the given lemma instances to the list of top-level hypotheses.
  See [hints] for the syntax of :use hints in defthm, which is
  essentially the same as the syntax here (see the example above).

  This command calls the prove command, and hence should only be used
  at the top of the conclusion.")
 (ACL2-PC::WRAP
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) execute the indicated instructions and combine all the
  new goals

    Example:
    (wrap induct) ; induct, then replace first new goal by the conjunction of all
                  ; the new goals, and drop all new goals after the first

    General Form:
    (wrap &rest instrs)

  First the instructions in instrs are executed, as in do-all. If this
  ``fails'' then no additional action is taken. Otherwise, the
  current goal after execution of instrs is conjoined with all
  ``new'' goals, in the sense that their names are not among the
  names of goals at the time instrs was begun. This conjunction
  becomes the new current goal and those ``new'' goals are dropped.

  See the code for the [proof-checker] command wrap-induct for an
  example of the use of wrap.")
 (ACL2-PC::WRAP-INDUCT
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) same as induct, but create a single goal

    Examples:
    wrap-induct
    (wrap-induct t)
    (wrap-induct (append (reverse x) y))

    General Form:
    (wrap-induct &optional term)

  The wrap-induct command is identical to the [proof-checker] induct
  command (see [ACL2-pc::induct]), except that only a single goal is
  created: the conjunction of the base and induction steps.

  Note: The output will generally indicate that more than goal has been
  created, e.g.:

    Creating two new goals:  (MAIN . 1) and (MAIN . 2).

  However, wrap-induct always creates a unique goal (when it succeeds).
  A subsequent message clarifies this, for example:

    NOTE: Created ONLY one new goal, which is the current goal:
      (MAIN . 1)")
 (ACL2-PC::WRAP1
  (PROOF-CHECKER-COMMANDS)
  "(primitive) combine goals into a single goal

    Examples:
    ; Keep (main . 1) and (main . 2) if they exist, as well as the current goal;
    ; and for each other goal, conjoin it into the current goal and delete it:
    (wrap1 ((main . 1) (main . 2)))

    ; As explained below, conjoin all subsequent siblings of the current goal
    ; into the current goal, and then delete them:
    (wrap1)

    General Form:
    (wrap1 &optional kept-goal-names)

  If kept-goal-names is not nil, the current goal is replaced by
  conjoining it with all goals other than the current goal and those
  indicated by kept-goal-names, and those other goals are deleted. If
  kept-goal-names is omitted, then the the current goal must be of
  the form (name . n), and the goals to conjoin into the current goal
  (and delete) are those with names of the form (name . k) for k >=
  n.

  NOTE: Wrap1 always ``succeeds'', even if there are no other goals to
  conjoin into the current goal (a message is printed in that case),
  and it always leaves you with no hypotheses at the top of the
  current goal's conclusion (as though top and demote had been
  executed, if necessary).

  Also see [ACL2-pc::wrap].")
 (ACL2-PC::X
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) expand and (maybe) simplify function call at the
  current subterm

    Examples:
    x --  expand and simplify.

  Also see [ACL2-pc::expand] and see [ACL2-pc::x-dumb], which do not
  perform simplification.

  For example, if the current subterm is (append a b), then after x the
  current subterm will probably be (cons (car a) (append (cdr a) b))
  if (consp a) and (true-listp a) are among the top-level hypotheses
  and governors. If there are no top-level hypotheses and governors,
  then after x the current subterm will probably be:

    (if (true-listp x)
        (if x
            (cons (car x) (append (cdr x) y))
          y)
      (apply 'binary-append (list x y))).

    General Form:
    (X &key
       rewrite normalize backchain-limit in-theory hands-off expand)

  Expand the function call at the current subterm, and simplify using
  the same conventions as with the s command (see [ACL2-pc::s]).

  Unlike s, it is permitted to set both :rewrite and :normalize to nil,
  which will result in no simplification; see [ACL2-pc::x-dumb].

  Remark (obscure): On rare occasions the current address may be
  affected by the use of x. For example, suppose we have the
  definition

    (defun g (x) (if (consp x) x 3))

  and then we enter the proof-checker with

    (verify (if (integerp x) (equal (g x) 3) t)) .

  Then after invoking the instruction (dive 2 1), so that the current
  subterm is (g x), followed by the instruction x, we would expect
  the conclusion to be (if (integerp x) (equal 3 3) t). However, the
  system actually replaces (equal 3 3) with t (because we use the
  ACL2 term-forming primitives), and hence the conclusion is actually
  (if (integerp x) t t). Therefore, the current address is put at (2)
  rather than (2 1). In such cases, a warning ``NOTE'' will be
  printed to the terminal.

  The other primitive commands to which the above ``truncation'' note
  applies are equiv, rewrite, and s.")
 (ACL2-PC::X-DUMB
  (PROOF-CHECKER-COMMANDS)
  "(atomic macro) expand function call at the current subterm, without
  simplifying

    General Form:
    x-dumb:  expand without simplification.

  Same as (expand t). See [ACL2-pc::expand].

  Also see [ACL2-pc::x], which performs simplification."))

)