aboutsummaryrefslogtreecommitdiff
path: root/src/interp/comp.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp/comp.lisp')
-rw-r--r--src/interp/comp.lisp409
1 files changed, 409 insertions, 0 deletions
diff --git a/src/interp/comp.lisp b/src/interp/comp.lisp
new file mode 100644
index 00000000..f46dc474
--- /dev/null
+++ b/src/interp/comp.lisp
@@ -0,0 +1,409 @@
+;; Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+;; All rights reserved.
+;;
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions are
+;; met:
+;;
+;; - Redistributions of source code must retain the above copyright
+;; notice, this list of conditions and the following disclaimer.
+;;
+;; - Redistributions in binary form must reproduce the above copyright
+;; notice, this list of conditions and the following disclaimer in
+;; the documentation and/or other materials provided with the
+;; distribution.
+;;
+;; - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+;; names of its contributors may be used to endorse or promote products
+;; derived from this software without specific prior written permission.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+;; IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+;; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+;; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+;; OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+;; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+; NAME: Compiler Utilities Package
+
+; PURPOSE: Comp is a modified version of Compile which is a preprocessor for
+; calls to Lisp Compile. It searches for variable assignments that use
+; (SPADLET a b). It allows you to create local variables without
+; declaring them local by moving them into a PROG variable list.
+; This is not an ordinary SPADLET. It looks and is used like a SETQ.
+; This preprocessor then collects the uses and creates the PROG.
+;
+; SPADLET is defined in Macro.Lisp.
+;
+; Comp recognizes as new lambda types the forms ILAM, SPADSLAM, SLAM,
+; and entries on $clamList. These cache results. ("Saving LAMbda".)
+; If the function is called with EQUAL arguments, returns the previous
+; result computed.
+;
+; The package also causes traced things which are recompiled to
+; become untraced.
+
+(in-package "BOOT")
+
+(export '(Comp FluidVars LocVars OptionList SLAM SPADSLAM ILAM FLUID))
+
+;;; Common Block section
+
+(defparameter FluidVars nil)
+(defparameter LocVars nil)
+; (defparameter OptionList nil) defined in nlib.lisp
+(defparameter SpecialVars nil)
+
+(defun |compAndDefine| (L)
+ (let ((*comp370-apply* (function print-and-eval-defun)))
+ (declare (special *comp370-apply*))
+ (COMP L)))
+
+(defun COMP (L) (MAPCAR #'COMP-2 (MAPCAN #'COMP-1 L)))
+
+;;(defun |compQuietly| (L)
+;; (let (U CUROUTSTREAM)
+;; (declare (special CUROUTSTREAM))
+;; (ADDOPTIONS 'LISTING NULLOUTSTREAM)
+;; (SETQ CUROUTSTREAM NULLOUTSTREAM)
+;; (setq U (COMP L))
+;; (setq OPTIONLIST (CDDR OPTIONLIST))
+;; U))
+
+(defun |compQuietly| (fn)
+ (let ((*comp370-apply*
+ (if |$InteractiveMode|
+ (if |$compileDontDefineFunctions| #'compile-defun #'eval-defun)
+ #'print-defun))
+ ;; following creates a null outputstream if $InteractiveMode
+ (*standard-output*
+ (if |$InteractiveMode| (make-broadcast-stream)
+ *standard-output*)))
+ (COMP fn)))
+
+#-:CCL
+(defun |compileFileQuietly| (fn)
+ (let (
+ ;; following creates a null outputstream if $InteractiveMode
+ (*standard-output*
+ (if |$InteractiveMode| (make-broadcast-stream)
+ *standard-output*)))
+ (COMPILE-FILE fn)))
+
+#+:CCL
+(defun |compileFileQuietly| (fn)
+ (let (
+ ;; following creates a null outputstream if $InteractiveMode
+ (*standard-output*
+ (if |$InteractiveMode| (make-broadcast-stream) *standard-output*)))
+ ;; The output-library is not opened before use unless set explicitly
+ (if (null output-library)
+ (|openOutputLibrary|
+ (setq |$outputLibraryName|
+ (if (null |$outputLibraryName|)
+ (make-pathname :directory (get-current-directory)
+ :name "user.lib")
+ (if (filep |$outputLibraryName|) (truename |$outputLibraryName|)
+ |$outputLibraryName|)))))
+ (compile-lib-file fn)))
+
+;; The following are used mainly in setvars.boot
+(defun notEqualLibs (u v)
+ (if (string= u (library-name v)) (seq (close-library v) t) nil))
+
+(defun |dropInputLibrary| (lib)
+ ;; Close any existing copies of this library on the input path
+ (setq input-libraries
+ (delete lib input-libraries :test #'notEqualLibs )))
+
+(defun |openOutputLibrary| (lib)
+ (|dropInputLibrary| lib)
+ (setq output-library (open-library lib 't))
+ (setq input-libraries (cons output-library input-libraries)) )
+
+(defun |addInputLibrary| (lib)
+ (|dropInputLibrary| lib)
+ (setq input-libraries (cons (open-library lib) input-libraries)) )
+
+
+
+;;(defun |compileQuietly| (L) (PROG (U CUROUTSTREAM)
+;; ;; calls lisp system COMPILE or DEFINE
+;; (ADDOPTIONS 'QUIET 'T)
+;; (ADDOPTIONS 'LISTING NULLOUTSTREAM)
+;; (SETQ CUROUTSTREAM NULLOUTSTREAM)
+;; (SETQ U (COND
+;; (|$compileDontDefineFunctions| (COMPILE L))
+;; ('T (DEFINE L))))
+;; (SETQ OPTIONLIST (CDDR OPTIONLIST))
+;; (RETURN U) ))
+
+(defun |compileQuietly| (fn)
+ (let ((*comp370-apply*
+ (if |$InteractiveMode|
+ (if |$compileDontDefineFunctions| #'compile-defun #'eval-defun)
+ #'print-defun))
+ ;; following creates a null outputstream if $InteractiveMode
+ (*standard-output*
+ (if |$InteractiveMode| (make-broadcast-stream)
+ *standard-output*)))
+ (COMP370 fn)))
+
+(defun COMP-1 (X)
+ (let* ((FNAME (car X))
+ ($FUNNAME FNAME)
+ ($FUNNAME_TAIL (LIST FNAME))
+ (LAMEX (second X))
+ ($closedfns nil))
+ (declare (special $FUNNAME $FUNNAME_TAIL $CLOSEDFNS))
+ (setq LAMEX (COMP-TRAN LAMEX))
+ (COMP-NEWNAM LAMEX)
+ (if (fboundp FNAME)
+ (format t "~&~%;;; *** ~S REDEFINED~%" FNAME))
+ (CONS (LIST FNAME LAMEX) $CLOSEDFNS)))
+
+(defun Comp-2 (args &aux name type argl bodyl junk)
+ (dsetq (NAME (TYPE ARGL . BODYL) . JUNK) args)
+ (cond (JUNK (MOAN (format nil "******pren error in (~S (~S ...) ...)" NAME TYPE)))
+ ((eq TYPE 'SLAM) (COMP-SLAM NAME ARGL BODYL))
+ ((LASSQ NAME |$clamList|) (|compClam| NAME ARGL BODYL |$clamList|))
+ ((eq TYPE 'SPADSLAM) (COMP-SPADSLAM NAME ARGL BODYL))
+ ((eq TYPE 'ILAM) (COMP-ILAM NAME ARGL BODYL))
+ ((setq BODYL (LIST NAME (CONS TYPE (CONS ARGL BODYL))))
+ (if |$PrettyPrint| (pprint bodyl))
+ (if (null $COMPILE) (SAY "No Compilation")
+ (COMP370 (LIST BODYL)))
+ NAME)))
+
+;; used to be called POSN - but that interfered with a CCL function
+(DEFUN POSN1 (X L) (position x l :test #'equal))
+
+(DEFUN COMP-ILAM (NAME ARGL BODYL)
+ (let* ((FARGL (NLIST (LENGTH ARGL) '(GENSYM)))
+ (BODYLP (SUBLISLIS FARGL ARGL BODYL)))
+ (MAKEPROP NAME 'ILAM T)
+ (SET NAME (CONS 'LAMBDA (CONS FARGL BODYLP)))
+ NAME))
+
+(DEFUN COMP-SPADSLAM (NAME ARGL BODYL)
+ (let* ((AL (INTERNL NAME ";AL"))
+ (AUXFN (INTERNL NAME ";"))
+ (G1 (GENSYM))
+ (G2 (GENSYM))
+ (U (COND ((NOT ARGL) (LIST NIL NIL (LIST AUXFN)))
+ ((NOT (CDR ARGL))
+ (LIST (LIST G1) (LIST '|devaluate| G1) (LIST AUXFN G1)))
+ ((LIST G1
+ (LIST '|devaluateList| G1)
+ (LIST 'APPLY (LIST 'FUNCTION AUXFN) G1)))))
+ (ARG (first U))
+ (ARGTRAN (second U))
+ (APP (third U))
+ (LAMEX `(lam ,ARG
+ (let (,g2)
+ (cond ,(COND (ARGL `((setq ,g2 (|assoc| ,argtran ,al))
+ (cdr ,g2)))
+ ((LIST AL)))
+ ,(COND (ARGL
+ `(t(setq ,al(|cons5|(cons ,argtran
+ (setq ,g2 ,app))
+ ,al))
+ ,g2))
+ (`(t (setq ,al ,app)))))))))
+ (setandfile AL NIL)
+ (setq U (LIST NAME LAMEX))
+ (if |$PrettyPrint| (PRETTYPRINT U))
+ (COMP370 (LIST U))
+ (setq U (LIST AUXFN (CONS 'LAMBDA (CONS ARGL BODYL))))
+ (COND (|$PrettyPrint| (PRETTYPRINT U)))
+ (COMP370 (LIST U))
+ NAME))
+
+(DEFUN COMP-SLAM (NAME ARGL BODYL)
+ (let* ((AL (INTERNL NAME ";AL"))
+ (AUXFN (INTERNL NAME ";"))
+ (G1 (GENSYM))
+ (G2 (GENSYM))
+ (U (COND ((NOT ARGL) `(nil (,auxfn)))
+ ((NOT (CDR ARGL)) `((,g1)(,auxfn ,g1)))
+ (`(,g1 (applx (function ,auxfn) ,g1)))))
+ (ARG (CAR U))
+ (APP (CADR U))
+ (LAMEX
+ (LIST 'LAM ARG
+ (LIST 'PROG (LIST G2)
+ (LIST 'RETURN
+ (LIST 'COND
+ (COND (ARGL
+ `((setq ,G2 (|assoc| ,G1 ,AL))
+ (CDR ,G2)))
+ ((LIST AL)))
+ (COND (ARGL (LIST ''T `(setq ,G2 ,APP)
+ (LIST 'SETQ AL
+ `(CONS
+ (CONS ,G1 ,G2) ,AL))
+ G2))
+ ((LIST ''T `(setq ,AL ,APP))))))))))
+ (set AL NIL)
+ (setq U (LIST NAME LAMEX))
+ (if |$PrettyPrint| (PRETTYPRINT U))
+ (COMP370 (LIST U))
+ (setq U (LIST AUXFN (CONS 'LAMBDA (CONS ARGL BODYL))))
+ (if |$PrettyPrint| (PRETTYPRINT U))
+ (COMP370 (LIST U))
+ NAME))
+
+(DEFUN COMP-NEWNAM (X)
+ (let (y u)
+ (cond ((ATOM X) NIL)
+ ((ATOM (setq Y (CAR X)))
+ ;; (AND (IDENTP Y) (setq U (GET Y 'NEWNAM)) (RPLACA X U))
+ (AND (NOT (eq Y 'QUOTE)) (COMP-NEWNAM (CDR X)))
+ (WHEN (and (EQ Y 'CLOSEDFN) (boundp '$closedfns))
+ (SETQ U (MAKE-CLOSEDFN-NAME))
+ (PUSH (list U (CADR X)) $closedfns)
+ (rplaca x 'FUNCTION)
+ (rplaca (cdr x) u)))
+ (t (COMP-NEWNAM (CAR X)) (COMP-NEWNAM (CDR X))))))
+
+(defun make-closedfn-name ()
+ (internl $FUNNAME "!" (STRINGIMAGE (LENGTH $CLOSEDFNS))))
+
+(DEFUN COMP-TRAN (X)
+ "SEXPR<FN. BODY> -> SEXPR"
+ (let ((X (COMP-EXPAND X)) FluidVars LocVars SpecialVars)
+ (COMP-TRAN-1 (CDDR X))
+ (setq X (list (first x) (second x)
+ (if (and (null (cdddr x))
+ (or (atom (third x))
+ (eq (car (third x)) 'SEQ)
+ (not (contained 'EXIT (third x)))))
+ (caddr x)
+ (cons 'SEQ (cddr x))))) ;catch naked EXITs
+ (let* ((FluidVars (REMDUP (NREVERSE FLUIDVARS)))
+ (LOCVARS (S- (S- (REMDUP (NREVERSE LOCVARS)) FLUIDVARS)
+ (LISTOFATOMS (CADR X))))
+ (LVARS (append fluidvars LOCVARS)))
+ (let ((fluids (S+ fluidvars SpecialVars)))
+ (setq x
+ (if fluids
+ `(,(first x) ,(second x)
+ (prog ,lvars (declare (special . ,fluids))
+ (return ,(third x))))
+ (list (first x) (second x)
+ (if (or lvars (contained 'RETURN (third x)))
+ `(prog ,lvars (return ,(third x)))
+ (third x)) )))))
+ (let ((fluids (S+ (comp-fluidize (second x)) SpecialVars)))
+ (if fluids
+ `(,(first x) ,(second x) (declare (special . ,fluids)) . ,(cddr x))
+ `(,(first x) ,(second x) . ,(cddr x))))))
+
+; Fluidize: Returns a list of fluid variables in X
+
+(DEFUN COMP-FLUIDIZE (X)
+ (COND ((AND (symbolp X)
+ (NE X '$)
+ (NE X '$$)
+ (char= #\$ (ELT (PNAME X) 0))
+ (NOT (DIGITP (ELT (PNAME X) 1))))
+ x)
+ ((atom x) nil)
+ ((eq (first X) 'FLUID) (second X))
+ ((let ((a (comp-fluidize (first x)))
+ (b (comp-fluidize (rest x))))
+ (if a (cons a b) b)))))
+
+(DEFUN COMP\,FLUIDIZE (X) (COND
+ ((AND (IDENTP X)
+ (NE X '$)
+ (NE X '$$)
+ (char= #\$ (ELT (PNAME X) 0)) (NULL (DIGITP (ELT (PNAME X) 1))))
+ (LIST 'FLUID X))
+ ((ATOM X) X)
+ ((EQ (QCAR X) 'FLUID) X)
+ ('T (PROG (A B)
+ (SETQ A (COMP\,FLUIDIZE (QCAR X)))
+ (SETQ B (COMP\,FLUIDIZE (QCDR X)))
+ (COND ((AND (EQ A (QCAR X)) (EQ B (QCDR X)))
+ (RETURN X))
+ ('T (RETURN (CONS A B)) )) ) )))
+
+; NOTE: It is potentially dangerous to assume every occurrence of element of
+; $COMP-MACROLIST is actually a macro call
+
+(defparameter $COMP-MACROLIST
+ '(COLLECT REPEAT SUCHTHATCLAUSE THETA COLLECTV COLLECTVEC
+ THETA1 SPADREDUCE SPADDO)
+ "???")
+
+(DEFUN COMP-EXPAND (X)
+ (COND ((atom x) x)
+ ((eq (CAR X) 'QUOTE) X)
+ ((memq (CAR X) $COMP-MACROLIST)
+ (comp-expand (macroexpand-1 x)))
+ ((let ((a (comp-expand (car x)))
+ (b (comp-expand (cdr x))))
+ (if (AND (eq A (CAR X)) (eq B (CDR X)))
+ x
+ (CONS A B))))))
+
+(DEFUN COMP-TRAN-1 (X)
+ (let (u)
+ (cond ((ATOM X) NIL)
+ ((eq (setq U (CAR X)) 'QUOTE) NIL)
+ ((AND (eq U 'MAKEPROP) $TRACELETFLAG (RPLAC (CAR X) 'MAKEPROP-SAY) NIL)
+ NIL)
+ ; temporarily make TRACELET cause MAKEPROPs to be reported
+ ((MEMQ U '(DCQ RELET PRELET SPADLET SETQ LET) )
+ (COND ((NOT (eq U 'DCQ))
+ (COND ((OR (AND (eq $NEWSPAD T) (NOT $BOOT))
+ (MEMQ $FUNNAME |$traceletFunctions|))
+ (NCONC X $FUNNAME_TAIL)
+ (RPLACA X 'LETT))
+ ; this devious trick (due to RDJ) is needed since the compile
+ ; looks only at global variables in top-level environment;
+ ; thus SPADLET cannot itself test for such flags (7/83).
+ ($TRACELETFLAG (RPLACA X '/TRACE-LET))
+ ((eq U 'LET) (RPLACA X 'SPADLET)))))
+ (COMP-TRAN-1 (CDDR X))
+ (AND (NOT (MEMQ U '(setq RELET)))
+ (COND ((IDENTP (CADR X)) (PUSHLOCVAR (CADR X)))
+ ((EQCAR (CADR X) 'FLUID)
+ (PUSH (CADADR X) FLUIDVARS)
+ (RPLAC (CADR X) (CADADR X)))
+ ((mapc #'pushlocvar (listofatoms (cadr x))) nil))))
+ ((and (symbolp u) (GET U 'ILAM))
+ (RPLACA X (EVAL U)) (COMP-TRAN-1 X))
+ ((MEMQ U '(PROG LAMBDA))
+ (PROG (NEWBINDINGS RES)
+ (setq NEWBINDINGS NIL)
+ (mapcar #'(lambda (Y)
+ (COND ((NOT (MEMQ Y LOCVARS))
+ (setq LOCVARS (CONS Y LOCVARS))
+ (setq NEWBINDINGS (CONS Y NEWBINDINGS)))))
+ (second x))
+ (setq RES (COMP-TRAN-1 (CDDR X)))
+ (setq locvars (remove-if #'(lambda (y) (memq y newbindings))
+ locvars))
+ (RETURN (CONS U (CONS (CADR X) RES)) )) )
+ ((PROGN (COMP-TRAN-1 U) (COMP-TRAN-1 (CDR X)))))))
+
+(DEFUN PUSHLOCVAR (X)
+ (let (p)
+ (cond ((AND (NE X '$)
+ (char= #\$ (ELT (setq P (PNAME X)) 0))
+ (NOT (char= #\, (ELT P 1)))
+ (NOT (DIGITP (ELT P 1)))) NIL)
+ ((PUSH X LOCVARS)))))
+
+(defmacro PRELET (L) `(spadlet . ,L))
+(defmacro RELET (L) `(spadlet . ,L))
+(defmacro PRESET (L) `(spadlet . ,L))
+(defmacro RESET (L) `(spadlet . ,L))