1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
; Copyright (C) 2024, Matt Kaufmann
; Written by Matt Kaufmann
; License: A 3-clause BSD license. See the LICENSE file distributed with ACL2.
; See README.txt for an overview of this example.
(in-package "ACL2")
(defstobj mem{ht}$c ; concrete stobj representing memory with a hash table
(mem{ht}$c-ht :type (hash-table eql)))
(defun list-alist-subsetp (index lst alist)
; At the top level, index is 0 and this predicate defines when a list, lst
; (representing an array) corresponds to an alist, alist (representing a hash
; table). It leaves open the possibility that the hash table has "junk" not
; corresponding to pairs <i,v> where v is the value at position i in lst
; (again, assuming we are at the top level).
(declare (xargs :measure (len lst)))
(cond ((atom lst) t)
(t (and (equal (car lst)
(cdr (hons-assoc-equal index alist)))
(list-alist-subsetp (1+ index) (cdr lst) alist)))))
(defun-nx mem{ht}$corr (mem{ht}$c x)
(declare (xargs :stobjs mem{ht}$c
:verify-guards nil))
(list-alist-subsetp 0 x (nth 0 mem{ht}$c)))
(include-book "logic")
(defun lookup{ht}$c (k mem{ht}$c)
; This is a little wrapper for mem{ht}$c-ht-get.
; We use cw to print evidence that mem{ht}$c-ht-get is being called.
(declare (xargs :stobjs mem{ht}$c
:guard (eqlablep k)))
(prog2$ (cw "@@ Calling: ~x0~|" `(mem{ht}$c-ht-get ,k mem{ht}$c))
(mem{ht}$c-ht-get k mem{ht}$c)))
(defun update{ht}$c (k v mem{ht}$c)
; This is a little wrapper for mem{ht}$c-ht-put.
; We use cw to print evidence that mem{ht}$c-ht-put is being called.
(declare (xargs :stobjs mem{ht}$c
:guard (eqlablep k)))
(prog2$ (cw "@@ Calling: ~x0~|" `(mem{ht}$c-ht-put ,k ,v mem{ht}$c))
(mem{ht}$c-ht-put k v mem{ht}$c)))
(progn
; The events below include the events that are automatically generated by the
; defabsstobj event below, which are all in upper case. Their proofs are
; supported by the lower-case events, which are all local.
(DEFTHM CREATE-MEM{HT}{CORRESPONDENCE}
(MEM{HT}$CORR (CREATE-MEM{HT}$C)
(CREATE-MEM$A))
:RULE-CLASSES NIL)
(DEFTHM CREATE-MEM{HT}{PRESERVED}
(MEM$AP (CREATE-MEM$A))
:RULE-CLASSES NIL)
(local (defthm list-alist-subsetp-works-1
(implies (and (natp index)
(natp k)
(< k (len lst))
(list-alist-subsetp index lst alist))
(equal (nth k lst)
(cdr (hons-assoc-equal (+ index k) alist))))
:rule-classes nil))
(local (defthm list-alist-subsetp-works
(implies (and (natp k)
(< k (len lst))
(list-alist-subsetp 0 lst alist))
(equal (equal (cdr (hons-assoc-equal k alist))
(nth k lst))
t))
:hints (("Goal" :use ((:instance list-alist-subsetp-works-1
(index 0)))))))
(DEFTHM LOOKUP{HT}{CORRESPONDENCE}
(IMPLIES (AND (MEM{HT}$CORR MEM{HT}$C MEM{HT})
(MEM-INDEXP K)
(MEM$AP MEM{HT}))
(EQUAL (LOOKUP{HT}$C K MEM{HT}$C)
(LOOKUP$A K MEM{HT})))
:hints (("Goal" :in-theory (disable hons-assoc-equal)))
:RULE-CLASSES NIL)
(DEFTHM LOOKUP{HT}{GUARD-THM}
(IMPLIES (AND (MEM{HT}$CORR MEM{HT}$C MEM{HT})
(MEM-INDEXP K)
(MEM$AP MEM{HT}))
(EQLABLEP K))
:RULE-CLASSES NIL)
(local (defun list-alist-subsetp-preserved-1-induction (index lst alist k)
(cond ((zp k) (list index lst alist k)) ; avoid irrelevant formals
((atom lst) t)
(t (list-alist-subsetp-preserved-1-induction
(1+ index) (cdr lst) alist (1- k))))))
(local (defthm list-alist-subsetp-preserved-1-1
(implies (and (integerp index)
(natp n)
(< n index)
(list-alist-subsetp index lst alist))
(list-alist-subsetp index
lst
(cons (cons n v) alist)))))
(local (defthm list-alist-subsetp-preserved-1
(implies (and (natp index)
(list-alist-subsetp index lst alist)
(integerp k)
(<= 0 k)
(< k (len lst)))
(list-alist-subsetp index
(update-nth k v lst)
(cons (cons (+ index k) v) alist)))
:hints (("Goal" :induct (list-alist-subsetp-preserved-1-induction
index lst alist k)))
:rule-classes nil))
(local (defthm list-alist-subsetp-preserved
(implies (and (list-alist-subsetp 0 lst alist)
(integerp k)
(<= 0 k)
(< k (len lst)))
(list-alist-subsetp 0
(update-nth k v lst)
(cons (cons k v) alist)))
:hints (("Goal" :use ((:instance list-alist-subsetp-preserved-1
(index 0)))))))
(DEFTHM UPDATE{HT}{CORRESPONDENCE}
(IMPLIES (AND (MEM{HT}$CORR MEM{HT}$C MEM{HT})
(MEM-INDEXP K)
(MEM$AP MEM{HT}))
(MEM{HT}$CORR (UPDATE{HT}$C K V MEM{HT}$C)
(UPDATE$A K V MEM{HT})))
:RULE-CLASSES NIL)
(DEFTHM UPDATE{HT}{GUARD-THM}
(IMPLIES (AND (MEM{HT}$CORR MEM{HT}$C MEM{HT})
(MEM-INDEXP K)
(MEM$AP MEM{HT}))
(EQLABLEP K))
:RULE-CLASSES NIL)
(DEFTHM UPDATE{HT}{PRESERVED}
(IMPLIES (AND (MEM-INDEXP K) (MEM$AP MEM{HT}))
(MEM$AP (UPDATE$A K V MEM{HT})))
:RULE-CLASSES NIL)
)
(defabsstobj mem{ht} ; abstract stobj, based on a hash table
:foundation mem{ht}$c
:recognizer (mem{ht}p :logic mem$ap :exec mem{ht}$cp)
:creator (create-mem{ht} :logic create-mem$a :exec create-mem{ht}$c)
:corr-fn mem{ht}$corr
:exports ((lookup{ht} :logic lookup$a :exec lookup{ht}$c)
(update{ht} :logic update$a :exec update{ht}$c)))
; This little test at certification time is skipped by include-book:
(value-triple (update{ht} 4 'four mem{ht})
:stobjs-out '(mem{ht}))
; This little test at certification time is skipped by include-book:
(assert-event (equal (lookup{ht} 4 mem{ht})
'four))
|