;;; -*- Mode:Lisp; Readtable:ZL; Package:USER; Base:8; Patch-File:T -*- ;;; Patch file for System version 121.59 ;;; Reason: ;;; Fix problem with *P1VALUE* when compiling LET* that has one form ;;; in its body. ;;; Written 1-May-87 18:13:09 by Rauen at site LMI Cambridge ;;; while running on Debtor in Possession from band 2 ;;; with Experimental System 121.58, Experimental Lambda-Diag 15.0, Experimental ZMail 70.2, Experimental KERMIT 32.0, Experimental Unix-Interface 10.0, Experimental Local-File 72.0, Experimental FILE-Server 21.0, Experimental Tape 13.0, microcode 1730, SDU Boot Tape 3.14, SDU ROM 103, 121.53. ; From file DJ: L.SYS; QCP1.LISP#682 at 1-May-87 18:13:15 #8R COMPILER#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "COMPILER"))) (PATCH-SOURCE-FILE "SYS: SYS; QCP1  " (DEFUN P1LET (FORM &OPTIONAL FOR-AUXVARS) (unless (cl:listp (cadr form)) (warn 'invalid-form :impossible "The second element, ~S, of the ~S special form is not a list" (cadr form) (car form)) (setq form `(,(car form) () . ,(cddr form)))) (LET ((*VARS* *VARS*) OUTER-VARS (FN (CAR FORM)) (*BINDP* NIL) ;%bind not yet used (VLIST (CADR FORM)) (LOCAL-DECLARATIONS LOCAL-DECLARATIONS) (ENTRY-LEXICAL-CLOSURE-COUNT *LEXICAL-CLOSURE-COUNT*)) (IF (EQ FN 'LET-FOR-AUXVARS) (SETQ FN 'LET*)) (dolist (var vlist) (cond ((symbolp var)) ((or (atom var) (not (symbolp (car var)))) (warn 'variable-not-symbol :impossible "~S appears in a list of variables to be bound." (or (car-safe var) var)) (setq vlist (remq var vlist))) ((not (cl:listp (cdr var))) (warn 'invalid-form :impossible "The ~S variable spec ~S is not a proper list" (car form) var) (setq vlist (remq var vlist))) ((cddr var) (warn 'invalid-form :implausible "More than two forms in ~S variable spec ~S" (car form) var) (setq vlist (cl:subst (list (car var) (cdr var)) var vlist))))) (MULTIPLE-VALUE-BIND (BODY THIS-FRAME-DECLARATIONS) (with-list (env *function-environment*) (EXTRACT-DECLARATIONS-RECORD-MACROS (CDDR FORM) NIL NIL ENV)) (PROCESS-SPECIAL-DECLARATIONS THIS-FRAME-DECLARATIONS) (SETQ OUTER-VARS *VARS*) ;; Treat parallel binding as serial if it doesn't matter. (WHEN (OR (NULL (CDR VLIST)) ; ie if only 1 symbol (AND (EQ FN 'LET) (DOLIST (XX VLIST) ;; or if binding each symbol to NIL, a constant, or itself. (OR (ATOM XX) ;(let (x) ...) (CONSTANTP (CADR XX)) ;(let ((x 'foo)) ...) (EQ (CAR XX) (CADR XX)) ;(let ((x x)) ...) (RETURN NIL))))) (SETQ FN 'LET*)) ;; Flush rebinding a var to itself if it isn't special ;; and range of rebinding is rest of function. (IF *TLEVEL* (SETQ VLIST (SUBSET-NOT (LAMBDA (VAR) (AND (CONSP VAR) (EQ (CAR VAR) (CADR VAR)) (EQ (FIND-TYPE (CAR VAR) THIS-FRAME-DECLARATIONS) 'FEF-LOCAL) (EQ (VAR-TYPE (ASSQ (CAR VAR) *VARS*)) 'FEF-LOCAL))) VLIST))) ;; All the local declarations should be in effect for the init forms. (SETQ LOCAL-DECLARATIONS (APPEND THIS-FRAME-DECLARATIONS LOCAL-DECLARATIONS)) ;; &AUX vars should be allowed to inherit special declarations ;; since that is what it looks like when you put a DECLARE inside the body. (IF FOR-AUXVARS (SETQ THIS-FRAME-DECLARATIONS LOCAL-DECLARATIONS)) (SETQ VLIST (P1SBIND VLIST (IF *TLEVEL* 'FEF-ARG-AUX 'FEF-ARG-INTERNAL-AUX) (EQ FN 'LET) NIL THIS-FRAME-DECLARATIONS)) ;; Now convert initial SETQs to variable initializations. ;; We win only for SETQs of variables bound but with no initialization spec'd, ;; which set them to constant values, and only if later vars' inits didn't use them. ;; When we come to anything other than a SETQ we can win for, we stop. ;; For LET*, we can't win for a special variable if anyone has called a function ;; to do initting, since that function might have referred to the special. ;; Even if we don't use tha ADL to init them, ;; we avoid redundant settings to NIL. (DO ((*P1VALUE* 1) ;setq only wants one value TEM HOME) (()) (COND ((EQUAL (CAR BODY) '((SETQ))) (POP BODY)) ((OR (ATOM (CAR BODY)) ;; Don't save the optimized form here because it was optimized ;; with *p1value* set incorrectly. We cannot just fix *p1value* ;; either because we don't yet know how many values (if any) we ;; do want. Of course, we really can't trust the optimizer to do ;; the right thing if *p1value* is bogus, so what are we doing here? ;; - JRM 1-May-87 18:03:05 (let ((tem (COMPILER-OPTIMIZE (car BODY)))) ;(push tem body) (ATOM TEM)) (NOT (EQ (CAR TEM) 'SETQ)) (NOT (MEMQ (CADR TEM) VLIST)) ;we're binding it (NOT (CONSTANTP (CADDR TEM))) ;initializing to constant (AND (SPECIALP (CADR TEM)) (OR TLFUNINIT (NOT *TLEVEL*)) (EQ FN 'LET*)) (NOT (ZEROP (VAR-USE-COUNT (SETQ HOME (ASSQ (CADR TEM) *VARS*)))))) (RETURN NIL)) (T (SETQ BODY (CONS `(SETQ . ,(CDDDR TEM)) (CDR BODY))) (SETF (CAR (MEMQ (CADR TEM) VLIST)) `(,(CADR TEM) ,(P1 (CADDR TEM)))) ;; For a variable bound at function entry, really set up its init. ;; Other vars (FEF-ARG-INTERNAL-AUX) will be initted by code, ;; despite our optimization, but it will be better code. (AND *TLEVEL* (EQ (VAR-KIND HOME) 'FEF-ARG-AUX) (SETF (VAR-INIT HOME) `(FEF-INI-PNTR ,(P1 (CADDR TEM)))))))) ;; Now P1 process what is left of the body. (WHEN (CDR BODY) (if *tlevel* (clear-tlevel))) (SETQ BODY (P1PROGN-1 BODY)) `(,FN ,VLIST ,OUTER-VARS ,*VARS* ,*BINDP* ,ENTRY-LEXICAL-CLOSURE-COUNT ,*LEXICAL-CLOSURE-COUNT* . ,BODY)))) ))