forked from acl2/acl2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
acl2-check.lisp
393 lines (329 loc) · 16.1 KB
/
acl2-check.lisp
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
; ACL2 Version 8.5 -- A Computational Logic for Applicative Common Lisp
; Copyright (C) 2024, Regents of the University of Texas
; This version of ACL2 is a descendent of ACL2 Version 1.9, Copyright
; (C) 1997 Computational Logic, Inc. See the documentation topic NOTE-2-0.
; This program is free software; you can redistribute it and/or modify
; it under the terms of the LICENSE file distributed with ACL2.
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; LICENSE for more details.
; Written by: Matt Kaufmann and J Strother Moore
; email: [email protected] and [email protected]
; Department of Computer Science
; University of Texas at Austin
; Austin, TX 78712 U.S.A.
; Because of the last form in this file, this file should not be loaded as part
; of an executable ACL2 image.
; Warning: This file should not be compiled. The intention is to load the
; .lisp file each time we build ACL2, regardless of the host Lisp.
(in-package "ACL2")
; See section "CHECKS" of acl2.lisp for more checks.
; We begin with a basic test related to the CR/NL character pairs that can
; occur in some systems, but which ACL2 assumes are not routinely present.
(or (equal (length "ab
cd")
5)
(error "We have tested that the string ab\\ncd (where \\n denotes
a Newline character) has length 5, but it does not. Perhaps your system
is using two characters to indicate a new line?"))
; We put the following check here to be sure that the function
; legal-variable-or-constant-namep checks for all possible lambda list
; keywords.
(dolist (name lambda-list-keywords)
(cond
; The check from legal-variable-or-constant-namep is here.
((let ((s (symbol-name name)))
(or (= (length s) 0)
(not (eql (char s 0) #\&))))
(error "We assume that all lambda-list-keywords start with the ~
character #\&.~%However, ~s does not. ACL2 will not work in ~
this Common Lisp."
name))))
(or (and (integerp char-code-limit)
(<= 256 char-code-limit)
(typep 256 'fixnum))
(error "We assume that 256 is a fixnum not exceeding char-code-limit, for ~
purposes of~%character manipulation. ACL2 will not work in this ~
Common Lisp."))
; Now we deal with the existence of case-sensitive images in Allegro.
#+(and allegro allegro-version>= (version>= 6 0))
(when (not (eq excl::*current-case-mode*
:case-insensitive-upper))
(error " This Allegro Common Lisp image is not compatible with ACL2
because *current-case-mode* has the value
~s
rather than the value
~s.
You can try executing the form
(set-case-mode :case-insensitive-upper)
before building ACL2 and that should solve the problem, although the
Allegro 6.0 documentation claims: \"... it is much better to use an
image with the desired case mode rather than changing the case mode
after the image has started.\""
*current-case-mode*
:case-insensitive-upper))
(or (equal (symbol-name 'a) "A")
(error "This Common Lisp image appears to be case-sensitive:~%~
(equal (symbol-name 'a) \"A\") evaluates to NIL.~%~
It is therefore not suitable for ACL2."))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ACL2 CHARACTERS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; It is difficult or impossible to ensure that #\c is read in as the same
; character in different ACL2 sessions, for any ACL2 character c. (Even
; #\Newline is potentially problematic, as its char-code is 10 in most Common
; Lisps but is 13 in [now-obsolete] MCL!) Thus, the soundness of ACL2 rests on
; a caveat that all books are certified using the same Lisp image. When we say
; ``same lisp image'' we don't mean the same exact process necessarily, but
; rather, an invocation of the same saved image. Character operations can
; differ between Lisps, too; see :DOC soundness. Another reason for such a
; caveat, independent of the character-reading issue, is that different saved
; images may be tied into different compilers, thus making the object files of
; the books incompatible.
; Nevertheless, it would of course be nice if all host Lisp implementations of
; ACL2 actually do agree on character and string constants provided by the Lisp
; reader (based on *acl2-readtable*). Our first check is intended to address
; this point, by providing some confidence that the host Lisp has an ASCII
; character set. As explained above, we only intend soundness in the case that
; all books are certified from scratch using the same host Lisp, and we do not
; actually assume ASCII characters -- more precisely, we do not assume any
; particular values for code-char and code-char -- so this check is not really
; necessary, except for a claim about ASCII characters in "Precise Description
; of the ACL2 Logic", which should perhaps be removed. However, as of January
; 2012 we seem to be able to make the following check in all supported Lisps,
; at least on our Linux and Mac OS platforms. It should be sound for users to
; comment out this check, but with the understanding that ACL2 is taking
; whatever the Lisp reader (using *acl2-readtable*) gives it.
(let ((filename "acl2-characters"))
; Why do we read from a separate file, rather than just saving the relevant
; characters in the present file? For example, it may seem reasonable to use a
; trusted host Lisp to obtain an alist by evaluating the following expression.
; (loop for i from 0 to 255 do (princ (cons i (code-char i))))
; Could the resulting the alist be placed into this file and used for the check
; below?
; We run into a problem right away with that approach because of Control-D.
; For example, try this
; (princ (cons 4 (code-char 4)))
; and then try quoting the output and reading it back in. Or,
; try evaluating the following.
; (read-from-string (format nil "~a" (code-char 4)))
; We have seen an error in both cases.
; So instead, we originally generated the file acl2-characters as follows,
; using an ACL2 image based on CCL.
; (with-open-file (str "acl2-characters" :direction :output)
; (loop for i from 0 to 255
; do (write-char (code-char i) str)))
; We explicitly specify the :external-format in the case of host Lisps for
; which we set the character encoding after the build, on the command line
; written by save-acl2.
(with-open-file
(str filename :direction :input)
(loop for i from 0 to 255
; The function legal-acl2-character-p, called in bad-lisp-objectp for
; characters and strings, checks that the char-code of any character that is
; read must be between 0 and 255.
do (let ((temp (read-char str)))
(when #-clisp (not (eql (char-code temp) i))
; In CLISP we find character 10 (Newline) at position 13 (expected Return).
; Perhaps this has something to do CLISP's attempt to comply with the CL
; HyperSpec Section 13.1.8, "Treatment of Newline during Input and Output".
; But something is amiss. Consider for example the following log (with some
; output edited in the case of the first two forms, but no editing of output
; for the third form).
; ACL2 [RAW LISP]> (with-open-file (str "tmp" :direction :output)
; (write-char (code-char 13) str))
; #\Return
; ACL2 [RAW LISP]> (with-open-file (str "tmp" :direction :input)
; (equal (read-char str) (code-char 10)))
; T
; ACL2 [RAW LISP]> (format nil "~a" (code-char 13))
; "
; ACL2 [RAW LISP]>
; So our check for CLISP is incomplete, but as explained in the comment just
; above this check, we can live with that.
#+clisp
(and (not (eql (char-code temp) i))
(not (eql i 13)))
(error "Bad character in file ~s: character ~s at position ~s."
filename (char-code temp) i))))))
; The check just above does not say anything about the six character names
; that we support (see acl2-read-character-string), as described in :doc
; characters; so we add suitable checks on these here.
(loop for pair in (pairlis '(#\Space #\Tab #\Newline #\Page #\Rubout #\Return)
'(32 9 10 12 127 13))
do (let* ((ch (car pair))
(code (cdr pair))
(val (char-code ch)))
(or (eql val code)
(error "(char-code ~s) evaluated to ~s (expected ~s)."
ch val code))))
; Test that all purportedly standard characters are standard, and vice versa.
(dotimes (i 256)
(let ((ch (code-char i)))
(or (equal (standard-char-p ch)
(or #+(and mcl (not ccl))
(= i 13)
#-(and mcl (not ccl))
(= i 10)
(and (>= i 32)
(<= i 126))))
#+sbcl
(let ((v (lisp-implementation-version)))
(when (and (string<= "2.4.2" v)
(string< v "2.4.2.46"))
(exit-with-build-error
"Please avoid SBCL versions 2.4.2 through ~
2.4.2.45.~%Instead use a later SBCL version --~%2.4.3 or ~
later or, for example, the latest from GitHub --~%or ~
else SBCL version 2.4.1 or earlier.~%(Technical reason: ~
function standard-char-p does not return t on ~
a~%standard character input, but instead returns the ~
input character.)")))
(exit-with-build-error
"This Common Lisp is unsuitable for ACL2 because the ~
character~%with char-code ~d ~a standard in this Common Lisp ~
but should~%~abe."
i
(if (standard-char-p ch) "is" "is not")
(if (standard-char-p ch) "not " "")))))
; Check that char-upcase and char-downcase have the same values in all lisps
; on standard characters.
(dotimes (i 256)
(let ((ch (code-char i)))
(or (not (standard-char-p ch))
(eql (char-downcase ch)
(if (and (>= i 65)
(<= i 90))
(code-char (+ i 32))
ch))
(exit-with-build-error
"This Common Lisp is unsuitable for ACL2 because ~
(char-downcase ~s)~%is ~s but should be ~s."
ch
(char-downcase ch)
(if (and (>= i 65)
(<= i 90))
(code-char (+ i 32))
ch)))))
(dotimes (i 256)
(let ((ch (code-char i)))
(or (not (standard-char-p ch))
(eql (char-upcase ch)
(if (and (>= i 97)
(<= i 122))
(code-char (- (char-code ch) 32))
ch))
(exit-with-build-error
"This Common Lisp is unsuitable for ACL2 because (char-upcase ~
~s)~%is ~s but should be ~s."
ch
(char-upcase ch)
(if (and (>= i 65)
(<= i 90))
(code-char (- (char-code ch) 32))
ch)))))
; The following test supports the partial-encapslate in axioms.lisp that
; introduces alpha-char-p-non-standard, upper-case-p-non-standard,
; lower-case-p-non-standard, char-downcase-non-standard, and
; char-upcase-non-standard. See comments there referencing:
; "Checks on character case".
(dotimes (i 256)
(let ((ch (code-char i))
bad)
(unless (equal (standard-char-p (char-upcase ch))
(standard-char-p ch))
(setq bad 0))
(unless (equal (standard-char-p (char-downcase ch))
(standard-char-p ch))
(setq bad 1))
(unless (or (not (upper-case-p ch))
(equal (char-upcase
(char-downcase ch))
ch))
(setq bad 2))
(unless (or (not (lower-case-p ch))
(equal (char-downcase
(char-upcase ch))
ch))
(setq bad 3))
(when bad
(exit-with-build-error
"This Common Lisp is unsuitable for ACL2 because the~%~
following test failed for the character ch = (code-char ~s):~%~s~a"
i
(case bad
(0 '(equal (standard-char-p (char-upcase ch))
(standard-char-p ch)))
(1 '(equal (standard-char-p (char-downcase ch))
(standard-char-p ch)))
(2 '(or (not (upper-case-p ch))
(equal (char-upcase
(char-downcase ch))
ch)))
(3 '(or (not (lower-case-p ch))
(equal (char-downcase
(char-upcase ch))
ch)))
(otherwise
"Implementation Error! Please contact the ACL2 implementors."))
#-cmucl ""
#+cmucl
(if (string< (subseq (lisp-implementation-version) 0 16)
"snapshot-2024-08")
"
NOTE: Please update your cmucl to the 8/2024 snapshot or later."
"")))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; FEATURES, MISC.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; The conditional reader macro doesn't care about the package when it looks for
; the symbol. In fact, :UNIX is not a member of *features* in gcl; LISP:UNIX
; is.
#-(or unix mswindows)
(exit-with-build-error
"This Common Lisp is unsuitable for ACL2 because~%neither :UNIX nor ~
:MSWINDOWS is a member of *features*.")
(or (typep array-dimension-limit 'fixnum)
; We assume this explicitly in the various copy-array functions.
(exit-with-build-error
"We assume that ARRAY-DIMENSION-LIMIT is a fixnum. CLTL2 requires ~
this.~%ACL2 will not work in this Common Lisp."))
(or (>= multiple-values-limit *number-of-return-values*)
(exit-with-build-error
"We assume that multiple-values-limit is at least ~s, but in this Common ~
Lisp its value is ~s. Please contact the ACL2 implementors about ~
lowering the value of ACL2 constant *NUMBER-OF-RETURN-VALUES*."
multiple-values-limit
*number-of-return-values*))
; The following check must be put last in this file, since we don't entirely
; trust that it won't corrupt the current image. We collect all symbols in
; *common-lisp-symbols-from-main-lisp-package*, other than those that have the
; syntax of a lambda list keyword, that are special.
(let ((badvars nil))
(dolist (var *copy-of-common-lisp-symbols-from-main-lisp-package*)
(or (member var *copy-of-common-lisp-specials-and-constants*
:test #'eq)
(if (and (let ((s (symbol-name var)))
(or (= (length s) 0)
(not (eql (char s 0) #\&))))
(eval `(let ((,var (gensym)))
; We are not aware of any predicate, defined in all Common Lisp
; implementations, for checking that a variable is special; so we write our own
; behavioral test here. If var is special, then the above binding will make it
; boundp and update its symbol-value. Conversely, if var is not special, then
; there are two cases: either it is not boundp before the binding above in
; which case it remains not boundp, or else its global value is not the above
; gensym value.
(and (boundp ',var)
(eq ,var (symbol-value ',var))))))
(setq badvars (cons var badvars)))))
(if badvars
(exit-with-build-error
"The following constants or special variables in the main~%Lisp ~
package needs to be included in the ~
list~%*common-lisp-specials-and-constants*:~%~s."
badvars)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(format t "Check completed.~%")
; Do not put any forms below! See comment above.