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

Last change on this file since 11912 was 11912, checked in by ehuelsmann, 14 years ago

Remove unused variable *LOCAL-FUNCTIONS-AND-MACROS*.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 41.7 KB
Line 
1;;; precompiler.lisp
2;;;
3;;; Copyright (C) 2003-2008 Peter Graves <peter@armedbear.org>
4;;; $Id: precompiler.lisp 11912 2009-05-21 10:19:53Z ehuelsmann $
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 &rest args)
253  (let ((callee (car args)))
254    (if (and (>= *speed* *debug*)
255             (consp callee)
256             (eq (%car callee) 'function)
257             (symbolp (cadr callee))
258             (not (special-operator-p (cadr callee)))
259             (not (macro-function (cadr callee) sys:*compile-file-environment*))
260             (memq (symbol-package (cadr callee))
261                   (list (find-package "CL") (find-package "SYS"))))
262        `(,(cadr callee) ,@(cdr args))
263        form)))
264
265(define-compiler-macro byte (size position)
266  `(cons ,size ,position))
267
268(define-compiler-macro byte-size (bytespec)
269  `(car ,bytespec))
270
271(define-compiler-macro byte-position (bytespec)
272  `(cdr ,bytespec))
273
274(define-source-transform concatenate (&whole form result-type &rest sequences)
275  (if (equal result-type '(quote STRING))
276      `(sys::concatenate-to-string (list ,@sequences))
277      form))
278
279(define-source-transform ldb (&whole form bytespec integer)
280  (if (and (consp bytespec)
281           (eq (%car bytespec) 'byte)
282           (= (length bytespec) 3))
283      (let ((size (%cadr bytespec))
284            (position (%caddr bytespec)))
285        `(%ldb ,size ,position ,integer))
286      form))
287
288(define-source-transform find (&whole form item sequence &key from-end test test-not start end key)
289  (cond ((and (>= (length form) 3) (null start) (null end))
290         (cond ((and (stringp sequence)
291                     (null from-end)
292                     (member test '(#'eql #'char=) :test #'equal)
293                     (null test-not)
294                     (null key))
295                `(string-find ,item ,sequence))
296               (t
297                (let ((item-var (gensym))
298                      (seq-var (gensym)))
299                  `(let ((,item-var ,item)
300                         (,seq-var ,sequence))
301                     (if (listp ,seq-var)
302                         (list-find* ,item-var ,seq-var ,from-end ,test ,test-not 0 (length ,seq-var) ,key)
303                         (vector-find* ,item-var ,seq-var ,from-end ,test ,test-not 0 (length ,seq-var) ,key)))))))
304        (t
305         form)))
306
307(define-source-transform adjoin (&whole form &rest args)
308  (if (= (length args) 2)
309      `(adjoin-eql ,(first args) ,(second args))
310      form))
311
312(define-compiler-macro catch (&whole form tag &rest args)
313  (declare (ignore tag))
314  (if (and (null (cdr args))
315           (constantp (car args)))
316      (car args)
317      form))
318
319(define-compiler-macro string= (&whole form &rest args)
320  (if (= (length args) 2)
321      `(sys::%%string= ,@args)
322      form))
323
324(define-compiler-macro <= (&whole form &rest args)
325  (cond ((and (= (length args) 3)
326              (numberp (first args))
327              (numberp (third args))
328              (= (first args) (third args)))
329         `(= ,(second args) ,(first args)))
330        (t
331         form)))
332
333(in-package "EXTENSIONS")
334
335(export '(precompile-form precompile))
336
337(unless (find-package "PRECOMPILER")
338  (make-package "PRECOMPILER"
339                :nicknames '("PRE")
340                :use '("COMMON-LISP" "EXTENSIONS" "SYSTEM")))
341
342(in-package "PRECOMPILER")
343
344;; No source-transforms and inlining in precompile-function-call
345;; No macro expansion in precompile-dolist and precompile-dotimes
346;; No macro expansion in precompile-do/do*
347;; No macro expansion in precompile-defun
348;; Special precompilation in precompile-case and precompile-cond
349;; Special precompilation in precompile-when and precompile-unless
350;; No precompilation in precompile-nth-value
351;; Special precompilation in precompile-return
352;; Special precompilation in expand-macro
353;;
354;; if *in-jvm-compile* is false
355
356(defvar *in-jvm-compile* nil)
357
358(defvar *local-variables* nil
359  "An alist with all local variables visible in the context
360of the form being preprocessed.")
361
362(declaim (ftype (function (t) t) find-varspec))
363(defun find-varspec (sym)
364  (dolist (varspec *local-variables*)
365    (when (eq sym (car varspec))
366      (return varspec))))
367
368(declaim (ftype (function (t) t) precompile1))
369(defun precompile1 (form)
370  (cond ((symbolp form)
371         (let ((varspec (find-varspec form)))
372           (cond ((and varspec (eq (second varspec) :symbol-macro))
373                  (precompile1 (copy-tree (third varspec))))
374                 ((null varspec)
375                  (let ((expansion (expand-macro form)))
376                    (if (eq expansion form)
377                        form
378                        (precompile1 expansion))))
379                 (t
380                  form))))
381        ((atom form)
382         form)
383        (t
384         (let ((op (%car form))
385               handler)
386           (when (symbolp op)
387             (cond ((setf handler (get op 'precompile-handler))
388                    (return-from precompile1 (funcall handler form)))
389                   ((macro-function op *compile-file-environment*)
390                    (return-from precompile1 (precompile1 (expand-macro form))))
391                   ((special-operator-p op)
392                    (error "PRECOMPILE1: unsupported special operator ~S." op))))
393           (precompile-function-call form)))))
394
395(defun precompile-identity (form)
396  (declare (optimize speed))
397  form)
398
399(declaim (ftype (function (t) cons) precompile-cons))
400(defun precompile-cons (form)
401  (cons (car form) (mapcar #'precompile1 (cdr form))))
402
403(declaim (ftype (function (t t) t) precompile-function-call))
404(defun precompile-function-call (form)
405  (let ((op (car form)))
406    (when (and (consp op) (eq (%car op) 'LAMBDA))
407      (return-from precompile-function-call
408                   (cons (precompile-lambda op)
409                         (mapcar #'precompile1 (cdr form)))))
410    (when (or (not *in-jvm-compile*) (notinline-p op))
411      (return-from precompile-function-call (precompile-cons form)))
412    (when (source-transform op)
413      (let ((new-form (expand-source-transform form)))
414        (when (neq new-form form)
415          (return-from precompile-function-call (precompile1 new-form)))))
416    (when *enable-inline-expansion*
417      (let ((expansion (inline-expansion op)))
418        (when expansion
419          (let ((explain *explain*))
420            (when (and explain (memq :calls explain))
421              (format t ";   inlining call to ~S~%" op)))
422          (return-from precompile-function-call (precompile1 (expand-inline form expansion))))))
423    (cons op (mapcar #'precompile1 (cdr form)))))
424
425(defun precompile-locally (form)
426  (let ((*inline-declarations* *inline-declarations*))
427    (process-optimization-declarations (cdr form))
428  (cons 'LOCALLY (mapcar #'precompile1 (cdr form)))))
429
430(defun precompile-block (form)
431  (let ((args (cdr form)))
432    (if (null (cdr args))
433        nil
434        (list* 'BLOCK (car args) (mapcar #'precompile1 (cdr args))))))
435
436(defun precompile-dolist (form)
437  (if *in-jvm-compile*
438      (precompile1 (macroexpand form *compile-file-environment*))
439      (cons 'DOLIST (cons (mapcar #'precompile1 (cadr form))
440                          (mapcar #'precompile1 (cddr form))))))
441
442(defun precompile-dotimes (form)
443  (if *in-jvm-compile*
444      (precompile1 (macroexpand form *compile-file-environment*))
445      (cons 'DOTIMES (cons (mapcar #'precompile1 (cadr form))
446                           (mapcar #'precompile1 (cddr form))))))
447
448(defun precompile-do/do*-vars (varlist)
449  (let ((result nil))
450    (dolist (varspec varlist)
451      (if (atom varspec)
452          (push varspec result)
453          (case (length varspec)
454            (1
455             (push (%car varspec) result))
456            (2
457             (let* ((var (%car varspec))
458                    (init-form (%cadr varspec)))
459               (unless (symbolp var)
460                 (error 'type-error))
461               (push (list var (precompile1 init-form))
462                     result)))
463            (3
464             (let* ((var (%car varspec))
465                    (init-form (%cadr varspec))
466                    (step-form (%caddr varspec)))
467               (unless (symbolp var)
468                 (error 'type-error))
469               (push (list var (precompile1 init-form) (precompile1 step-form))
470                     result))))))
471    (nreverse result)))
472
473(defun precompile-do/do*-end-form (end-form)
474  (let ((end-test-form (car end-form))
475        (result-forms (cdr end-form)))
476    (list* end-test-form (mapcar #'precompile1 result-forms))))
477
478(defun precompile-do/do* (form)
479  (if *in-jvm-compile*
480      (precompile1 (macroexpand form *compile-file-environment*))
481      (list* (car form)
482             (precompile-do/do*-vars (cadr form))
483             (precompile-do/do*-end-form (caddr form))
484             (mapcar #'precompile1 (cdddr form)))))
485
486(defun precompile-do-symbols (form)
487  (list* (car form) (cadr form) (mapcar #'precompile1 (cddr form))))
488
489(defun precompile-load-time-value (form)
490  form)
491
492(defun precompile-progn (form)
493  (let ((body (cdr form)))
494    (if (eql (length body) 1)
495        (let ((res (precompile1 (%car body))))
496          ;; If the result turns out to be a bare symbol, leave it wrapped
497          ;; with PROGN so it won't be mistaken for a tag in an enclosing
498          ;; TAGBODY.
499          (if (symbolp res)
500              (list 'progn res)
501              res))
502        (cons 'PROGN (mapcar #'precompile1 body)))))
503
504(defun precompile-progv (form)
505  (if (< (length form) 3)
506      (compiler-error "Not enough arguments for ~S." 'progv)
507      (list* 'PROGV (mapcar #'precompile1 (%cdr form)))))
508
509(defun precompile-setf (form)
510  (let ((place (second form)))
511    (cond ((and (consp place)
512                (eq (%car place) 'VALUES))
513     (setf form
514     (list* 'SETF
515      (list* 'VALUES
516             (mapcar #'precompile1 (%cdr place)))
517      (cddr form)))
518     (precompile1 (expand-macro form)))
519    ((symbolp place)
520           (let ((varspec (find-varspec place)))
521             (if (and varspec (eq (second varspec) :symbol-macro))
522                 (precompile1 (list* 'SETF (copy-tree (third varspec)) (cddr form)))
523                 (precompile1 (expand-macro form)))))
524          (t
525           (precompile1 (expand-macro form))))))
526
527(defun precompile-setq (form)
528  (let* ((args (cdr form))
529         (len (length args)))
530    (when (oddp len)
531      (error 'simple-program-error
532             :format-control "Odd number of arguments to SETQ."))
533    (if (= len 2)
534        (let* ((sym (%car args))
535               (val (%cadr args))
536               (varspec (find-varspec sym)))
537          (if (and varspec (eq (second varspec) :symbol-macro))
538              (precompile1 (list 'SETF (copy-tree (third varspec)) val))
539              (list 'SETQ sym (precompile1 val))))
540        (let ((result ()))
541          (loop
542            (when (null args)
543              (return))
544            (push (precompile-setq (list 'SETQ (car args) (cadr args))) result)
545            (setq args (cddr args)))
546          (setq result (nreverse result))
547          (push 'PROGN result)
548          result))))
549
550(defun precompile-psetf (form)
551  (setf form
552        (list* 'PSETF
553               (mapcar #'precompile1 (cdr form))))
554  (precompile1 (expand-macro form)))
555
556(defun precompile-psetq (form)
557  ;; Make sure all the vars are symbols.
558  (do* ((rest (cdr form) (cddr rest))
559        (var (car rest)))
560       ((null rest))
561    (unless (symbolp var)
562      (error 'simple-error
563             :format-control "~S is not a symbol."
564             :format-arguments (list var))))
565  ;; Delegate to PRECOMPILE-PSETF so symbol macros are handled correctly.
566  (precompile-psetf form))
567
568
569(defun precompile-lambda-list (form)
570  (let (new aux-tail)
571    (dolist (arg form (nreverse new))
572       (if (or (atom arg) (> 2 (length arg)))
573           (progn
574             (when (eq arg '&aux)
575               (setf aux-tail t))
576             (push arg new))
577          ;; must be a cons of more than 1 cell
578          (let ((new-arg (copy-list arg)))
579            (unless (<= 1 (length arg) (if aux-tail 2 3))
580              ;; the aux-vars have a maximum length of 2 conses
581              ;; optional and key vars may have 3
582              (error 'program-error
583                     :format-control
584                     "The ~A binding specification ~S is invalid."
585                     :format-arguments (list (if aux-tail "&AUX"
586                                                 "&OPTIONAL/&KEY") arg)))
587             (setf (second new-arg)
588                   (precompile1 (second arg)))
589             (push new-arg new))))))
590
591(defun precompile-lambda (form)
592  (let ((body (cddr form))
593        (precompiled-lambda-list
594           (precompile-lambda-list (cadr form)))
595        (*inline-declarations* *inline-declarations*))
596    (process-optimization-declarations body)
597    (list* 'LAMBDA precompiled-lambda-list
598           (mapcar #'precompile1 body))))
599
600(defun precompile-named-lambda (form)
601  (let ((lambda-form (list* 'LAMBDA (caddr form) (cdddr form))))
602    (let ((body (cddr lambda-form))
603          (precompiled-lambda-list
604           (precompile-lambda-list (cadr lambda-form)))
605          (*inline-declarations* *inline-declarations*))
606      (process-optimization-declarations body)
607      (list* 'NAMED-LAMBDA (cadr form) precompiled-lambda-list
608             (mapcar #'precompile1 body)))))
609
610(defun precompile-defun (form)
611  (if *in-jvm-compile*
612      (precompile1 (expand-macro form))
613      form))
614
615(defun precompile-macrolet (form)
616  (let ((*compile-file-environment*
617         (make-environment *compile-file-environment*)))
618    (dolist (definition (cadr form))
619      (environment-add-macro-definition
620       *compile-file-environment*
621       (car definition)
622       (make-macro (car definition)
623                   (make-closure
624                    (make-expander-for-macrolet definition)
625                    NIL))))
626    (multiple-value-bind (body decls)
627        (parse-body (cddr form) nil)
628      `(locally ,@decls ,@(mapcar #'precompile1 body)))))
629
630(defun precompile-symbol-macrolet (form)
631  (let ((*local-variables* *local-variables*)
632        (*compile-file-environment*
633         (make-environment *compile-file-environment*))
634        (defs (cadr form)))
635    (dolist (def defs)
636      (let ((sym (car def))
637            (expansion (cadr def)))
638        (when (special-variable-p sym)
639          (error 'program-error
640                 :format-control "Attempt to bind the special variable ~S with SYMBOL-MACROLET."
641                 :format-arguments (list sym)))
642        (push (list sym :symbol-macro expansion) *local-variables*)
643        (environment-add-symbol-binding *compile-file-environment*
644                                        sym
645                                        (sys::make-symbol-macro expansion))
646        ))
647    (multiple-value-bind (body decls)
648        (parse-body (cddr form) nil)
649      (when decls
650        (let ((specials ()))
651          (dolist (decl decls)
652            (when (eq (car decl) 'DECLARE)
653              (dolist (declspec (cdr decl))
654                (when (eq (car declspec) 'SPECIAL)
655                  (setf specials (append specials (cdr declspec)))))))
656          (when specials
657            (let ((syms (mapcar #'car (cadr form))))
658              (dolist (special specials)
659                (when (memq special syms)
660                  (error 'program-error
661                         :format-control "~S is a symbol-macro and may not be declared special."
662                         :format-arguments (list special))))))))
663      `(locally ,@decls ,@(mapcar #'precompile1 body)))))
664
665(defun precompile-the (form)
666  (list 'THE
667        (second form)
668        (precompile1 (third form))))
669
670(defun precompile-truly-the (form)
671  (list 'TRULY-THE
672        (second form)
673        (precompile1 (third form))))
674
675(defun precompile-let/let*-vars (vars)
676  (let ((result nil))
677    (dolist (var vars)
678      (cond ((consp var)
679             (unless (<= 1 (length var) 2)
680               (error 'program-error
681                       :format-control
682                       "The LET/LET* binding specification ~S is invalid."
683                       :format-arguments (list var)))
684             (let ((v (%car var))
685                   (expr (cadr var)))
686               (unless (symbolp v)
687                 (error 'simple-type-error
688                        :format-control "The variable ~S is not a symbol."
689                        :format-arguments (list v)))
690               (push (list v (precompile1 expr)) result)
691               (push (list v :variable) *local-variables*)))
692            (t
693             (push var result)
694             (push (list var :variable) *local-variables*))))
695    (nreverse result)))
696
697(defun precompile-let (form)
698  (let ((*local-variables* *local-variables*))
699    (list* 'LET
700           (precompile-let/let*-vars (cadr form))
701           (mapcar #'precompile1 (cddr form)))))
702
703;; (LET* ((X 1)) (LET* ((Y 2)) (LET* ((Z 3)) (+ X Y Z)))) =>
704;; (LET* ((X 1) (Y 2) (Z 3)) (+ X Y Z))
705(defun maybe-fold-let* (form)
706  (if (and (= (length form) 3)
707           (consp (%caddr form))
708           (eq (%car (%caddr form)) 'LET*))
709      (let ((third (maybe-fold-let* (%caddr form))))
710        (list* 'LET* (append (%cadr form) (cadr third)) (cddr third)))
711      form))
712
713(defun precompile-let* (form)
714  (setf form (maybe-fold-let* form))
715  (let ((*local-variables* *local-variables*))
716    (list* 'LET*
717           (precompile-let/let*-vars (cadr form))
718           (mapcar #'precompile1 (cddr form)))))
719
720(defun precompile-case (form)
721  (if *in-jvm-compile*
722      (precompile1 (macroexpand form *compile-file-environment*))
723      (let* ((keyform (cadr form))
724             (clauses (cddr form))
725             (result (list (precompile1 keyform))))
726        (dolist (clause clauses)
727          (push (precompile-case-clause clause) result))
728        (cons (car form) (nreverse result)))))
729
730(defun precompile-case-clause (clause)
731  (let ((keys (car clause))
732        (forms (cdr clause)))
733    (cons keys (mapcar #'precompile1 forms))))
734
735(defun precompile-cond (form)
736  (if *in-jvm-compile*
737      (precompile1 (macroexpand form *compile-file-environment*))
738      (let ((clauses (cdr form))
739            (result nil))
740        (dolist (clause clauses)
741          (push (precompile-cond-clause clause) result))
742        (cons 'COND (nreverse result)))))
743
744(defun precompile-cond-clause (clause)
745  (let ((test (car clause))
746        (forms (cdr clause)))
747    (cons (precompile1 test) (mapcar #'precompile1 forms))))
748
749(defun precompile-local-function-def (def)
750  (let ((name (car def))
751        (body (cddr def)))
752    ;; Macro names are shadowed by local functions.
753    (environment-add-function-definition *compile-file-environment* name body)
754    (cdr (precompile-named-lambda (list* 'NAMED-LAMBDA def)))))
755
756(defun precompile-local-functions (defs)
757  (let ((result nil))
758    (dolist (def defs (nreverse result))
759      (push (precompile-local-function-def def) result))))
760
761(defun find-use (name expression)
762  (cond ((atom expression)
763         nil)
764        ((eq (%car expression) name)
765         t)
766        ((consp name)
767         t) ;; FIXME Recognize use of SETF functions!
768        (t
769         (or (find-use name (%car expression))
770             (find-use name (%cdr expression))))))
771
772(defun precompile-flet/labels (form)
773  (let ((*compile-file-environment*
774         (make-environment *compile-file-environment*))
775        (operator (car form))
776        (locals (cadr form))
777        (body (cddr form)))
778    (dolist (local locals)
779      (let* ((name (car local))
780             (used-p (find-use name body)))
781        (unless used-p
782          (when (eq operator 'LABELS)
783            (dolist (local locals)
784              (when (neq name (car local))
785                (when (find-use name (cddr local))
786                  (setf used-p t)
787                  (return))
788                ;; Scope of defined function names includes
789                ;; &OPTIONAL, &KEY and &AUX parameters
790                ;; (LABELS.7B, LABELS.7C and LABELS.7D).
791                (let ((vars (or
792                             (cdr (memq '&optional (cadr local)))
793                             (cdr (memq '&key (cadr local)))
794                             (cdr (memq '&aux (cadr local))))))
795                  (when (and vars (find-use name vars)
796                             (setf used-p t)
797                             (return))))))))
798        (unless used-p
799          (format t "; Note: deleting unused local function ~A ~S~%" operator name)
800          (let* ((new-locals (remove local locals :test 'eq))
801                 (new-form
802                  (if new-locals
803                      (list* operator new-locals body)
804                      (list* 'LOCALLY body))))
805            (return-from precompile-flet/labels (precompile1 new-form))))))
806    (list* (car form)
807           (precompile-local-functions locals)
808           (mapcar #'precompile1 body))))
809
810(defun precompile-function (form)
811  (if (and (consp (cadr form)) (eq (caadr form) 'LAMBDA))
812      (list 'FUNCTION (precompile-lambda (%cadr form)))
813      form))
814
815(defun precompile-if (form)
816  (let ((args (cdr form)))
817    (case (length args)
818      (2
819       (let ((test (precompile1 (%car args))))
820         (cond ((null test)
821                nil)
822               (;;(constantp test)
823                (eq test t)
824                (precompile1 (%cadr args)))
825               (t
826                (list 'IF
827                      test
828                      (precompile1 (%cadr args)))))))
829      (3
830       (let ((test (precompile1 (%car args))))
831         (cond ((null test)
832                (precompile1 (%caddr args)))
833               (;;(constantp test)
834                (eq test t)
835                (precompile1 (%cadr args)))
836               (t
837                (list 'IF
838                      test
839                      (precompile1 (%cadr args))
840                      (precompile1 (%caddr args)))))))
841      (t
842       (error "wrong number of arguments for IF")))))
843
844(defun precompile-when (form)
845  (if *in-jvm-compile*
846      (precompile1 (macroexpand form *compile-file-environment*))
847      (precompile-cons form)))
848
849(defun precompile-unless (form)
850  (if *in-jvm-compile*
851      (precompile1 (macroexpand form *compile-file-environment*))
852      (precompile-cons form)))
853
854;; MULTIPLE-VALUE-BIND is handled explicitly by the JVM compiler.
855(defun precompile-multiple-value-bind (form)
856  (let ((vars (cadr form))
857        (values-form (caddr form))
858        (body (cdddr form)))
859    (list* 'MULTIPLE-VALUE-BIND
860           vars
861           (precompile1 values-form)
862           (mapcar #'precompile1 body))))
863
864;; MULTIPLE-VALUE-LIST is handled explicitly by the JVM compiler.
865(defun precompile-multiple-value-list (form)
866  (list 'MULTIPLE-VALUE-LIST (precompile1 (cadr form))))
867
868(defun precompile-nth-value (form)
869  (if *in-jvm-compile*
870      (precompile1 (macroexpand form *compile-file-environment*))
871      form))
872
873(defun precompile-return (form)
874  (if *in-jvm-compile*
875      (precompile1 (macroexpand form *compile-file-environment*))
876      (list 'RETURN (precompile1 (cadr form)))))
877
878(defun precompile-return-from (form)
879  (list 'RETURN-FROM (cadr form) (precompile1 (caddr form))))
880
881(defun precompile-tagbody (form)
882  (do ((body (cdr form) (cdr body))
883       (result ()))
884      ((null body) (cons 'TAGBODY (nreverse result)))
885    (if (atom (car body))
886        (push (car body) result)
887        (push (let* ((first-form (car body))
888                     (expanded (precompile1 first-form)))
889                (if (and (symbolp expanded)
890                         (neq expanded first-form))
891                    ;; Workaround:
892                    ;;  Since our expansion/compilation order
893                    ;;   is out of sync with the definition of
894                    ;;   TAGBODY (which requires the compiler
895                    ;;   to look for tags before expanding),
896                    ;;   we need to disguise anything which might
897                    ;;   look like a tag. We do this by wrapping
898                    ;;   it in a PROGN form.
899                    (list 'PROGN expanded)
900                    expanded)) result))))
901
902(defun precompile-eval-when (form)
903  (list* 'EVAL-WHEN (cadr form) (mapcar #'precompile1 (cddr form))))
904
905(defun precompile-unwind-protect (form)
906  (list* 'UNWIND-PROTECT
907         (precompile1 (cadr form))
908         (mapcar #'precompile1 (cddr form))))
909
910;; EXPAND-MACRO is like MACROEXPAND, but EXPAND-MACRO quits if *IN-JVM-COMPILE*
911;; is false and a macro is encountered that is also implemented as a special
912;; operator, so interpreted code can use the special operator implementation.
913(defun expand-macro (form)
914  (loop
915    (unless *in-jvm-compile*
916      (when (and (consp form)
917                 (symbolp (%car form))
918                 (special-operator-p (%car form)))
919        (return-from expand-macro form)))
920    (multiple-value-bind (result expanded)
921        (macroexpand-1 form *compile-file-environment*)
922      (unless expanded
923        (return-from expand-macro result))
924      (setf form result))))
925
926(declaim (ftype (function (t t) t) precompile-form))
927(defun precompile-form (form in-jvm-compile)
928  (let ((*in-jvm-compile* in-jvm-compile)
929        (*inline-declarations* *inline-declarations*))
930    (precompile1 form)))
931
932(defun install-handler (symbol &optional handler)
933  (declare (type symbol symbol))
934  (let ((handler (or handler
935                     (find-symbol (sys::%format nil "PRECOMPILE-~A" (symbol-name symbol))
936                                  'precompiler))))
937    (unless (and handler (fboundp handler))
938      (error "No handler for ~S." symbol))
939    (setf (get symbol 'precompile-handler) handler)))
940
941(defun install-handlers ()
942  (mapcar #'install-handler '(BLOCK
943                              CASE
944                              COND
945                              DOLIST
946                              DOTIMES
947                              EVAL-WHEN
948                              FUNCTION
949                              IF
950                              LAMBDA
951                              MACROLET
952                              MULTIPLE-VALUE-BIND
953                              MULTIPLE-VALUE-LIST
954                              NAMED-LAMBDA
955                              NTH-VALUE
956                              PROGN
957                              PROGV
958                              PSETF
959                              PSETQ
960                              RETURN
961                              RETURN-FROM
962                              SETF
963                              SETQ
964                              SYMBOL-MACROLET
965                              TAGBODY
966                              UNWIND-PROTECT
967                              UNLESS
968                              WHEN))
969
970  (dolist (pair '((ECASE                precompile-case)
971
972                  (AND                  precompile-cons)
973                  (OR                   precompile-cons)
974
975                  (CATCH                precompile-cons)
976                  (MULTIPLE-VALUE-CALL  precompile-cons)
977                  (MULTIPLE-VALUE-PROG1 precompile-cons)
978
979                  (DO                   precompile-do/do*)
980                  (DO*                  precompile-do/do*)
981
982                  (LET                  precompile-let)
983                  (LET*                 precompile-let*)
984
985                  (LOCALLY              precompile-locally)
986
987                  (FLET                 precompile-flet/labels)
988                  (LABELS               precompile-flet/labels)
989
990                  (LOAD-TIME-VALUE      precompile-load-time-value)
991
992                  (DECLARE              precompile-identity)
993;;                   (DEFMETHOD            precompile-identity)
994                  (DEFUN                precompile-defun)
995                  (GO                   precompile-identity)
996                  (QUOTE                precompile-identity)
997                  (THE                  precompile-the)
998                  (THROW                precompile-cons)
999                  (TRULY-THE            precompile-truly-the)))
1000    (install-handler (first pair) (second pair))))
1001
1002(install-handlers)
1003
1004(in-package #:system)
1005
1006(defun macroexpand-all (form &optional env)
1007  (let ((*compile-file-environment* env))
1008    (precompile-form form nil)))
1009
1010(defmacro compiler-let (bindings &body forms &environment env)
1011  (let ((bindings (mapcar #'(lambda (binding)
1012                              (if (atom binding) (list binding) binding))
1013                          bindings)))
1014    (progv (mapcar #'car bindings)
1015           (mapcar #'(lambda (binding)
1016                       (eval (cadr binding))) bindings)
1017      (macroexpand-all `(progn ,@forms) env))))
1018
1019(defun set-function-definition (name new old)
1020  (let ((*warn-on-redefinition* nil))
1021    (sys::%set-lambda-name new name)
1022    (sys:set-call-count new (sys:call-count old))
1023    (sys::%set-arglist new (sys::arglist old))
1024    (when (macro-function name)
1025      (setf new (make-macro name new)))
1026    (if (typep old 'standard-generic-function)
1027        (mop:set-funcallable-instance-function old new)
1028        (setf (fdefinition name) new))))
1029
1030(defun precompile (name &optional definition)
1031  (unless definition
1032    (setq definition (or (and (symbolp name) (macro-function name))
1033                         (fdefinition name))))
1034  (let (expr result)
1035    (cond ((functionp definition)
1036           (multiple-value-bind (form closure-p)
1037             (function-lambda-expression definition)
1038             (unless form
1039;;                (format t "; No lambda expression available for ~S.~%" name)
1040               (return-from precompile (values nil t t)))
1041             (when closure-p
1042               (format t "; Unable to compile function ~S defined in non-null lexical environment.~%" name)
1043               (finish-output)
1044               (return-from precompile (values nil t t)))
1045             (setq expr form)))
1046          ((and (consp definition) (eq (%car definition) 'lambda))
1047           (setq expr definition))
1048          (t
1049;;            (error 'type-error)))
1050           (format t "Unable to precompile ~S.~%" name)
1051           (return-from precompile (values nil t t))))
1052    (setf result (coerce-to-function (precompile-form expr nil)))
1053    (when (and name (functionp result))
1054      (sys::set-function-definition name result definition))
1055    (values (or name result) nil nil)))
1056
1057(defun precompile-package (pkg &key verbose)
1058  (dolist (sym (package-symbols pkg))
1059    (when (fboundp sym)
1060      (unless (special-operator-p sym)
1061        (let ((f (fdefinition sym)))
1062          (unless (compiled-function-p f)
1063            (when verbose
1064              (format t "Precompiling ~S~%" sym)
1065              (finish-output))
1066            (precompile sym))))))
1067  t)
1068
1069(defun %compile (name definition)
1070  (if (and name (fboundp name) (%typep (symbol-function name) 'generic-function))
1071      (values name nil nil)
1072      (precompile name definition)))
1073
1074;; ;; Redefine EVAL to precompile its argument.
1075;; (defun eval (form)
1076;;   (%eval (precompile-form form nil)))
1077
1078;; ;; Redefine DEFMACRO to precompile the expansion function on the fly.
1079;; (defmacro defmacro (name lambda-list &rest body)
1080;;   (let* ((form (gensym "WHOLE-"))
1081;;          (env (gensym "ENVIRONMENT-")))
1082;;     (multiple-value-bind (body decls)
1083;;         (parse-defmacro lambda-list form body name 'defmacro :environment env)
1084;;       (let ((expander `(lambda (,form ,env) ,@decls (block ,name ,body))))
1085;;         `(progn
1086;;            (let ((macro (make-macro ',name
1087;;                                     (or (precompile nil ,expander) ,expander))))
1088;;              ,@(if (special-operator-p name)
1089;;                    `((put ',name 'macroexpand-macro macro))
1090;;                    `((fset ',name macro)))
1091;;              (%set-arglist macro ',lambda-list)
1092;;              ',name))))))
1093
1094;; Make an exception just this one time...
1095(when (get 'defmacro 'macroexpand-macro)
1096  (fset 'defmacro (get 'defmacro 'macroexpand-macro))
1097  (remprop 'defmacro 'macroexpand-macro))
1098
1099(defvar *defined-functions*)
1100
1101(defvar *undefined-functions*)
1102
1103(defun note-name-defined (name)
1104  (when (boundp '*defined-functions*)
1105    (push name *defined-functions*))
1106  (when (and (boundp '*undefined-functions*) (not (null *undefined-functions*)))
1107    (setf *undefined-functions* (remove name *undefined-functions*))))
1108
1109;; Redefine DEFUN to precompile the definition on the fly.
1110(defmacro defun (name lambda-list &body body &environment env)
1111  (note-name-defined name)
1112  (multiple-value-bind (body decls doc)
1113      (parse-body body)
1114    (let* ((block-name (fdefinition-block-name name))
1115           (lambda-expression
1116            `(named-lambda ,name ,lambda-list
1117                           ,@decls
1118                           ,@(when doc `(,doc))
1119                           (block ,block-name ,@body))))
1120      (cond ((and (boundp 'jvm::*file-compilation*)
1121                  ;; when JVM.lisp isn't loaded yet, this variable isn't bound
1122                  ;; meaning that we're not trying to compile to a file:
1123                  ;; Both COMPILE and COMPILE-FILE bind this variable.
1124                  ;; This function is also triggered by MACROEXPAND, though
1125                  jvm::*file-compilation*)
1126             `(fset ',name ,lambda-expression))
1127            (t
1128             (when (and env (empty-environment-p env))
1129               (setf env nil))
1130             (when (null env)
1131               (setf lambda-expression (precompile-form lambda-expression nil)))
1132             `(progn
1133                (%defun ',name ,lambda-expression)
1134                ,@(when doc
1135                   `((%set-documentation ',name 'function ,doc)))))))))
Note: See TracBrowser for help on using the repository browser.