other
(in-package "STD")
other
(include-book "xdoc/top" :dir :system)
other
(include-book "std/util/bstar" :dir :system)
other
(defxdoc support :parents (std/util) :short "Miscellaneous supporting functions used by the @(see std/util) library.")
other
(defsection tuplep :parents (support) :short "@(call tuplep) recognizes nil-terminated @('n')-tuples." (defun tuplep (n x) (declare (xargs :guard (natp n))) (mbe :logic (and (true-listp x) (equal (len x) n)) :exec (and (true-listp x) (eql (length x) n)))))
other
(defsection tuple-listp :parents (support) :short "@(call tuple-listp) recognizes a list of nil-terminated @('n')-tuples." (defun tuple-listp (n x) (declare (xargs :guard (natp n))) (if (consp x) (and (tuplep n (car x)) (tuple-listp n (cdr x))) t)))
other
(defsection cons-listp :parents (support) :short "@(call cons-listp) is like @(see alistp) but does not require the list to be nil-terminated." (defun cons-listp (x) (declare (xargs :guard t)) (if (consp x) (and (consp (car x)) (cons-listp (cdr x))) t)))
other
(defsection raise :parents (support define er) :short "Shorthand for causing hard errors." :long "<p>@(call raise) is equivalent to @('(er hard? ...)'), but it automatically fills in the function name using @('__function__').</p> <p>This only works in contexts where @('__function__') is bound, e.g., the body of a @(see define) or within a @(see defconsts) form. In these contexts, rather than write something like:</p> @({ (er hard? __function__ "bad input value ~x0~%" x) }) <p>You can just write:</p> @({ (raise "bad input value ~x0~%" x) }) <p>Logically @('raise') just returns @('nil').</p> @(def raise)" (defmacro raise (&rest args) `(er hard? __function__ . ,STD::ARGS)))
other
(defsection legal-kwds-p :parents (support) :short "List of legal keywords for extract-keywords." :long "<p>Recognizes a list where each element is either a symbol a singleton list containing a symbol. In @(see extract-keywords), a bare symbol is a legal keyword and a symbol in a singleton list is a keyword that can occur multiple times in an argument list.</p>" (defun legal-kwds-p (x) (declare (xargs :guard t)) (if (atom x) (eq x nil) (and (or (symbolp (car x)) (and (consp (car x)) (symbolp (caar x)) (not (cdar x)))) (legal-kwds-p (cdr x))))))
other
(defsection keyword-legality :parents (support) :short "Check whether x is a legal keyword" :long "<p>Returns :single if x is allowed to occur once in the argument list, :multiple if it is allowed to occur more than once, and NIL if not allowed.</p>" (defun keyword-legality (x legals) (declare (xargs :guard (and (symbolp x) (legal-kwds-p legals)))) (cond ((atom legals) nil) ((eq x (car legals)) :single) ((and (consp (car legals)) (eq x (caar legals))) :multiple) (t (keyword-legality x (cdr legals))))))
other
(local (defthm alistp-of-remove1-assoc-equal (implies (alistp alist) (alistp (remove1-assoc-equal key alist)))))
other
(defsection extract-keywords :parents (support) :short "Extract legal keyword/value pairs from an argument list." :long "<p>If a keyword occurs as a singleton list in legal-kwds, it may have mulitple occurrences in the args, and the result stored in the kwd-alist will be a list of the arguments to the occurrences. For example:</p> @({ (extract-keywords 'foo '((:bar)) '(:bar x :bar y) nil) }) <p>produces @('((:bar y x))') as its keyword alist result.</p>" (defun extract-keywords (ctx legal-kwds args kwd-alist) "Returns (mv kwd-alist other-args)" (declare (xargs :guard (and (legal-kwds-p legal-kwds) (alistp kwd-alist)))) (b* ((__function__ 'extract-keywords) ((when (atom args)) (mv kwd-alist args)) (arg1 (first args)) ((unless (keywordp arg1)) (b* (((mv kwd-alist other-args) (extract-keywords ctx legal-kwds (cdr args) kwd-alist))) (mv kwd-alist (cons arg1 other-args)))) (legality (keyword-legality arg1 legal-kwds)) ((unless legality) (raise (concatenate 'string "~x0: invalid keyword ~x1." (if legal-kwds " Valid keywords: ~&2." " No keywords are valid here.")) ctx arg1 legal-kwds) (mv nil nil)) ((when (atom (rest args))) (raise "~x0: keyword ~x1 has no argument." ctx arg1) (mv nil nil)) ((when (and (not (eq legality :multiple)) (assoc arg1 kwd-alist))) (raise "~x0: multiple occurrences of keyword ~x1." ctx arg1) (mv nil nil)) (value (second args)) (kwd-alist (if (eq legality :multiple) (acons arg1 (cons value (cdr (assoc arg1 kwd-alist))) (remove1-assoc arg1 kwd-alist)) (acons arg1 value kwd-alist)))) (extract-keywords ctx legal-kwds (cddr args) kwd-alist))))
other
(defsection getarg :parents (support) :short "Get a value from the keyword-value alist produced by @(see extract-keywords), with default-value support." (defun getarg (arg default alist) (declare (xargs :guard (and (eqlablep arg) (alistp alist)))) (b* ((look (assoc arg alist))) (if look (cdr look) default))))
other
(defsection getarg+ :parents (support) :short "Get a value from the keyword-value alist produced by @(see extract-keywords), with default-value support, and additionally return a flag saying whether the key was bound. Returns (mv value boundp)." (defun getarg+ (arg default alist) (declare (xargs :guard (and (eqlablep arg) (alistp alist)))) (b* ((look (assoc arg alist))) (if look (mv (cdr look) t) (mv default nil)))))
assigns-for-getargsfunction
(defun assigns-for-getargs (args alist lazyp) (declare (xargs :mode :program)) (if (atom args) nil (append (let ((arg (car args))) (case-match arg ((var default boundp) (b* (((mv basevar ?ign) (decode-varname-for-patbind var)) (key (intern-in-package-of-symbol (symbol-name basevar) :key))) (if (and lazyp (consp default) (not (eq (car default) 'quote))) `((,BOUNDP (assoc ,STD::KEY ,STD::ALIST)) (,STD::VAR (if boundp (cdr boundp) ,STD::DEFAULT))) `(((mv ,STD::VAR ,BOUNDP) (getarg+ ,STD::KEY ,STD::DEFAULT ,STD::ALIST)))))) ((var default) (b* (((mv basevar ?ign) (decode-varname-for-patbind var)) (key (intern-in-package-of-symbol (symbol-name basevar) :key))) (if (and lazyp (consp default) (not (eq (car default) 'quote))) `((,STD::VAR (let ((tmp-look (assoc ,STD::KEY ,STD::ALIST))) (if tmp-look (cdr tmp-look) (check-vars-not-free (tmp-look) ,STD::DEFAULT))))) `((,STD::VAR (getarg ,STD::KEY ,STD::DEFAULT ,STD::ALIST)))))) (var (b* (((mv basevar ?ign) (decode-varname-for-patbind var)) (key (intern-in-package-of-symbol (symbol-name basevar) :key))) `((,STD::VAR (getarg ,STD::KEY nil ,STD::ALIST))))))) (assigns-for-getargs (cdr args) alist lazyp))))
other
(def-b*-binder getargs :short "@(see b*) binder for getargs on a keyword alist." :long "<p>Usage:</p> @({ (b* (((getargs :lazyp t a (b b-default-term) (c c-default-term cp) d) alst)) form) }) <p>is equivalent to</p> @({ (b* ((a (getarg :a nil alst)) (b (getarg :b b-default-term alst)) ((mv c cp) (getarg+ :c c-default-term alst)) (d (getarg :d nil alist))) form) })" :body (b* (((mv kwd-alist args) (extract-keywords 'getargs '(:lazyp) args nil)) (lazyp (cdr (assoc :lazyp kwd-alist)))) (mv-let (pre-bindings name rest) (if (and (consp (car forms)) (not (eq (caar forms) 'quote))) (mv `((?tmp-for-getargs ,(CAR FORMS))) 'tmp-for-getargs `(check-vars-not-free (tmp-for-getargs) ,REST-EXPR)) (mv nil (car forms) rest-expr)) `(b* (,@STD::PRE-BINDINGS . ,(STD::ASSIGNS-FOR-GETARGS STD::ARGS STD::NAME STD::LAZYP)) ,REST))))
keys-for-getargsfunction
(defun keys-for-getargs (args) (declare (xargs :mode :program)) (if (atom args) nil (b* ((arg (car args)) (var (if (consp arg) (car arg) arg)) ((mv basevar ?ign) (decode-varname-for-patbind var)) (key (intern-in-package-of-symbol (symbol-name basevar) :key))) (cons key (keys-for-getargs (cdr args))))))
other
(def-b*-binder extract-keyword-args :short "@(see b*) binder for getargs on a keyword alist." :long "<p>Usage:</p> @({ (b* (((extract-keyword-args :other-args other-args-var :allowed-keys allowed-keys-term :kwd-alist kwd-alist-var :defaults default-kwd-alist :ctx context :lazyp lazyp a (b b-default-term) (c c-default-term cp) d) args)) form) }) <p>is equivalent to</p> @({ (b* (((mv kwd-alist-var other-args-var) (extract-keywords context (append '(:a :b :c :d) allowed-keys-term) ;; allowed keys args nil)) ((getargs :lazyp lazyp a (b b-default-term) (c c-default-term cp) d) (append kwd-alist-var default-kwd-alist))) form) })" :body (b* (((mv keywords args) (extract-keywords 'extract-keyword-args '(:lazyp :other-args :kwd-alist :ctx :allowed-keys :defaults) args nil)) ((getargs lazyp allowed-keys (other-args '?other-args) (kwd-alist '?kwd-alist) (ctx '__function__) (defaults nil)) keywords) (getarg-keys (keys-for-getargs args)) ((mv kwd-alist-var ?ign) (decode-varname-for-patbind kwd-alist)) ((mv pre-bindings name rest) (if (and (consp (car forms)) (not (eq (caar forms) 'quote))) (mv `((?tmp-for-extract-keyword-args ,(CAR FORMS))) 'tmp-for-extract-keyword-args `(check-vars-not-free (tmp-for-extract-keyword-args) ,REST-EXPR)) (mv nil (car forms) rest-expr)))) `(b* (,@STD::PRE-BINDINGS ((mv ,STD::KWD-ALIST ,STD::OTHER-ARGS) (extract-keywords ,STD::CTX ,(IF STD::ALLOWED-KEYS (IF STD::GETARG-KEYS `(APPEND ',STD::GETARG-KEYS ,STD::ALLOWED-KEYS) STD::ALLOWED-KEYS) `',STD::GETARG-KEYS) ,STD::NAME nil)) ((getargs :lazyp ,STD::LAZYP . ,STD::ARGS) ,(IF STD::DEFAULTS `(APPEND ,STD::KWD-ALIST-VAR ,STD::DEFAULTS) STD::KWD-ALIST-VAR))) ,REST)))
other
(defsection split-/// :parents (support) :short "Split an argument list into pre- and post-@('///') contents." (defun split-/// (ctx x) "Returns (mv pre-/// post-///)" (declare (xargs :guard t)) (b* ((__function__ 'split-///) ((when (not x)) (mv nil nil)) ((when (atom x)) (raise "~x0: expected nil-terminated arguments but found ~x1." ctx x) (mv nil nil)) ((when (eq (car x) '///)) (mv nil (cdr x))) ((mv pre post) (split-/// ctx (cdr x)))) (mv (cons (car x) pre) post))) (defthmd true-listp-of-split-///.pre-/// (true-listp (mv-nth 0 (split-/// ctx x)))) (defthm true-listp-of-split-///.post-/// (implies (true-listp x) (true-listp (mv-nth 1 (split-/// ctx x))))) (in-theory (disable split-///)))
other
(defsection ends-with-period-p :parents (support) :short "Determines if a string ends with a period." (defun ends-with-period-p (x) (declare (xargs :guard (stringp x))) (let ((xl (length x))) (and (> xl 0) (eql (char x (- (length x) 1)) #\.)))))
other
(defsection dumb-string-sublis :parents (support) :short "Non-recursively applies a list of substring substitutions to a string." :long "<p>Earlier key/value pairs take precedence over later ones, and no substitutions are reapplied to the result of other substitutions.</p>" (defun dumb-str-sublis-iter (remainder alist x start end len) (declare (xargs :mode :program)) (b* (((when (atom remainder)) (if (or (not (int= start 0)) (not (int= end len))) (subseq x start end) x)) ((cons old-str new-str) (car remainder)) (loc (search old-str x :start2 start :end2 end)) ((unless loc) (dumb-str-sublis-iter (cdr remainder) alist x start end len)) (prefix-rw (dumb-str-sublis-iter (cdr remainder) alist x start loc len)) (suffix-rw (dumb-str-sublis-iter alist alist x (+ loc (length old-str)) end len))) (if (and (string-equal prefix-rw "") (string-equal suffix-rw "")) new-str (concatenate 'string prefix-rw new-str suffix-rw)))) (defun dumb-str-sublis (alist str) (declare (xargs :mode :program)) (let ((len (length str))) (dumb-str-sublis-iter alist alist str 0 len len))))
other
(defsection generic-eval-requirement :parents (std/lists/abstract) :short "Evaluate a requirement of a generic theorem for deflist/defprojection/defmapappend" :long "<p>See @(see acl2::std/lists/abstract).</p>" (mutual-recursion (defun generic-eval-requirement (req req-alist) (declare (xargs :mode :program)) (if (atom req) (let ((look (assoc req req-alist))) (if look (cdr look) (er hard? 'generic-eval-requirement "Unrecognized requirement variable: ~x0~%" req))) (case (car req) ('not (not (generic-eval-requirement (cadr req) req-alist))) ('and (generic-and-requirements (cdr req) req-alist)) ('or (generic-or-requirements (cdr req) req-alist)) ('if (if (generic-eval-requirement (cadr req) req-alist) (generic-eval-requirement (caddr req) req-alist) (generic-eval-requirement (cadddr req) req-alist))) (otherwise (er hard? 'generic-eval-requirement "malformed requirement term: ~x0~%" req))))) (defun generic-and-requirements (reqs req-alist) (if (atom reqs) t (and (generic-eval-requirement (car reqs) req-alist) (generic-and-requirements (cdr reqs) req-alist)))) (defun generic-or-requirements (reqs req-alist) (if (atom reqs) nil (or (generic-eval-requirement (car reqs) req-alist) (generic-or-requirements (cdr reqs) req-alist))))))
other
(mutual-recursion (defun find-calls-of-fns-term (x fns acc) (declare (xargs :mode :program)) (cond ((or (atom x) (eq (car x) 'quote)) acc) ((member-eq (car x) fns) (find-calls-of-fns-list (cdr x) fns (cons x acc))) (t (find-calls-of-fns-list (cdr x) fns acc)))) (defun find-calls-of-fns-list (x fns acc) (if (atom x) acc (find-calls-of-fns-term (car x) fns (find-calls-of-fns-list (cdr x) fns acc)))))
expand-calls-computed-hintfunction
(defun expand-calls-computed-hint (clause fns) (declare (xargs :mode :program)) (let ((expand-list (find-calls-of-fns-term (car (last clause)) fns nil))) `(:expand ,STD::EXPAND-LIST)))
expand-callsmacro
(defmacro expand-calls (&rest fns) `(expand-calls-computed-hint clause ',STD::FNS))