0.8.1.33:
[sbcl.git] / src / compiler / macros.lisp
index f6e4fb0..dd15d8c 100644 (file)
@@ -54,7 +54,8 @@
     (multiple-value-bind (body decls doc)
        (parse-defmacro lambda-list n-form body name "special form"
                        :environment n-env
-                       :error-fun 'convert-condition-into-compiler-error)
+                       :error-fun 'convert-condition-into-compiler-error
+                        :wrap-block nil)
       `(progn
         (declaim (ftype (function (continuation continuation t) (values))
                         ,fn-name))
 ;;; If the desirability of the transformation depends on the current
 ;;; OPTIMIZE parameters, then the POLICY macro should be used to
 ;;; determine when to pass.
-(defmacro define-source-transform (name lambda-list &body body)
-  (let ((fn-name
-        (if (listp name)
-            (collect ((pieces))
-              (dolist (piece name)
-                (pieces "-")
-                (pieces piece))
-              (apply #'symbolicate "SOURCE-TRANSFORM" (pieces)))
-            (symbolicate "SOURCE-TRANSFORM-" name)))
-       (n-form (gensym))
-       (n-env (gensym)))
+(defmacro source-transform-lambda (lambda-list &body body)
+  (let ((n-form (gensym))
+       (n-env (gensym))
+       (name (gensym)))
     (multiple-value-bind (body decls)
-       (parse-defmacro lambda-list n-form body name "form"
+       (parse-defmacro lambda-list n-form body "source transform" "form"
                        :environment n-env
                        :error-fun `(lambda (&rest stuff)
                                      (declare (ignore stuff))
-                                     (return-from ,fn-name
-                                       (values nil t))))
-      `(progn
-        (defun ,fn-name (,n-form)
-          (let ((,n-env *lexenv*))
-            ,@decls
-            ,body))
-        (setf (info :function :source-transform ',name) #',fn-name)))))
+                                     (return-from ,name
+                                       (values nil t)))
+                        :wrap-block nil)
+      `(lambda (,n-form &aux (,n-env *lexenv*))
+         ,@decls
+         (block ,name
+           ,body)))))
+(defmacro define-source-transform (name lambda-list &body body)
+  `(setf (info :function :source-transform ',name)
+         (source-transform-lambda ,lambda-list ,@body)))
 \f
 ;;;; boolean attribute utilities
 ;;;;
 
 (deftype attributes () 'fixnum)
 
-(eval-when (:compile-toplevel :load-toplevel :execute)
+(eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
 
 ;;; Given a list of attribute names and an alist that translates them
 ;;; to masks, return the OR of the masks.
 ;;;
 ;;;    NAME-attributes attribute-name*
 ;;;      Return a set of the named attributes.
-#+sb-xc-host
-(progn 
+#-sb-xc
+(progn
   (def!macro !def-boolean-attribute (name &rest attribute-names)
 
     (let ((translations-name (symbolicate "*" name "-ATTRIBUTE-TRANSLATIONS*"))
-         (test-name (symbolicate name "-ATTRIBUTEP")))
+         (test-name (symbolicate name "-ATTRIBUTEP"))
+          (decoder-name (symbolicate "DECODE-" name "-ATTRIBUTES")))
       (collect ((alist))
         (do ((mask 1 (ash mask 1))
             (names attribute-names (cdr names)))
           ;; building the xc and when building the target compiler.
           (!def-boolean-attribute-setter ,test-name
                                          ,translations-name
-                                         ,@attribute-names)))))
+                                         ,@attribute-names)
+           (defun ,decoder-name (attributes)
+             (loop for (name . mask) in ,translations-name
+                   when (logtest mask attributes)
+                     collect name))))))
 
   ;; It seems to be difficult to express in DEF!MACRO machinery what
   ;; to do with target-vs-host GET-SETF-EXPANSION in here, so we just
 ;;;; to parse the IR1 representation of a function call using a
 ;;;; standard function lambda-list.
 
-(eval-when (:compile-toplevel :load-toplevel :execute)
+(eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
 
 ;;; Given a DEFTRANSFORM-style lambda-list, generate code that parses
 ;;; the arguments of a combination with respect to that lambda-list.
 ;;; keywords specify the initial values for various optimizers that
 ;;; the function might have.
 (defmacro defknown (name arg-types result-type &optional (attributes '(any))
-                        &rest keys)
+                    &rest keys)
   (when (and (intersection attributes '(any call unwind))
             (intersection attributes '(movable)))
     (error "function cannot have both good and bad attributes: ~S" attributes))
 
   (when (member 'any attributes)
-    (setf attributes (union '(call unsafe unwind) attributes)))
+    (setq attributes (union '(call unsafe unwind) attributes)))
   (when (member 'flushable attributes)
     (pushnew 'unsafely-flushable attributes))
 
                         (not (legal-fun-name-p name)))
                    name
                    (list name))
-             '(function ,arg-types ,result-type)
+             '(sfunction ,arg-types ,result-type)
              (ir1-attributes ,@attributes)
              ,@keys))
 
                             `(continuation-next ,cont-var)))
             (,cont-var (node-cont ,node-var) (node-cont ,node-var)))
            (())
+         (declare (type node ,node-var))
         ,@body
         (when ,(if restart-p
-                   `(eq ,node-var (block-last ,n-block))
+                   `(or (eq ,node-var (block-last ,n-block))
+                         (block-delete-p ,n-block))
                    `(eq ,cont-var ,n-last-cont))
           (return nil))))))
 ;;; like DO-NODES, only iterating in reverse order
         (when (eq ,n-next ,n-start)
           (return nil))))))
 
+(defmacro do-nodes-carefully ((node-var cont-var block) &body body)
+  (with-unique-names (n-block n-last)
+    `(loop with ,n-block = ,block
+           with ,n-last = (block-last ,n-block)
+           for ,cont-var = (block-start ,n-block) then (node-cont ,node-var)
+           for ,node-var = (and ,cont-var (continuation-next ,cont-var))
+           while ,node-var
+           do (progn ,@body)
+           until (eq ,node-var ,n-last))))
+
 ;;; Bind the IR1 context variables to the values associated with NODE,
 ;;; so that new, extra IR1 conversion related to NODE can be done
 ;;; after the original conversion pass has finished.
         (values (cdr ,n-res) t)
         (values nil nil))))
 
-;;;
-(defmacro with-continuation-type-assertion ((cont ctype context) &body body)
-  `(let ((*lexenv* (ir1ize-the-or-values ,ctype ,cont *lexenv* ,context)))
-     ,@body))
-
 (defmacro with-component-last-block ((component block) &body body)
-  (let ((old-last-block (gensym "OLD-LAST-BLOCK")))
+  (with-unique-names (old-last-block)
     (once-only ((component component)
                 (block block))
       `(let ((,old-last-block (component-last-block ,component)))
 ;;; experimentation, not for ordinary use, so it should probably
 ;;; become conditional on SB-SHOW.
 
-(eval-when (:compile-toplevel :load-toplevel :execute)
+(eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
 
 (defstruct (event-info (:copier nil))
   ;; The name of this event.