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 (defpackage :sb-cltl2-tests
9 (:use
:sb-cltl2
:cl
:sb-rt
:sb-ext
:sb-kernel
:sb-int
))
11 (in-package :sb-cltl2-tests
)
15 (defmacro *x
*-value
()
16 (declare (special *x
*))
19 (deftest compiler-let
.1
21 (compiler-let ((*x
* :inner
))
22 (list *x
* (*x
*-value
))))
23 ;; See the X3J13 writeup for why the interpreter
24 ;; might return (and does return) a different answer.
25 #.
(if (eq sb-ext
:*evaluator-mode
* :compile
)
29 (defvar *expansions
* nil
)
30 (defmacro macroexpand-macro
(arg)
31 (push arg
*expansions
*)
34 (deftest macroexpand-all
.1
36 (macroexpand-all '(defmethod foo ((x fixnum
)) (1+ x
)))
40 (deftest macroexpand-all
.2
41 (let ((*expansions
* nil
))
42 (macroexpand-all '(list (macroexpand-macro 1)
43 (let (macroexpand-macro :no
)
44 (macroexpand-macro 2))))
45 (remove-duplicates (sort *expansions
* #'<)))
48 (deftest macroexpand-all
.3
49 (let ((*expansions
* nil
))
50 (compile nil
'(lambda ()
51 (declare (muffle-conditions style-warning
))
52 (macrolet ((foo (key &environment env
)
53 (macroexpand-all `(bar ,key
) env
)))
56 (push key
*expansions
*)
59 (remove-duplicates *expansions
*))
63 (multiple-value-bind (expansion macro-p
)
64 (macroexpand 'srlt env
)
65 (when macro-p
(eval expansion
))))
66 (defmacro testr
(&environment env
)
67 `',(getf (smv env
) nil
))
69 (deftest macroexpand-all
.4
70 (macroexpand-all '(symbol-macrolet ((srlt '(nil zool
))) (testr)))
71 (symbol-macrolet ((srlt '(nil zool
))) 'zool
))
74 (deftest macroexpand-all
.5
75 ;; The second use of (W) is expanded to X, the first is untouched.
76 ;; Use EQUALP explicitly because the RT tester's EQUALP-WITH-CASE
77 ;; is not quite EQUALP with regard to structures.
78 (equalp (macroexpand-all '(macrolet ((w () 'x
))
79 `(let ((y `(z ,(w) ,,(w)))) (g))))
80 '(macrolet ((w () 'x
)) `(let ((y `(z ,(w) ,,x
))) (g))))
83 (deftest macroexpand-all
.6
84 ;; The subform (AND Z) in (PROGN `(F ,(WHEN X Y) . `(,B ,,(AND Z))))
85 ;; is evaluable though unlikely to appear in real code. Unless F is a
86 ;; macro, this form when evaluated does not comprise a well-formed sexpr.
87 (equalp (macroexpand-all '(progn `(f ,(when x y
) .
`(,b
,,(and z
)))))
88 '(progn `(f ,(if x y
) .
`(,b
,,(the t z
)))))
92 (define-symbol-macro global-symbol-macro xxx
)
94 (deftest macroexpand-all
.7
95 (equalp (macroexpand-all 'global-symbol-macro
) 'xxx
)
97 (deftest macroexpand-all
.8
98 (symbol-macrolet ((global-symbol-macro yyy
))
99 (macrolet ((frob (&environment env form
)
100 `',(macroexpand-all form env
)))
101 (equalp (frob global-symbol-macro
) 'yyy
)))
103 (deftest macroexpand-all
.9
104 (let ((global-symbol-macro 3))
105 (macrolet ((frob (&environment env form
)
106 `',(macroexpand-all form env
)))
107 (equalp (frob global-symbol-macro
) 'global-symbol-macro
)))
109 (deftest macroexpand-all
.10
110 (macrolet ((frob (&environment env form
)
111 `',(macroexpand-all form env
)))
112 (equalp (frob (let ((anything 1)) global-symbol-macro
))
113 '(let ((anything 1)) xxx
)))
115 (deftest macroexpand-all
.11
116 (macrolet ((frob (&environment env form
)
117 `',(macroexpand-all form env
)))
118 (equalp (frob (let ((global-symbol-macro global-symbol-macro
))
119 global-symbol-macro
))
120 '(let ((global-symbol-macro xxx
)) global-symbol-macro
)))
122 (deftest macroexpand-all
.12
123 (macrolet ((frob (&environment env form
)
124 `',(macroexpand-all form env
)))
125 (equalp (frob (symbol-macrolet ((global-symbol-macro 3))
126 global-symbol-macro
))
127 '(symbol-macrolet ((global-symbol-macro 3)) 3)))
129 (deftest macroexpand-all
.13
130 (symbol-macrolet ((x y
))
131 (macrolet ((frob (&environment env form
)
132 `',(macroexpand-all form env
)))
133 (equalp (frob (+ x x
))
136 ;;;; DECLARATION-INFORMATION
138 (defmacro dinfo
(thing &environment env
)
139 `',(declaration-information thing env
))
142 `(macrolet ((frob (suffix answer
&optional declaration
)
143 `(deftest ,(intern (concatenate 'string
144 "DECLARATION-INFORMATION."
147 (locally (declare ,@(when declaration
149 (cadr (assoc ',',x
(dinfo optimize
))))
152 (frob ".0" 0 (optimize (,x
0)))
153 (frob ".1" 1 (optimize (,x
1)))
154 (frob ".2" 2 (optimize (,x
2)))
155 (frob ".3" 3 (optimize (,x
3)))
156 (frob ".IMPLICIT" 3 (optimize ,x
)))))
160 (def compilation-speed
)
164 (deftest declaration-information.restrict-compiler-policy
.1
165 (with-compilation-unit (:policy
'(optimize) :override t
)
166 (restrict-compiler-policy 'speed
3)
167 (eval '(cadr (assoc 'speed
(dinfo optimize
)))))
170 ;; This usage is esoteric, and the expected answer differs based on whether the
171 ;; code is interpreted or compiled. Compiling RESTRICT-COMPILER-POLICY doesn't
172 ;; actually do anything to affect the compiler since it is not a toplevel form
173 ;; in an eval-when. (I suspect that it wouldn't normally be used this way)
174 ;; But the interpreter calls it, which has an immediate visible effect.
175 (deftest declaration-information.restrict-compiler-policy
.2
176 (with-compilation-unit (:policy
'(optimize) :override t
)
177 (restrict-compiler-policy 'speed
3)
178 (locally (declare (optimize (speed 2)))
179 (cadr (assoc 'speed
(dinfo optimize
)))))
180 ;; sb-rt doesn't eval the "expected result" form.
181 #.
(if (eq sb-ext
:*evaluator-mode
* :compile
) 2 3))
183 (deftest declaration-information.restrict-compiler-policy
.3
184 (locally (declare (optimize (speed 2)))
185 (with-compilation-unit (:policy
'(optimize) :override t
)
186 (restrict-compiler-policy 'speed
3)
187 (cadr (assoc 'speed
(dinfo optimize
)))))
188 #.
(if (eq sb-ext
:*evaluator-mode
* :compile
) 2 3))
190 (deftest declaration-information.muffle-conditions.default
191 (dinfo sb-ext
:muffle-conditions
)
193 (deftest declaration-information.muffle-conditions
.1
194 (locally (declare (sb-ext:muffle-conditions warning
))
195 (dinfo sb-ext
:muffle-conditions
))
197 (deftest declaration-information.muffle-conditions
.2
198 (let ((junk (dinfo sb-ext
:muffle-conditions
)))
199 (declare (sb-ext:muffle-conditions warning
))
200 (locally (declare (sb-ext:unmuffle-conditions style-warning
))
201 (let ((dinfo (dinfo sb-ext
:muffle-conditions
)))
204 (and (subtypep dinfo
`(or (and warning
(not style-warning
))
205 (and ,junk
(not style-warning
))))
206 (subtypep '(and warning
(not style-warning
)) dinfo
)))))))
210 (declaim (declaration fubar
))
212 (deftest declaration-information.declaration
213 (if (member 'fubar
(declaration-information 'declaration
)) 'yay
)
216 ;;;; VARIABLE-INFORMATION
220 (defmacro var-info
(var &environment env
)
221 (list 'quote
(multiple-value-list (variable-information var env
))))
223 (deftest variable-info.global-special
/unbound
227 (defvar *variable-info.global-special
/unbound.deprecation
*)
228 (declaim (sb-ext:deprecated
:early
("SBCL" "1.2.3")
229 (variable *variable-info.global-special
/unbound.deprecation
* :replacement foo
)))
230 (deftest variable-info.global-special
/unbound.deprecation
231 (var-info *variable-info.global-special
/unbound.deprecation
*)
232 (:special nil
((sb-ext:deprecated .
(:state
:early
233 :since
("SBCL" "1.2.3")
234 :replacements
(foo))))))
236 (deftest variable-info.global-special
/unbound
/extra-decl
237 (locally (declare (special *foo
*))
241 (deftest variable-info.global-special
/bound
246 (deftest variable-info.global-special
/bound
/extra-decl
248 (declare (special *foo
*))
252 (deftest variable-info.local-special
/unbound
253 (locally (declare (special x
))
257 (deftest variable-info.local-special
/bound
259 (declare (special x
))
263 (deftest variable-info.local-special
/shadowed
265 (declare (special x
))
272 (deftest variable-info.local-special
/shadows-lexical
275 (declare (special x
))
279 (deftest variable-info.lexical
284 (deftest variable-info.lexical.type
288 (:lexical t
((type . fixnum
))))
290 (deftest variable-info.lexical.type
.2
294 (locally (declare (fixnum x
))
295 (assert (plusp x
)))))
298 (deftest variable-info.lexical.type
.3
300 (locally (declare (fixnum x
))
302 (:lexical t
((type . fixnum
))))
304 (deftest variable-info.ignore
308 (:lexical t
((ignore . t
))))
310 (deftest variable-info.symbol-macro
/local
311 (symbol-macrolet ((x 8))
313 (:symbol-macro t nil
))
315 (define-symbol-macro my-symbol-macro t
)
317 (deftest variable-info.symbol-macro
/global
318 (var-info my-symbol-macro
)
319 (:symbol-macro nil nil
))
321 (deftest variable-info.undefined
322 (var-info #:undefined
)
325 (declaim (sb-ext:deprecated
:early
("SBCL" "1.2.3")
326 (variable *variable-info.undefined.deprecation
* :replacement foo
)))
327 (deftest variable-info.undefined.deprecation
328 (var-info *variable-info.undefined.deprecation
*)
329 (nil nil
((sb-ext:deprecated .
(:state
:early
330 :since
("SBCL" "1.2.3")
331 :replacements
(foo))))))
333 (declaim (global this-is-global
))
334 (deftest global-variable
335 (var-info this-is-global
)
338 (defglobal this-is-global-too
42)
339 (deftest global-variable
.2
340 (var-info this-is-global-too
)
341 (:global nil
((always-bound . t
))))
343 (sb-alien:define-alien-variable
"errno" sb-alien
:int
)
344 (deftest alien-variable
348 (defglobal *variable-info.global.deprecation
* 1)
349 (declaim (sb-ext:deprecated
:early
("SBCL" "1.2.3")
350 (variable *variable-info.global.deprecation
* :replacement foo
)))
351 (deftest variable-info.global.deprecation
352 (var-info *variable-info.global.deprecation
*)
353 (:global nil
((always-bound . t
)
354 (sb-ext:deprecated .
(:state
:early
355 :since
("SBCL" "1.2.3")
356 :replacements
(foo))))))
358 ;;;; FUNCTION-INFORMATION
360 (defmacro fun-info
(var &environment env
)
361 (list 'quote
(multiple-value-list (function-information var env
))))
363 (defun my-global-fun (x) x
)
365 (deftest function-info.global
/no-ftype
366 (fun-info my-global-fun
)
369 (declaim (ftype (function (cons) (values t
&optional
)) my-global-fun-2
))
371 (defun my-global-fun-2 (x) x
)
373 (deftest function-info.global
/ftype
374 (fun-info my-global-fun-2
)
375 (:function nil
((ftype .
(function (cons) (values t
&optional
))))))
377 (defun function-info.global.deprecation
())
378 (declaim (sb-ext:deprecated
:early
"1.2.3"
379 (function function-info.global.deprecation
:replacement foo
)))
380 (deftest function-info.global.deprecation
381 (fun-info function-info.global.deprecation
)
382 (:function nil
((sb-ext:deprecated .
(:state
:early
384 :replacements
(foo))))))
386 (deftest function-info.global.deprecation.lexically-shadowed
387 (flet ((function-info.global.deprecation
()))
388 (fun-info function-info.global.deprecation
))
391 (defmacro my-macro
(x) x
)
393 (deftest function-info.macro
397 (deftest function-info.macrolet
398 (macrolet ((thingy () nil
))
402 (deftest function-info.special-form
404 (:special-form nil nil
))
406 (deftest function-info.notinline
/local
408 (declare (notinline x
))
411 (:function t
((inline . notinline
))))
413 (declaim (notinline my-notinline
))
414 (defun my-notinline (x) x
)
416 (deftest function-info.notinline
/global
417 (fun-info my-notinline
)
418 (:function nil
((inline . notinline
))))
420 (declaim (inline my-inline
))
421 (defun my-inline (x) x
)
423 (deftest function-info.inline
/global
425 (:function nil
((inline . inline
))))
427 (deftest function-information.known-inline
428 (locally (declare (inline identity
))
430 (:function nil
((inline . inline
)
431 (ftype function
(t) (values t
&optional
)))))
433 (deftest function-information.ftype
435 (declare (ftype (sfunction (integer) integer
) foo
))
439 ((ftype function
(integer) (values integer
&optional
)))))
441 ;;;;; AUGMENT-ENVIRONMENT
443 (defmacro ct
(form &environment env
)
444 (let ((toeval `(let ((lexenv (quote ,env
)))
446 `(quote ,(eval toeval
))))
449 (deftest augment-environment.variable1
450 (multiple-value-bind (kind local alist
)
451 (variable-information
453 (augment-environment nil
:variable
(list 'x
) :declare
'((type integer x
))))
454 (list kind local
(cdr (assoc 'type alist
))))
455 (:lexical t integer
))
459 (deftest augment-environment.variable2
460 (identity (variable-information '*foo
* (augment-environment nil
:variable
'(*foo
*))))
463 (deftest augment-environment.variable3
464 (identity (variable-information 'foo
(augment-environment nil
:variable
'(foo))))
467 (deftest augment-environment.variable.special1
468 (identity (variable-information 'x
(augment-environment nil
:variable
'(x) :declare
'((special x
)))))
471 (deftest augment-environment.variable.special12
472 (locally (declare (special x
))
474 (variable-information
476 (identity (augment-environment lexenv
:variable
'(x))))))
479 (deftest augment-environment.variable.special13
480 (let* ((e1 (augment-environment nil
:variable
'(x) :declare
'((special x
))))
481 (e2 (augment-environment e1
:variable
'(x))))
482 (identity (variable-information 'x e2
)))
485 (deftest augment-environment.variable.special.mask
486 (let* ((e1 (augment-environment nil
:variable
'(x) :declare
'((ignore x
))))
487 (e2 (augment-environment e1
:variable
'(x))))
489 (nth 2 (multiple-value-list
490 (variable-information 'x e2
)))))
493 (deftest augment-environment.variable.ignore
494 (variable-information
496 (augment-environment nil
498 :declare
'((ignore x
))))
503 (deftest augment-environment.function
504 (function-information
506 (augment-environment nil
508 :declare
'((ftype (sfunction (integer) integer
) foo
))))
511 ((ftype function
(integer) (values integer
&optional
))))
514 (deftest augment-environment.macro
515 (macroexpand '(mac feh
)
518 :macro
(list (list 'mac
#'(lambda (form benv
)
519 (declare (ignore env
))
520 `(quote ,form
,form
,form
))))))
521 (quote (mac feh
) (mac feh
) (mac feh
))
524 (deftest augment-environment.symbol-macro
528 :symbol-macro
(list (list 'sym
'(foo bar baz
)))))
532 (deftest augment-environment.macro2
533 (eval (macroexpand '(newcond
536 (augment-environment nil
:macro
(list (list 'newcond
(macro-function 'cond
))))))
540 (deftest augment-environment.nest
543 (let* ((e (augment-environment lexenv
:variable
'(y))))
545 (variable-information 'x e
)
546 (variable-information 'y e
)))))
549 (deftest augment-environment.nest2
550 (symbol-macrolet ((x "x"))
552 (let* ((e (augment-environment lexenv
:variable
'(y))))
555 (variable-information 'y e
)))))
558 (deftest augment-environment.symbol-macro-var
559 (let ((e (augment-environment
561 :symbol-macro
(list (list 'sym
'(foo bar baz
)))
563 (list (macroexpand 'sym e
)
564 (variable-information 'x e
)))
568 ;;;;; DEFINE-DECLARATION
570 (defmacro third-value
(form)
571 (sb-int::with-unique-names
(a b c
)
572 `(multiple-value-bind (,a
,b
,c
) ,form
573 (declare (ignore ,a
,b
))
576 (deftest define-declaration.declare
578 (define-declaration zaphod
(spec env
)
579 (declare (ignore env
))
580 (values :declare
(cons 'zaphod spec
)))
581 (locally (declare (zaphod beblebrox
))
582 (locally (declare (zaphod and ford
))
583 (ct (declaration-information 'zaphod lexenv
)))))
587 (deftest define-declaration.declare2
589 (define-declaration zaphod
(spec env
)
590 (declare (ignore env
))
591 (values :declare
(cons 'zaphod spec
)))
593 (declare (zaphod beblebrox
)
595 (ct (declaration-information 'zaphod lexenv
))))
598 (deftest define-declaration.variable
600 (define-declaration vogon
(spec env
)
601 (declare (ignore env
))
602 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
603 (locally (declare (vogon poetry
))
607 (variable-information
610 (vogon-key . vogon-value
))
613 (deftest define-declaration.variable.special
615 (define-declaration vogon
(spec env
)
616 (declare (ignore env
))
617 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
620 (declare (special x
))
624 (variable-information 'x lexenv
))))))
625 (vogon-key . vogon-value
))
627 (deftest define-declaration.variable.special2
629 (define-declaration vogon
(spec env
)
630 (declare (ignore env
))
631 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
633 (declare (special x
))
638 (variable-information 'x lexenv
))))))
639 (vogon-key . vogon-value
))
641 (deftest define-declaration.variable.mask
643 (define-declaration vogon
(spec env
)
644 (declare (ignore env
))
645 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
652 (third (multiple-value-list (variable-information 'x lexenv
))))))))
655 (deftest define-declaration.variable.macromask
657 (define-declaration vogon
(spec env
)
658 (declare (ignore env
))
659 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
662 (symbol-macrolet ((x 42))
666 (third (multiple-value-list (variable-information 'x lexenv
))))))))
669 (deftest define-declaration.variable.macromask2
671 (define-declaration vogon
(spec env
)
672 (declare (ignore env
))
673 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
674 (symbol-macrolet ((x 42))
681 (third (multiple-value-list (variable-information 'x lexenv
))))))
685 (third (multiple-value-list (variable-information 'x lexenv
))))))))
686 (nil (vogon-key . vogon-value
)))
688 (deftest define-declaration.variable.mask2
690 (define-declaration vogon-a
(spec env
)
691 (declare (ignore env
))
692 (values :variable
`((,(cadr spec
) vogon-key a
))))
693 (define-declaration vogon-b
(spec env
)
694 (declare (ignore env
))
695 (values :variable
`((,(cadr spec
) vogon-key b
))))
697 (declare (vogon-a x
))
699 (declare (vogon-b x
)))
703 (third (multiple-value-list (variable-information 'x lexenv
)))))))
706 (deftest define-declaration.variable.specialmask
708 (define-declaration vogon
(spec env
)
709 (declare (ignore env
))
710 (values :variable
`((,(cadr spec
) vogon-key vogon-value
))))
712 (declare (vogon *foo
*))
717 (third (multiple-value-list (variable-information '*foo
* lexenv
))))))))
718 (vogon-key . vogon-value
))
722 (deftest define-declaration.function
724 (define-declaration sad
(spec env
)
725 (declare (ignore env
))
726 (values :function
`((,(cadr spec
) emotional-state sad
))))
727 (locally (declare (zaphod beblebrox
))
728 (locally (declare (sad robot
))
730 (assoc 'emotional-state
731 (third-value (function-information
734 (emotional-state . sad
))
736 (deftest define-declaration.function.lexical
738 (define-declaration sad
(spec env
)
739 (declare (ignore env
))
740 (values :function
`((,(cadr spec
) emotional-state sad
))))
742 (locally (declare (sad robot
))
744 (assoc 'emotional-state
745 (third-value (function-information
748 (emotional-state . sad
))
751 (deftest define-declaration.function.lexical2
753 (define-declaration sad
(spec env
)
754 (declare (ignore env
))
755 (values :function
`((,(cadr spec
) emotional-state sad
))))
756 (labels ((robot nil
))
757 (declare (sad robot
))
759 (assoc 'emotional-state
760 (third-value (function-information
763 (emotional-state . sad
))
765 (deftest define-declaration.function.mask
767 (define-declaration sad
(spec env
)
768 (declare (ignore env
))
769 (values :function
`((,(cadr spec
) emotional-state sad
))))
770 (labels ((robot nil
))
771 (declare (sad robot
))
772 (labels ((robot nil
))
774 (assoc 'emotional-state
775 (third-value (function-information
781 (deftest define-declaration.function.mask2
783 (define-declaration sad
(spec env
)
784 (declare (ignore env
))
785 (values :function
`((,(cadr spec
) emotional-state sad
))))
787 (declare (sad robot
))
788 (labels ((robot nil
))
790 (assoc 'emotional-state
791 (third-value (function-information
796 (deftest define-declaration.function2
798 (define-declaration happy
(spec env
)
799 (declare (ignore env
))
800 (values :function
`((,(cadr spec
) emotional-state happy
))))
801 (locally (declare (zaphod beblebrox
))
802 (locally (declare (sad robot
))
803 (locally (declare (happy robot
))
805 (assoc 'emotional-state
806 (third-value (function-information
809 (emotional-state . happy
))
811 (deftest macroexpand-all.special-binding
812 (let ((form '(macrolet ((v (x &environment env
)
813 (sb-cltl2:variable-information x env
)))
816 (declare (special x
))
819 (eval (sb-cltl2:macroexpand-all form
))))
820 ((:special
:special
) (:special
:special
)))
822 (deftest macroexpand-all.symbol-macro-shadowed
823 (let ((form '(macrolet ((v (x &environment env
)
824 (macroexpand x env
)))
825 (symbol-macrolet ((x :bad
))
830 (eval (sb-cltl2:macroexpand-all form
))))