Utility predicates for packing: UNBOUNDED-SC-P and UNBOUNDED-TN-P
[sbcl.git] / src / compiler / deftype.lisp
index fe56d65..3708525 100644 (file)
@@ -9,20 +9,46 @@
 
 (in-package "SB!IMPL")
 
-(file-comment
- "$Header$")
+(defun constant-type-expander (expansion)
+  (declare (optimize safety))
+  (lambda (whole)
+    (if (cdr whole)
+        (sb!kernel::arg-count-error 'deftype (car whole) (cdr whole) nil 0 0)
+        expansion)))
 
-(def!macro sb!xc:deftype (name arglist &body body)
+(defun %deftype (name)
+  (setf (classoid-cell-pcl-class (find-classoid-cell name :create t)) nil))
+
+(def!macro sb!xc:deftype (&whole form name lambda-list &body body)
   #!+sb-doc
   "Define a new type, with syntax like DEFMACRO."
   (unless (symbolp name)
-    (error "type name not a symbol: ~S" name))
-  (let ((whole (gensym "WHOLE-")))
-    (multiple-value-bind (body local-decs doc)
-       (parse-defmacro arglist whole body name 'deftype :default-default ''*)
-      `(eval-when (:compile-toplevel :load-toplevel :execute)
-        (%compiler-deftype ',name
-                           #'(lambda (,whole)
-                               ,@local-decs
-                               (block ,name ,body))
-                           ,@(when doc `(,doc)))))))
+    (bad-type name 'symbol "Type name is not a symbol:~%  ~S"
+              form))
+  (multiple-value-bind (expander-form doc source-location-form)
+      (multiple-value-bind (forms decls doc) (parse-body body)
+        ;; FIXME: We could use CONSTANTP here to deal with slightly more
+        ;; complex deftypes using CONSTANT-TYPE-EXPANDER, but that XC:CONSTANTP
+        ;; is not availble early enough.
+        (if (and (not lambda-list) (not decls) (not (cdr forms))
+                 (or (member (car forms) '(t nil))
+                     (and (consp (car forms)) (eq 'quote (caar forms)))))
+            (values `(constant-type-expander ,(car forms)) doc '(sb!c:source-location))
+            (with-unique-names (whole)
+              (multiple-value-bind (macro-body local-decs doc)
+                  (parse-defmacro lambda-list whole body name 'deftype :default-default ''*)
+                (values `(lambda (,whole)
+                           ,@local-decs
+                           ,macro-body)
+                        doc
+                        nil)))))
+    `(progn
+       (eval-when (:compile-toplevel :load-toplevel :execute)
+         (%compiler-deftype ',name
+                            ',lambda-list
+                            ,expander-form
+                            ,doc
+                            ,source-location-form))
+       (eval-when (:load-toplevel :execute)
+         (%deftype ',name))
+       ',name)))