1
; Computational Object Inference
2
; Copyright (C) 2005-2014 Kookamara LLC
7
; 11410 Windermere Meadows
8
; Austin, TX 78759, USA
9
; http://www.kookamara.com/
11
; License: (An MIT/X11-style license)
13
; Permission is hereby granted, free of charge, to any person obtaining a
14
; copy of this software and associated documentation files (the "Software"),
15
; to deal in the Software without restriction, including without limitation
16
; the rights to use, copy, modify, merge, publish, distribute, sublicense,
17
; and/or sell copies of the Software, and to permit persons to whom the
18
; Software is furnished to do so, subject to the following conditions:
20
; The above copyright notice and this permission notice shall be included in
21
; all copies or substantial portions of the Software.
23
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28
; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
; DEALINGS IN THE SOFTWARE.
1
31
; Jared: what's this file for? It's not certifiable, so I'm
2
32
; renaming it to a .lsp extension for Make compatibility
23
53
; For write tests we will just zero out a block of memory. It doesn't really
24
54
; matter what addresses we use, because they're all the same depth from the
25
; root. For read tests, we'll just sequentially scan a block of memory.
55
; root. For read tests, we'll just sequentially scan a block of memory.
27
57
(defun zero-memory (i mem)
28
58
(declare (xargs :guard (and (memory-p mem)
29
59
(address-p i mem)))
30
(type (signed-byte 29) i))
60
(type (signed-byte 29) i))
31
61
(if (mbe :logic (zp i)
44
74
(let ((element (load i mem)))
45
75
(declare (ignore element))
46
76
(scan-memory (the-fixnum (1- i)) mem))))
48
78
(local (defthm signed-byte-natural
49
79
(implies (force (natp x))
50
80
(equal (signed-byte-p 29 x)
201
231
(mbe :logic (_memtree-load addr mtree depth)
202
232
:exec (if (= depth 0)
204
(_fix-addr/depth-memtree-load
234
(_fix-addr/depth-memtree-load
205
235
(the-fixnum (ash addr -1))
206
236
(if (= (the-fixnum (logand addr 1)) 0)
238
268
; We now provide a store function. I think this definition is pretty standard
239
; following from the definition of load.
269
; following from the definition of load.
241
271
; One interesting aspect is that we require that our element is non-nil. This
242
272
; is because we would really like to keep our trees in a canonical form, where
243
273
; "nil" elements are not even stored, and paths to them are not created. But,
244
; this function would not preserve this property if we gave it "nil" to store.
274
; this function would not preserve this property if we gave it "nil" to store.
245
275
; For example, (_memtree-store 0 nil nil 2) = ((nil)) instead of nil, violating
246
; our notion of canonicality. Indeed, this creates problems when we try to
276
; our notion of canonicality. Indeed, this creates problems when we try to
247
277
; prove properties of the form (store addr (load addr mem) mem) = mem.
249
279
; To address this, we actually provide a separate function below,
266
296
(cons (_memtree-store quotient elem (car mtree) (1- depth))
268
298
(cons (car mtree)
269
(_memtree-store quotient elem (cdr mtree)
299
(_memtree-store quotient elem (cdr mtree)
270
300
(1- depth))))))))
272
302
; As with loading, we create an efficient version that assumes addr and depth
285
315
(let ((quotient (the-fixnum (ash addr -1))))
286
316
(if (= (the-fixnum (logand addr 1)) 0)
287
(cons (_fix-addr/depth-memtree-store
317
(cons (_fix-addr/depth-memtree-store
288
318
quotient elem (car mtree) (the-fixnum (1- depth)))
290
320
(cons (car mtree)
291
(_fix-addr/depth-memtree-store
292
quotient elem (cdr mtree)
321
(_fix-addr/depth-memtree-store
322
quotient elem (cdr mtree)
293
323
(the-fixnum (1- depth)))))))))
295
325
; And as before, we create a "self-optimizing" version which drops the
306
336
(_fix-addr/depth-memtree-store addr elem mtree depth)
307
337
(let ((quotient (ash addr -1)))
308
338
(if (= (the-fixnum (logand addr 1)) 0)
309
(cons (_fixnum-memtree-store
339
(cons (_fixnum-memtree-store
310
340
quotient elem (car mtree) (the-fixnum (1- depth)))
312
342
(cons (car mtree)
313
(_fixnum-memtree-store
314
quotient elem (cdr mtree)
343
(_fixnum-memtree-store
344
quotient elem (cdr mtree)
315
345
(the-fixnum (1- depth)))))))))
318
; Now we are ready to implement "memory erasing", that is, storing nils into
348
; Now we are ready to implement "memory erasing", that is, storing nils into
319
349
; our memory. We want to keep our trees in canonical format, so we go to some
320
350
; lengths to eliminate branches that are no longer needed.
358
388
(let ((quotient (the-fixnum (ash addr -1))))
359
389
(if (= (the-fixnum (logand addr 1)) 0)
360
(let ((left (_fix-addr/depth-memtree-store-nil
390
(let ((left (_fix-addr/depth-memtree-store-nil
362
392
(the-fixnum (1- depth))))
363
393
(right (cdr mtree)))
364
394
(if (and (null left)
387
417
(let ((quotient (ash addr -1)))
388
418
(if (= (the-fixnum (logand addr 1)) 0)
389
(let ((left (_fixnum-memtree-store-nil
419
(let ((left (_fixnum-memtree-store-nil
391
421
(the-fixnum (1- depth))))
392
422
(right (cdr mtree)))
393
423
(if (and (null left)
426
456
; This is the same technique used in my ordered sets book in order to enforce
427
457
; the non-sets convention, and you can think of these as "a poor man's
428
; congruence rules". Take for example _memtree-load-fix-a below, which
458
; congruence rules". Take for example _memtree-load-fix-a below, which
429
459
; says that the following:
431
461
; (defthm _memtree-load-fix-addr
471
501
(defthm _memtree-load-fix-depth
472
502
(equal (_memtree-load addr mtree (nfix depth))
473
503
(_memtree-load addr mtree depth))
475
505
:in-theory (disable _memtree-fix-nfix)
476
506
:use ((:instance _memtree-fix-nfix)))))
525
555
;;; Key Lemmas: "equivalent" _addresses can be interchanged in stores
527
557
; These lemmas needs to stay disabled because they can easily cause loops. It
528
; doesn't seem that simple loop stoppers fix the issue, and I'm too lazy to
558
; doesn't seem that simple loop stoppers fix the issue, and I'm too lazy to
529
559
; figure out a better solution.
531
561
(local (defthmd _memtree-store-addr-switch-1
572
602
(_memtree-p mtree depth)))))
574
604
; We implement a typical fixing function for memories. Our default memory is
575
; an empty tree with size 1 and depth 1.
605
; an empty tree with size 1 and depth 1.
577
607
(defun _memory-fix (mem)
578
608
(declare (xargs :guard (_memory-p mem)))
689
719
; give a multi-step process for removing hyptheses:
691
721
; (1) determine a normal form for the data structure such that "equivalent"
692
; structures are equal.
722
; structures are equal.
694
724
; (2) define the desired operations assuming well formed data structures (we
695
725
; already did this too, our load and store operations)
825
855
; Below is the "user's notion" of what a memory is. It should always be
826
856
; disabled. Basically, we require that a user's memory is always has a depth
827
; and size of at least one.
857
; and size of at least one.
829
859
; This gives us the crucial property that "bad memories" are not memories in
830
860
; the user's sense. Why is this so important? Well, we are very much
831
; concerned with efficiency of operations. As long as we know that our
832
; arguments are not bad, we can skip all of this mapping and just provide
861
; concerned with efficiency of operations. As long as we know that our
862
; arguments are not bad, we can skip all of this mapping and just provide
833
863
; high speed execution using MBE.
835
865
(defun memory-p (mem)
946
976
:exec (let* ((fast (cdar mem))
947
977
(mtree (caar mem))
948
978
(depth (caddr mem)))
950
980
(_fixnum-memtree-load addr mtree depth)
951
981
(_memtree-load addr mtree depth)))))
953
983
(defun _store (addr elem mem)
954
984
(declare (xargs :guard (and (memory-p mem)
955
985
(address-p addr mem))
956
:guard-hints (("Goal"
986
:guard-hints (("Goal"
957
987
:use (:instance _address-from-address)
958
988
:in-theory (enable _memory-p
963
993
_memory-size)))))
964
994
(mbe :logic (let ((fast (_memory-fast mem))
965
995
(mtree (_memory-mtree mem))
997
1027
(defthm _store-size
998
1028
(equal (_memory-size (_store addr elem mem))
999
1029
(_memory-size mem))
1000
:hints(("Goal" :in-theory (e/d (_memory-size)
1030
:hints(("Goal" :in-theory (e/d (_memory-size)
1001
1031
(_store-memory))
1002
1032
:use (:instance _store-memory))))
1004
1034
(defthm _store-fast
1005
1035
(equal (_memory-fast (_store addr elem mem))
1006
1036
(_memory-fast mem))
1007
:hints(("Goal" :in-theory (e/d (_memory-fast)
1037
:hints(("Goal" :in-theory (e/d (_memory-fast)
1008
1038
(_store-memory))
1009
1039
:use (:instance _store-memory))))
1012
1042
(equal (_memory-mtree (_store addr elem mem))
1013
1043
(if (address-p addr mem)
1015
(_memtree-store addr elem
1045
(_memtree-store addr elem
1016
1046
(_memory-mtree mem)
1017
1047
(_memory-depth mem))
1018
(_memtree-store-nil addr
1048
(_memtree-store-nil addr
1019
1049
(_memory-mtree mem)
1020
1050
(_memory-depth mem)))
1021
1051
(_memory-mtree mem)))
1022
:hints(("Goal" :in-theory (e/d (_memory-mtree)
1052
:hints(("Goal" :in-theory (e/d (_memory-mtree)
1023
1053
(_store-memory))
1024
1054
:use (:instance _store-memory))))
1026
1056
(defthm _store-depth
1027
1057
(equal (_memory-depth (_store addr elem mem))
1028
1058
(_memory-depth mem))
1029
:hints(("Goal" :in-theory (e/d (_memory-depth)
1059
:hints(("Goal" :in-theory (e/d (_memory-depth)
1030
1060
(_store-memory))
1031
1061
:use (:instance _store-memory))))
1096
1126
:exec (let* ((fast (cdar mem))
1097
1127
(mtree (caar mem))
1098
1128
(depth (caddr mem)))
1100
1130
(_fixnum-memtree-load addr mtree depth)
1101
1131
(_memtree-load addr mtree depth)))))
1103
1133
(defun store (addr elem mem)
1104
1134
(declare (xargs :guard (and (memory-p mem)
1105
1135
(address-p addr mem))
1106
:guard-hints(("Goal"
1136
:guard-hints(("Goal"
1107
1137
:use (:instance _address-from-address)
1108
1138
:in-theory (enable _memory-p
1346
1376
(<= (- (expt 2 15)) x)
1347
1377
(< x (expt 2 15))))
1349
1379
(defun fix-sbp16 (x)
1350
1380
(declare (xargs :guard t))
1351
1381
(if (sbp16 x) x 0))
1353
1383
(defrecord sbp :rd getbv :wr putbv :fix fix-sbp16 :typep sbp16)
1355
1385
The "raw" record structure introduced in the standard records book is
1356
1386
used to define records defined using defrecord, and the functions for
1357
1387
accessing and updating a record that are introduced by defrecord are
1387
1417
In addition, the defrecord macro proves one additional lemma that is
1388
1418
not provable about raw records:
1391
1421
(typep (g a r)))
1393
for a typep predicate provided by the user.
1423
for a typep predicate provided by the user.
1395
1425
What makes this implementation of records interesting is that it has
1396
1426
the peculiar property that each of the lemmas has no "type"
1633
1663
(defthmd abstract-localfixedpoint
1634
1664
(equal (localfixedpoint x)
1635
1665
(subsetp (rkeys x) (list nil)))
1636
:hints (("Goal" :in-theory (enable
1666
:hints (("Goal" :in-theory (enable
1637
1667
localfixedpoint
2016
2046
(and r (if (acl2::fixedpoint r) a
2017
2047
(not (subsetp (rkeys r) (list a)))))))
2018
2048
:hints (("Goal" :in-theory (e/d (iff-s-to-iff-s-fixedpoint
2020
2050
fixedpoint-impact-on-keys)
2021
2051
(LIST::MEMBERP-WHEN-NOT-MEMBERP-OF-CDR-CHEAP)))
2022
2052
("Subgoal 3''" :in-theory (enable list::memberp))))
2024
2054
(defthm fixedpoint-s
2025
2055
(equal (fixedpoint (s a v r))
2027
2057
;; Results from (not (s a v r))
2029
2059
(and r (if (acl2::fixedpoint r) a
2030
2060
(not (subsetp (rkeys r) (list a)))))))
2032
2062
;; Results from (localfixedpoint (s a v r))
2033
2063
(if v (subsetp (cons a (rkeys r)) (list nil))
2034
2064
(subsetp (rkeys r) (list a nil)))
2083
2113
(set::union (cons-onto-all '0 (mem::domain-aux (car mem-tree) (+ -1 depth)))
2084
2114
(cons-onto-all '1 (mem::domain-aux (cdr mem-tree) (+ -1 depth)))))))
2087
2117
;this bits are in reverse order (least significant bit comes first in the list)
2088
2118
(defun convert-reversed-bit-list-to-integer (bit-list)
2091
2121
(+ (car bit-list)
2092
2122
(* 2 (convert-reversed-bit-list-to-integer (cdr bit-list))))))
2094
;; (defmacro def-set-processor (&key (processor-name 'unsupplied)
2124
;; (defmacro def-set-processor (&key (processor-name 'unsupplied)
2095
2125
;; (element-processor 'unsupplied) ;can this be a term?
2096
2126
;; (predicate 'unsupplied))
2097
2127
;; `(defun ,processor-name (set) ;can this take more than one arg?
2150
2180
;;always return nats less than size? Not necessarily. There
2151
2181
;;may be nats less than 2^depth but greater than size. We
2152
2182
;;have to filter them out.
2154
2184
(SET::FILTER<not-NATP-LESS-THAN-SIZE> (set::rkeys record-part) size)
2500
2530
;; (and (equal len (len (set::head x)))
2501
2531
;; (all-have-len len (set::tail x)))))
2503
(defun len-equal (a len)
2533
(defun len-equal (a len)
2504
2534
(declare (xargs :guard t))
2505
2535
(equal (len a) (rfix len)))
2507
2537
(defthm all-len-equal-of-union
2508
2538
(equal (set::all<len-equal> (set::union x y) depth)
2509
2539
(and (set::all<len-equal> x depth)
2589
2619
(implies (and (not (natp a))
2590
2620
(force (set::all<bit-listp> bit-lists)))
2591
2621
(not (set::in a (convert-reversed-bit-lists-to-integers bit-lists))))
2592
:hints (("Goal" :in-theory (enable SET::ALL<BIT-LISTP>
2622
:hints (("Goal" :in-theory (enable SET::ALL<BIT-LISTP>
2594
2624
:do-not '(generalize eliminate-destructors))))
2682
2712
(SET::IN (CONVERT-REVERSED-BIT-LIST-TO-INTEGER a)
2683
2713
(CONVERT-REVERSED-BIT-LISTS-TO-INTEGERS x))))
2684
:hints (("Goal" :in-theory (enable set::in
2714
:hints (("Goal" :in-theory (enable set::in
2686
2716
:do-not '(generalize eliminate-destructors))))
2780
2810
(defthm all-bit-listp-of-domain-aux
2781
2811
(set::all<bit-listp> (mem::domain-aux tree depth))
2782
2812
:hints (("Goal" :in-theory (enable mem::domain-aux acl2::equal-booleans-reducton))))
2783
;; LIST::EQUAL-OF-BOOLEANS-REWRITE
2813
;; LIST::EQUAL-OF-BOOLEANS-REWRITE
2785
2815
(defthm setp-of-domain-aux
2786
2816
(set::setp (mem::domain-aux tree depth))
3064
3094
MEM::|_MEMORY-P|
3067
(in-theory (disable MEM::MEM-TREE-DOMAIN))
3097
(in-theory (disable MEM::MEM-TREE-DOMAIN))
3069
3099
(defthm mem-tree-domain-after-store
3070
3100
(implies (good-memoryp mem)
3071
3101
(equal (MEM::MEM-TREE-DOMAIN (CAAR (MEM::STORE A V MEM))
3072
(CADDR ;(MEM::STORE A V
3102
(CADDR ;(MEM::STORE A V