;;; -*- Mode:Lisp; Readtable:ZL; Package:USER; Base:8; Patch-File:T -*-
;;; Private patches made by keith
;;; Written 29-Oct-88 11:27:44 by keith (Keith Corbett) at site Gigamos Cambridge
;;; while running on Breaking Glass from band 3
;;; with Experimental ZWEI 126.27, Experimental ZMail 74.13, Experimental Local-File 76.0, Experimental File-Server 25.0, Experimental Lambda-Diag 18.0, Experimental Unix-Interface 15.0, Experimental Tape 26.4, Experimental System 128.0, Microcode 1762, SDU Boot Tape 3.14, SDU ROM 103, 10/27.



; From modified file DJ: L.SYS; QCP1.LISP#743 at 29-Oct-88 11:27:54
#8R COMPILER#: 
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "COMPILER")))
  (PATCH-SOURCE-FILE "SYS: SYS; QCP1  "


(DEFUN P1 (FORM &OPTIONAL DONT-OPTIMIZE &AUX TEM)
  (unless (eq dont-optimize 'dont-rewrite)
    (setq form (compiler-optimize form dont-optimize)))
  (SETQ FORM (COND ((ATOM FORM)
		    (COND ((SELF-EVALUATING-P FORM)
			   `',FORM)
			  ((SETQ TEM (cl:find FORM *VARS* :key #'var-name))
			   (AND (EQ (VAR-KIND TEM) 'FEF-ARG-FREE)
				(ZEROP (VAR-USE-COUNT TEM))
				(PUSH (VAR-NAME TEM) *FREEVARS*))
			   (INCF (VAR-USE-COUNT TEM))
			   (VAR-LAP-ADDRESS TEM))
			  ((TRY-REF-SELF FORM))
			  ((and (symbolp form)		;smh 22aug88
				(setq tem (getdecl form 'compiler:constant-for-compilation))
				(consp tem)		;We expect a list of the value
				;;Type-check constant-value:  |||Keith 10oct88
				(or (numberp (setq tem (car tem)))	;EQL-equivalent objects; smh 13sep88
				    (symbolp tem)
				    (characterp tem)))
			   ;;Got valid constant value:
			   (print`(quote ,tem)))
			  ((integrable-constant? form)
			   `(QUOTE ,(eval form)))
			  ((SPECIALP FORM)
			   (MAKESPECIAL FORM) FORM)
			  ((TRY-REF-LEXICAL-VAR FORM))
			  ((and (symbolp form)
				(eq *target-computer* 'k)
				;; @#$@#$ This should be NC::REGISTER or COMPILER::REGISTER
				(get form :register))
			   form)
			  (T (MAKESPECIAL FORM) FORM)))
		   ((EQ (CAR FORM) 'QUOTE) FORM)
		   ;; Certain constructs must be checked for here
		   ;; so we can call P1 recursively without setting *TLEVEL* to NIL.
		   ((NOT (ATOM (CAR FORM)))
		    ;; Expand any lambda macros -- just returns old function if none found
		    (LET ((FCTN (CAR FORM)))
		      (OR (SYMBOLP (CAR FCTN))
			  (WARN 'BAD-FUNCTION-CALLED :IMPOSSIBLE
				"There appears to be a call to a function whose CAR is ~S."
				(CAR FCTN)))
		      (IF (MEMQ (CAR FCTN) '(LAMBDA NAMED-LAMBDA))
			  (P1LAMBDA FCTN (CDR FORM))
			;; Old Maclisp evaluated functions.
			(WARN 'EXPRESSION-AS-FUNCTION :VERY-OBSOLETE
			      "The expression ~S is used as a function; use ~S."
			      (CAR FORM) 'FUNCALL)
			(P1 `(FUNCALL . ,FORM)))))
		   ((NOT (SYMBOLP (CAR FORM)))
		    (WARN 'BAD-FUNCTION-CALLED :IMPOSSIBLE
			  "~S is used as a function to be called." (CAR FORM))
		    (P1 `(PROGN . ,(CDR FORM))))
		   ((SETQ TEM (ASSQ (CAR FORM) *LOCAL-FUNCTIONS*))
		    (INCF (VAR-USE-COUNT (CADR TEM)))
		    `(funcall ,(try-ref-lexical-home (cadr tem) `(function ,(car form)))
			      . ,(loop for x in (cdr form)
				    collect (p1 x 1))))
		   ((MEMQ (CAR FORM) '(PROG PROG*))
		    (P1PROG FORM))
		   ((MEMQ (CAR FORM) '(LET LET*))
		    (P1LET FORM))
		   ((EQ (CAR FORM) 'BLOCK)
		    (P1BLOCK FORM))
		   ((EQ (CAR FORM) 'TAGBODY)
		    (P1TAGBODY FORM))
		   ((EQ (CAR FORM) '%POP)	;P2 specially checks for this
		    FORM)
		   (T
		    (if *tlevel* (clear-tlevel))
		    ;; Check for functions with special P1 handlers.
		    (setq form (IF (SETQ TEM (or (and (neq *target-computer* 'lambda-interface)
						      (get (car form) 'p1cross))
						 (GET (CAR FORM) 'P1)))
				   (FUNCALL TEM FORM)
				   (P1ARGC FORM (GETARGDESC (CAR FORM)))))
		    (if (setq tem (get (car form) 'qintcmp))
			(let ((len (length (cdr form))))
			  (cond ((= len tem)
				 form)
				;; Have alread barfed about wrong-number-of-args
				;;  Just silently append nils or truncate
				((< len tem)
				 (append form (make-list (- tem len)
							 :initial-element ''())))
				(t
				 (subseq form 0 (1+ tem)))))
		      form)
;		    (IF (NOT (AND ALLOW-VARIABLES-IN-FUNCTION-POSITION-SWITCH
;		 	  (find (CAR FORM) *VARS* :key #'var-name)
;				  (NULL (FUNCTION-P (CAR FORM)))))
;			(P1ARGC FORM (GETARGDESC (CAR FORM)))
;		      (WARN 'EXPRESSION-AS-FUNCTION :VERY-OBSOLETE
;			    "The variable ~S is used in function position; use ~S."
;			    (CAR FORM) 'FUNCALL)
;		      (P1 `(FUNCALL . ,FORM)))
		    )))
  (IF (AND (ATOM FORM) (SELF-EVALUATING-P FORM))
      ;; a p1 handler may return :foo, for example
      `',FORM
      FORM))

))

; From modified file DJ: L.SYS; QCFILE.LISP#384 at 29-Oct-88 11:28:59
#8R COMPILER#: 
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "COMPILER")))
  (PATCH-SOURCE-FILE "SYS: SYS; QCFILE  "


(DEFUN COMPILE-DRIVER (FORM PROCESS-FN OVERRIDE-FN &OPTIONAL COMPILE-TIME-TOO (TOP-LEVEL-P T)
		       &AUX FN (OFORM FORM))
  ;; The following loop is essentially MACROEXPAND,
  ;; but for each expansion, we create an appropriate warn-on-errors message
  ;; containing the name of the macro about to be (perhaps) expanded this time.
  (DO ((NFORM))
      (())
    (IF (AND OVERRIDE-FN
	     (FUNCALL OVERRIDE-FN FORM))
	(RETURN-FROM COMPILE-DRIVER NIL))
    (IF (ATOM FORM) (RETURN NIL))
    ;;;Style checkers now being invoked on top level forms...! -Keith 10/88
    ;;;
    (maybe-invoke-style-checker form)
;;;
;    ;; Don't expand LOCALLY into PROGN here!
;    ;; This way, we protect DECLAREs inside the LOCALLY
;    ;; from being treated as top-level DECLARE, which would be erroneous.
;    ;; The LOCALLY form will just be executed as a random form.
;    (IF (EQ (CAR FORM) 'LOCALLY)
;	 (RETURN))
    ;;;$$$ Also need to run optimizers on top level forms.  Especially, now
    ;;; that DEFCONSTANTs only gets folded-in if their values are considered likely EQL-able
    ;;; by comparison to themselves... numbers, characters, etc.
    ;;;
    ;;; So, the following prevents losing advantage of a constant, by allowing optimization on
    ;;; things like (DEFCONSTANT FOO (BYTE 5. 0.)). <29-Oct-88 keith>
    ;;;
;    (setq nform
;	  (warn-on-errors ('form-optimization-error
;			   "Error while compiling (~S ~@[~S ~]...)~
;                            (optimizing) at top level"
;			   (car form) (cadr form))
;	    (compiler-optimize-external form)))
    (SETQ NFORM
	  (WARN-ON-ERRORS ('MACRO-EXPANSION-ERROR
			   "Error while compiling (~S ~@[~S ~]...)~
                            (expanding macro) at top level"
			   (CAR FORM) (cadr form))
	    (MACROEXPAND-1 FORM)))
    (IF (EQ FORM NFORM) (RETURN)
      (SETQ FORM NFORM)))
  ;; If this was a top-level macro, supply a good guess
  ;; for the function-parent for any DEFUNs inside the expansion.
  (LET ((LOCAL-DECLARATIONS LOCAL-DECLARATIONS))
    (COND ((ATOM FORM))
	  ((AND (NEQ FORM OFORM) (SYMBOLP (CADR OFORM)))
	   (PUSH `(FUNCTION-PARENT ,(CADR OFORM)) LOCAL-DECLARATIONS))
	  ((EQ (CAR OFORM) 'DEFSTRUCT)
	   (PUSH `(FUNCTION-PARENT ,(IF (SYMBOLP (CADR OFORM)) (CADR OFORM) (CAADR OFORM)))
		 LOCAL-DECLARATIONS)))
    (AND (CONSP FORM)
	 (NEQ (CAR FORM) 'EVAL-WHEN)
	 COMPILE-TIME-TOO
	 (FUNCALL PROCESS-FN FORM 'DECLARE))
    (COND ((ATOM FORM)
	   (FUNCALL PROCESS-FN FORM 'RANDOM))
	  ((EQ (CAR FORM) 'EVAL-WHEN)
	   (OR (AND (CL:LISTP (CADR FORM))
		    (LOOP FOR TIME IN (CADR FORM)
			  ALWAYS (MEMQ TIME '(EVAL LOAD COMPILE))))
	       (FERROR "~S invalid ~S times;~%  must be a list of ~S, ~S, and//or ~S."
			   (CADR FORM) 'EVAL-WHEN 'EVAL 'LOAD 'COMPILE))
	   (LET* ((COMPILE (MEMQ 'COMPILE (CADR FORM)))
		  (LOAD (MEMQ 'LOAD (CADR FORM)))
		  (EVAL (MEMQ 'EVAL (CADR FORM)))
		  (EVAL-NOW (OR COMPILE (AND COMPILE-TIME-TOO EVAL))))
	     (DOLIST (FORM1 (CDDR FORM))
	       (IF LOAD
		   (IF EVAL-NOW
		       (COMPILE-DRIVER FORM1 PROCESS-FN OVERRIDE-FN T NIL)
		     (COMPILE-DRIVER FORM1 PROCESS-FN OVERRIDE-FN NIL NIL))
		 (IF EVAL-NOW
		     (FUNCALL PROCESS-FN FORM1 'DECLARE))))))
	  ((EQ (SETQ FN (CAR FORM)) 'DEFF)
	   (COMPILATION-DEFINE (CADR FORM))
	   (FUNCALL PROCESS-FN FORM 'RANDOM))
	  ((EQ FN 'DEF)
	   (COMPILATION-DEFINE (CADR FORM))
	   (MAPC (LAMBDA (FORM)
		   (COMPILE-DRIVER FORM PROCESS-FN OVERRIDE-FN COMPILE-TIME-TOO NIL))
		 (CDDR FORM)))
	  ((EQ FN 'WITH-SELF-ACCESSIBLE)
	   (MAPC (LAMBDA (FORM)
		   (COMPILE-DRIVER FORM PROCESS-FN OVERRIDE-FN COMPILE-TIME-TOO NIL))
		 (CDDR FORM)))
	  ((EQ FN 'PROGN)
	   (MAPC (LAMBDA (FORM)
		   (COMPILE-DRIVER FORM PROCESS-FN OVERRIDE-FN COMPILE-TIME-TOO T))
		 (CDR FORM)))
	  ((MEMQ FN '(MACRO DEFSUBST))
	   (FUNCALL PROCESS-FN FORM 'MACRO))
	  ((AND TOP-LEVEL-P
		(MEMQ FN '(SPECIAL UNSPECIAL MAKE-PACKAGE IN-PACKAGE SHADOW SHADOWING-IMPORT
			   EXPORT UNEXPORT USE-PACKAGE UNUSE-PACKAGE IMPORT DEFF-MACRO
			   REQUIRE)))
	   (FUNCALL PROCESS-FN FORM 'SPECIAL))
	  ((EQ FN 'DECLARE)
	   (COMPILE-DECLARE (CDR FORM) PROCESS-FN))
	  ((EQ FN 'PROCLAIM)
	   (COMPILE-PROCLAIM (CDR FORM) PROCESS-FN))
	  ((EQ FN 'COMMENT) NIL)
	  ((EQ FN 'PATCH-SOURCE-FILE)
	   (COMPILE-DRIVER `(EVAL-WHEN (LOAD EVAL)
			      (SETQ SI:PATCH-SOURCE-FILE-NAMESTRING ,(CADR FORM)))
			   PROCESS-FN OVERRIDE-FN COMPILE-TIME-TOO T)
	   (MAPC (LAMBDA (FORM)
		   (COMPILE-DRIVER FORM PROCESS-FN OVERRIDE-FN COMPILE-TIME-TOO T))
		 (CDDR FORM))
	   (COMPILE-DRIVER `(EVAL-WHEN (LOAD EVAL)
			      (SETQ SI:PATCH-SOURCE-FILE-NAMESTRING NIL))
			   PROCESS-FN OVERRIDE-FN COMPILE-TIME-TOO T))
	  ((EQ FN 'COMPILER-LET)
	   (PROGW (CADR FORM)
	     (COMPILE-DRIVER `(PROGN . ,(CDDR FORM))
			     PROCESS-FN OVERRIDE-FN COMPILE-TIME-TOO T)))
	  ((EQ FN 'DEFUN)
	   (LET (TEM)
	     (WARN-ON-ERRORS ('MALFORMED-DEFUN "Malformed DEFUN")
	       (SETQ TEM (DEFUN-COMPATIBILITY (CDR FORM))))
	     (COND ((EQ (CDR TEM) (CDR FORM))
		    (IF (NULL (CDDR TEM))
			(WARN 'MALFORMED-DEFUN :IMPOSSIBLE "Malformed defun ~S" FORM)
		      (FUNCALL PROCESS-FN FORM 'DEFUN)))
		   (T (COMPILE-DRIVER TEM PROCESS-FN OVERRIDE-FN COMPILE-TIME-TOO NIL)))))
	  (T (FUNCALL PROCESS-FN FORM 'RANDOM)))))

))

; From modified file DJ: L.SYS; QCOPT.LISP#190 at 29-Oct-88 11:30:35
#8R COMPILER#: 
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "COMPILER")))
  (PATCH-SOURCE-FILE "SYS: SYS; QCOPT  "


(defun fold-constants (form)
  "Replace an expression by its value...if it evaluates ok."
  (condition-case (val)
      (multiple-value-list (eval form))
    (error
     (warn 'constant-folding :error
	   "~Error during constant-folding on expression ~S:~%  ~A~" form val)
     form)
    (:no-error
     (if (= (length val) 1)
	 `',(first val)
       `(values . ,(mapcar (lambda (elt) `',elt) val))))))	; Get multiple-values

;;; This really can't do much in the Lambda compiler -- or can it ?

))

; From modified file DJ: L.SYS; QCOPT.LISP#190 at 29-Oct-88 11:31:04
#8R COMPILER#: 
(COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "COMPILER")))
  (PATCH-SOURCE-FILE "SYS: SYS; QCOPT  "

;;;DEFCONSTANT  <$$$ 29-Oct-88 keith>
;;;
;;;In (DEFCONSTANT X (FOO)), optimize (FOO) if possible and sensible.
;;;Sensible means it must be a likely function call.  Prevents common
;;;missed-optimization on things like (DEFCONSTANT X (BYTE 1. 0.))

;Tried calling optimizer on value.  But we don't know if it was expanded this way into code...?

;(defoptimizer optimize-defconst-value defconstant (form &aux (val (third form)))
;  (let ((check-val (and val (consp val) (symbolp (car val)) (compiler-optimize val))))
;    (and check-val (setf (third form) check-val))
;    form))

;;;This should win -- gets same value that is used to fold into code.
;;;Unfortunately, after macroexpansion of DEFCONST, DEFCONSTANT-1 is not getting optimized. @@@bug.

(defoptimizer optimize-constant-for-compilation defconst (form &aux list-of-value)
  (prog1 form
	 (typecase (setq list-of-value (getdecl (car form) 'constant-for-compilation))
	   (null)
	   (cons (setf (third form) (first list-of-value))))))

))
