0.7.8.7:
[sbcl.git] / src / compiler / ir1-translators.lisp
index e809bb3..8c11111 100644 (file)
@@ -12,7 +12,7 @@
 
 (in-package "SB!C")
 \f
-;;;; control special forms
+;;;; special forms for control
 
 (def-ir1-translator progn ((&rest forms) start cont)
   #!+sb-doc
@@ -84,7 +84,6 @@
       (push env-entry (continuation-lexenv-uses cont))
       (ir1-convert-progn-body dummy cont forms))))
 
-
 (def-ir1-translator return-from ((name &optional value) start cont)
   #!+sb-doc
   "Return-From Block-Name Value-Form
          (compiler-error
           "The local symbol macro name ~S is not a symbol."
           name))
+       (let ((kind (info :variable :kind name)))
+        (when (member kind '(:special :constant))
+          (compiler-error "Attempt to bind a ~(~A~) variable with SYMBOL-MACROLET: ~S" kind name)))
        `(,name . (MACRO . ,expansion))))
    :vars
    definitions
 ;;; VOP or %VOP.. -- WHN 2001-06-11
 ;;; FIXME: Look at doing this ^, it doesn't look too hard actually.
 (def-ir1-translator %primitive ((name &rest args) start cont)
-  (unless (symbolp name)
-    (compiler-error "internal error: Primitive name ~S is not a symbol." name))
+  (declare (type symbol name))
   (let* ((template (or (gethash name *backend-template-names*)
-                      (compiler-error
-                       "internal error: Primitive name ~A is not defined."
-                       name)))
+                      (bug "undefined primitive ~A" name)))
         (required (length (template-arg-types template)))
         (info (template-info-arg-count template))
         (min (+ required info))
         (nargs (length args)))
     (if (template-more-args-type template)
        (when (< nargs min)
-         (compiler-error "internal error: Primitive ~A was called ~
-                           with ~R argument~:P, ~
-                          but wants at least ~R."
-                         name
-                         nargs
-                         min))
+         (bug "Primitive ~A was called with ~R argument~:P, ~
+               but wants at least ~R."
+              name
+              nargs
+              min))
        (unless (= nargs min)
-         (compiler-error "internal error: Primitive ~A was called ~
-                           with ~R argument~:P, ~
-                          but wants exactly ~R."
-                         name
-                         nargs
-                         min)))
+         (bug "Primitive ~A was called with ~R argument~:P, ~
+                but wants exactly ~R."
+              name
+              nargs
+              min)))
 
     (when (eq (template-result-types template) :conditional)
-      (compiler-error
-       "%PRIMITIVE was used with a conditional template."))
+      (bug "%PRIMITIVE was used with a conditional template."))
 
     (when (template-more-results-type template)
-      (compiler-error
-       "%PRIMITIVE was used with an unknown values template."))
+      (bug "%PRIMITIVE was used with an unknown values template."))
 
     (ir1-convert start
                 cont
 ;;; FUNCALL is implemented on %FUNCALL, which can only call functions
 ;;; (not symbols). %FUNCALL is used directly in some places where the
 ;;; call should always be open-coded even if FUNCALL is :NOTINLINE.
-(deftransform funcall ((function &rest args) * * :when :both)
+(deftransform funcall ((function &rest args) * *)
   (let ((arg-names (make-gensym-list (length args))))
     `(lambda (function ,@arg-names)
        (%funcall ,(if (csubtypep (continuation-type function)
       (values nil t)))
 
 (deftransform %coerce-callable-to-fun ((thing) (function) *
-                                      :when :both
                                       :important t)
   "optimize away possible call to FDEFINITION at runtime"
   'thing)
 ;;;; any pervasive declarations also affect the evaluation of the
 ;;;; arguments.)
 
-;;; Given a list of binding specifiers in the style of Let, return:
+;;; Given a list of binding specifiers in the style of LET, return:
 ;;;  1. The list of var structures for the variables bound.
 ;;;  2. The initial value form for each variable.
 ;;;
 ;;; The variable names are checked for legality and globally special
 ;;; variables are marked as such. Context is the name of the form, for
 ;;; error reporting purposes.
-(declaim (ftype (function (list symbol) (values list list list))
+(declaim (ftype (function (list symbol) (values list list))
                extract-let-vars))
 (defun extract-let-vars (bindings context)
   (collect ((vars)
        (cond ((atom spec)
               (let ((var (get-var spec)))
                 (vars var)
-                (names (cons spec var))
+                (names spec)
                 (vals nil)))
              (t
               (unless (proper-list-of-length-p spec 1 2)
                 (names name)
                 (vals (second spec)))))))
 
-    (values (vars) (vals) (names))))
+    (values (vars) (vals))))
 
 (def-ir1-translator let ((bindings &body body)
                         start cont)
   During evaluation of the Forms, bind the Vars to the result of evaluating the
   Value forms. The variables are bound in parallel after all of the Values are
   evaluated."
-  (multiple-value-bind (forms decls) (sb!sys:parse-body body nil)
+  (multiple-value-bind (forms decls) (parse-body body nil)
     (multiple-value-bind (vars values) (extract-let-vars bindings 'let)
-      (let* ((*lexenv* (process-decls decls vars nil cont))
-            (fun-cont (make-continuation))
-            (fun (ir1-convert-lambda-body
-                  forms vars :debug-name (debug-namify "LET ~S" bindings))))
-       (reference-leaf start fun-cont fun)
-       (ir1-convert-combination-args fun-cont cont values)))))
+      (let ((fun-cont (make-continuation)))
+        (let* ((*lexenv* (process-decls decls vars nil cont))
+               (fun (ir1-convert-lambda-body
+                     forms vars
+                     :debug-name (debug-namify "LET ~S" bindings))))
+          (reference-leaf start fun-cont fun))
+        (ir1-convert-combination-args fun-cont cont values)))))
 
 (def-ir1-translator let* ((bindings &body body)
                          start cont)
   "LET* ({(Var [Value]) | Var}*) Declaration* Form*
   Similar to LET, but the variables are bound sequentially, allowing each Value
   form to reference any of the previous Vars."
-  (multiple-value-bind (forms decls) (sb!sys:parse-body body nil)
+  (multiple-value-bind (forms decls) (parse-body body nil)
     (multiple-value-bind (vars values) (extract-let-vars bindings 'let*)
       (let ((*lexenv* (process-decls decls vars nil cont)))
        (ir1-convert-aux-bindings start cont forms vars values)))))
 ;;; forms before we hit the IR1 transform level.
 (defun ir1-translate-locally (body start cont)
   (declare (type list body) (type continuation start cont))
-  (multiple-value-bind (forms decls) (sb!sys:parse-body body nil)
+  (multiple-value-bind (forms decls) (parse-body body nil)
     (let ((*lexenv* (process-decls decls nil nil cont)))
       (ir1-convert-aux-bindings start cont forms nil nil))))
 
       (let ((name (first def)))
        (check-fun-name name)
        (names name)
-       (multiple-value-bind (forms decls) (sb!sys:parse-body (cddr def))
+       (multiple-value-bind (forms decls) (parse-body (cddr def))
          (defs `(lambda ,(second def)
                   ,@decls
                   (block ,(fun-name-block-name name)
   Evaluate the Body-Forms with some local function definitions. The bindings
   do not enclose the definitions; any use of Name in the Forms will refer to
   the lexically apparent function definition in the enclosing environment."
-  (multiple-value-bind (forms decls) (sb!sys:parse-body body nil)
+  (multiple-value-bind (forms decls) (parse-body body nil)
     (multiple-value-bind (names defs)
        (extract-flet-vars definitions 'flet)
       (let* ((fvars (mapcar (lambda (n d)
   Evaluate the Body-Forms with some local function definitions. The bindings
   enclose the new definitions, so the defined functions can call themselves or
   each other."
-  (multiple-value-bind (forms decls) (sb!sys:parse-body body nil)
+  (multiple-value-bind (forms decls) (parse-body body nil)
     (multiple-value-bind (names defs)
        (extract-flet-vars definitions 'labels)
       (let* (;; dummy LABELS functions, to be used as placeholders
 ;;; We make this work by getting USE-CONTINUATION to do the unioning
 ;;; across COND branches. We can't do it here, since we don't know how
 ;;; many branches there are going to be.
-(defun ir1ize-the-or-values (type cont lexenv name)
+(defun ir1ize-the-or-values (type cont lexenv place)
   (declare (type continuation cont) (type lexenv lexenv))
-  (let* ((ctype (values-specifier-type type))
+  (let* ((ctype (if (typep type 'ctype) type (compiler-values-specifier-type type)))
         (old-type (or (lexenv-find cont type-restrictions)
                       *wild-type*))
         (intersects (values-types-equal-or-intersect old-type ctype))
-        (int (values-type-intersection old-type ctype))
-        (new (if intersects int old-type)))
+        (new (values-type-intersection old-type ctype)))
     (when (null (find-uses cont))
       (setf (continuation-asserted-type cont) new))
     (when (and (not intersects)
+              ;; FIXME: Is it really right to look at *LEXENV* here,
+              ;; instead of looking at the LEXENV argument? Why?
               (not (policy *lexenv*
                            (= inhibit-warnings 3)))) ;FIXME: really OK to suppress?
       (compiler-warn
-       "The type ~S in ~S declaration conflicts with an ~
-        enclosing assertion:~%   ~S"
+       "The type ~S ~A conflicts with an enclosing assertion:~%   ~S"
        (type-specifier ctype)
-       name
+       place
        (type-specifier old-type)))
     (make-lexenv :type-restrictions `((,cont . ,new))
                 :default lexenv)))
 ;;; this didn't seem to expand into an assertion, at least for ALIEN
 ;;; values. Check that SBCL doesn't have this problem.
 (def-ir1-translator the ((type value) start cont)
-  (let ((*lexenv* (ir1ize-the-or-values type cont *lexenv* 'the)))
+  (with-continuation-type-assertion (cont (compiler-values-specifier-type type)
+                                          "in THE declaration")
     (ir1-convert start cont value)))
 
 ;;; This is like the THE special form, except that it believes
 (def-ir1-translator truly-the ((type value) start cont)
   #!+sb-doc
   (declare (inline member))
-  (let ((type (values-specifier-type type))
+  (let ((type (compiler-values-specifier-type type))
        (old (find-uses cont)))
     (ir1-convert start cont value)
     (do-uses (use cont)
     (continuation-starts-block dummy-start)
     (ir1-convert start dummy-start result)
 
-    (substitute-continuation-uses cont dummy-start)
+    (with-continuation-type-assertion
+        (cont (continuation-asserted-type dummy-start)
+              "of the first form")
+      (substitute-continuation-uses cont dummy-start))
 
     (continuation-starts-block dummy-result)
     (ir1-convert-progn-body dummy-start dummy-result forms)