summaryrefslogtreecommitdiff
path: root/books/workshops/2002/kaufmann-sumners/support/records0.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'books/workshops/2002/kaufmann-sumners/support/records0.lisp')
-rw-r--r--books/workshops/2002/kaufmann-sumners/support/records0.lisp427
1 files changed, 427 insertions, 0 deletions
diff --git a/books/workshops/2002/kaufmann-sumners/support/records0.lisp b/books/workshops/2002/kaufmann-sumners/support/records0.lisp
new file mode 100644
index 0000000..50aee49
--- /dev/null
+++ b/books/workshops/2002/kaufmann-sumners/support/records0.lisp
@@ -0,0 +1,427 @@
+; Matt Kaufmann and Rob Sumners
+
+(in-package "ACL2")
+
+#|
+
+We define properties of a generic record accessor function and updater
+function. The basic functions are (g a r) and (s a v r) where a is an
+address/key, v is a value, r is a record, and (g a r) returns the value set to
+address a in record r, and (s a v r) returns a new record with address a set to
+value v in record r.
+
+The following main lemma are "exported" about record (g)et and (s)et:
+
+(defthm g-same-s
+ (equal (g a (s a v r))
+ v))
+
+(defthm g-diff-s
+ (implies (not (equal a b))
+ (equal (g a (s b v r))
+ (g a r))))
+
+(defthm s-same-g
+ (equal (s a (g a r) r)
+ r))
+
+(defthm s-same-s
+ (equal (s a y (s a x r))
+ (s a y r)))
+
+(defthm s-diff-s
+ (implies (not (equal a b))
+ (equal (s b y (s a x r))
+ (s a x (s b y r))))
+ :rule-classes ((:rewrite :loop-stopper ((b a s)))))
+
+
+we also include some auxiliary lemmas which have proven useful,
+
+(defthm access-of-nil-is-nil
+ (not (g a nil)))
+
+(defthm record-set-cannot-be-nil
+ (implies v (s a v r)))
+
+(defthm record-get-non-nil-cannot-be-nil
+ (implies (g a r) r))
+
+(defthm s-preserves-recordp
+ (implies (rcdp r)
+ (rcdp (s a v r))))
+
+
+and we include a theorem formerly from record-equality.lisp
+
+(defthm rcdp-equality-sufficiency
+ (implies (and (rcdp r1) (rcdp r2))
+ (equal (equal r1 r2)
+ (let ((field (bad-field r1 r2)))
+ (implies (symbolp field)
+ (equal (g field r1)
+ (g field r2)))))))
+
+Main idea of how this all works:
+
+A record is an ordered alist whose values are all non-nil.
+
+A lookup structure is the cons of a record onto any object, such that this
+object is (recursively) not a lookup structure.
+
+So, the cdr of a lookup structure is "junk", while the car is the record that
+holds the values. However, if we have other than a lookup structure then we
+view its entirety as "junk."
+
+G ("get") returns nil on a non-lookup structure, else looks up in the record
+part (the car).
+
+S ("set") would "like" simply to set the value in the record part. However, it
+respects the form of the lookup structure, so for example it has to delete an
+existing key if it wants to set a key's value to nil.
+
+|#
+
+(include-book "../../../../misc/total-order")
+
+(defun rcdp (x)
+
+; This is the recognizer for an ordered alist with no nil cdrs.
+
+ (declare (xargs :guard t))
+ (if (atom x) (null x)
+ (and (consp (car x))
+ (cdar x)
+ (if (atom (cdr x))
+ (null (cdr x))
+ (and (rcdp (cdr x))
+ (<< (caar x) (caadr x)))))))
+
+(defun lsp (x)
+
+; This is the recognizer for a lookup structure (see earlier comment).
+
+ (declare (xargs :guard t))
+ (or (rcdp x)
+ (and (consp x)
+ (not (lsp (cdr x)))
+ (rcdp (car x))
+ (car x))))
+
+(defun g (a x)
+
+; Get the value of a in x.
+
+ (declare (xargs :guard t))
+ (cond ((rcdp x)
+ (cdr (assoc-equal a x)))
+ ((lsp x)
+ (cdr (assoc-equal a (car x))))
+ (t nil)))
+
+(defun s-aux (a v r)
+
+; Update record r by binding a to a non-nil value, v.
+
+ (declare (xargs :guard (rcdp r)))
+ (cond ((endp r)
+ (cons (cons a v) nil))
+ ((equal a (caar r))
+ (cons (cons a v) (cdr r)))
+ ((<< a (caar r))
+ (cons (cons a v) r))
+ (t (cons (car r) (s-aux a v (cdr r))))))
+
+(defun delete-key (key alist)
+ (declare (xargs :guard (rcdp alist)))
+ (cond ((endp alist) alist)
+ ((equal key (caar alist))
+ (cdr alist))
+ (t (cons (car alist)
+ (delete-key key (cdr alist))))))
+
+(defun s (a v x)
+ (declare (xargs :guard t))
+ (cond ((rcdp x)
+ (if (null v)
+ (delete-key a x)
+ (s-aux a v x)))
+ ((not (lsp x))
+ (if v
+ ;; then make x into the cdr of the returned lookup structure
+ (cons (list (cons a v)) x)
+ ;; else x already is an appropriate result
+ x))
+ ;; else we have (cons record junk)
+ ((null v)
+ (if (and (null (cdr (car x)))
+ (equal (caar (car x)) a))
+ ;; then return the junk; there is nothing left of the record
+ (cdr x)
+ ;; else delete the key, a, from the record portion
+ (cons (delete-key a (car x))
+ (cdr x))))
+ (t
+ ;; since (lsp x) and v is non-nil, we simply update the record portion
+ (cons (s-aux a v (car x))
+ (cdr x)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Interaction properties for s and g;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(local
+(defthm delete-key-no-op
+ (implies (and (rcdp alist)
+ (not (assoc-equal key alist)))
+ (equal (delete-key key alist) alist))))
+
+(local
+(defthm values-not-nil
+ (implies (rcdp alist)
+ ;; The order below ooks dangerous, but apparently the prover's
+ ;; heuristics save us.
+ (iff (assoc-equal key alist)
+ (cdr (assoc-equal key alist))))))
+
+(local
+(defthm key-order-lemma
+ (implies (and (rcdp alist)
+ (<< a (caar alist)))
+ (not (cdr (assoc-equal a alist))))))
+
+(local
+(defthm s-aux-to-same
+ (implies (and (rcdp alist)
+ (cdr (assoc-equal a alist)))
+ (equal (s-aux a (cdr (assoc-equal a alist))
+ alist)
+ alist))))
+
+;;;; we can now prove s-same-g
+;;;; (equal (s a (g a r) r)
+;;;; r))
+
+(local
+(defthm value-s-aux
+ (implies (rcdp alist)
+ (equal (cdr (assoc-equal a (s-aux a v alist)))
+ v))))
+
+(local
+(defthm s-aux-preserves-rcdp
+ (implies (and (rcdp x)
+ v)
+ (rcdp (s-aux a v x)))))
+
+(local
+(defthm cdr-assoc-equal-delete-key
+ (implies (rcdp x)
+ (not (cdr (assoc-equal a (delete-key a x)))))))
+
+; G-diff-s should go here, but I forgot it on the first pass, so I'll put
+; it at the end where more lemmas are available.
+
+(local
+(defthm rcdp-delete-key
+ (implies (rcdp alist)
+ (rcdp (delete-key a alist)))))
+
+;;;; we can now prove g-same-s
+;;;; (equal (g a (s a v r))
+;;;; v))
+
+(local
+(defthm s-aux-s-aux-same
+ (implies (rcdp alist)
+ (equal (s-aux a v (s-aux a w alist))
+ (s-aux a v alist)))))
+
+(local
+(defthm delete-key-s-aux-same
+ (implies (rcdp alist)
+ (equal (delete-key a (s-aux a v alist))
+ (delete-key a alist)))))
+
+(local
+(defthm <<-s-aux
+ (implies (and (rcdp alist)
+ (<< b (caar alist))
+ (not (<< a b))
+ (not (equal a b)))
+ (<< b (caar (s-aux a v alist))))))
+
+(local
+(defthm value-nil-sufficiency
+ (implies (and (rcdp alist)
+ (<< a (caar alist)))
+ (equal (cdr (assoc-equal a alist))
+ nil))))
+
+(local
+(defthm caar-delete-key
+ (implies (rcdp alist)
+ (equal (caar (delete-key a alist))
+ (if (eq a (caar alist))
+ (caadr alist)
+ (caar alist))))))
+
+(local
+(defthm s-aux-delete-key
+ (implies (rcdp alist)
+ (equal (s-aux a x (delete-key a alist))
+ (s-aux a x alist)))))
+
+(local
+(defthm <<-hack
+ (implies (and (<< r6 r9)
+ (not (<< r4 r9))
+ (not (equal r6 r4)))
+ (<< r6 r4))
+ :hints (("Goal" :in-theory (disable <<-trichotomy)
+ :use ((:instance <<-trichotomy
+ (x r6) (y r4)))))))
+
+;;;; we can now prove s-same-s
+;;;; (equal (s a y (s a x r))
+;;;; (s a y r)))
+
+(local
+(defthm s-aux-diff-s-aux
+ (implies (and (not (equal a b))
+ (rcdp r)
+ x
+ y)
+ (equal (s-aux b y (s-aux a x r))
+ (s-aux a x (s-aux b y r))))
+ :rule-classes ((:rewrite :loop-stopper ((b a s-aux))))))
+
+(local
+(defthm rcdp-s-aux
+ (implies (and (rcdp x)
+ v)
+ (rcdp (s-aux a v x)))))
+
+(local
+(defthm consp-delete-key
+ (implies (rcdp alist)
+ (equal (consp (delete-key a alist))
+ (or (consp (cdr alist))
+ (and (consp alist)
+ (not (equal a (caar alist)))))))))
+
+(local
+(defthm delete-key-delete-key
+ (implies (rcdp r)
+ (equal (delete-key b (delete-key a r))
+ (delete-key a (delete-key b r))))
+ :rule-classes ((:rewrite :loop-stopper ((b a delete-key))))))
+
+(local
+(defthm delete-key-s-aux
+ (implies (and (not (equal a b))
+ (rcdp r)
+ x)
+ (equal (delete-key b (s-aux a x r))
+ (s-aux a x (delete-key b r))))))
+
+(local
+(defthm delete-key-nil
+ (implies (not (delete-key a x))
+ (not (delete-key a (delete-key b x))))))
+
+;;;; we can now prove s-diff-s
+;;;; (implies (not (equal a b))
+;;;; (equal (s b y (s a x r))
+;;;; (s a x (s b y r))))
+
+(local
+(defthm assoc-equal-s-aux-different
+ (implies (not (equal a b))
+ (equal (assoc-equal a (s-aux b v alist))
+ (assoc-equal a alist)))))
+
+(local
+(defthm assoc-equal-delete-key-different
+ (implies (not (equal a b))
+ (equal (assoc-equal a (delete-key b alist))
+ (assoc-equal a alist)))))
+
+(defun bad-field (r1 r2)
+ (declare (xargs :guard (and (rcdp r1) (rcdp r2))))
+ (cond ((endp r1) (caar r2))
+ ((endp r2) (caar r1))
+ ((equal (car r1) (car r2))
+ (bad-field (cdr r1) (cdr r2)))
+ ((<< (caar r1) (caar r2))
+ (caar r1))
+ (t (caar r2))))
+
+(local
+(defthm assoc-eq-symbol-<
+ (implies (and (rcdp s)
+ (<< field (caar s)))
+ (equal (assoc-equal field s) nil))))
+
+;;;; we can now prove g-diff-s
+;;;; (implies (not (equal a b))
+;;;; (equal (g a (s b v r))
+;;;; (g a r))))
+
+;;;;;;;;;;; THE MAIN (exported) THEOREMS ;;;;;;;;;;;;
+
+(defthm access-of-nil-is-nil
+ (not (g a nil)))
+
+(defthm record-set-cannot-be-nil
+ (implies v (s a v r)))
+
+(defthm record-get-non-nil-cannot-be-nil
+ (implies (g a r) r)
+ :rule-classes :forward-chaining)
+
+(defthm s-same-g
+ (equal (s a (g a r) r)
+ r))
+
+(defthm g-same-s
+ (equal (g a (s a v r))
+ v))
+
+(defthm s-same-s
+ (equal (s a y (s a x r))
+ (s a y r)))
+
+(defthm s-diff-s
+ (implies (not (equal a b))
+ (equal (s b y (s a x r))
+ (s a x (s b y r))))
+ :rule-classes ((:rewrite :loop-stopper ((b a s)))))
+
+(defthm g-diff-s
+ (implies (not (equal a b))
+ (equal (g a (s b v r))
+ (g a r))))
+
+(defthm s-preserves-recordp
+ (implies (rcdp r)
+ (rcdp (s a v r)))
+ :rule-classes ((:forward-chaining
+ :trigger-terms ((s a v r)))
+ :rewrite))
+
+(defthm rcdp-equality-sufficiency
+ (implies (and (rcdp r1) (rcdp r2))
+ (equal (equal r1 r2)
+ (let ((field (bad-field r1 r2)))
+ (equal (g field r1)
+ (g field r2)))))
+ :hints (("Goal" :induct (bad-field r1 r2))))
+
+; We will almost surely never care about the definition of bad-field, other
+; than the rule above. We also disable s and g, assuming the rules proven in
+; this book are sufficient to manipulate record terms which are encountered.
+; Finally, we disable rcdp-equality-sufficiency, since it can be an expensive
+; rewrite rule (because it is hung on equal).
+
+(in-theory (disable s g bad-field rcdp-equality-sufficiency))