source: trunk/source/level-1/l1-readloop.lisp @ 12205

Last change on this file since 12205 was 12205, checked in by gz, 10 years ago

Merge r11495, r12082: new options in ccl:quit.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 34.1 KB
Line 
1;;;-*-Mode: LISP; Package: CCL -*-
2;;;
3;;;   Copyright (C) 1994-2001 Digitool, Inc
4;;;   This file is part of OpenMCL. 
5;;;
6;;;   OpenMCL is licensed under the terms of the Lisp Lesser GNU Public
7;;;   License , known as the LLGPL and distributed with OpenMCL as the
8;;;   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
9;;;   which is distributed with OpenMCL as the file "LGPL".  Where these
10;;;   conflict, the preamble takes precedence. 
11;;;
12;;;   OpenMCL is referenced in the preamble as the "LIBRARY."
13;;;
14;;;   The LLGPL is also available online at
15;;;   http://opensource.franz.com/preamble.html
16
17(in-package "CCL")
18
19;L1-readloop.lisp
20
21
22(defvar *break-on-signals* nil
23  "When (TYPEP condition *BREAK-ON-SIGNALS*) is true, then calls to SIGNAL will
24   enter the debugger prior to signalling that condition.")
25(defvar *break-on-warnings* nil)
26(defvar *break-on-errors* t "Not CL.")
27(defvar *debugger-hook* nil
28  "This is either NIL or a function of two arguments, a condition and the value
29   of *DEBUGGER-HOOK*. This function can either handle the condition or return
30   which causes the standard debugger to execute. The system passes the value
31   of this variable to the function because it binds *DEBUGGER-HOOK* to NIL
32   around the invocation.")
33(defvar *backtrace-on-break* nil)
34(defvar *** nil
35  "the previous value of **")
36(defvar ** nil
37  "the previous value of *")
38(defvar * nil
39  "the value of the most recent top level EVAL")
40(defvar /// nil
41  "the previous value of //")
42(defvar // nil
43  "the previous value of /")
44(defvar / nil
45  "a list of all the values returned by the most recent top level EVAL")
46(defvar +++ nil
47  "the previous value of ++")
48(defvar ++ nil
49  "the previous value of +")
50(defvar + nil
51  "the value of the most recent top level READ")
52(defvar - nil
53  "the form currently being evaluated")
54
55(defvar *continuablep* nil)
56(defvar *in-read-loop* nil 
57 "Is T if waiting for input in the read loop")
58
59
60(defvar *did-startup* nil)
61
62
63
64(defmacro catch-cancel (&body body)
65  `(catch :cancel ,@body))
66
67(defmacro throw-cancel (&optional value)
68  `(throw :cancel ,value))
69
70;;; Throwing like this works in listeners and in the initial process.
71;;; Can't easily tell if a process is a listener.  Should be able to.
72(defun toplevel ()
73  (throw :toplevel nil))
74
75
76;;; It's not clear that this is the right behavior, but aborting CURRENT-PROCESS -
77;;; when no one's sure just what CURRENT-PROCESS is - doesn't seem right either.
78(defun interactive-abort ()
79  (interactive-abort-in-process *current-process*))
80
81(defun interactive-abort-in-process (p)
82  (if p (process-interrupt p 
83                           #'(lambda ()
84                               (unless *inhibit-abort*
85                                 (if *in-read-loop* 
86                                        (abort-break)
87                                        (abort))
88                                 )))))
89
90
91(defun abort (&optional condition)
92  "Transfer control to a restart named ABORT, signalling a CONTROL-ERROR if
93   none exists."
94  (invoke-restart-no-return (find-restart 'abort condition)))
95
96(defun continue (&optional condition)
97  "Transfer control to a restart named CONTINUE, or return NIL if none exists."
98  (let ((r (find-restart 'continue condition)))
99    (if r (invoke-restart r))))
100
101(defun muffle-warning (&optional condition)
102  "Transfer control to a restart named MUFFLE-WARNING, signalling a
103   CONTROL-ERROR if none exists."
104  (invoke-restart-no-return (find-restart 'muffle-warning condition)))
105
106(defun abort-break ()
107  (invoke-restart-no-return 'abort-break))
108
109
110(defun quit (&optional (exit 0) &key error-handler)
111  "exit must be either a (signed-byte 32) exit status or a function to call to exit lisp
112   error-handler can be a function of one argument, the condition, that will be called if an
113   error occurs while preparing to quit.  The error handler should exit"
114  (if (or (null exit) (typep exit '(signed-byte 32)))
115    (setq exit (let ((exit-status (or exit 0)))
116                 #'(lambda () (#__exit exit-status))))
117    (unless (typep exit 'function)
118      (report-bad-arg exit '(or (signed-byte 32) function))))
119  (let* ((ip *initial-process*)
120         (cp *current-process*))
121    (when (process-verify-quit ip)
122      (process-interrupt ip
123                         #'(lambda ()
124                             (handler-bind ((error (lambda (c)
125                                                     (when error-handler
126                                                       (funcall error-handler c)))))
127                               (process-exit-application *current-process*
128                                                         #'(lambda ()
129                                                             (%set-toplevel nil)
130                                                             (funcall exit) ;; must exit
131                                                             (bug "Exit function didn't exit"))))))
132      (unless (eq cp ip)
133        (process-kill cp)))))
134
135
136(defloadvar *quitting* nil)
137
138
139(defun prepare-to-quit (&optional part)
140  (let-globally ((*quitting* t))
141    (when (or (null part) (eql 0 part))
142      (dolist (f *lisp-cleanup-functions*)
143        (funcall f)))
144    (let* ((stragglers ()))
145      (dolist (p (all-processes))
146        (unless (or (eq p *initial-process*)
147                    (not (process-active-p p)))
148          (if (process-persistent p)
149            (process-reset p :shutdown)
150            (process-kill p))))
151      (dolist (p (all-processes))
152        (let* ((semaphore (process-termination-semaphore p)))
153          (when semaphore
154            (unless (eq p *initial-process*)
155              (unless (timed-wait-on-semaphore semaphore 0.05)
156                (push p stragglers))))))
157      (dolist (p stragglers)
158        (let* ((semaphore (process-termination-semaphore p)))
159          (maybe-finish-process-kill p :kill)
160          (when semaphore
161            (timed-wait-on-semaphore semaphore 0.10)))))
162    (shutdown-lisp-threads)
163    (loop
164      (let* ((streams (open-file-streams)))
165        (when (null streams) (return))
166        (let* ((ioblock (stream-ioblock (car streams) nil)))
167          (when ioblock
168            (setf (ioblock-inbuf-lock ioblock) nil
169                  (ioblock-outbuf-lock ioblock) nil
170                  (ioblock-owner ioblock) nil)))
171        (close (car streams))))
172    (setf (interrupt-level) -1)         ; can't abort after this
173    )
174  ;; Didn't abort, so really quitting.
175  (setq *quitting* t))
176
177
178(defun signal (condition &rest args)
179  "Invokes the signal facility on a condition formed from DATUM and
180   ARGUMENTS. If the condition is not handled, NIL is returned. If
181   (TYPEP condition *BREAK-ON-SIGNALS*) is true, the debugger is invoked
182   before any signalling is done."
183  (setq condition (condition-arg condition args 'simple-condition))
184  (let* ((*break-on-signals* *break-on-signals*))
185     (let* ((old-bos *break-on-signals*))
186       (when (unknown-ctype-p (let* ((*break-on-signals* nil)) (specifier-type old-bos)))
187         (setq *break-on-signals* nil)
188         (warn "~S : Ignoring invalid type specifier ~s." '*break-on-signals* old-bos)))
189         
190   (when (typep condition *break-on-signals*)
191     (let ((*break-on-signals* nil))
192       (cbreak-loop "Signal" "Signal the condition." condition (%get-frame-ptr)))))
193  (let ((%handlers% %handlers%))
194    (while %handlers%
195      (do* ((tag (pop %handlers%)) (handlers tag (cddr handlers)))
196           ((null handlers))
197        (when (typep condition (car handlers))
198          (let ((fn (cadr handlers)))
199            (cond ((null fn) (throw tag condition))
200                  ((fixnump fn) (throw tag (cons fn condition)))
201                  (t (funcall fn condition)))))))))
202
203(defvar *error-print-circle* nil)   ; reset to T when we actually can print-circle
204
205
206
207;;;***********************************
208;;;Mini-evaluator
209;;;***********************************
210
211(defun new-lexical-environment (&optional parent)
212  (%istruct 'lexical-environment parent nil nil nil nil nil nil))
213
214(defmethod make-load-form ((e lexical-environment) &optional env)
215  (declare (ignore env))
216  nil)
217
218(defun new-definition-environment (&optional (type 'compile-file))
219  (%istruct 'definition-environment (list type)  nil nil nil nil nil nil nil nil nil nil nil nil ))
220
221(defun definition-environment (env &optional clean-only &aux parent)
222  (if (and env (not (istruct-typep env 'lexical-environment))) (report-bad-arg env 'lexical-environment))
223  (do* () 
224       ((or (null env) 
225            (listp (setq parent (lexenv.parent-env env)))
226            (and clean-only (or (lexenv.variables env) (lexenv.functions env)))))
227    (setq env parent))
228  (if (consp parent)
229    env))
230
231(defvar *symbol-macros* (make-hash-table :test #'eq))
232
233(defun %define-symbol-macro (name expansion)
234  (if (or (constant-symbol-p name)
235          (proclaimed-special-p name))
236      (signal-program-error "Symbol ~s already globally defined as a ~A"
237                            name (if (constant-symbol-p name)
238                                     'constant
239                                     'variable)))
240  (setf (gethash name *symbol-macros*) expansion)
241  name)
242
243(defvar *macroexpand-hook* 'funcall
244  "The value of this variable must be a designator for a function that can
245  take three arguments, a macro expander function, the macro form to be
246  expanded, and the lexical environment to expand in. The function should
247  return the expanded form. This function is called by MACROEXPAND-1
248  whenever a runtime expansion is needed. Initially this is set to
249  FUNCALL.") ; Should be #'funcall.
250;(queue-fixup (setq *macroexpand-hook* #'funcall)) ;  No it shouldn't.
251
252(defun %symbol-macroexpand-1 (sym env)
253  (flet ((expand-it (expansion)
254           (funcall *macroexpand-hook*
255                    (constantly expansion)
256                    sym
257                    env)))
258    (if (and env (not (istruct-typep env 'lexical-environment)))
259      (report-bad-arg env 'lexical-environment))
260    (do* ((env env (lexenv.parent-env env)))
261         ((null env))
262      (if (istruct-typep env 'definition-environment)
263        (let* ((info (assq sym (defenv.symbol-macros env))))
264          (if info
265            (return-from %symbol-macroexpand-1 (values (expand-it (cdr info)) t))
266            (return)))
267        (let* ((vars (lexenv.variables env)))
268          (when (consp vars)
269            (let* ((info (dolist (var vars)
270                           (if (eq (var-name var) sym)
271                             (return var)))))           
272              (when info
273                (if (and (consp (setq info (var-expansion info)))
274                         (eq (%car info) :symbol-macro))
275                  (return-from %symbol-macroexpand-1 (values (expand-it (%cdr info)) t))
276                  (return-from %symbol-macroexpand-1 (values sym nil)))))))))
277    ;; Look it up globally.
278    (multiple-value-bind (expansion win) (gethash sym *symbol-macros*)
279      (if win (values (expand-it expansion) t) (values sym nil)))))
280
281(defun macroexpand-all (form &optional (env (new-lexical-environment)))
282  "Recursivly expand all macros in FORM."
283  (flet ((mexpand (forms env)
284           (mapcar (lambda (form) (macroexpand-all form env)) forms)))
285    (macrolet ((destructuring-bind-body (binds form &body body)
286                 (if (eql '&body (first (last binds)))
287                   (let ((&body (gensym "&BODY")))
288                     `(destructuring-bind ,(append (butlast binds) (list '&body &body))
289                          ,form
290                        (multiple-value-bind (body decls)
291                            (parse-body ,&body env nil)
292                          ,@body)))
293                   `(destructuring-bind ,binds ,form ,@body))))
294      (multiple-value-bind (expansion win)
295          (macroexpand-1 form env)
296        (if win
297          (macroexpand-all expansion env)
298          (if (atom form)
299            form
300            (case (first form)
301              (macrolet
302               (destructuring-bind-body (macros &body) (rest form)
303                (setf env (augment-environment env
304                                               :macro (mapcar (lambda (macro)
305                                                                (destructuring-bind
306                                                                      (name arglist &body body)
307                                                                    macro
308                                                                  (list name (enclose (parse-macro name arglist body env)))))
309                                                              macros)
310                                               :declare (decl-specs-from-declarations decls)))
311                (let ((body (mexpand body env)))
312                  (if decls
313                    `(locally ,@decls ,@body)
314                    `(progn ,@body)))))
315              (symbol-macrolet
316               (destructuring-bind-body (symbol-macros &body) (rest form)
317                (setf env (augment-environment env :symbol-macro symbol-macros :declare (decl-specs-from-declarations decls)))
318                (let ((body (mexpand body env)))
319                  (if decls
320                    `(locally ,@decls ,@body)
321                    `(progn ,@body)))))
322              ((let let* compiler-let)
323               (destructuring-bind-body (bindings &body) (rest form)
324                `(,(first form)
325                   ,(mapcar (lambda (binding)
326                             
327                              (if (listp binding)
328                                (list (first binding) (macroexpand-all (second binding) env))
329                                binding))
330                            bindings)
331                   ,@decls
332                   ,@(mexpand body env))))
333              ((flet labels)
334               (destructuring-bind-body (bindings &body) (rest form)
335                `(,(first form)
336                   ,(mapcar (lambda (binding)
337                              (list* (first binding) (cdr (macroexpand-all `(lambda ,@(rest binding)) env))))
338                            bindings)
339                   ,@decls
340                   ,@(mexpand body env))))
341              (nfunction (list* 'nfunction (second form) (macroexpand-all (third form) env)))
342              (function
343                 (if (and (consp (second form))
344                          (eql 'lambda (first (second form))))
345                   (destructuring-bind (lambda arglist &body body&decls)
346                       (second form)
347                     (declare (ignore lambda))
348                     (multiple-value-bind (body decls)
349                         (parse-body body&decls env)
350                       `(lambda ,arglist ,@decls ,@(mexpand body env))))
351                   form))
352              ((eval-when the locally block return-from)
353                 (list* (first form) (second form) (mexpand (cddr form) env)))
354              (setq
355                 `(setq ,@(loop for (name value) on (rest form) by #'cddr
356                                collect name
357                                collect (macroexpand-all value env))))
358              ((go quote) form)
359              ((fbind with-c-frame with-variable-c-frame ppc-lap-function)
360               (error "Unable to macroexpand ~S." form))
361              ((catch if load-time-value multiple-value-call multiple-value-prog1 progn
362                progv tagbody throw unwind-protect)
363               (cons (first form) (mexpand (rest form) env)))
364              (t
365               ;; need to check that (first form) is either fboundp or a local function...
366               (cons (first form) (mexpand (rest form) env))))))))))
367
368(defun macroexpand-1 (form &optional env &aux fn)
369  "If form is a macro (or symbol macro), expand it once. Return two values,
370   the expanded form and a T-or-NIL flag indicating whether the form was, in
371   fact, a macro. ENV is the lexical environment to expand in, which defaults
372   to the null environment."
373  (declare (resident))
374  (if (and (consp form)
375           (symbolp (%car form)))
376    (if (setq fn (macro-function (%car form) env))
377      (values (funcall *macroexpand-hook* fn form env) t)
378      (values form nil))
379    (if (and form (symbolp form))
380      (%symbol-macroexpand-1 form env)
381      (values form nil))))
382
383(defun macroexpand (form &optional env)
384  "Repetitively call MACROEXPAND-1 until the form can no longer be expanded.
385   Returns the final resultant form, and T if it was expanded. ENV is the
386   lexical environment to expand in, or NIL (the default) for the null
387   environment."
388  (declare (resident))
389  (multiple-value-bind (new win) (macroexpand-1 form env)
390    (do* ((won-at-least-once win))
391         ((null win) (values new won-at-least-once))
392      (multiple-value-setq (new win) (macroexpand-1 new env)))))
393
394(defun %symbol-macroexpand (form env &aux win won)
395  ; Keep expanding until no longer a symbol-macro or no longer a symbol.
396  (loop
397    (unless (and form (symbolp form)) (return))
398    (multiple-value-setq (form win) (macroexpand-1 form env))
399    (if win (setq won t) (return)))
400  (values form won))
401
402(defun retain-lambda-expression (name lambda-expression env)
403  (if (and (let* ((lambda-list (cadr lambda-expression)))
404             (and (not (memq '&lap lambda-list))
405                  (not (memq '&method lambda-list))
406                  (not (memq '&lexpr lambda-list))))
407           (nx-declared-inline-p name env)
408           (not (gethash name *nx1-alphatizers*))
409           ; A toplevel definition defined inside a (symbol-)macrolet should
410           ; be inlineable.  It isn't; call DEFINITION-ENVIRONMENT with a
411           ; "clean-only" argument to ensure that there are no lexically
412           ; bound macros or symbol-macros.
413           (definition-environment env t))
414    lambda-expression))
415
416
417(defun %cons-def-info (type &optional lfbits keyvect lambda specializers qualifiers)
418  (ecase type
419    (defun nil)
420    (defmacro (setq lambda '(macro) lfbits nil)) ;; some code assumes lfbits=nil
421    (defgeneric (setq lambda (list :methods)))
422    (defmethod (setq lambda (list :methods (cons qualifiers specializers))))
423    (deftype (setq lambda '(type) lfbits (cons nil *loading-file-source-file*))))
424  (vector lfbits keyvect *loading-file-source-file* lambda))
425
426(defun def-info.lfbits (def-info)
427  (and def-info
428       (let ((lfbits (svref def-info 0)))
429         (if (consp lfbits) (%car lfbits) lfbits))))
430
431(defun def-info.keyvect (def-info)
432  (and def-info (svref def-info 1)))
433
434(defun def-info.file (def-info)
435  (and def-info (svref def-info 2)))
436
437(defun def-info.lambda (def-info)
438  (and def-info
439       (let ((data (svref def-info 3)))
440         (and (eq (car data) 'lambda) data))))
441
442(defun def-info.methods (def-info)
443  (and def-info
444       (let ((data (svref def-info 3)))
445         (and (eq (car data) :methods) (%cdr data)))))
446
447(defun def-info-with-new-methods (def-info new-methods)
448  (if (eq new-methods (def-info.methods def-info))
449    def-info
450    (let ((new (copy-seq def-info)))
451      (setf (svref new 3) (cons :methods new-methods))
452      new)))
453
454(defun def-info.macro-p (def-info)
455  (let ((data (and def-info (svref def-info 3))))
456    (eq (car data) 'macro)))
457
458(defun def-info.function-p (def-info)
459  (not (and def-info (eq (car (svref def-info 3)) 'type))))
460
461(defun def-info.function-type (def-info)
462  (if (null def-info)
463    nil ;; ftype only, for the purposes here, is same as nothing.
464    (let ((data (svref def-info 3)))
465      (ecase (car data)
466        ((nil lambda) 'defun)
467        (:methods 'defgeneric)
468        (macro 'defmacro)
469        (ftype nil)
470        (type nil)))))
471
472(defun def-info.deftype (def-info)
473  (and def-info
474       (let ((bits (svref def-info 0)))
475         ;; bits or (bits . type-source-file)
476         (and (consp bits) bits))))
477
478(defun def-info.deftype-type (def-info)
479  ;; 'class (for defclass/defstruct) or 'macro (for deftype et. al.)
480  (and def-info
481       (consp (svref def-info 0))
482       (svref def-info 1)))
483
484(defparameter *one-arg-defun-def-info* (%cons-def-info 'defun (encode-lambda-list '(x))))
485
486(defvar *compiler-warn-on-duplicate-definitions* t)
487
488(defun combine-deftype-infos (name def-info old-deftype new-deftype)
489  (when (or new-deftype old-deftype)
490    (when (and old-deftype new-deftype *compiler-warn-on-duplicate-definitions*)
491      (nx1-whine :duplicate-definition
492                 `(type ,name)
493                 (cdr old-deftype)
494                 (cdr new-deftype)))
495    (let ((target (if new-deftype
496                      (or (cdr new-deftype) (cdr old-deftype))
497                      (cdr old-deftype)))
498          (target-deftype (def-info.deftype def-info)))
499      (unless (and target-deftype (eq (cdr target-deftype) target))
500        (setq def-info (copy-seq (or def-info '#(nil nil nil (ftype)))))
501        (setf (svref def-info 0) (cons (def-info.lfbits def-info) target)))))
502  def-info)
503
504#+debug
505(defun describe-def-info (def-info)
506  (list :lfbits (def-info.lfbits def-info)
507        :keyvect (def-info.keyvect def-info)
508        :macro-p (def-info.macro-p def-info)
509        :function-p (def-info.function-p def-info)
510        :lambda (and (def-info.function-p def-info) (def-info.lambda def-info))
511        :methods (and (def-info.function-p def-info) (def-info.methods def-info))
512        :function-type (def-info.function-type def-info)
513        :deftype (def-info.deftype def-info)
514        :deftype-type (def-info.deftype-type def-info)))
515
516(defun combine-definition-infos (name old-info new-info)
517  (let ((old-type (def-info.function-type old-info))  ;; defmacro
518        (old-deftype (def-info.deftype old-info))      ;; nil
519        (new-type (def-info.function-type new-info))  ;; nil
520        (new-deftype (def-info.deftype new-info)))   ;; (nil . file)
521    (cond ((and (eq old-type 'defgeneric) (eq new-type 'defgeneric))
522           ;; TODO: Check compatibility of lfbits...
523           ;; TODO: check that all methods implement defgeneric keys
524           (let ((old-methods (def-info.methods old-info))
525                 (new-methods (def-info.methods new-info)))
526             (loop for new-method in new-methods
527                   do (if (member new-method old-methods :test #'equal)
528                        (when *compiler-warn-on-duplicate-definitions*
529                          (nx1-whine :duplicate-definition
530                                     `(method ,@(car new-method) ,name ,(cdr new-method))
531                                     (def-info.file old-info)
532                                     (def-info.file new-info)))
533                        (push new-method old-methods)))
534             (setq new-info (def-info-with-new-methods old-info old-methods))))
535          ((or (eq (or old-type 'defun) (or new-type 'defun))
536               (eq (or old-type 'defgeneric) (or new-type 'defgeneric)))
537           (when (and old-type new-type *compiler-warn-on-duplicate-definitions*)
538             (nx1-whine :duplicate-definition name (def-info.file old-info) (def-info.file new-info)))
539           (unless new-info (setq new-info old-info)))
540          (t
541           (when (and (def-info.function-p old-info) (def-info.function-p new-info)
542                      *compiler-warn-on-duplicate-definitions*)
543             (apply #'nx1-whine :duplicate-definition
544                    name
545                    (def-info.file old-info)
546                    (def-info.file new-info)
547                    (cond ((eq old-type 'defmacro) '("macro" "function"))
548                          ((eq new-type 'defmacro) '("function" "macro"))
549                          ((eq old-type 'defgeneric) '("generic function" "function"))
550                          (t '("function" "generic function")))))
551           (unless new-type (setq new-info old-info))))
552    (combine-deftype-infos name new-info old-deftype new-deftype)))
553
554(defun record-definition-info (name info env)
555  (let* ((definition-env (definition-environment env)))
556    (if definition-env
557      (let* ((defs (defenv.defined definition-env))
558             (already (if (listp defs) (assq name defs) (gethash name defs))))
559        (if already
560          (setf (%cdr already) (combine-definition-infos name (%cdr already) info))
561          (let ((outer (loop for defer = (cdr (defenv.type definition-env))
562                               then (deferred-warnings.parent defer)
563                             while (typep defer 'deferred-warnings)
564                             thereis (gethash name (deferred-warnings.defs defer)))))
565            (when outer
566              (setq info (combine-definition-infos name (%cdr outer) info)))
567            (let ((new (cons name info)))
568              (if (listp defs)
569                (setf (defenv.defined definition-env) (cons new defs))
570                (setf (gethash name defs) new)))))
571        info))))
572
573(defun record-function-info (name info env)
574  (record-definition-info name info env))
575
576;;; This is different from AUGMENT-ENVIRONMENT.
577(defun note-function-info (name lambda-expression env)
578  (let* ((info nil)
579         (name (maybe-setf-function-name name)))
580    (when (lambda-expression-p lambda-expression)
581      (multiple-value-bind (lfbits keyvect) (encode-lambda-list (cadr lambda-expression) t)
582        (setq info (%cons-def-info 'defun lfbits keyvect
583                                   (retain-lambda-expression name lambda-expression env)))))
584    (record-function-info name info env))
585  name)
586
587(defun note-type-info (name kind env)
588  (record-definition-info name (%cons-def-info 'deftype nil kind) env))
589
590
591; And this is different from FUNCTION-INFORMATION.
592(defun retrieve-environment-function-info (name env)
593 (let ((defenv (definition-environment env)))
594   (when defenv
595     (let* ((defs (defenv.defined defenv))
596            (sym (maybe-setf-function-name name))
597            (info (if (listp defs) (assq sym defs) (gethash sym defs))))
598       (and info (def-info.function-p (cdr info)) info)))))
599
600;;; Must differ from -something-, but not sure what ...
601(defun note-variable-info (name info env)
602  (let ((definition-env (definition-environment env)))
603    (if definition-env (push (cons name info) (defenv.specials definition-env)))
604    name))
605
606(defun compile-file-environment-p (env)
607  (let ((defenv (definition-environment env)))
608    (and defenv (eq 'compile-file (car (defenv.type defenv))))))
609
610(defun cheap-eval (form)
611  (cheap-eval-in-environment form nil))
612
613; used by nfcomp too
614; Should preserve order of decl-specs; it sometimes matters.
615(defun decl-specs-from-declarations (declarations)
616  (let ((decl-specs nil))
617    (dolist (declaration declarations decl-specs)
618      ;(unless (eq (car declaration) 'declare) (say "what"))
619      (dolist (decl-spec (cdr declaration))
620        (setq decl-specs (nconc decl-specs (list decl-spec)))))))
621
622(defun cheap-eval-macroexpand-1 (form env)
623  (multiple-value-bind (new win) (macroexpand-1 form env)
624    (when win
625      (note-source-transformation form new))
626    (values new win)))
627
628(defun cheap-eval-transform (original new)
629  (note-source-transformation original new)
630  new)
631
632(defun cheap-eval-function (name lambda env)
633  (multiple-value-bind (lfun warnings)
634                       (compile-named-function lambda
635                                               :name name
636                                               :env env
637                                               :function-note *loading-toplevel-location*
638                                               :keep-lambda *save-definitions*
639                                               :keep-symbols *save-local-symbols*
640                                               :source-notes *nx-source-note-map*)
641    (signal-or-defer-warnings warnings env)
642    lfun))
643
644(fset 'nx-source-note (nlambda bootstrapping-source-note (form) (declare (ignore form)) nil))
645
646(defun cheap-eval-in-environment (form env &aux sym)
647  (declare (resident))
648  ;; records source locations if *nx-source-note-map* is bound by caller
649  (setq *loading-toplevel-location* (or (nx-source-note form) *loading-toplevel-location*))
650  (flet ((progn-in-env (body&decls parse-env base-env)
651           (multiple-value-bind (body decls) (parse-body body&decls parse-env)
652             (setq base-env (augment-environment base-env :declare (decl-specs-from-declarations decls)))
653             (loop with default-location = *loading-toplevel-location*
654               while (cdr body) as form = (pop body)
655               do (cheap-eval-in-environment form base-env)
656               do (setq *loading-toplevel-location* default-location))
657             (cheap-eval-in-environment (car body) base-env))))
658    (if form
659      (cond ((symbolp form) 
660             (multiple-value-bind (expansion win) (cheap-eval-macroexpand-1 form env)
661               (if win 
662                 (cheap-eval-in-environment expansion env)
663                 (let* ((defenv (definition-environment env))
664                        (constant (if defenv (assq form (defenv.constants defenv))))
665                        (constval (%cdr constant)))
666                   (if constant
667                     (if (neq (%unbound-marker-8) constval)
668                       constval
669                       (error "Can't determine value of constant symbol ~s" form))
670                     (if (constant-symbol-p form)
671                       (%sym-global-value form)
672                       (symbol-value form)))))))
673            ((atom form) form)
674            ((eq (setq sym (%car form)) 'quote)
675             (verify-arg-count form 1 1)
676             (%cadr form))
677            ((eq sym 'function)
678             (verify-arg-count form 1 1)
679             (cond ((symbolp (setq sym (%cadr form)))
680                    (multiple-value-bind (kind local-p)
681                        (function-information sym env)
682                      (if (and local-p (eq kind :macro))
683                        (error "~s can't be used to reference lexically defined macro ~S" 'function sym)))
684                    (%function sym))
685                   ((and (consp sym) (eq (%car sym) 'setf) (consp (%cdr sym)) (null (%cddr sym)))
686                    (multiple-value-bind (kind local-p)
687                        (function-information sym env)
688                      (if (and local-p (eq kind :macro))
689                        (error "~s can't be used to reference lexically defined macro ~S" 'function sym)))
690                    (%function (setf-function-name (%cadr sym))))
691                   (t (cheap-eval-function nil sym env))))
692            ((eq sym 'nfunction)
693             (verify-arg-count form 2 2)
694             (cheap-eval-function (%cadr form) (%caddr form) env))
695            ((eq sym 'progn) (progn-in-env (%cdr form) env env))
696            ((eq sym 'setq)
697             (if (not (%ilogbitp 0 (list-length form)))
698               (verify-arg-count form 0 0)) ;Invoke a "Too many args" error.
699             (let* ((sym nil)
700                    (val nil)
701                    (original form))
702               (while (setq form (%cdr form))
703                 (setq sym (require-type (pop form) 'symbol))
704                 (multiple-value-bind (expansion expanded)
705                                      (cheap-eval-macroexpand-1 sym env)
706                   (if expanded
707                     (setq val (cheap-eval-in-environment
708                                (cheap-eval-transform original `(setf ,expansion ,(%car form)))
709                                env))
710                     (set sym (setq val (cheap-eval-in-environment (%car form) env))))))
711               val))
712            ((eq sym 'eval-when)
713             (destructuring-bind (when . body) (%cdr form)
714               (when (or (memq 'eval when) (memq :execute when)) (progn-in-env body env env))))
715            ((eq sym 'if)
716             (destructuring-bind (test true &optional false) (%cdr form)
717               (setq test (let ((*loading-toplevel-location* *loading-toplevel-location*))
718                            (cheap-eval-in-environment test env)))
719               (cheap-eval-in-environment (if test true false) env)))
720            ((eq sym 'locally) (progn-in-env (%cdr form) env env))
721            ((eq sym 'symbol-macrolet)
722             (multiple-value-bind (body decls) (parse-body (cddr form) env)
723               (progn-in-env body env (augment-environment env :symbol-macro (cadr form) :declare (decl-specs-from-declarations decls)))))
724            ((eq sym 'macrolet)
725             (let ((temp-env (augment-environment env
726                                                  :macro 
727                                                  (mapcar #'(lambda (m)
728                                                              (destructuring-bind (name arglist &body body) m
729                                                                (list name (enclose (parse-macro name arglist body env)
730                                                                                    env))))
731                                                          (cadr form)))))
732               (progn-in-env (cddr form) temp-env temp-env)))
733            ((and (symbolp sym) 
734                  (compiler-special-form-p sym)
735                  (not (functionp (fboundp sym))))
736             (if (eq sym 'unwind-protect)
737               (destructuring-bind (protected-form . cleanup-forms) (cdr form)
738                 (unwind-protect
739                     (let ((*loading-toplevel-location* *loading-toplevel-location*))
740                       (cheap-eval-in-environment protected-form env))
741                   (progn-in-env cleanup-forms env env)))
742               (funcall (cheap-eval-function nil (cheap-eval-transform form `(lambda () (progn ,form))) env))))
743            ((and (symbolp sym) (macro-function sym env))
744             (cheap-eval-in-environment (cheap-eval-macroexpand-1 form env) env))
745            ((or (symbolp sym)
746                 (and (consp sym) (eq (%car sym) 'lambda)))
747             (let ((args nil) (form-location *loading-toplevel-location*))
748               (dolist (elt (%cdr form))
749                 (push (cheap-eval-in-environment elt env) args)
750                 (setq *loading-toplevel-location* form-location))
751               (apply #'call-check-regs (if (symbolp sym) sym (cheap-eval-function nil sym env))
752                      (nreverse args))))
753            (t (signal-simple-condition 'simple-program-error "Car of ~S is not a function name or lambda-expression." form))))))
754
755
756(%fhave 'eval #'cheap-eval)
757
758
759
760 
761(defun call-check-regs (fn &rest args)
762  (declare (dynamic-extent args)
763           (optimize (debug 3)))        ; don't use any saved registers
764  (let ((old-regs (multiple-value-list (get-saved-register-values))))
765    (declare (dynamic-extent old-regs))
766    (multiple-value-prog1 (apply fn args)
767      (let* ((new-regs (multiple-value-list (get-saved-register-values)))
768             (new-regs-tail new-regs))
769        (declare (dynamic-extent new-regs))
770        (unless (dolist (old-reg old-regs t)
771                  (unless (eq old-reg (car new-regs-tail))
772                    (return nil))
773                  (pop new-regs-tail))
774          (apply 'error "Registers clobbered applying ~s to ~s~%~@{~a sb: ~s, Was: ~s~%~}"
775                 fn args
776                 (mapcan 'list
777                         (let ((res nil))
778                           (dotimes (i (length old-regs))
779                             (push (format nil "save~d" i) res))
780                           (nreverse res))
781                         old-regs
782                         new-regs)))))))
783
784
785
786
787
788;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
789;; Stack frame accessors.
790
791; Kinda scant, wouldn't you say ?
792
793
794;end of L1-readloop.lisp
795
Note: See TracBrowser for help on using the repository browser.