0.pre7.38:
[sbcl.git] / src / compiler / ir1tran.lisp
index f8bb594..45f95c6 100644 (file)
@@ -18,7 +18,7 @@
 ;;; taken through the source to reach the form. This provides a way to
 ;;; keep track of the location of original source forms, even when
 ;;; macroexpansions and other arbitary permutations of the code
-;;; happen. This table is initialized by calling Find-Source-Paths on
+;;; happen. This table is initialized by calling FIND-SOURCE-PATHS on
 ;;; the original source.
 (declaim (hash-table *source-paths*))
 (defvar *source-paths*)
@@ -40,7 +40,7 @@
 ;;; *CURRENT-PATH* is the source path of the form we are currently
 ;;; translating. See NODE-SOURCE-PATH in the NODE structure.
 (declaim (list *current-path*))
-(defvar *current-path* nil)
+(defvar *current-path*)
 
 (defvar *derive-function-types* nil
   "Should the compiler assume that function types will never change,
 
 ;;; This function takes a form and the top-level form number for that
 ;;; form, and returns a lambda representing the translation of that
-;;; form in the current global environment. The lambda is top-level
-;;; lambda that can be called to cause evaluation of the forms. This
-;;; lambda is in the initial component. If FOR-VALUE is T, then the
-;;; value of the form is returned from the function, otherwise NIL is
-;;; returned.
+;;; form in the current global environment. The returned lambda is a
+;;; top-level lambda that can be called to cause evaluation of the
+;;; forms. This lambda is in the initial component. If FOR-VALUE is T,
+;;; then the value of the form is returned from the function,
+;;; otherwise NIL is returned.
 ;;;
 ;;; This function may have arbitrary effects on the global environment
 ;;; due to processing of PROCLAIMs and EVAL-WHENs. All syntax error
 
 ;;; *CURRENT-FORM-NUMBER* is used in FIND-SOURCE-PATHS to compute the
 ;;; form number to associate with a source path. This should be bound
-;;; to 0 around the processing of each truly top-level form.
+;;; to an initial value of 0 before the processing of each truly
+;;; top-level form.
 (declaim (type index *current-form-number*))
 (defvar *current-form-number*)
 
     (pushnew fun (component-reanalyze-functions *current-component*)))
   fun)
 
-;;; Generate a Ref node for LEAF, frobbing the LEAF structure as
+;;; Generate a REF node for LEAF, frobbing the LEAF structure as
 ;;; needed. If LEAF represents a defined function which has already
 ;;; been converted, and is not :NOTINLINE, then reference the
 ;;; functional instead.
              (new-venv nil cons))
 
       (dolist (var vars)
+       ;; As far as I can see, LAMBDA-VAR-HOME should never have
+       ;; been set before. Let's make sure. -- WHN 2001-09-29
+       (aver (null (lambda-var-home var)))
        (setf (lambda-var-home var) lambda)
        (let ((specvar (lambda-var-specvar var)))
          (cond (specvar
       last-entry)))
 
 ;;; This function generates the entry point functions for the
-;;; optional-dispatch Res. We accomplish this by recursion on the list of
-;;; arguments, analyzing the arglist on the way down and generating entry
-;;; points on the way up.
+;;; OPTIONAL-DISPATCH RES. We accomplish this by recursion on the list
+;;; of arguments, analyzing the arglist on the way down and generating
+;;; entry points on the way up.
 ;;;
-;;; Default-Vars is a reversed list of all the argument vars processed
-;;; so far, including supplied-p vars. Default-Vals is a list of the
-;;; names of the Default-Vars.
+;;; DEFAULT-VARS is a reversed list of all the argument vars processed
+;;; so far, including supplied-p vars. DEFAULT-VALS is a list of the
+;;; names of the DEFAULT-VARS.
 ;;;
-;;; Entry-Vars is a reversed list of processed argument vars,
-;;; excluding supplied-p vars. Entry-Vals is a list things that can be
-;;; evaluated to get the values for all the vars from the Entry-Vars.
+;;; ENTRY-VARS is a reversed list of processed argument vars,
+;;; excluding supplied-p vars. ENTRY-VALS is a list things that can be
+;;; evaluated to get the values for all the vars from the ENTRY-VARS.
 ;;; It has the var name for each required or optional arg, and has T
 ;;; for each supplied-p arg.
 ;;;
-;;; Vars is a list of the Lambda-Var structures for arguments that
-;;; haven't been processed yet. Supplied-p-p is true if a supplied-p
+;;; VARS is a list of the LAMBDA-VAR structures for arguments that
+;;; haven't been processed yet. SUPPLIED-P-P is true if a supplied-p
 ;;; argument has already been processed; only in this case are the
-;;; Default-XXX and Entry-XXX different.
+;;; DEFAULT-XXX and ENTRY-XXX different.
 ;;;
 ;;; The result at each point is a lambda which should be called by the
 ;;; above level to default the remaining arguments and evaluate the
 ;;; returning it as the result when the recursion bottoms out.
 ;;;
 ;;; Each level in the recursion also adds its entry point function to
-;;; the result Optional-Dispatch. For most arguments, the defaulting
+;;; the result OPTIONAL-DISPATCH. For most arguments, the defaulting
 ;;; function and the entry point function will be the same, but when
-;;; supplied-p args are present they may be different.
+;;; SUPPLIED-P args are present they may be different.
 ;;;
 ;;; When we run into a &REST or &KEY arg, we punt out to
 ;;; IR1-CONVERT-MORE, which finishes for us in this case.
                                aux-vals cont)))))))
 
 ;;; This function deals with the case where we have to make an
-;;; Optional-Dispatch to represent a lambda. We cons up the result and
+;;; OPTIONAL-DISPATCH to represent a LAMBDA. We cons up the result and
 ;;; call IR1-CONVERT-HAIRY-ARGS to do the work. When it is done, we
-;;; figure out the min-args and max-args.
+;;; figure out the MIN-ARGS and MAX-ARGS.
 (defun ir1-convert-hairy-lambda (body vars keyp allowp aux-vars aux-vals cont)
   (declare (list body vars aux-vars aux-vals) (type continuation cont))
   (let ((res (make-optional-dispatch :arglist vars
 ;;;; mark its extent. When doing GO or RETURN-FROM, we emit an Exit
 ;;;; node.
 
-;;; Make a :entry cleanup and emit an Entry node, then convert the
-;;; body in the modified environment. We make Cont start a block now,
+;;; Make a :ENTRY cleanup and emit an ENTRY node, then convert the
+;;; body in the modified environment. We make CONT start a block now,
 ;;; since if it was done later, the block would be in the wrong
 ;;; environment.
 (def-ir1-translator block ((name &rest forms) start cont)
       (ir1-convert-progn-body dummy cont forms))))
 
 
-;;; We make Cont start a block just so that it will have a block
+;;; We make CONT start a block just so that it will have a block
 ;;; assigned. People assume that when they pass a continuation into
-;;; IR1-Convert as Cont, it will have a block when it is done.
+;;; IR1-CONVERT as CONT, it will have a block when it is done.
 (def-ir1-translator return-from ((name &optional value)
                                 start cont)
   #!+sb-doc
 ;;; lambda-list and comparing it with the new one.
 (def-ir1-translator %defmacro ((qname qdef lambda-list doc) start cont
                               :kind :function)
-  (let (;; QNAME is typically a quoted name. I think the idea is to let
-       ;; %DEFMACRO work as an ordinary function when interpreting. Whatever
-       ;; the reason it's there, we don't want it any more. -- WHN 19990603
+  (let (;; QNAME is typically a quoted name. I think the idea is to
+       ;; let %DEFMACRO work as an ordinary function when
+       ;; interpreting. Whatever the reason the quote is there, we
+       ;; don't want it any more. -- WHN 19990603
        (name (eval qname))
-       ;; QDEF should be a sharp-quoted definition. We don't want to make a
-       ;; function of it just yet, so we just drop the sharp-quote.
+       ;; QDEF should be a sharp-quoted definition. We don't want to
+       ;; make a function of it just yet, so we just drop the
+       ;; sharp-quote.
        (def (progn
               (aver (eq 'function (first qdef)))
               (aver (proper-list-of-length-p qdef 2))
 
 ;;; Convert FUN as a lambda in the null environment, but use the
 ;;; current compilation policy. Note that FUN may be a
-;;; LAMBDA-WITH-ENVIRONMENT, so we may have to augment the environment
-;;; to reflect the state at the definition site.
+;;; LAMBDA-WITH-LEXENV, so we may have to augment the environment to
+;;; reflect the state at the definition site.
 (defun ir1-convert-inline-lambda (fun &optional name)
   (destructuring-bind (decls macros symbol-macros &rest body)
-                     (if (eq (car fun) 'lambda-with-environment)
+                     (if (eq (car fun) 'lambda-with-lexenv)
                          (cdr fun)
                          `(() () () . ,(cdr fun)))
     (let ((*lexenv* (make-lexenv
                     :policy (lexenv-policy *lexenv*))))
       (ir1-convert-lambda `(lambda ,@body) name))))
 
-;;; Return a lambda that has been "closed" with respect to ENV,
-;;; returning a LAMBDA-WITH-ENVIRONMENT if there are interesting
-;;; macros or declarations. If there is something too complex (like a
-;;; lexical variable) in the environment, then we return NIL.
-(defun inline-syntactic-closure-lambda (lambda &optional (env *lexenv*))
-  (let ((variables (lexenv-variables env))
-       (functions (lexenv-functions env))
-       (decls ())
-       (symmacs ())
-       (macros ()))
-    (cond ((or (lexenv-blocks env) (lexenv-tags env)) nil)
-         ((and (null variables) (null functions))
-          lambda)
-         ((dolist (x variables nil)
-            (let ((name (car x))
-                  (what (cdr x)))
-              (when (eq x (assoc name variables :test #'eq))
-                (typecase what
-                  (cons
-                   (aver (eq (car what) 'macro))
-                   (push x symmacs))
-                  (global-var
-                   (aver (eq (global-var-kind what) :special))
-                   (push `(special ,name) decls))
-                  (t (return t))))))
-          nil)
-         ((dolist (x functions nil)
-            (let ((name (car x))
-                  (what (cdr x)))
-              (when (eq x (assoc name functions :test #'equal))
-                (typecase what
-                  (cons
-                   (push (cons name
-                               (function-lambda-expression (cdr what)))
-                         macros))
-                  (global-var
-                   (when (defined-function-p what)
-                     (push `(,(car (rassoc (defined-function-inlinep what)
-                                           *inlinep-translations*))
-                             ,name)
-                           decls)))
-                  (t (return t))))))
-          nil)
-         (t
-          `(lambda-with-environment ,decls
-                                    ,macros
-                                    ,symmacs
-                                    . ,(rest lambda))))))
-
 ;;; Get a DEFINED-FUNCTION object for a function we are about to
 ;;; define. If the function has been forward referenced, then
 ;;; substitute for the previous references.
 ;;; types if appropriate. This assertion is suppressed by the
 ;;; EXPLICIT-CHECK attribute, which is specified on functions that
 ;;; check their argument types as a consequence of type dispatching.
-;;; This avoids redundant checks such as NUMBERP on the args to +,
-;;; etc.
+;;; This avoids redundant checks such as NUMBERP on the args to +, etc.
 (defun assert-new-definition (var fun)
   (let ((type (leaf-type var))
        (for-real (eq (leaf-where-from var) :declared))
        (when expansion (setf (defined-function-functional var) fun)))
       fun)))
 
-;;; Convert the definition and install it in the global environment
-;;; with a LABELS-like effect. If the lexical environment is not null,
-;;; then we only install the definition during the processing of this
-;;; DEFUN, ensuring that the function cannot be called outside of the
-;;; correct environment. If the function is globally NOTINLINE, then
-;;; that inhibits even local substitution. Also, emit top-level code
-;;; to install the definition.
+;;; the even-at-compile-time part of DEFUN
 ;;;
-;;; This is one of the major places where the semantics of block
-;;; compilation is handled. Substitution for global names is totally
-;;; inhibited if *BLOCK-COMPILE* is NIL. And if *BLOCK-COMPILE* is
-;;; true and entry points are specified, then we don't install global
-;;; definitions for non-entry functions (effectively turning them into
-;;; local lexical functions.)
-(def-ir1-translator %defun ((name def doc source) start cont
-                           :kind :function)
-  (declare (ignore source))
-  (let* ((name (eval name))
-        (lambda (second def))
-        (*current-path* (revert-source-path 'defun))
-        (expansion (unless (eq (info :function :inlinep name) :notinline)
-                     (inline-syntactic-closure-lambda lambda))))
-    ;; If not in a simple environment or NOTINLINE, then discard any
-    ;; forward references to this function.
-    (unless expansion (remhash name *free-functions*))
-
-    (let* ((var (get-defined-function name))
-          (save-expansion (and (member (defined-function-inlinep var)
-                                       '(:inline :maybe-inline))
-                               expansion)))
-      (setf (defined-function-inline-expansion var) expansion)
-      (setf (info :function :inline-expansion name) save-expansion)
-      ;; If there is a type from a previous definition, blast it,
-      ;; since it is obsolete.
-      (when (eq (leaf-where-from var) :defined)
-       (setf (leaf-type var) (specifier-type 'function)))
-
-      (let ((fun (ir1-convert-lambda-for-defun lambda
-                                              var
-                                              expansion
-                                              #'ir1-convert-lambda)))
-       (ir1-convert
-        start cont
-        (if (and *block-compile* *entry-points*
-                 (not (member name *entry-points* :test #'equal)))
-            `',name
-            `(%%defun ',name ,fun ,doc
-                      ,@(when save-expansion `(',save-expansion)))))
-
-       (when sb!xc:*compile-print*
-         (compiler-mumble "~&; converted ~S~%" name))))))
+;;; The INLINE-EXPANSION is a LAMBDA-WITH-LEXENV, or NIL if there is
+;;; no inline expansion.
+(defun %compiler-defun (name lambda-with-lexenv)
+
+  (let ((defined-function nil)) ; will be set below if we're in the compiler
+    
+    ;; when in the compiler
+    (when (boundp '*lexenv*) 
+      (when sb!xc:*compile-print*
+       (compiler-mumble "~&; recognizing DEFUN ~S~%" name))
+      (remhash name *free-functions*)
+      (setf defined-function (get-defined-function name)))
+
+    (become-defined-function-name name)
+
+    (cond (lambda-with-lexenv
+          (setf (info :function :inline-expansion name) lambda-with-lexenv)
+          (when defined-function 
+            (setf (defined-function-inline-expansion defined-function)
+                  lambda-with-lexenv)))
+         (t
+          (clear-info :function :inline-expansion name)))
+
+    ;; old CMU CL comment:
+    ;;   If there is a type from a previous definition, blast it,
+    ;;   since it is obsolete.
+    (when (and defined-function
+              (eq (leaf-where-from defined-function) :defined))
+      (setf (leaf-type defined-function)
+           ;; FIXME: If this is a block compilation thing, shouldn't
+           ;; we be setting the type to the full derived type for the
+           ;; definition, instead of this most general function type?
+           (specifier-type 'function))))
+
+  (values))
+\f
+;;;; hacking function names
+
+;;; This is like LAMBDA, except the result is tweaked so that
+;;; %FUNCTION-NAME or BYTE-FUNCTION-NAME can extract a name. (Also
+;;; possibly the name could also be used at compile time to emit
+;;; more-informative name-based compiler diagnostic messages as well.)
+(defmacro-mundanely named-lambda (name args &body body)
+
+  ;; FIXME: For now, in this stub version, we just discard the name. A
+  ;; non-stub version might use either macro-level LOAD-TIME-VALUE
+  ;; hackery or customized IR1-transform level magic to actually put
+  ;; the name in place.
+  (aver (legal-function-name-p name))
+  `(lambda ,args ,@body))