source: trunk/abcl/src/org/armedbear/lisp/precompiler.lisp @ 11994

Last change on this file since 11994 was 11994, checked in by vvoutilainen, 12 years ago

Move macroexpand-all and compiler-let to EXT and LISP packages,
respectively.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 41.2 KB
Line 
1;;; precompiler.lisp
2;;;
3;;; Copyright (C) 2003-2008 Peter Graves <peter@armedbear.org>
4;;; $Id: precompiler.lisp 11994 2009-06-06 14:03:16Z vvoutilainen $
5;;;
6;;; This program is free software; you can redistribute it and/or
7;;; modify it under the terms of the GNU General Public License
8;;; as published by the Free Software Foundation; either version 2
9;;; of the License, or (at your option) any later version.
10;;;
11;;; This program is distributed in the hope that it will be useful,
12;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of the GNU General Public License
17;;; along with this program; if not, write to the Free Software
18;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19;;;
20;;; As a special exception, the copyright holders of this library give you
21;;; permission to link this library with independent modules to produce an
22;;; executable, regardless of the license terms of these independent
23;;; modules, and to copy and distribute the resulting executable under
24;;; terms of your choice, provided that you also meet, for each linked
25;;; independent module, the terms and conditions of the license of that
26;;; module.  An independent module is a module which is not derived from
27;;; or based on this library.  If you modify this library, you may extend
28;;; this exception to your version of the library, but you are not
29;;; obligated to do so.  If you do not wish to do so, delete this
30;;; exception statement from your version.
31
32(in-package "SYSTEM")
33
34(export '(*inline-declarations*
35          process-optimization-declarations
36          process-special-declarations
37          inline-p notinline-p inline-expansion expand-inline
38          *defined-functions* *undefined-functions* note-name-defined))
39
40(defvar *inline-declarations* nil)
41
42(declaim (ftype (function (t) t) process-optimization-declarations))
43(defun process-optimization-declarations (forms)
44  (dolist (form forms)
45    (unless (and (consp form) (eq (%car form) 'DECLARE))
46      (return))
47    (dolist (decl (%cdr form))
48      (case (car decl)
49        (OPTIMIZE
50         (dolist (spec (%cdr decl))
51           (let ((val 3)
52                 (quality spec))
53             (when (consp spec)
54               (setf quality (%car spec)
55                     val (cadr spec)))
56             (when (and (fixnump val)
57                        (<= 0 val 3))
58               (case quality
59                 (speed
60                  (setf *speed* val))
61                 (safety
62                  (setf *safety* val))
63                 (debug
64                  (setf *debug* val))
65                 (space
66                  (setf *space* val))
67                 (compilation-speed) ;; Ignored.
68                 (t
69                  (compiler-warn "Ignoring unknown optimization quality ~S in ~S." quality decl)))))))
70        ((INLINE NOTINLINE)
71         (dolist (symbol (%cdr decl))
72           (push (cons symbol (%car decl)) *inline-declarations*)))
73        (:explain
74         (dolist (spec (%cdr decl))
75           (let ((val t)
76                 (quality spec))
77             (when (consp spec)
78               (setf quality (%car spec))
79               (when (= (length spec) 2)
80                 (setf val (%cadr spec))))
81             (if val
82                 (pushnew quality *explain*)
83                 (setf *explain* (remove quality *explain*)))))))))
84  t)
85
86;; Returns list of declared specials.
87(declaim (ftype (function (list) list) process-special-declarations))
88(defun process-special-declarations (forms)
89  (let ((specials nil))
90    (dolist (form forms)
91      (unless (and (consp form) (eq (%car form) 'DECLARE))
92        (return))
93      (let ((decls (%cdr form)))
94        (dolist (decl decls)
95          (when (eq (car decl) 'special)
96            (setq specials (append (cdr decl) specials))))))
97    specials))
98
99(declaim (ftype (function (t) t) inline-p))
100(defun inline-p (name)
101  (declare (optimize speed))
102  (let ((entry (assoc name *inline-declarations*)))
103    (if entry
104        (eq (cdr entry) 'INLINE)
105        (and (symbolp name) (eq (get name '%inline) 'INLINE)))))
106
107(declaim (ftype (function (t) t) notinline-p))
108(defun notinline-p (name)
109  (declare (optimize speed))
110  (let ((entry (assoc name *inline-declarations*)))
111    (if entry
112        (eq (cdr entry) 'NOTINLINE)
113        (and (symbolp name) (eq (get name '%inline) 'NOTINLINE)))))
114
115(defun expand-inline (form expansion)
116;;   (format t "expand-inline form = ~S~%" form)
117;;   (format t "expand-inline expansion = ~S~%" expansion)
118  (let* ((op (car form))
119         (proclaimed-ftype (proclaimed-ftype op))
120         (args (cdr form))
121         (vars (cadr expansion))
122         (varlist ())
123         new-form)
124;;     (format t "op = ~S proclaimed-ftype = ~S~%" op (proclaimed-ftype op))
125    (do ((vars vars (cdr vars))
126         (args args (cdr args)))
127        ((null vars))
128      (push (list (car vars) (car args)) varlist))
129    (setf new-form (list* 'LET (nreverse varlist)
130                          (copy-tree (cddr expansion))))
131    (when proclaimed-ftype
132      (let ((result-type (ftype-result-type proclaimed-ftype)))
133        (when (and result-type
134                   (neq result-type t)
135                   (neq result-type '*))
136          (setf new-form (list 'TRULY-THE result-type new-form)))))
137;;     (format t "expand-inline new form = ~S~%" new-form)
138    new-form))
139
140(define-compiler-macro assoc (&whole form &rest args)
141  (cond ((and (= (length args) 4)
142              (eq (third args) :test)
143              (or (equal (fourth args) '(quote eq))
144                  (equal (fourth args) '(function eq))))
145         `(assq ,(first args) ,(second args)))
146        ((= (length args) 2)
147         `(assql ,(first args) ,(second args)))
148        (t form)))
149
150(define-compiler-macro member (&whole form &rest args)
151  (let ((arg1 (first args))
152        (arg2 (second args)))
153    (case (length args)
154      (2
155       `(memql ,arg1 ,arg2))
156      (4
157       (let ((arg3 (third args))
158             (arg4 (fourth args)))
159         (cond ((and (eq arg3 :test)
160                     (or (equal arg4 '(quote eq))
161                         (equal arg4 '(function eq))))
162                `(memq ,arg1 ,arg2))
163               ((and (eq arg3 :test)
164                     (or (equal arg4 '(quote eql))
165                         (equal arg4 '(function eql))
166                         (equal arg4 '(quote char=))
167                         (equal arg4 '(function char=))))
168                `(memql ,arg1 ,arg2))
169               (t
170                form))))
171      (t
172       form))))
173
174(define-compiler-macro search (&whole form &rest args)
175  (if (= (length args) 2)
176      `(simple-search ,@args)
177      form))
178
179(define-compiler-macro identity (&whole form &rest args)
180  (if (= (length args) 1)
181      `(progn ,(car args))
182      form))
183
184(defun quoted-form-p (form)
185  (and (consp form) (eq (%car form) 'QUOTE) (= (length form) 2)))
186
187(define-compiler-macro eql (&whole form &rest args)
188  (let ((first (car args))
189        (second (cadr args)))
190    (if (or (and (quoted-form-p first) (symbolp (cadr first)))
191            (and (quoted-form-p second) (symbolp (cadr second))))
192        `(eq ,first ,second)
193        form)))
194
195(define-compiler-macro not (&whole form arg)
196  (if (atom arg)
197      form
198      (let ((op (case (car arg)
199                  (>= '<)
200                  (<  '>=)
201                  (<= '>)
202                  (>  '<=)
203                  (t  nil))))
204        (if (and op (= (length arg) 3))
205            (cons op (cdr arg))
206            form))))
207
208(defun predicate-for-type (type)
209  (cdr (assq type '((ARRAY             . arrayp)
210                    (ATOM              . atom)
211                    (BIT-VECTOR        . bit-vector-p)
212                    (CHARACTER         . characterp)
213                    (COMPLEX           . complexp)
214                    (CONS              . consp)
215                    (FIXNUM            . fixnump)
216                    (FLOAT             . floatp)
217                    (FUNCTION          . functionp)
218                    (HASH-TABLE        . hash-table-p)
219                    (INTEGER           . integerp)
220                    (LIST              . listp)
221                    (NULL              . null)
222                    (NUMBER            . numberp)
223                    (NUMBER            . numberp)
224                    (PACKAGE           . packagep)
225                    (RATIONAL          . rationalp)
226                    (REAL              . realp)
227                    (SIMPLE-BIT-VECTOR . simple-bit-vector-p)
228                    (SIMPLE-STRING     . simple-string-p)
229                    (SIMPLE-VECTOR     . simple-vector-p)
230                    (STREAM            . streamp)
231                    (STRING            . stringp)
232                    (SYMBOL            . symbolp)))))
233
234(define-compiler-macro typep (&whole form &rest args)
235  (if (= (length args) 2) ; no environment arg
236      (let* ((object (%car args))
237             (type-specifier (%cadr args))
238             (type (and (consp type-specifier)
239                        (eq (%car type-specifier) 'QUOTE)
240                        (%cadr type-specifier)))
241             (predicate (and type (predicate-for-type type))))
242        (if predicate
243            `(,predicate ,object)
244            `(%typep ,@args)))
245      form))
246
247(define-compiler-macro subtypep (&whole form &rest args)
248  (if (= (length args) 2)
249      `(%subtypep ,@args)
250      form))
251
252(define-compiler-macro funcall (&whole form
253                                &environment env &rest args)
254  (let ((callee (car args)))
255    (if (and (>= *speed* *debug*)
256             (consp callee)
257             (eq (%car callee) 'function)
258             (symbolp (cadr callee))
259             (not (special-operator-p (cadr callee)))
260             (not (macro-function (cadr callee) env))
261             (memq (symbol-package (cadr callee))
262                   (list (find-package "CL") (find-package "SYS"))))
263        `(,(cadr callee) ,@(cdr args))
264        form)))
265
266(define-compiler-macro byte (size position)
267  `(cons ,size ,position))
268
269(define-compiler-macro byte-size (bytespec)
270  `(car ,bytespec))
271
272(define-compiler-macro byte-position (bytespec)
273  `(cdr ,bytespec))
274
275(define-source-transform concatenate (&whole form result-type &rest sequences)
276  (if (equal result-type '(quote STRING))
277      `(sys::concatenate-to-string (list ,@sequences))
278      form))
279
280(define-source-transform ldb (&whole form bytespec integer)
281  (if (and (consp bytespec)
282           (eq (%car bytespec) 'byte)
283           (= (length bytespec) 3))
284      (let ((size (%cadr bytespec))
285            (position (%caddr bytespec)))
286        `(%ldb ,size ,position ,integer))
287      form))
288
289(define-source-transform find (&whole form item sequence &key from-end test test-not start end key)
290  (cond ((and (>= (length form) 3) (null start) (null end))
291         (cond ((and (stringp sequence)
292                     (null from-end)
293                     (member test '(#'eql #'char=) :test #'equal)
294                     (null test-not)
295                     (null key))
296                `(string-find ,item ,sequence))
297               (t
298                (let ((item-var (gensym))
299                      (seq-var (gensym)))
300                  `(let ((,item-var ,item)
301                         (,seq-var ,sequence))
302                     (if (listp ,seq-var)
303                         (list-find* ,item-var ,seq-var ,from-end ,test ,test-not 0 (length ,seq-var) ,key)
304                         (vector-find* ,item-var ,seq-var ,from-end ,test ,test-not 0 (length ,seq-var) ,key)))))))
305        (t
306         form)))
307
308(define-source-transform adjoin (&whole form &rest args)
309  (if (= (length args) 2)
310      `(adjoin-eql ,(first args) ,(second args))
311      form))
312
313(define-compiler-macro catch (&whole form tag &rest args)
314  (declare (ignore tag))
315  (if (and (null (cdr args))
316           (constantp (car args)))
317      (car args)
318      form))
319
320(define-compiler-macro string= (&whole form &rest args)
321  (if (= (length args) 2)
322      `(sys::%%string= ,@args)
323      form))
324
325(define-compiler-macro <= (&whole form &rest args)
326  (cond ((and (= (length args) 3)
327              (numberp (first args))
328              (numberp (third args))
329              (= (first args) (third args)))
330         `(= ,(second args) ,(first args)))
331        (t
332         form)))
333
334(in-package "EXTENSIONS")
335
336(unless (find-package "PRECOMPILER")
337  (make-package "PRECOMPILER"
338                :nicknames '("PRE")
339                :use '("COMMON-LISP" "EXTENSIONS" "SYSTEM")))
340
341(in-package "PRECOMPILER")
342
343;; No source-transforms and inlining in precompile-function-call
344;; No macro expansion in precompile-dolist and precompile-dotimes
345;; No macro expansion in precompile-do/do*
346;; No macro expansion in precompile-defun
347;; Special precompilation in precompile-case and precompile-cond
348;; Special precompilation in precompile-when and precompile-unless
349;; No precompilation in precompile-nth-value
350;; Special precompilation in precompile-return
351;; Special precompilation in expand-macro
352;;
353;; if *in-jvm-compile* is false
354
355(defvar *in-jvm-compile* nil)
356(defvar *precompile-env* nil)
357
358
359(declaim (ftype (function (t) t) precompile1))
360(defun precompile1 (form)
361  (cond ((symbolp form)
362         (multiple-value-bind
363               (expansion expanded)
364             (expand-macro form)
365           (if expanded
366               (precompile1 expansion)
367               form)))
368        ((atom form)
369         form)
370        (t
371         (let ((op (%car form))
372               handler)
373           (when (symbolp op)
374             (cond ((setf handler (get op 'precompile-handler))
375                    (return-from precompile1 (funcall handler form)))
376                   ((macro-function op *precompile-env*)
377                    (return-from precompile1 (precompile1 (expand-macro form))))
378                   ((special-operator-p op)
379                    (error "PRECOMPILE1: unsupported special operator ~S." op))))
380           (precompile-function-call form)))))
381
382(defun precompile-identity (form)
383  (declare (optimize speed))
384  form)
385
386(declaim (ftype (function (t) cons) precompile-cons))
387(defun precompile-cons (form)
388  (cons (car form) (mapcar #'precompile1 (cdr form))))
389
390(declaim (ftype (function (t t) t) precompile-function-call))
391(defun precompile-function-call (form)
392  (let ((op (car form)))
393    (when (and (consp op) (eq (%car op) 'LAMBDA))
394      (return-from precompile-function-call
395                   (cons (precompile-lambda op)
396                         (mapcar #'precompile1 (cdr form)))))
397    (when (or (not *in-jvm-compile*) (notinline-p op))
398      (return-from precompile-function-call (precompile-cons form)))
399    (when (source-transform op)
400      (let ((new-form (expand-source-transform form)))
401        (when (neq new-form form)
402          (return-from precompile-function-call (precompile1 new-form)))))
403    (when *enable-inline-expansion*
404      (let ((expansion (inline-expansion op)))
405        (when expansion
406          (let ((explain *explain*))
407            (when (and explain (memq :calls explain))
408              (format t ";   inlining call to ~S~%" op)))
409          (return-from precompile-function-call (precompile1 (expand-inline form expansion))))))
410    (cons op (mapcar #'precompile1 (cdr form)))))
411
412(defun precompile-locally (form)
413  (let ((*inline-declarations* *inline-declarations*))
414    (process-optimization-declarations (cdr form))
415  (cons 'LOCALLY (mapcar #'precompile1 (cdr form)))))
416
417(defun precompile-block (form)
418  (let ((args (cdr form)))
419    (if (null (cdr args))
420        nil
421        (list* 'BLOCK (car args) (mapcar #'precompile1 (cdr args))))))
422
423(defun precompile-dolist (form)
424  (if *in-jvm-compile*
425      (precompile1 (macroexpand form *precompile-env*))
426      (cons 'DOLIST (cons (mapcar #'precompile1 (cadr form))
427                          (mapcar #'precompile1 (cddr form))))))
428
429(defun precompile-dotimes (form)
430  (if *in-jvm-compile*
431      (precompile1 (macroexpand form *precompile-env*))
432      (cons 'DOTIMES (cons (mapcar #'precompile1 (cadr form))
433                           (mapcar #'precompile1 (cddr form))))))
434
435(defun precompile-do/do*-vars (varlist)
436  (let ((result nil))
437    (dolist (varspec varlist)
438      (if (atom varspec)
439          (push varspec result)
440          (case (length varspec)
441            (1
442             (push (%car varspec) result))
443            (2
444             (let* ((var (%car varspec))
445                    (init-form (%cadr varspec)))
446               (unless (symbolp var)
447                 (error 'type-error))
448               (push (list var (precompile1 init-form))
449                     result)))
450            (3
451             (let* ((var (%car varspec))
452                    (init-form (%cadr varspec))
453                    (step-form (%caddr varspec)))
454               (unless (symbolp var)
455                 (error 'type-error))
456               (push (list var (precompile1 init-form) (precompile1 step-form))
457                     result))))))
458    (nreverse result)))
459
460(defun precompile-do/do*-end-form (end-form)
461  (let ((end-test-form (car end-form))
462        (result-forms (cdr end-form)))
463    (list* end-test-form (mapcar #'precompile1 result-forms))))
464
465(defun precompile-do/do* (form)
466  (if *in-jvm-compile*
467      (precompile1 (macroexpand form *precompile-env*))
468      (list* (car form)
469             (precompile-do/do*-vars (cadr form))
470             (precompile-do/do*-end-form (caddr form))
471             (mapcar #'precompile1 (cdddr form)))))
472
473(defun precompile-do-symbols (form)
474  (list* (car form) (cadr form) (mapcar #'precompile1 (cddr form))))
475
476(defun precompile-load-time-value (form)
477  form)
478
479(defun precompile-progn (form)
480  (let ((body (cdr form)))
481    (if (eql (length body) 1)
482        (let ((res (precompile1 (%car body))))
483          ;; If the result turns out to be a bare symbol, leave it wrapped
484          ;; with PROGN so it won't be mistaken for a tag in an enclosing
485          ;; TAGBODY.
486          (if (symbolp res)
487              (list 'progn res)
488              res))
489        (cons 'PROGN (mapcar #'precompile1 body)))))
490
491(defun precompile-progv (form)
492  (if (< (length form) 3)
493      (compiler-error "Not enough arguments for ~S." 'progv)
494      (list* 'PROGV (mapcar #'precompile1 (%cdr form)))))
495
496(defun precompile-setf (form)
497  (let ((place (second form)))
498    (cond ((and (consp place)
499                (eq (%car place) 'VALUES))
500     (setf form
501     (list* 'SETF
502      (list* 'VALUES
503             (mapcar #'precompile1 (%cdr place)))
504      (cddr form)))
505     (precompile1 (expand-macro form)))
506    ((symbolp place)
507           (multiple-value-bind
508                 (expansion expanded)
509               (expand-macro place)
510             (if expanded
511                 (precompile1 (list* 'SETF expansion
512                                     (cddr form)))
513                 (precompile1 (expand-macro form)))))
514          (t
515           (precompile1 (expand-macro form))))))
516
517(defun precompile-setq (form)
518  (let* ((args (cdr form))
519         (len (length args)))
520    (when (oddp len)
521      (error 'simple-program-error
522             :format-control "Odd number of arguments to SETQ."))
523    (if (= len 2)
524        (let* ((sym (%car args))
525               (val (%cadr args)))
526          (multiple-value-bind
527                (expansion expanded)
528              (expand-macro sym)
529            (if expanded
530                (precompile1 (list 'SETF expansion val))
531                (list 'SETQ sym (precompile1 val)))))
532        (let ((result ()))
533          (loop
534            (when (null args)
535              (return))
536            (push (precompile-setq (list 'SETQ (car args) (cadr args))) result)
537            (setq args (cddr args)))
538          (setq result (nreverse result))
539          (push 'PROGN result)
540          result))))
541
542(defun precompile-psetf (form)
543  (setf form
544        (list* 'PSETF
545               (mapcar #'precompile1 (cdr form))))
546  (precompile1 (expand-macro form)))
547
548(defun precompile-psetq (form)
549  ;; Make sure all the vars are symbols.
550  (do* ((rest (cdr form) (cddr rest))
551        (var (car rest)))
552       ((null rest))
553    (unless (symbolp var)
554      (error 'simple-error
555             :format-control "~S is not a symbol."
556             :format-arguments (list var))))
557  ;; Delegate to PRECOMPILE-PSETF so symbol macros are handled correctly.
558  (precompile-psetf form))
559
560
561(defun precompile-lambda-list (form)
562  (let (new aux-tail)
563    (dolist (arg form (nreverse new))
564       (if (or (atom arg) (> 2 (length arg)))
565           (progn
566             (when (eq arg '&aux)
567               (setf aux-tail t))
568             (push arg new))
569          ;; must be a cons of more than 1 cell
570          (let ((new-arg (copy-list arg)))
571            (unless (<= 1 (length arg) (if aux-tail 2 3))
572              ;; the aux-vars have a maximum length of 2 conses
573              ;; optional and key vars may have 3
574              (error 'program-error
575                     :format-control
576                     "The ~A binding specification ~S is invalid."
577                     :format-arguments (list (if aux-tail "&AUX"
578                                                 "&OPTIONAL/&KEY") arg)))
579             (setf (second new-arg)
580                   (precompile1 (second arg)))
581             (push new-arg new))))))
582
583(defun precompile-lambda (form)
584  (let ((body (cddr form))
585        (precompiled-lambda-list
586           (precompile-lambda-list (cadr form)))
587        (*inline-declarations* *inline-declarations*))
588    (process-optimization-declarations body)
589    (list* 'LAMBDA precompiled-lambda-list
590           (mapcar #'precompile1 body))))
591
592(defun precompile-named-lambda (form)
593  (let ((lambda-form (list* 'LAMBDA (caddr form) (cdddr form))))
594    (let ((body (cddr lambda-form))
595          (precompiled-lambda-list
596           (precompile-lambda-list (cadr lambda-form)))
597          (*inline-declarations* *inline-declarations*))
598      (process-optimization-declarations body)
599      (list* 'NAMED-LAMBDA (cadr form) precompiled-lambda-list
600             (mapcar #'precompile1 body)))))
601
602(defun precompile-defun (form)
603  (if *in-jvm-compile*
604      (precompile1 (expand-macro form))
605      form))
606
607(defun precompile-macrolet (form)
608  (let ((*precompile-env* (make-environment *precompile-env*)))
609    (dolist (definition (cadr form))
610      (environment-add-macro-definition
611       *precompile-env*
612       (car definition)
613       (make-macro (car definition)
614                   (make-closure
615                    (make-expander-for-macrolet definition)
616                    NIL))))
617    (multiple-value-bind (body decls)
618        (parse-body (cddr form) nil)
619      `(locally ,@decls ,@(mapcar #'precompile1 body)))))
620
621(defun precompile-symbol-macrolet (form)
622  (let ((*precompile-env* (make-environment *precompile-env*))
623        (defs (cadr form)))
624    (dolist (def defs)
625      (let ((sym (car def))
626            (expansion (cadr def)))
627        (when (special-variable-p sym)
628          (error 'program-error
629                 :format-control
630                 "Attempt to bind the special variable ~S with SYMBOL-MACROLET."
631                 :format-arguments (list sym)))
632        (environment-add-symbol-binding *precompile-env*
633                                        sym
634                                        (sys::make-symbol-macro expansion))))
635    (multiple-value-bind (body decls)
636        (parse-body (cddr form) nil)
637      (when decls
638        (let ((specials ()))
639          (dolist (decl decls)
640            (when (eq (car decl) 'DECLARE)
641              (dolist (declspec (cdr decl))
642                (when (eq (car declspec) 'SPECIAL)
643                  (setf specials (append specials (cdr declspec)))))))
644          (when specials
645            (let ((syms (mapcar #'car (cadr form))))
646              (dolist (special specials)
647                (when (memq special syms)
648                  (error 'program-error
649                         :format-control
650                         "~S is a symbol-macro and may not be declared special."
651                         :format-arguments (list special))))))))
652      `(locally ,@decls ,@(mapcar #'precompile1 body)))))
653
654(defun precompile-the (form)
655  (list 'THE
656        (second form)
657        (precompile1 (third form))))
658
659(defun precompile-truly-the (form)
660  (list 'TRULY-THE
661        (second form)
662        (precompile1 (third form))))
663
664(defun precompile-let/let*-vars (vars)
665  (let ((result nil))
666    (dolist (var vars)
667      (cond ((consp var)
668             (unless (<= 1 (length var) 2)
669               (error 'program-error
670                       :format-control
671                       "The LET/LET* binding specification ~S is invalid."
672                       :format-arguments (list var)))
673             (let ((v (%car var))
674                   (expr (cadr var)))
675               (unless (symbolp v)
676                 (error 'simple-type-error
677                        :format-control "The variable ~S is not a symbol."
678                        :format-arguments (list v)))
679               (push (list v (precompile1 expr)) result)
680               (environment-add-symbol-binding *precompile-env* v nil)))
681               ;; any value will do: we just need to shadow any symbol macros
682            (t
683             (push var result)
684             (environment-add-symbol-binding *precompile-env* var nil))))
685    (nreverse result)))
686
687(defun precompile-let (form)
688  (let ((*precompile-env* (make-environment *precompile-env*)))
689    (list* 'LET
690           (precompile-let/let*-vars (cadr form))
691           (mapcar #'precompile1 (cddr form)))))
692
693;; (LET* ((X 1)) (LET* ((Y 2)) (LET* ((Z 3)) (+ X Y Z)))) =>
694;; (LET* ((X 1) (Y 2) (Z 3)) (+ X Y Z))
695(defun maybe-fold-let* (form)
696  (if (and (= (length form) 3)
697           (consp (%caddr form))
698           (eq (%car (%caddr form)) 'LET*))
699      (let ((third (maybe-fold-let* (%caddr form))))
700        (list* 'LET* (append (%cadr form) (cadr third)) (cddr third)))
701      form))
702
703(defun precompile-let* (form)
704  (setf form (maybe-fold-let* form))
705  (let ((*precompile-env* (make-environment *precompile-env*)))
706    (list* 'LET*
707           (precompile-let/let*-vars (cadr form))
708           (mapcar #'precompile1 (cddr form)))))
709
710(defun precompile-case (form)
711  (if *in-jvm-compile*
712      (precompile1 (macroexpand form *precompile-env*))
713      (let* ((keyform (cadr form))
714             (clauses (cddr form))
715             (result (list (precompile1 keyform))))
716        (dolist (clause clauses)
717          (push (precompile-case-clause clause) result))
718        (cons (car form) (nreverse result)))))
719
720(defun precompile-case-clause (clause)
721  (let ((keys (car clause))
722        (forms (cdr clause)))
723    (cons keys (mapcar #'precompile1 forms))))
724
725(defun precompile-cond (form)
726  (if *in-jvm-compile*
727      (precompile1 (macroexpand form *precompile-env*))
728      (let ((clauses (cdr form))
729            (result nil))
730        (dolist (clause clauses)
731          (push (precompile-cond-clause clause) result))
732        (cons 'COND (nreverse result)))))
733
734(defun precompile-cond-clause (clause)
735  (let ((test (car clause))
736        (forms (cdr clause)))
737    (cons (precompile1 test) (mapcar #'precompile1 forms))))
738
739(defun precompile-local-function-def (def)
740  (let ((name (car def))
741        (body (cddr def)))
742    ;; Macro names are shadowed by local functions.
743    (environment-add-function-definition *precompile-env* name body)
744    (cdr (precompile-named-lambda (list* 'NAMED-LAMBDA def)))))
745
746(defun precompile-local-functions (defs)
747  (let ((result nil))
748    (dolist (def defs (nreverse result))
749      (push (precompile-local-function-def def) result))))
750
751(defun find-use (name expression)
752  (cond ((atom expression)
753         nil)
754        ((eq (%car expression) name)
755         t)
756        ((consp name)
757         t) ;; FIXME Recognize use of SETF functions!
758        (t
759         (or (find-use name (%car expression))
760             (find-use name (%cdr expression))))))
761
762(defun precompile-flet/labels (form)
763  (let ((*precompile-env* (make-environment *precompile-env*))
764        (operator (car form))
765        (locals (cadr form))
766        (body (cddr form)))
767    (dolist (local locals)
768      (let* ((name (car local))
769             (used-p (find-use name body)))
770        (unless used-p
771          (when (eq operator 'LABELS)
772            (dolist (local locals)
773              (when (neq name (car local))
774                (when (find-use name (cddr local))
775                  (setf used-p t)
776                  (return))
777                ;; Scope of defined function names includes
778                ;; &OPTIONAL, &KEY and &AUX parameters
779                ;; (LABELS.7B, LABELS.7C and LABELS.7D).
780                (let ((vars (or
781                             (cdr (memq '&optional (cadr local)))
782                             (cdr (memq '&key (cadr local)))
783                             (cdr (memq '&aux (cadr local))))))
784                  (when (and vars (find-use name vars)
785                             (setf used-p t)
786                             (return))))))))
787        (unless used-p
788          (format t "; Note: deleting unused local function ~A ~S~%"
789                  operator name)
790          (let* ((new-locals (remove local locals :test 'eq))
791                 (new-form
792                  (if new-locals
793                      (list* operator new-locals body)
794                      (list* 'LOCALLY body))))
795            (return-from precompile-flet/labels (precompile1 new-form))))))
796    (list* (car form)
797           (precompile-local-functions locals)
798           (mapcar #'precompile1 body))))
799
800(defun precompile-function (form)
801  (if (and (consp (cadr form)) (eq (caadr form) 'LAMBDA))
802      (list 'FUNCTION (precompile-lambda (%cadr form)))
803      form))
804
805(defun precompile-if (form)
806  (let ((args (cdr form)))
807    (case (length args)
808      (2
809       (let ((test (precompile1 (%car args))))
810         (cond ((null test)
811                nil)
812               (;;(constantp test)
813                (eq test t)
814                (precompile1 (%cadr args)))
815               (t
816                (list 'IF
817                      test
818                      (precompile1 (%cadr args)))))))
819      (3
820       (let ((test (precompile1 (%car args))))
821         (cond ((null test)
822                (precompile1 (%caddr args)))
823               (;;(constantp test)
824                (eq test t)
825                (precompile1 (%cadr args)))
826               (t
827                (list 'IF
828                      test
829                      (precompile1 (%cadr args))
830                      (precompile1 (%caddr args)))))))
831      (t
832       (error "wrong number of arguments for IF")))))
833
834(defun precompile-when (form)
835  (if *in-jvm-compile*
836      (precompile1 (macroexpand form *precompile-env*))
837      (precompile-cons form)))
838
839(defun precompile-unless (form)
840  (if *in-jvm-compile*
841      (precompile1 (macroexpand form *precompile-env*))
842      (precompile-cons form)))
843
844;; MULTIPLE-VALUE-BIND is handled explicitly by the JVM compiler.
845(defun precompile-multiple-value-bind (form)
846  (let ((vars (cadr form))
847        (values-form (caddr form))
848        (body (cdddr form))
849        (*precompile-env* (make-environment *precompile-env*)))
850    (dolist (var vars)
851      (environment-add-symbol-binding *precompile-env* var nil))
852    (list* 'MULTIPLE-VALUE-BIND
853           vars
854           (precompile1 values-form)
855           (mapcar #'precompile1 body))))
856
857;; MULTIPLE-VALUE-LIST is handled explicitly by the JVM compiler.
858(defun precompile-multiple-value-list (form)
859  (list 'MULTIPLE-VALUE-LIST (precompile1 (cadr form))))
860
861(defun precompile-nth-value (form)
862  (if *in-jvm-compile*
863      (precompile1 (macroexpand form *precompile-env*))
864      form))
865
866(defun precompile-return (form)
867  (if *in-jvm-compile*
868      (precompile1 (macroexpand form *precompile-env*))
869      (list 'RETURN (precompile1 (cadr form)))))
870
871(defun precompile-return-from (form)
872  (list 'RETURN-FROM (cadr form) (precompile1 (caddr form))))
873
874(defun precompile-tagbody (form)
875  (do ((body (cdr form) (cdr body))
876       (result ()))
877      ((null body) (cons 'TAGBODY (nreverse result)))
878    (if (atom (car body))
879        (push (car body) result)
880        (push (let* ((first-form (car body))
881                     (expanded (precompile1 first-form)))
882                (if (and (symbolp expanded)
883                         (neq expanded first-form))
884                    ;; Workaround:
885                    ;;  Since our expansion/compilation order
886                    ;;   is out of sync with the definition of
887                    ;;   TAGBODY (which requires the compiler
888                    ;;   to look for tags before expanding),
889                    ;;   we need to disguise anything which might
890                    ;;   look like a tag. We do this by wrapping
891                    ;;   it in a PROGN form.
892                    (list 'PROGN expanded)
893                    expanded)) result))))
894
895(defun precompile-eval-when (form)
896  (list* 'EVAL-WHEN (cadr form) (mapcar #'precompile1 (cddr form))))
897
898(defun precompile-unwind-protect (form)
899  (list* 'UNWIND-PROTECT
900         (precompile1 (cadr form))
901         (mapcar #'precompile1 (cddr form))))
902
903;; EXPAND-MACRO is like MACROEXPAND, but EXPAND-MACRO quits if *IN-JVM-COMPILE*
904;; is false and a macro is encountered that is also implemented as a special
905;; operator, so interpreted code can use the special operator implementation.
906(defun expand-macro (form)
907  (let (exp)
908    (loop
909       (unless *in-jvm-compile*
910         (when (and (consp form)
911                    (symbolp (%car form))
912                    (special-operator-p (%car form)))
913           (return-from expand-macro form)))
914       (multiple-value-bind (result expanded)
915           (macroexpand-1 form *precompile-env*)
916         (unless expanded
917           (return-from expand-macro (values result exp)))
918         (setf form result
919               exp t)))))
920
921(declaim (ftype (function (t t) t) precompile-form))
922(defun precompile-form (form in-jvm-compile
923                        &optional precompile-env)
924  (let ((*in-jvm-compile* in-jvm-compile)
925        (*inline-declarations* *inline-declarations*)
926        (pre::*precompile-env* precompile-env))
927    (precompile1 form)))
928
929(defun install-handler (symbol &optional handler)
930  (declare (type symbol symbol))
931  (let ((handler (or handler
932                     (find-symbol (sys::%format nil "PRECOMPILE-~A"
933                                                (symbol-name symbol))
934                                  'precompiler))))
935    (unless (and handler (fboundp handler))
936      (error "No handler for ~S." symbol))
937    (setf (get symbol 'precompile-handler) handler)))
938
939(defun install-handlers ()
940  (mapcar #'install-handler '(BLOCK
941                              CASE
942                              COND
943                              DOLIST
944                              DOTIMES
945                              EVAL-WHEN
946                              FUNCTION
947                              IF
948                              LAMBDA
949                              MACROLET
950                              MULTIPLE-VALUE-BIND
951                              MULTIPLE-VALUE-LIST
952                              NAMED-LAMBDA
953                              NTH-VALUE
954                              PROGN
955                              PROGV
956                              PSETF
957                              PSETQ
958                              RETURN
959                              RETURN-FROM
960                              SETF
961                              SETQ
962                              SYMBOL-MACROLET
963                              TAGBODY
964                              UNWIND-PROTECT
965                              UNLESS
966                              WHEN))
967
968  (dolist (pair '((ECASE                precompile-case)
969
970                  (AND                  precompile-cons)
971                  (OR                   precompile-cons)
972
973                  (CATCH                precompile-cons)
974                  (MULTIPLE-VALUE-CALL  precompile-cons)
975                  (MULTIPLE-VALUE-PROG1 precompile-cons)
976
977                  (DO                   precompile-do/do*)
978                  (DO*                  precompile-do/do*)
979
980                  (LET                  precompile-let)
981                  (LET*                 precompile-let*)
982
983                  (LOCALLY              precompile-locally)
984
985                  (FLET                 precompile-flet/labels)
986                  (LABELS               precompile-flet/labels)
987
988                  (LOAD-TIME-VALUE      precompile-load-time-value)
989
990                  (DECLARE              precompile-identity)
991                  (DEFUN                precompile-defun)
992                  (GO                   precompile-identity)
993                  (QUOTE                precompile-identity)
994                  (THE                  precompile-the)
995                  (THROW                precompile-cons)
996                  (TRULY-THE            precompile-truly-the)))
997    (install-handler (first pair) (second pair))))
998
999(install-handlers)
1000
1001(export '(precompile-form))
1002
1003(in-package #:ext)
1004(defun macroexpand-all (form &optional env)
1005  (precompiler:precompile-form form nil env))
1006
1007(in-package #:lisp)
1008
1009(defmacro compiler-let (bindings &body forms &environment env)
1010  (let ((bindings (mapcar #'(lambda (binding)
1011                              (if (atom binding) (list binding) binding))
1012                          bindings)))
1013    (progv (mapcar #'car bindings)
1014           (mapcar #'(lambda (binding)
1015                       (eval (cadr binding))) bindings)
1016      (macroexpand-all `(progn ,@forms) env))))
1017
1018(in-package #:system)
1019
1020(defun set-function-definition (name new old)
1021  (let ((*warn-on-redefinition* nil))
1022    (sys::%set-lambda-name new name)
1023    (sys:set-call-count new (sys:call-count old))
1024    (sys::%set-arglist new (sys::arglist old))
1025    (when (macro-function name)
1026      (setf new (make-macro name new)))
1027    (if (typep old 'standard-generic-function)
1028        (mop:set-funcallable-instance-function old new)
1029        (setf (fdefinition name) new))))
1030
1031(defun precompile (name &optional definition)
1032  (unless definition
1033    (setq definition (or (and (symbolp name) (macro-function name))
1034                         (fdefinition name))))
1035  (let ((expr definition)
1036        env result
1037        (pre::*precompile-env* nil))
1038    (when (functionp definition)
1039      (multiple-value-bind (form closure-p)
1040          (function-lambda-expression definition)
1041        (unless form
1042          (return-from precompile (values nil t t)))
1043        (setq env closure-p)
1044        (setq expr form)))
1045    (unless (and (consp expr) (eq (car expr) 'lambda))
1046      (format t "Unable to precompile ~S.~%" name)
1047      (return-from precompile (values nil t t)))
1048    (setf result
1049          (sys:make-closure (precompiler:precompile-form expr nil env) env))
1050    (when (and name (functionp result))
1051      (sys::set-function-definition name result definition))
1052    (values (or name result) nil nil)))
1053
1054(defun precompile-package (pkg &key verbose)
1055  (dolist (sym (package-symbols pkg))
1056    (when (fboundp sym)
1057      (unless (special-operator-p sym)
1058        (let ((f (fdefinition sym)))
1059          (unless (compiled-function-p f)
1060            (when verbose
1061              (format t "Precompiling ~S~%" sym)
1062              (finish-output))
1063            (precompile sym))))))
1064  t)
1065
1066(defun %compile (name definition)
1067  (if (and name (fboundp name) (%typep (symbol-function name) 'generic-function))
1068      (values name nil nil)
1069      (precompile name definition)))
1070
1071;; ;; Redefine EVAL to precompile its argument.
1072;; (defun eval (form)
1073;;   (%eval (precompile-form form nil)))
1074
1075;; ;; Redefine DEFMACRO to precompile the expansion function on the fly.
1076;; (defmacro defmacro (name lambda-list &rest body)
1077;;   (let* ((form (gensym "WHOLE-"))
1078;;          (env (gensym "ENVIRONMENT-")))
1079;;     (multiple-value-bind (body decls)
1080;;         (parse-defmacro lambda-list form body name 'defmacro :environment env)
1081;;       (let ((expander `(lambda (,form ,env) ,@decls (block ,name ,body))))
1082;;         `(progn
1083;;            (let ((macro (make-macro ',name
1084;;                                     (or (precompile nil ,expander) ,expander))))
1085;;              ,@(if (special-operator-p name)
1086;;                    `((put ',name 'macroexpand-macro macro))
1087;;                    `((fset ',name macro)))
1088;;              (%set-arglist macro ',lambda-list)
1089;;              ',name))))))
1090
1091;; Make an exception just this one time...
1092(when (get 'defmacro 'macroexpand-macro)
1093  (fset 'defmacro (get 'defmacro 'macroexpand-macro))
1094  (remprop 'defmacro 'macroexpand-macro))
1095
1096(defvar *defined-functions*)
1097
1098(defvar *undefined-functions*)
1099
1100(defun note-name-defined (name)
1101  (when (boundp '*defined-functions*)
1102    (push name *defined-functions*))
1103  (when (and (boundp '*undefined-functions*) (not (null *undefined-functions*)))
1104    (setf *undefined-functions* (remove name *undefined-functions*))))
1105
1106;; Redefine DEFUN to precompile the definition on the fly.
1107(defmacro defun (name lambda-list &body body &environment env)
1108  (note-name-defined name)
1109  (multiple-value-bind (body decls doc)
1110      (parse-body body)
1111    (let* ((block-name (fdefinition-block-name name))
1112           (lambda-expression
1113            `(named-lambda ,name ,lambda-list
1114                           ,@decls
1115                           ,@(when doc `(,doc))
1116                           (block ,block-name ,@body))))
1117      (cond ((and (boundp 'jvm::*file-compilation*)
1118                  ;; when JVM.lisp isn't loaded yet, this variable isn't bound
1119                  ;; meaning that we're not trying to compile to a file:
1120                  ;; Both COMPILE and COMPILE-FILE bind this variable.
1121                  ;; This function is also triggered by MACROEXPAND, though
1122                  jvm::*file-compilation*)
1123             `(fset ',name ,lambda-expression))
1124            (t
1125             (when (and env (empty-environment-p env))
1126               (setf env nil))
1127             (when (null env)
1128               (setf lambda-expression (precompiler:precompile-form lambda-expression nil)))
1129             `(progn
1130                (%defun ',name ,lambda-expression)
1131                ,@(when doc
1132                   `((%set-documentation ',name 'function ,doc)))))))))
1133
1134(export '(precompile))
1135
1136;;(provide "PRECOMPILER")
Note: See TracBrowser for help on using the repository browser.