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 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
(in-package "ACL2")
; block-listp.lisp Mihir Mehta
; Here we define the size of a block to be 8 characters, and define functions
; for making blocks from text and retrieving text from blocks, with proofs of
; their correctness and their one-way inverse relationship.
(local (include-book "../file-system-lemmas"))
;; I don't think blocks are 8 characters long in any system; I simply set this
;; in order to actually get fragmentation without having to make unreasonably
;; large examples.
(defconst *blocksize* 8)
;; This fragments a character-list into blocks that are *blocksize*-character
;; long. If the character-list is not exactly aligned to a block boundary, we
;; fill the space with null characters.
;; It will be used in wrchs.
(defund make-blocks (text)
(declare (xargs :guard (character-listp text)
:measure (len text)))
(if (atom text)
nil
(cons (make-character-list (take *blocksize* text))
(make-blocks (nthcdr *blocksize* text)))))
(defthm
make-blocks-correctness-5
(iff (consp (make-blocks text))
(consp text))
:rule-classes
(:rewrite
(:rewrite
:corollary (iff (equal (len (make-blocks text)) 0)
(atom text))
:hints (("goal''" :expand (len (make-blocks text))))))
:hints (("goal" :in-theory (enable make-blocks))))
;; Characterisation of a disk, which is a list of blocks as described before.
(defun block-listp (block-list)
(declare (xargs :guard t))
(if (atom block-list)
(eq block-list nil)
(and (character-listp (car block-list))
(equal (len (car block-list)) *blocksize*)
(block-listp (cdr block-list)))))
;; Proving that we get a proper block-list out of make-blocks.
(defthm make-blocks-correctness-2
(implies (character-listp text)
(block-listp (make-blocks text)))
:hints (("Goal" :in-theory (enable make-blocks))))
(defthm block-listp-correctness-1
(implies (block-listp block-list)
(true-listp block-list))
:rule-classes (:forward-chaining))
(defthm block-listp-correctness-2
(implies (true-listp block-list1)
(equal (block-listp (binary-append block-list1 block-list2))
(and (block-listp block-list1)
(block-listp block-list2)))))
;; This function spells out how many characters can be in a file given the
;; number of blocks associated with it. It is kept disabled in order to avoid
;; huge arithmetic-heavy subgoals where they're not wanted.
(defund feasible-file-length-p (index-list-length file-length)
(declare (xargs :guard (and (natp file-length) (natp index-list-length))))
(and (> file-length
(* *blocksize* (- index-list-length 1)))
(<= file-length
(* *blocksize* index-list-length))))
;; This is the counterpart of make-blocks that collapses blocks into a
;; character-list of the appropriate length.
;; It will be used in stat and, by extension, in rdchs.
(defun
unmake-blocks (blocks n)
(declare
(xargs
:guard (and (block-listp blocks)
(natp n)
(feasible-file-length-p (len blocks) n))
:guard-hints
(("goal" :in-theory (enable feasible-file-length-p)))))
(if (atom blocks)
nil
(if (atom (cdr blocks))
(take n (car blocks))
(binary-append (car blocks)
(unmake-blocks (cdr blocks)
(- n *blocksize*))))))
;; Proving that we get a proper character-list out provided we don't ask for
;; more characters than we have.
(defthm unmake-blocks-correctness-1
(implies (and (block-listp blocks)
(natp n)
(feasible-file-length-p (len blocks) n))
(character-listp (unmake-blocks blocks n)))
:hints (("Goal" :in-theory (enable feasible-file-length-p)) ))
(defthm
unmake-blocks-correctness-2
(implies (and (block-listp blocks)
(natp n)
(feasible-file-length-p (len blocks) n))
(equal (len (unmake-blocks blocks n))
n))
:rule-classes
((:rewrite :corollary (implies (and (block-listp blocks)
(natp n)
(feasible-file-length-p (len blocks) n))
(iff (consp (unmake-blocks blocks n))
(not (zp n))))))
:hints (("goal" :in-theory (enable feasible-file-length-p))
("subgoal *1/5'''" :expand (len (cdr blocks)))))
(defthm unmake-make-blocks-lemma-1
(implies (natp n)
(iff (consp (nthcdr n l)) (> (len l) n)))
:hints (("Goal" :induct (nthcdr n l))))
(encapsulate ()
(local (include-book "std/lists/repeat" :dir :system))
;; Proving that make and unmake are, in a sense, inverse functions of each
;; other.
(defthm
unmake-make-blocks
(implies (and (character-listp text))
(equal (unmake-blocks (make-blocks text)
(len text))
text))
:hints
(("goal" :in-theory (enable make-blocks))
("subgoal *1/3.3"
:in-theory (disable take-of-make-character-list
take-of-too-many)
:use ((:instance take-of-make-character-list
(i (len text))
(l (first-n-ac 8 text nil)))
(:instance take-of-too-many (x text)
(n *blocksize*)))))))
;; This is a constant that might be needed later.
;; This is to be returned when a block is not found. It's full of null
;; characters and is *blocksize* long.
(defconst *nullblock* (make-character-list (take *blocksize* nil)))
(defthm
make-blocks-correctness-1
(implies (character-listp text)
(and (< (- (* *blocksize* (len (make-blocks text)))
*blocksize*)
(len text))
(not (< (* *blocksize* (len (make-blocks text)))
(len text)))))
:hints (("goal" :in-theory (enable make-blocks)
:induct t)))
(defthm
make-blocks-correctness-3
(implies (and (character-listp cl))
(feasible-file-length-p (len (make-blocks cl))
(len cl)))
:hints
(("goal"
:in-theory (e/d (feasible-file-length-p)
(make-blocks-correctness-1))
:use (:instance make-blocks-correctness-1 (text cl)))))
(encapsulate ()
(local (include-book "std/lists/nthcdr" :dir :system))
(local (defun nthcdr-*blocksize*-induction-2 (text1 text2)
(cond ((or (atom text1) (atom text2))
(list text1 text2))
(t (nthcdr-*blocksize*-induction-2 (nthcdr *blocksize* text1)
(nthcdr *blocksize* text2))))))
(defthm
make-blocks-correctness-4
(implies (equal (len text1) (len text2))
(equal (len (make-blocks text1))
(len (make-blocks text2))))
:hints (("goal" :in-theory (enable make-blocks)
:induct (nthcdr-*blocksize*-induction-2 text1 text2)))))
(defthm
len-of-make-unmake
(implies (and (block-listp blocks)
(natp n)
(feasible-file-length-p (len blocks) n))
(equal (len (make-blocks (unmake-blocks blocks n)))
(len blocks)))
:hints
(("goal" :in-theory (e/d (make-blocks feasible-file-length-p)
(consp-of-append)))
("subgoal *1/8"
:expand (append (car blocks)
(unmake-blocks (cdr blocks) (+ -8 n))))
("subgoal *1/5.2" :cases ((atom (cdr blocks)))
:expand (len (cdr blocks)))
("subgoal *1/5.1'"
:expand (append (car blocks)
(unmake-blocks (cdr blocks) (+ -8 n))))
("subgoal *1/2"
:expand (make-blocks (first-n-ac n (car blocks) nil)))))
|