Index: /branches/working-0711/ccl/compiler/nx0.lisp
===================================================================
--- /branches/working-0711/ccl/compiler/nx0.lisp	(revision 8513)
+++ /branches/working-0711/ccl/compiler/nx0.lisp	(revision 8514)
@@ -927,13 +927,10 @@
     (nx1-punt-var v (pop initforms))))
 
-; at the beginning of a binding construct, note which lexical variables are bound to other
-; variables and the number of setqs done so far on the initform.
-; After executing the body, if neither variable has been closed over,
-; the new variable hasn't been setq'ed, and the old guy wasn't setq'ed
-; in the body, the binding can be punted.
-(defun nx1-note-var-bindings (vars initforms &aux alist)
-  (dolist (var vars alist)
-    (let* ((binding (nx1-note-var-binding var (pop initforms))))
-      (if binding (push binding alist)))))
+;;; at the beginning of a binding construct, note which lexical
+;;; variables are bound to other variables and the number of setqs
+;;; done so far on the initform.  After executing the body, if neither
+;;; variable has been closed over, the new variable hasn't been
+;;; setq'ed, and the old guy wasn't setq'ed in the body, the binding
+;;; can be punted.
 
 (defun nx1-note-var-binding (var initform)
@@ -961,4 +958,18 @@
               nil)))))))
                       
+;;; Process entries involving variables bound to other variables at
+;;; the end of a binding construct.  Each entry is of the form
+;;; (source-var setq-count . target-var), where setq-count is the
+;;; assignment count of TARGET-VAR at the time that the binding's
+;;; initform was evaluated (not, in the case of LET, at the time that
+;;; the bindinw was established.).  If the target isn't closed-over
+;;; and SETQed (somewhere), and wasn't setqed in the body (e.g.,
+;;; still has the same assignment-count as it had when the initform
+;;; was executed), then we can "punt" the source (and replace references
+;;; to it with references to the target.)
+;;; It obviously makes no sense to do this if the source is SPECIAL;
+;;; in some cases (LET), we create the source variable and add it to
+;;; this alist before it's known whether or not the source variable
+;;; is SPECIAL. so we have to ignore that case here.
 (defun nx1-check-var-bindings (alist)
   (dolist (pair alist)
@@ -968,6 +979,9 @@
            (target-bits (nx-var-bits target)))
       (unless (or
-               ; var can't be setq'ed or closed; target can't be setq'ed AND closed.
-               (neq (%ilogand vbits (%ilogior (%ilsl $vbitsetq 1) (%ilsl $vbitclosed 1))) 0)
+               ;; var can't be special, setq'ed or closed; target can't be
+               ;; setq'ed AND closed.
+               (neq (%ilogand vbits (%ilogior (%ilsl $vbitsetq 1)
+                                              (%ilsl $vbitclosed 1)
+                                              (%ilsl $vbitspecial 1))) 0)
                (eq (%ilogior (%ilsl $vbitsetq 1) (%ilsl $vbitclosed 1)) 
                    (%ilogand
Index: /branches/working-0711/ccl/compiler/nx1.lisp
===================================================================
--- /branches/working-0711/ccl/compiler/nx1.lisp	(revision 8513)
+++ /branches/working-0711/ccl/compiler/nx1.lisp	(revision 8514)
@@ -1775,35 +1775,39 @@
 
 (defnx1 nx1-let let (pairs &body forms &environment old-env)
-  (let* ((vars nil)
-         (vals nil)
-         (varspecs nil))
+  (collect ((vars)
+            (vals)
+            (varbindings))
     (with-nx-declarations (pending)
       (multiple-value-bind (body decls)
                            (parse-body forms *nx-lexical-environment* nil)
         (nx-process-declarations pending decls)
-        ; Make sure that the initforms are processed in the outer
-        ; environment (in case any declaration handlers side-effected
-        ; the environment.)
+        ;; Make sure that the initforms are processed in the outer
+        ;; environment (in case any declaration handlers side-effected
+        ;; the environment.)
+        
         (let* ((*nx-lexical-environment* old-env))
           (dolist (pair pairs)
-            (push (nx-need-var (nx-pair-name pair)) vars)
-            (push (nx1-typed-var-initform pending (car vars) (nx-pair-initform pair)) vals)))
-        (let* ((*nx-bound-vars* (append vars *nx-bound-vars*))
-               (varbindings (nx1-note-var-bindings
-                             (dolist (sym vars varspecs)
-                               (push (nx-new-var pending sym) varspecs))
-                             (setq vals (nreverse vals))))
-               (form 
-                (make-acode 
-                 (%nx1-operator let)
-                 varspecs
-                 vals
-                 (progn
-                   (nx-effect-other-decls pending *nx-lexical-environment*)
-                   (nx1-env-body body old-env))
+            (let* ((sym (nx-need-var (nx-pair-name pair)))
+                   (var (nx-cons-var sym))
+                   (val (nx1-typed-var-initform pending sym (nx-pair-initform pair)))
+                   (binding (nx1-note-var-binding var val)))
+              (vars var)
+              (vals val)
+              (when binding (varbindings binding)))))
+        (let* ((*nx-bound-vars* *nx-bound-vars*)
+               (varbindings (varbindings)))
+          (dolist (v (vars)) (nx-init-var pending v))
+          (let* ((form 
+                  (make-acode 
+                   (%nx1-operator let)
+                   (vars)
+                   (vals)
+                   (progn
+                     (nx-effect-other-decls pending *nx-lexical-environment*)
+                     (nx1-env-body body old-env))
                  *nx-new-p2decls*)))
           (nx1-check-var-bindings varbindings)
-          (nx1-punt-bindings varspecs vals)
-          form)))))
+          (nx1-punt-bindings (vars) (vals))
+          form))))))
 
 
