1 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; The software is in the public domain and is provided with
5 ;;;; absolutely no warranty. See the COPYING and CREDITS files for
8 ;; Undo default contribs mufflage so that DECLARATION-INFORMATION tests pass.
9 sb-ext
::(declaim (unmuffle-conditions compiler-note
))
11 (defpackage :sb-cltl2-tests
12 (:use
:sb-cltl2
:cl
:sb-rt
:sb-ext
:sb-kernel
:sb-int
))
14 (in-package :sb-cltl2-tests
)
18 (defmacro *x
*-value
()
19 (declare (special *x
*))
22 (deftest compiler-let
.1
24 (compiler-let ((*x
* :inner
))
25 (list *x
* (*x
*-value
))))
26 ;; See the X3J13 writeup for why the interpreter
27 ;; might return (and does return) a different answer.
28 #.
(if (eq sb-ext
:*evaluator-mode
* :compile
)
32 (defvar *expansions
* nil
)
33 (defmacro macroexpand-macro
(arg)
34 (push arg
*expansions
*)
37 (deftest macroexpand-all
.1
39 (macroexpand-all '(defmethod foo ((x fixnum
)) (1+ x
)))
43 (deftest macroexpand-all
.2
44 (let ((*expansions
* nil
))
45 (macroexpand-all '(list (macroexpand-macro 1)
46 (let (macroexpand-macro :no
)
47 (macroexpand-macro 2))))
48 (remove-duplicates (sort *expansions
* #'<)))
51 (deftest macroexpand-all
.3
52 (let ((*expansions
* nil
))
53 (compile nil
'(lambda ()
54 (declare (muffle-conditions style-warning
))
55 (macrolet ((foo (key &environment env
)
56 (macroexpand-all `(bar ,key
) env
)))
59 (push key
*expansions
*)
62 (remove-duplicates *expansions
*))
66 (multiple-value-bind (expansion macro-p
)
67 (macroexpand 'srlt env
)
68 (when macro-p
(eval expansion
))))
69 (defmacro testr
(&environment env
)
70 `',(getf (smv env
) nil
))
72 (deftest macroexpand-all
.4
73 (macroexpand-all '(symbol-macrolet ((srlt '(nil zool
))) (testr)))
74 (symbol-macrolet ((srlt '(nil zool
))) 'zool
))
77 (deftest macroexpand-all
.5
78 ;; The second use of (W) is expanded to X, the first is untouched.
79 ;; Use EQUALP explicitly because the RT tester's EQUALP-WITH-CASE
80 ;; is not quite EQUALP with regard to structures.
81 (equalp (macroexpand-all '(macrolet ((w () 'x
))
82 `(let ((y `(z ,(w) ,,(w)))) (g))))
83 '(macrolet ((w () 'x
)) `(let ((y `(z ,(w) ,,x
))) (g))))
86 (deftest macroexpand-all
.6
87 ;; The subform (AND Z) in (PROGN `(F ,(WHEN X Y) . `(,B ,,(AND Z))))
88 ;; is evaluable though unlikely to appear in real code. Unless F is a
89 ;; macro, this form when evaluated does not comprise a well-formed sexpr.
90 (equalp (macroexpand-all '(progn `(f ,(when x y
) .
`(,b
,,(and z
)))))
91 '(progn `(f ,(if x y
) .
`(,b
,,(the t z
)))))
95 (define-symbol-macro global-symbol-macro xxx
)
97 (deftest macroexpand-all
.7
98 (equalp (macroexpand-all 'global-symbol-macro
) 'xxx
)
100 (deftest macroexpand-all
.8
101 (symbol-macrolet ((global-symbol-macro yyy
))
102 (macrolet ((frob (&environment env form
)
103 `',(macroexpand-all form env
)))
104 (equalp (frob global-symbol-macro
) 'yyy
)))
106 (deftest macroexpand-all
.9
107 (let ((global-symbol-macro 3))
108 (macrolet ((frob (&environment env form
)
109 `',(macroexpand-all form env
)))
110 (equalp (frob global-symbol-macro
) 'global-symbol-macro
)))
112 (deftest macroexpand-all
.10
113 (macrolet ((frob (&environment env form
)
114 `',(macroexpand-all form env
)))
115 (equalp (frob (let ((anything 1)) global-symbol-macro
))
116 '(let ((anything 1)) xxx
)))
118 (deftest macroexpand-all
.11
119 (macrolet ((frob (&environment env form
)
120 `',(macroexpand-all form env
)))
121 (equalp (frob (let ((global-symbol-macro global-symbol-macro
))
122 global-symbol-macro
))
123 '(let ((global-symbol-macro xxx
)) global-symbol-macro
)))
125 (deftest macroexpand-all
.12
126 (macrolet ((frob (&environment env form
)
127 `',(macroexpand-all form env
)))
128 (equalp (frob (symbol-macrolet ((global-symbol-macro 3))
129 global-symbol-macro
))
130 '(symbol-macrolet ((global-symbol-macro 3)) 3)))
132 (deftest macroexpand-all
.13
133 (symbol-macrolet ((x y
))
134 (macrolet ((frob (&environment env form
)
135 `',(macroexpand-all form env
)))
136 (equalp (frob (+ x x
))
139 ;;;; DECLARATION-INFORMATION
141 (defmacro dinfo
(thing &environment env
)
142 `',(declaration-information thing env
))
145 `(macrolet ((frob (suffix answer
&optional declaration
)
146 `(deftest ,(intern (concatenate 'string
147 "DECLARATION-INFORMATION."
150 (locally (declare ,@(when declaration
152 (cadr (assoc ',',x
(dinfo optimize
))))
155 (frob ".0" 0 (optimize (,x
0)))
156 (frob ".1" 1 (optimize (,x
1)))
157 (frob ".2" 2 (optimize (,x
2)))
158 (frob ".3" 3 (optimize (,x
3)))
159 (frob ".IMPLICIT" 3 (optimize ,x
)))))
163 (def compilation-speed
)
167 (deftest declaration-information.restrict-compiler-policy
.1
168 (with-compilation-unit (:policy
'(optimize) :override t
)
169 (restrict-compiler-policy 'speed
3)
170 (eval '(cadr (assoc 'speed
(dinfo optimize
)))))
173 ;; This usage is esoteric, and the expected answer differs based on whether the
174 ;; code is interpreted or compiled. Compiling RESTRICT-COMPILER-POLICY doesn't
175 ;; actually do anything to affect the compiler since it is not a toplevel form
176 ;; in an eval-when. (I suspect that it wouldn't normally be used this way)
177 ;; But the interpreter calls it, which has an immediate visible effect.
178 (deftest declaration-information.restrict-compiler-policy
.2
179 (with-compilation-unit (:policy
'(optimize) :override t
)
180 (restrict-compiler-policy 'speed
3)
181 (locally (declare (optimize (speed 2)))
182 (cadr (assoc 'speed
(dinfo optimize
)))))
183 ;; sb-rt doesn't eval the "expected result" form.
184 #.
(if (eq sb-ext
:*evaluator-mode
* :compile
) 2 3))
186 (deftest declaration-information.restrict-compiler-policy
.3
187 (locally (declare (optimize (speed 2)))
188 (with-compilation-unit (:policy
'(optimize) :override t
)
189 (restrict-compiler-policy 'speed
3)
190 (cadr (assoc 'speed
(dinfo optimize
)))))
191 #.
(if (eq sb-ext
:*evaluator-mode
* :compile
) 2 3))
193 (deftest declaration-information.muffle-conditions.default
194 (dinfo sb-ext
:muffle-conditions
)
196 (deftest declaration-information.muffle-conditions
.1
197 (locally (declare (sb-ext:muffle-conditions warning
))
198 (dinfo sb-ext
:muffle-conditions
))
200 (deftest declaration-information.muffle-conditions
.2
201 (let ((junk (dinfo sb-ext
:muffle-conditions
)))
202 (declare (sb-ext:muffle-conditions warning
))
203 (locally (declare (sb-ext:unmuffle-conditions style-warning
))
204 (let ((dinfo (dinfo sb-ext
:muffle-conditions
)))
207 (and (subtypep dinfo
`(or (and warning
(not style-warning
))
208 (and ,junk
(not style-warning
))))
209 (subtypep '(and warning
(not style-warning
)) dinfo
)))))))
213 (declaim (declaration fubar
))
215 (deftest declaration-information.declaration
216 (if (member 'fubar
(declaration-information 'declaration
)) 'yay
)
219 ;;;; VARIABLE-INFORMATION
223 (defmacro var-info
(var &environment env
)
224 (list 'quote
(multiple-value-list (variable-information var env
))))
226 (deftest variable-info.global-special
/unbound
230 (defvar *variable-info.global-special
/unbound.deprecation
*)
231 (declaim (sb-ext:deprecated
:early
("SBCL" "1.2.3")
232 (variable *variable-info.global-special
/unbound.deprecation
* :replacement foo
)))
233 (deftest variable-info.global-special
/unbound.deprecation
234 (var-info *variable-info.global-special
/unbound.deprecation
*)
235 (:special nil
((sb-ext:deprecated .
(:state
:early
236 :since
("SBCL" "1.2.3")
237 :replacements
(foo))))))
239 (deftest variable-info.global-special
/unbound
/extra-decl
240 (locally (declare (special *foo
*))
244 (deftest variable-info.global-special
/bound
249 (deftest variable-info.global-special
/bound
/extra-decl
251 (declare (special *foo
*))
255 (deftest variable-info.local-special
/unbound
256 (locally (declare (special x
))
260 (deftest variable-info.local-special
/bound
262 (declare (special x
))
266 (deftest variable-info.local-special
/shadowed
268 (declare (special x
))
275 (deftest variable-info.local-special
/shadows-lexical
278 (declare (special x
))
282 (deftest variable-info.lexical
287 (deftest variable-info.lexical.type
291 (:lexical t
((type . fixnum
))))
293 (deftest variable-info.lexical.type
.2
297 (locally (declare (fixnum x
))
298 (assert (plusp x
)))))
301 (deftest variable-info.lexical.type
.3
303 (locally (declare (fixnum x
))
305 (:lexical t
((type . fixnum
))))
307 (deftest variable-info.ignore
311 (:lexical t
((ignore . t
))))
313 (deftest variable-info.symbol-macro
/local
314 (symbol-macrolet ((x 8))
316 (:symbol-macro t nil
))
318 (define-symbol-macro my-symbol-macro t
)
320 (deftest variable-info.symbol-macro
/global
321 (var-info my-symbol-macro
)
322 (:symbol-macro nil nil
))
324 (deftest variable-info.undefined
325 (var-info #:undefined
)
328 (declaim (sb-ext:deprecated
:early
("SBCL" "1.2.3")
329 (variable *variable-info.undefined.deprecation
* :replacement foo
)))
330 (deftest variable-info.undefined.deprecation
331 (var-info *variable-info.undefined.deprecation
*)
332 (nil nil
((sb-ext:deprecated .
(:state
:early
333 :since
("SBCL" "1.2.3")
334 :replacements
(foo))))))
336 (declaim (global this-is-global
))
337 (deftest global-variable
338 (var-info this-is-global
)
341 (defglobal this-is-global-too
42)
342 (deftest global-variable
.2
343 (var-info this-is-global-too
)
344 (:global nil
((always-bound . t
))))
346 (sb-alien:define-alien-variable
"errno" sb-alien
:int
)
347 (deftest alien-variable
351 (defglobal *variable-info.global.deprecation
* 1)
352 (declaim (sb-ext:deprecated
:early
("SBCL" "1.2.3")
353 (variable *variable-info.global.deprecation
* :replacement foo
)))
354 (deftest variable-info.global.deprecation
355 (var-info *variable-info.global.deprecation
*)
356 (:global nil
((always-bound . t
)
357 (sb-ext:deprecated .
(:state
:early
358 :since
("SBCL" "1.2.3")
359 :replacements
(foo))))))
361 ;;;; FUNCTION-INFORMATION
363 (defmacro fun-info
(var &environment env
)
364 (list 'quote
(multiple-value-list (function-information var env
))))
366 (defun my-global-fun (x) x
)
368 (deftest function-info.global
/no-ftype
369 (fun-info my-global-fun
)
372 (declaim (ftype (function (cons) (values t
&optional
)) my-global-fun-2
))
374 (defun my-global-fun-2 (x) x
)
376 (deftest function-info.global
/ftype
377 (fun-info my-global-fun-2
)
378 (:function nil
((ftype .
(function (cons) (values t
&optional
))))))
380 (defun function-info.global.deprecation
())
381 (declaim (sb-ext:deprecated
:early
"1.2.3"
382 (function function-info.global.deprecation
:replacement foo
)))
383 (deftest function-info.global.deprecation
384 (fun-info function-info.global.deprecation
)
385 (:function nil
((sb-ext:deprecated .
(:state
:early
387 :replacements
(foo))))))
389 (deftest function-info.global.deprecation.lexically-shadowed
390 (flet ((function-info.global.deprecation
()))
391 (fun-info function-info.global.deprecation
))
394 (defmacro my-macro
(x) x
)
396 (deftest function-info.macro
400 (deftest function-info.macrolet
401 (macrolet ((thingy () nil
))
405 (deftest function-info.special-form
407 (:special-form nil nil
))
409 (deftest function-info.notinline
/local
411 (declare (notinline x
))
414 (:function t
((inline . notinline
))))
416 (declaim (notinline my-notinline
))
417 (defun my-notinline (x) x
)
419 (deftest function-info.notinline
/global
420 (fun-info my-notinline
)
421 (:function nil
((inline . notinline
))))
423 (declaim (inline my-inline
))
424 (defun my-inline (x) x
)
426 (deftest function-info.inline
/global
428 (:function nil
((inline . inline
))))
430 (deftest function-information.known-inline
431 (locally (declare (inline identity
))
433 (:function nil
((inline . inline
)
434 (ftype function
(t) (values t
&optional
)))))
436 (deftest function-information.ftype
438 (declare (ftype (sfunction (integer) integer
) foo
))
442 ((ftype function
(integer) (values integer
&optional
)))))
444 ;;;;; AUGMENT-ENVIRONMENT
446 (defmacro ct
(form &environment env
)
447 (let ((toeval `(let ((lexenv (quote ,env
)))
449 `(quote ,(eval toeval
))))
452 (deftest augment-environment.variable1
453 (multiple-value-bind (kind local alist
)
454 (variable-information
456 (augment-environment nil
:variable
(list 'x
) :declare
'((type integer x
))))
457 (list kind local
(cdr (assoc 'type alist
))))
458 (:lexical t integer
))
462 (deftest augment-environment.variable2
463 (identity (variable-information '*foo
* (augment-environment nil
:variable
'(*foo
*))))
466 (deftest augment-environment.variable3
467 (identity (variable-information 'foo
(augment-environment nil
:variable
'(foo))))
470 (deftest augment-environment.variable.special1
471 (identity (variable-information 'x
(augment-environment nil
:variable
'(x) :declare
'((special x
)))))
474 (deftest augment-environment.variable.special12
475 (locally (declare (special x
))
477 (variable-information
479 (identity (augment-environment lexenv
:variable
'(x))))))
482 (deftest augment-environment.variable.special13
483 (let* ((e1 (augment-environment nil
:variable
'(x) :declare
'((special x
))))
484 (e2 (augment-environment e1
:variable
'(x))))
485 (identity (variable-information 'x e2
)))
488 (deftest augment-environment.variable.special.mask
489 (let* ((e1 (augment-environment nil
:variable
'(x) :declare
'((ignore x
))))
490 (e2 (augment-environment e1
:variable
'(x))))
492 (nth 2 (multiple-value-list
493 (variable-information 'x e2
)))))
496 (deftest augment-environment.variable.ignore
497 (variable-information
499 (augment-environment nil
501 :declare
'((ignore x
))))
506 (deftest augment-environment.function
507 (function-information
509 (augment-environment nil
511 :declare
'((ftype (sfunction (integer) integer
) foo
))))
514 ((ftype function
(integer) (values integer
&optional
))))
517 (deftest augment-environment.macro
518 (macroexpand '(mac feh
)
521 :macro
(list (list 'mac
#'(lambda (form benv
)
522 (declare (ignore env
))
523 `(quote ,form
,form
,form
))))))
524 (quote (mac feh
) (mac feh
) (mac feh
))
527 (deftest augment-environment.symbol-macro
531 :symbol-macro
(list (list 'sym
'(foo bar baz
)))))
535 (deftest augment-environment.macro2
536 (eval (macroexpand '(newcond
539 (augment-environment nil
:macro
(list (list 'newcond
(macro-function 'cond
))))))
543 (deftest augment-environment.nest
546 (let* ((e (augment-environment lexenv
:variable
'(y))))
548 (variable-information 'x e
)
549 (variable-information 'y e
)))))
552 (deftest augment-environment.nest2
553 (symbol-macrolet ((x "x"))
555 (let* ((e (augment-environment lexenv
:variable
'(y))))
558 (variable-information 'y e
)))))
561 (deftest augment-environment.symbol-macro-var
562 (let ((e (augment-environment
564 :symbol-macro
(list (list 'sym
'(foo bar baz
)))
566 (list (macroexpand 'sym e
)
567 (variable-information 'x e
)))
571 ;;;;; DEFINE-DECLARATION
573 (defmacro third-value
(form)
574 (sb-int::with-unique-names
(a b c
)
575 `(multiple-value-bind (,a
,b
,c
) ,form
576 (declare (ignore ,a
,b
))
579 (deftest define-declaration.declare
581 (define-declaration zaphod
(spec env
)
582 (declare (ignore env
))
583 (values :declare
(cons 'zaphod spec
)))
584 (locally (declare (zaphod beblebrox
))
585 (locally (declare (zaphod and ford
))
586 (ct (declaration-information 'zaphod lexenv
)))))
590 (deftest define-declaration.declare2
592 (define-declaration zaphod
(spec env
)
593 (declare (ignore env
))
594 (values :declare
(cons 'zaphod spec
)))
596 (declare (zaphod beblebrox
)
598 (ct (declaration-information 'zaphod lexenv
))))
601 (deftest define-declaration.variable
603 (define-declaration vogon
(spec env
)
604 (declare (ignore env
))
605 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
606 (locally (declare (vogon poetry
))
610 (variable-information
613 (vogon-key . vogon-value
))
616 (deftest define-declaration.variable.special
618 (define-declaration vogon
(spec env
)
619 (declare (ignore env
))
620 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
623 (declare (special x
))
627 (variable-information 'x lexenv
))))))
628 (vogon-key . vogon-value
))
630 (deftest define-declaration.variable.special2
632 (define-declaration vogon
(spec env
)
633 (declare (ignore env
))
634 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
636 (declare (special x
))
641 (variable-information 'x lexenv
))))))
642 (vogon-key . vogon-value
))
644 (deftest define-declaration.variable.mask
646 (define-declaration vogon
(spec env
)
647 (declare (ignore env
))
648 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
655 (third (multiple-value-list (variable-information 'x lexenv
))))))))
658 (deftest define-declaration.variable.macromask
660 (define-declaration vogon
(spec env
)
661 (declare (ignore env
))
662 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
665 (symbol-macrolet ((x 42))
669 (third (multiple-value-list (variable-information 'x lexenv
))))))))
672 (deftest define-declaration.variable.macromask2
674 (define-declaration vogon
(spec env
)
675 (declare (ignore env
))
676 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
677 (symbol-macrolet ((x 42))
684 (third (multiple-value-list (variable-information 'x lexenv
))))))
688 (third (multiple-value-list (variable-information 'x lexenv
))))))))
689 (nil (vogon-key . vogon-value
)))
691 (deftest define-declaration.variable.mask2
693 (define-declaration vogon-a
(spec env
)
694 (declare (ignore env
))
695 (values :variable
`((,(cadr spec
) vogon-key a
))))
696 (define-declaration vogon-b
(spec env
)
697 (declare (ignore env
))
698 (values :variable
`((,(cadr spec
) vogon-key b
))))
700 (declare (vogon-a x
))
702 (declare (vogon-b x
)))
706 (third (multiple-value-list (variable-information 'x lexenv
)))))))
709 (deftest define-declaration.variable.specialmask
711 (define-declaration vogon
(spec env
)
712 (declare (ignore env
))
713 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
715 (declare (vogon *foo
*))
720 (third (multiple-value-list (variable-information '*foo
* lexenv
))))))))
721 (vogon-key . vogon-value
))
725 (deftest define-declaration.function
727 (define-declaration sad
(spec env
)
728 (declare (ignore env
))
729 (values :function
`((,(cadr spec
) emotional-state sad
))))
730 (locally (declare (zaphod beblebrox
))
731 (locally (declare (sad robot
))
733 (assoc 'emotional-state
734 (third-value (function-information
737 (emotional-state . sad
))
739 (deftest define-declaration.function.lexical
741 (define-declaration sad
(spec env
)
742 (declare (ignore env
))
743 (values :function
`((,(cadr spec
) emotional-state sad
))))
745 (locally (declare (sad robot
))
747 (assoc 'emotional-state
748 (third-value (function-information
751 (emotional-state . sad
))
754 (deftest define-declaration.function.lexical2
756 (define-declaration sad
(spec env
)
757 (declare (ignore env
))
758 (values :function
`((,(cadr spec
) emotional-state sad
))))
759 (labels ((robot nil
))
760 (declare (sad robot
))
762 (assoc 'emotional-state
763 (third-value (function-information
766 (emotional-state . sad
))
768 (deftest define-declaration.function.mask
770 (define-declaration sad
(spec env
)
771 (declare (ignore env
))
772 (values :function
`((,(cadr spec
) emotional-state sad
))))
773 (labels ((robot nil
))
774 (declare (sad robot
))
775 (labels ((robot nil
))
777 (assoc 'emotional-state
778 (third-value (function-information
784 (deftest define-declaration.function.mask2
786 (define-declaration sad
(spec env
)
787 (declare (ignore env
))
788 (values :function
`((,(cadr spec
) emotional-state sad
))))
790 (declare (sad robot
))
791 (labels ((robot nil
))
793 (assoc 'emotional-state
794 (third-value (function-information
799 (deftest define-declaration.function2
801 (define-declaration happy
(spec env
)
802 (declare (ignore env
))
803 (values :function
`((,(cadr spec
) emotional-state happy
))))
804 (locally (declare (zaphod beblebrox
))
805 (locally (declare (sad robot
))
806 (locally (declare (happy robot
))
808 (assoc 'emotional-state
809 (third-value (function-information
812 (emotional-state . happy
))
814 (deftest macroexpand-all.special-binding
815 (let ((form '(macrolet ((v (x &environment env
)
816 (sb-cltl2:variable-information x env
)))
819 (declare (special x
))
822 (eval (sb-cltl2:macroexpand-all form
))))
823 ((:special
:special
) (:special
:special
)))
825 (deftest macroexpand-all.symbol-macro-shadowed
826 (let ((form '(macrolet ((v (x &environment env
)
827 (macroexpand x env
)))
828 (symbol-macrolet ((x :bad
))
833 (eval (sb-cltl2:macroexpand-all form
))))