Remove SIMPLE-EVAL-IN-LEXENV with #!+sb-fasteval
[sbcl.git] / src / interpreter / special-forms.lisp
blobebab4b34d0504dacf2dab6a9124b41828147b6e1
1 ;;;; This software is part of the SBCL system. See the README file for
2 ;;;; more information.
3 ;;;;
4 ;;;; This software is derived from the CMU CL system, which was
5 ;;;; written at Carnegie Mellon University and released into the
6 ;;;; public domain. The software is in the public domain and is
7 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
8 ;;;; files for more information.
10 (in-package "SB-INTERPRETER")
12 ;;; Return a THE form that wraps EXPRESSION, but if CTYPE is NIL,
13 ;;; just return EXPRESSION.
14 (defun cast-to (ctype expression)
15 (aver (neq ctype *universal-type*)) ; should never store this
16 (if ctype `(the ,ctype ,expression) expression))
18 ;;; Given a list of FORMS, return a vector of SEXPRs that will eval those.
19 ;;; There "should" be more than one SEXPR because any PROGN-like form with
20 ;;; less than 2 subforms should have the singleton (or NIL) form lifted
21 ;;; to its containing SEXPR by that SEXPR's digester. Lifting happens
22 ;;; automatically when you use %PROGN to build a list of subforms.
23 ;;; i.e. (PROGN (PROGN FOO)) == FOO after twice lifting.
24 ;;;
25 ;;; Pathological silly examples:
26 ;;; 1) Loop using a circular list does not work.
27 ;;; This works ok in purely recursive-descent EVAL, but is precluded
28 ;;; by VECTOR-OF-SEXPR asking for list-length of the PROGN form.
29 ;;; (BLOCK X (let ((I 0)) .
30 ;;; #1=((IF (< (INCF I) 10) (PRINT I) (RETURN-FROM X)) . #1#)))
31 ;;;
32 ;;; 2) Factorial by recursing in syntax rather than semantics works
33 ;;; because it's CAR circular, not CDR circular.
34 ;;; (#1=(LAMBDA (N) (IF (ZEROP N) 1 (* N (#1# (1- N))))) 6)
35 ;;; Athough it forces an awful lot of consing on each recursion.
36 (defun vector-of-sexpr (forms)
37 (let ((n (list-length forms)))
38 (cond ((null n) (error "Circular form"))
39 ((eql n 0) '#()) ; all empty vectors are the same to me
41 (let ((a (make-array n)))
42 (loop for i from 0 for elt in forms
43 do (setf (svref a i) (%sexpr elt)))
44 a)))))
46 ;;; Return a handler for a SEXPR which reads SYMBOL in ENV.
47 ;;; If TYPE is non-nil, it is a CTYPE to check against.
48 ;;; Unlike for handlers defined with DEFSPECIAL, this one both
49 ;;; preprocesses the sexpr *and* evals the symbol immediately.
50 ;;;
51 ;;; Todo: some re-testing of (INFO :VARIABLE :KIND) can be eliminated if
52 ;;; we just touch the *globaldb-cookie* whenever a global macro or symbol-macro
53 ;;; is defined or redefined (incl. a global variable changing its :KIND).
54 ;;; This might be more efficient than, and is definitely simpler than, the
55 ;;; checks below. On the other hand, we only need to kill memoized data
56 ;;; when strange stuff happens that can't be anticipated, of which there
57 ;;; are vanishingly few reasons now.
58 ;;;
59 (defun symeval (symbol env sexpr)
60 (binding* (((binding kind frame-ptr expansion) (find-lexical-var env symbol))
61 (type (var-type-assertion env symbol binding :read)))
62 (if kind ; lexically apparent binding (possibly special or macro)
63 (if (eq kind :macro)
64 ;; digest-form would lose the type constraint, so pass it in using
65 ;; a THE wrapper. We use the same hack as in the compiler:
66 ;; THE is supposed to take a type-specifier but we allow a CTYPE
67 ;; to avoid unparsing and reparsing.
68 (digest-form (cast-to type (symexpand env symbol expansion))
69 env sexpr)
70 (progn
71 (setf (sexpr-handler sexpr)
72 (if (eq kind :special)
73 (specvar-reffer symbol type)
74 (lexvar-reffer frame-ptr type)))
75 (%dispatch sexpr env))) ; DISPATCH would be fine but for the noise
76 (case (info :variable :kind symbol)
77 (:macro
78 ;; Interestingly it's not even a style warning to redefine
79 ;; a global symbol-macro.
80 (let* ((expanded-form (symexpand env symbol))
81 (expanded-sexpr (%sexpr (cast-to type expanded-form))))
82 (setf
83 (sexpr-handler sexpr)
84 (if (and type (neq type *universal-type*))
85 ;; Don't need to additionally capture the original expansion
86 ;; because it is available as the third subform of (THE).
87 (hlambda SYMEVAL (symbol expanded-sexpr) (env sexpr)
88 (multiple-value-bind (x winp)
89 (info :variable :macro-expansion symbol)
90 (if (and winp (eq (third (sexpr-form expanded-sexpr)) x))
91 (dispatch expanded-sexpr env)
92 (digest-form symbol env sexpr))))
93 (hlambda SYMEVAL (symbol expanded-sexpr) (env sexpr)
94 (multiple-value-bind (x winp)
95 (info :variable :macro-expansion symbol)
96 (if (and winp (eq (sexpr-form expanded-sexpr) x))
97 (dispatch expanded-sexpr env)
98 (digest-form symbol env sexpr))))))
99 (dispatch expanded-sexpr env)))
100 (:alien
101 ;; can there be a type restriction?
102 (let ((info (info :variable :alien-info symbol)))
103 (setf (sexpr-handler sexpr)
104 (hlambda SYMEVAL (symbol info) (env sexpr)
105 (if (eq (info :variable :alien-info symbol) info)
106 (%heap-alien info)
107 (digest-form symbol env sexpr))))
108 (%heap-alien info)))
109 (t ; everything else
110 ;; The PARANOID argument to SPECVAR-REFFER is not a safety-related
111 ;; quality - it affects convenience, which is considered inversely
112 ;; correlated to SPEED.
113 (setf (sexpr-handler sexpr)
114 (specvar-reffer symbol type (< (policy env speed) 2)))
115 (%dispatch sexpr env)))))) ; DISPATCH would be fine but for the noise
117 (defun immediate-setq-1 (symbol newval env)
118 (binding* (((binding kind frame-ptr value) (find-lexical-var env symbol))
119 (type (var-type-assertion env symbol binding :write)))
120 (flet ((setf-it (expansion)
121 (%eval `(setf ,expansion ,(cast-to type newval)) env))
122 (eval-it ()
123 (let ((newval (%eval newval env)))
124 (when type
125 (unless (itypep newval type)
126 (typecheck-fail symbol newval type)))
127 newval)))
128 (if kind ; lexically apparent binding (possibly special or macro)
129 (if (eq kind :macro)
130 (setf-it (symexpand env symbol value))
131 (let ((newval (eval-it)))
132 (if (eq kind :special)
133 (set symbol newval)
134 (setf (%cell-ref env frame-ptr) newval))))
135 (case (info :variable :kind symbol)
136 (:macro
137 (setf-it (symexpand env symbol)))
138 (:alien
139 (locally
140 (declare (muffle-conditions compiler-note)) ; can't open-code
141 (setf (%heap-alien (info :variable :alien-info symbol))
142 (eval-it))))
143 (t ; everything else - no need to check for constants
144 ;; as the runtime will signal an error.
145 (set symbol (eval-it))))))))
147 ;;; Perform a SETQ, verifying that the variable still is of the kind it was
148 ;;; when the form was digested.
149 ;;; Like SYMEVAL and unlike handlers defined with DEFSPECIAL, this one both
150 ;;; preprocesses the sexpr *and* performs its action.
151 ;;; Todo: figure out what global changes in :KIND are actually possible,
152 ;;; such as :macro -> :constant. Some of them generate continuable errors
153 ;;; and some not; but by hacking on globaldb you can do anything you want.
154 ;;; The globaldb cookie will take care of any loose ends.
155 (defun deferred-setq-1 (symbol newval env sexpr)
156 (binding* (((binding kind frame-ptr expansion) (find-lexical-var env symbol))
157 (type (var-type-assertion env symbol binding :write)))
158 (aver (neq type *universal-type*))
159 (if kind ; lexically apparent binding (possibly special or macro)
160 (if (eq kind :macro)
161 ;; symbol-macros are handled as if the form were SETF
162 (digest-form `(setf ,(symexpand env symbol expansion)
163 ,(cast-to type newval)) env sexpr)
164 (let ((newval (%sexpr newval)))
165 (setf (sexpr-handler sexpr)
166 (if (eq kind :special)
167 ;; It is unusual to more restrictively constrain a
168 ;; special var than by its globally declaimed type
169 ;; which is checked by SET, but check again anyway.
170 (if type
171 (hlambda SETQ (newval symbol type) (env)
172 (let ((newval (dispatch newval env)))
173 (if (itypep newval type)
174 (set symbol newval)
175 (typecheck-fail symbol newval type))))
176 (hlambda SETQ (newval symbol) (env)
177 (set symbol (dispatch newval env))))
178 (lexvar-setter frame-ptr newval type)))
179 (%dispatch sexpr env)))
180 (case (info :variable :kind symbol)
181 (:macro
182 (digest-form `(setf ,(symexpand env symbol) ,(cast-to type newval))
183 env sexpr)
184 (%dispatch sexpr env))
185 (:alien
186 (let ((info (info :variable :alien-info symbol))
187 (newval (%sexpr newval)))
188 ;; don't care that we're unable to optimize %HEAP-ALIEN
189 (setf (sexpr-handler sexpr)
190 (hlambda SETQ (newval symbol info) (env sexpr)
191 (if (eq (info :variable :alien-info symbol) info)
192 (locally (declare (muffle-conditions compiler-note))
193 (setf (%heap-alien info) (dispatch newval env)))
194 (digest-form (sexpr-form sexpr) env sexpr))))
195 (%dispatch sexpr env)))
196 (t ; everything else
197 ;; FIXME: missing type check
198 (let ((newval (%sexpr newval)))
199 (setf (sexpr-handler sexpr)
200 (hlambda SETQ (newval symbol) (env sexpr)
201 (if (member (info :variable :kind symbol) '(:alien :macro))
202 (digest-form (sexpr-form sexpr) env sexpr)
203 (set symbol (dispatch newval env)))))
204 (set symbol (dispatch newval env))))))))
206 ;; Return a handler for, but do not evaluate, a list of FORMS.
207 (defun digest-progn (forms)
208 (cond ((not forms) (return-constant nil))
209 ((not (cdr forms)) (handler #'digest-form (first forms)))
210 ((not (cddr forms))
211 (let ((one (%sexpr (first forms))) (two (%sexpr (second forms))))
212 (hlambda PROGN (one two) (env)
213 (dispatch one env) (dispatch two env))))
214 ((not (list-length forms))
215 (error "Circular list"))
217 ;; Convert to a vector of sexprs.
218 ;; Alternatively, could express in terms of prog2 and progn,
219 ;; which would allow this evaluator to handle circular forms,
220 ;; albeit with great inefficiency.
221 (let ((forms (nreverse (vector-of-sexpr forms))))
222 (hlambda PROGN (forms) (env)
223 (declare (simple-vector forms))
224 (let ((i (1- (length forms))))
225 (loop (dispatch (svref forms i) env)
226 (if (zerop (decf i)) (return))))
227 (dispatch (svref forms 0) env))))))
229 ;;; Some simple handlers
231 (defun eval-progn (body env) ; Immediate-mode handler for PROGN
232 (let ((previous-exp nil))
233 (dolist (exp body)
234 (if previous-exp
235 (%eval previous-exp env))
236 (setf previous-exp exp))
237 ;; Preserve tail call
238 (%eval previous-exp env)))
240 (defspecial progn (&rest forms)
241 :immediate (env) (eval-progn forms env)
242 :deferred () (digest-progn forms))
244 (defspecial quote (object)
245 :immediate () object
246 :deferred () (return-constant object))
248 ;;; Special operator THE can use local-call for its helper functions.
249 (flet ((enforce-values-types (type &rest values)
250 (declare (optimize (safety 0)))
251 ;; Check VALUES against TYPE and return all the values.
252 ;; This should not cons except on error.
253 ;; NTH on a &REST list is random-access, not a pointer traversal.
254 ;; [cf. comment in src/code/numbers.lisp re. "very clever"
255 ;; versus "charmingly naive"]
256 (let ((i 0) (n (length values)) (rest (values-type-rest type)))
257 (declare (index i))
258 (tagbody
259 (dolist (x (values-type-required type))
260 (if (or (>= i n) (not (itypep (nth i values) x)))
261 (go fail))
262 (incf i))
263 (dolist (x (values-type-optional type))
264 (cond ((>= i n) (go done))
265 ((not (itypep (nth i values) x))
266 (go fail)))
267 (incf i))
268 (if (= i n) (go done))
269 (if (not rest) (go fail))
270 rest
271 (unless (itypep (nth i values) rest)
272 (go fail))
273 (if (< (incf i) n) (go rest))
274 done
275 (return-from enforce-values-types (apply #'values values))
276 fail)
277 ;; Punting keeps the consing out of this function so that I can
278 ;; determine that the non-consing claim remains true.
279 (apply #'values-typecheck-fail type values)))
281 ;; Check the first of VALUES against TYPE and return all values.
282 ;; Unlike ENFORCE-TYPE, this returns all VALUES though only one
283 ;; was expected. This should not cons except on error.
284 (enforce-single-type (type &rest values)
285 (cond ((null values)
286 (error "~S received no values"
287 (list 'the (specifier-from-checkfun type))))
288 ((itypep (first values) type)
289 (apply #'values values))
291 (error 'type-error
292 :datum (first values)
293 :expected-type (specifier-from-checkfun type)))))
295 (parse-type (spec-or-obj)
296 (type-checker
297 (if (ctype-p spec-or-obj)
298 spec-or-obj
299 (values-specifier-type spec-or-obj)))))
301 ;; If a THE form returns multiple values we have to propagate all of them
302 ;; even if it was not (THE (VALUES ...))
303 ;; If TYPE contains an unknown type, it'll be allowed it as long as it
304 ;; is not reached. (typep 3 '(and (not integer) no-such-type)) returns NIL.
305 (defspecial the (type-specifier form)
306 :immediate (env)
307 ;; If speed is more important than safety, don't process THE forms.
308 (if (policy env (> speed safety))
309 (%eval form env)
310 (let ((type (parse-type type-specifier)))
311 (multiple-value-call (if (sb-kernel::%values-type-p type)
312 #'enforce-values-types
313 #'enforce-single-type)
314 type (%eval form env))))
315 :deferred (env)
316 (if (policy env (> speed safety))
317 (handler #'digest-form form)
318 (let ((type (parse-type type-specifier)))
319 (if (eq type *universal-type*) ; don't type-check if T
320 (handler #'digest-form form)
321 (let ((form (%sexpr form)))
322 (if (sb-kernel::%values-type-p type)
323 (hlambda THE/MULTI (type form) (env)
324 (multiple-value-call #'enforce-values-types
325 type (dispatch form env)))
326 (hlambda THE/SINGLE (type form) (env)
327 (multiple-value-call #'enforce-single-type
328 type (dispatch form env))))))))))
330 ;;; Even though TRULY-THE has a macroexpander into THE, it would
331 ;;; be suboptimal to use that because it would force type-checking
332 ;;; when the entire point is to skip checking.
333 (defspecial truly-the (type-specifier form)
334 ;; Perhaps this should at least parse the specifier?
335 :immediate (env) type-specifier ; ignoring it
336 (%eval form env)
337 :deferred () type-specifier ; ignoring it
338 (handler #'digest-form form))
340 (defspecial if (test then &optional else)
341 :immediate (env) (if (%eval test env) (%eval then env) (%eval else env))
342 :deferred ()
343 ;; Many common idioms (builtin or otherwise) expand to IF with
344 ;; only one consequent.
345 (let ((test (%sexpr test)) (then (%sexpr then)) (else (%sexpr else)))
346 (cond ((and then else)
347 (hlambda IF (test then else) (env)
348 (if (dispatch test env) (dispatch then env) (dispatch else env))))
349 ((and then (not else))
350 (hlambda IF (test then) (env)
351 (if (dispatch test env) (dispatch then env))))
352 ((and (not then) else)
353 (hlambda IF (test else) (env)
354 (if (dispatch test env) nil (dispatch else env))))
356 ;; Does (IF (HAIRY-TEST) nil nil) actually occur in real life?
357 (hlambda IF (test) (env)
358 (dispatch test env)
359 nil)))))
361 (defspecial catch (tag &body forms)
362 :immediate (env) (catch (%eval tag env) (eval-progn forms env))
363 :deferred ()
364 (let ((tag (%sexpr tag)) (forms (%progn forms)))
365 (hlambda CATCH (tag forms) (env)
366 (catch (dispatch tag env) (dispatch forms env)))))
368 (defspecial throw (tag result)
369 :immediate (env) (throw (%eval tag env) (%eval result env))
370 :deferred ()
371 (let ((tag (%sexpr tag)) (result (%sexpr result)))
372 (hlambda THROW (tag result) (env)
373 (throw (dispatch tag env) (dispatch result env)))))
375 (defspecial unwind-protect (protected-form &rest cleanup-forms)
376 :immediate (env)
377 (unwind-protect (%eval protected-form env)
378 (eval-progn cleanup-forms env))
379 :deferred ()
380 (let ((protected-form (%sexpr protected-form))
381 (cleanup-forms (%progn cleanup-forms)))
382 (hlambda UNWIND-PROTECT (protected-form cleanup-forms) (env)
383 (unwind-protect (dispatch protected-form env)
384 (dispatch cleanup-forms env)))))
386 (defspecial progv (symbols values &body forms)
387 :immediate (env)
388 (progv (%eval symbols env) (%eval values env) (eval-progn forms env))
389 :deferred ()
390 (let ((symbols (%sexpr symbols)) (values (%sexpr values))
391 (forms (%progn forms)))
392 (hlambda PROGV (symbols values forms) (env)
393 (progv (dispatch symbols env) (dispatch values env)
394 (dispatch forms env)))))
396 (defspecial load-time-value (form &optional read-only-p)
397 (declare (ignore read-only-p))
398 :immediate () (%eval form nil)
399 ;; full-eval used the enviroment here. CLHS says use the null environment.
400 ;; I wonder if the true intent was to use the macro and symbol-macro
401 ;; environment but otherwise have no lexical bindings visible?
402 ;; In other words, is this allowed?
403 ;; (macrolet ((foo (x) `(car ,x))) (load-time-value (foo (thing)))
404 ;; The compiler seems not to think so, but CLHS is ambiguous.
405 :deferred () (return-constant (%eval form nil)))
407 (defspecial multiple-value-call (function &rest forms)
408 :immediate (env)
409 (apply (%eval function env)
410 (loop for form in forms
411 nconc (multiple-value-list (%eval form env))))
412 ;; Todo: specialize when FUNCTION satisfies QUOTED-FUNCTION-NAME-P ?
413 :deferred ()
414 (if (not forms)
415 (handler #'digest-form `(funcall ,function))
416 (let ((function (%sexpr function)))
417 (cond ((not (cdr forms))
418 (let ((form (%sexpr (car forms))))
419 (hlambda MULTIPLE-VALUE-CALL (function form) (env)
420 (locally (declare (muffle-conditions compiler-note))
421 (multiple-value-call (dispatch function env)
422 (dispatch form env))))))
423 ((not (cddr forms))
424 (let ((a (%sexpr (car forms))) (b (%sexpr (cadr forms))))
425 (hlambda MULTIPLE-VALUE-CALL (function a b) (env)
426 (locally (declare (muffle-conditions compiler-note))
427 (multiple-value-call (dispatch function env)
428 (dispatch a env) (dispatch b env))))))
430 (let ((forms (vector-of-sexpr forms)))
431 (hlambda MULTIPLE-VALUE-CALL (function forms) (env)
432 (locally (declare (muffle-conditions compiler-note))
433 (apply (dispatch function env)
434 (loop for x across (the simple-vector forms)
435 nconc (multiple-value-list
436 (dispatch x env))))))))))))
438 (defspecial multiple-value-prog1 (first-form &rest more-forms)
439 :immediate (env)
440 (multiple-value-prog1 (%eval first-form env) (eval-progn more-forms env))
441 :deferred ()
442 (let ((first-form (%sexpr first-form)) (more-forms (%progn more-forms)))
443 (hlambda MULTIPLE-VALUE-PROG1 (first-form more-forms) (env)
444 (multiple-value-prog1 (dispatch first-form env)
445 (dispatch more-forms env)))))
447 (defspecial eval-when (situations &body body &aux ct lt ex)
448 ;; FIXME: this might signal a compiler error instead of an IP-ERROR.
449 (multiple-value-setq (ct lt ex)
450 (parse-eval-when-situations situations))
451 :immediate (env) (if ex (eval-progn body env))
452 :deferred () (if ex (digest-progn body) (return-constant nil)))
454 ;;; BLOCK and RETURN-FROM
455 (macrolet ((eval-it (eval-fn)
456 ;; An ENV can not represent itself as a catch point, because
457 ;; freezing changes its identity. Use a fresh cons cell instead.
458 `(let ((env (make-block-env env (list name) nil *vacuous-decls*)))
459 (catch (env-payload env) (,eval-fn forms env)))))
460 (defspecial block (name &rest forms)
461 (unless (symbolp name)
462 (ip-error "~@<The block name ~S is not a symbol.~:@>" name))
463 :immediate (env) (eval-it eval-progn)
464 :deferred ()
465 (let ((forms (%progn forms)))
466 (hlambda BLOCK (name forms) (env) (eval-it dispatch)))))
468 ;;; Establishing a handler to catch SIMPLE-CONTROL-ERROR would incorrectly
469 ;;; alter the handler chain as established by user code, in addition
470 ;;; to being needlessly slow. The code in 'interr' can recognize when
471 ;;; an invalid control transfer was initiated by interpreted code,
472 ;;; and it adjusts the error message accordingly.
473 (macrolet ((eval-it (tag eval-fn)
474 `(throw ,tag (,eval-fn result env))))
475 (defspecial return-from (name &optional result &aux (block-env env) (depth 0))
476 ;; unfortunately the only way to write this OAOO is with an &AUX var
477 (declare (fixnum depth))
478 (unless (symbolp name)
479 (ip-error "~@<The block name ~S is not a symbol.~:@>" name))
480 (loop (if (null block-env)
481 (ip-error "~@<Return for unknown block: ~S~:@>" name))
482 (when (eq (typecase block-env
483 (lambda-env (car (lambda-env-block block-env)))
484 (block-env (car (env-payload block-env)))
485 (t 0)) name)
486 (return))
487 (incf depth)
488 (setq block-env (env-parent block-env)))
489 :immediate (env)
490 (eval-it (if (lambda-env-p block-env)
491 (lambda-env-block block-env) (env-payload block-env))
492 %eval)
493 :deferred (env)
494 (let ((result (%sexpr result)))
495 (if (lambda-env-p block-env)
496 (hlambda RETURN-FROM (depth result) (env)
497 (eval-it (lambda-env-block (env-ancestor env depth)) dispatch))
498 (hlambda RETURN-FROM (depth result) (env)
499 (eval-it (env-payload (env-ancestor env depth)) dispatch))))))
501 ;;;;
502 #+Nil
503 (defun map-into-vector-reversed (f list length)
504 (let ((output (make-array length)) (i length))
505 (loop (if (minusp (decf i)) (return))
506 (setf (svref output i) (funcall f (pop list))))
507 output))
509 ;;; A TAGBODY is parsed into a vector of expressions each of which is either
510 ;;; a SEXPR, an unconditional GO, or a conditional GO. Preprocessing speeds
511 ;;; up (DOTIMES (I N) ..) by at least a factor of 10, especially the hoisting
512 ;;; of conditional GO, which would otherwise entail throwing to the catch point
513 ;;; and restarting. Such catch/throw is necessary when the GO is embedded in
514 ;;; deeper subforms, but picking off the shallow cases is easy.
516 (defun parse-tagbody (body env)
517 (collect ((tags) (new-body))
518 ;; First pass: just collect the tags
519 (let (any-forms)
520 (dolist (item body)
521 (cond ((consp item) (setq any-forms t))
522 ((or (symbolp item) (integerp item))
523 (if (assoc item (tags))
524 (ip-error "Duplicate tag ~S in tagbody" item)
525 (tags (list item))))
527 (ip-error "Bad thing to appear in a tagbody: ~S" item))))
528 (cond ((not any-forms)
529 (return-from parse-tagbody (return-constant nil)))
530 ((not (tags))
531 (return-from parse-tagbody (digest-progn `(,@body nil))))))
532 (flet ((go-p (form)
533 (and (typep form '(cons (eql go) (cons t null)))
534 (assoc (cadr form) (tags)))))
535 ;; Second pass: rewrite conditioned GO forms appearing directly in
536 ;; this tagbody which transfer control to a tag in this tagbody.
537 ;; Local function bindings for WHEN/UNLESS will inhibit this.
538 (dolist (item (unless (or (find-lexical-fun env 'when)
539 (find-lexical-fun env 'unless))
540 body))
541 (or (and (typep item '(cons (eql if)
542 (cons t (cons t (or null (cons t null))))))
543 ;; Look for IF forms in which either consequent is a branch.
544 (destructuring-bind (test then &optional else) (cdr item)
545 (multiple-value-bind (op branch fallthru)
546 (cond ((go-p then) (values 'when then else))
547 ((go-p else) (values 'unless else then)))
548 (when op
549 (new-body `(,op ,test ,branch))
550 (when fallthru
551 (new-body
552 (if (atom fallthru) `(progn ,fallthru) fallthru)))
553 t))))
554 ;; Transform a WHEN or UNLESS if there is more than one subform
555 ;; in the consequent, and the last subform is a control transfer.
556 ;; This is necessary because the tagbody handler recognizes
557 ;; only (WHEN|UNLESS c (GO tag)) as a fast conditional GO.
558 ;; (WHEN (TEST) (stmt1) ... (stmtN) (GO tag)) becomes
559 ;; (WHEN (WHEN (TEST) (stmt1) ... (stmtN) T) (GO tag))
560 ;; (UNLESS (TEST) (stmt1) ... (stmtN) (GO tag)) becomes
561 ;; (WHEN (UNLESS (TEST) (stmt1) ... (stmtN) T) (GO tag))
562 (and (typep item '(cons (member when unless)))
563 (cdddr item)
564 (awhen (go-p (car (last item)))
565 (new-body
566 `(when (,(car item) ,(cadr item) ,@(butlast (cddr item)) t)
567 (go ,(car it))))))
568 (new-body item))) ; everything else
569 (let ((body (or (new-body) body)))
570 ;; Next assign tags their indices. Interleaving this with the final
571 ;; pass would need a fixup step for forward branches, so do this first.
572 (let ((line-num 1))
573 (dolist (item body)
574 (if (atom item)
575 (rplacd (assoc item (tags)) line-num)
576 (incf line-num))))
577 ;; Collect the executable statements.
578 (let ((line-num 1)
579 (lines (make-array (- (1+ (length body)) (length (tags))))))
580 (setf (aref lines 0) (tags))
581 (dolist (form body (handler #'eval-tagbody lines))
582 (unless (atom form)
583 (setf (aref lines (prog1 line-num (incf line-num)))
584 (acond ((go-p form) (cdr it)) ; just the line number
585 ((and (typep form '(cons (member when unless)))
586 (singleton-p (cddr form))
587 (go-p (third form)))
588 (let ((line (cdr it)))
589 (cons (%sexpr (second form))
590 (if (eq (car form) 'when) line (- line)))))
591 (t (%sexpr form)))))))))))
593 (defun eval-tagbody (code env sexpr)
594 (declare (simple-vector code) (ignore sexpr)
595 #.+handler-optimize+)
596 ;; Cons a fresh object as the catch tag.
597 (let* ((env (make-tagbody-env env (list (svref code 0)) nil *vacuous-decls*))
598 ;; If the element 1 is an unconditional GO label, such as in a
599 ;; trailing-test loop, then START is that value, otherwise it is 1.
600 (start (let ((elt (svref code 1)))
601 (if (fixnump elt) elt 1)))
602 (end (length code)))
603 (declare (index start end))
604 (loop
605 (setq start
606 (catch (env-payload env)
607 (let ((line-num start))
608 (declare (index line-num))
609 (loop
610 (when (>= line-num end)
611 (return line-num))
612 (setq
613 line-num
614 (let ((line (svref code line-num)))
615 (cond ((%instancep line)
616 (dispatch line env)
617 (1+ line-num))
618 ((fixnump line) line) ; unconditional GO
619 (t ; otherwise, a conditional GO
620 (let ((test (dispatch (car line) env))
621 (target (the fixnum (cdr line))))
622 (if (minusp target)
623 (if test (1+ line-num) (- target))
624 (if test target (1+ line-num))))))))))))
625 (if (>= start end) (return)))))
627 ;;; There is no immediate mode for TAGBODY because its primary use is for loops,
628 ;;; which benefit from preprocessing even when used at toplevel and discarded.
629 (defspecial tagbody (&rest body)
630 :deferred (env) (parse-tagbody body env))
632 ;;; As a corollary to above, there's no immediate mode processor for GO.
633 (defspecial go (tag)
634 :deferred (env)
635 (let ((depth 0) cell)
636 (declare (fixnum depth))
637 (loop (typecase env
638 (null (ip-error "~@<Attempt to GO to nonexistent tag: ~S~:@>" tag))
639 (tagbody-env
640 (when (setq cell (assoc tag (car (env-payload env)))) (return))))
641 (setq env (env-parent env)) (incf depth))
642 (let ((index (make-frame-ptr (cdr cell) depth)))
643 (hlambda GO (index) (env)
644 (throw (env-payload (env-ancestor env index))
645 (frame-ptr-cell-index index))))))
647 ;;; FIXME: this special case makes it a bit difficult to turn the intepreter
648 ;;; into exactly a minimal compiler, since SETQ always wants to do something
649 ;;; that has an immediate effect.
650 (defun eval-setq (assignments env sexpr) ; SEXPR is nil for immediate mode
651 (cond ((not assignments)
652 (when sexpr
653 (setf (sexpr-handler sexpr) (return-constant nil)))
654 nil)
655 ((oddp (list-length assignments)) (ip-error "Bad syntax in SETQ"))
656 ((cddr assignments)
657 (let ((form `(progn ,@(loop for (sym val) on assignments by #'cddr
658 collect `(setq ,sym ,val)))))
659 (if sexpr
660 (digest-form form env sexpr)
661 (%eval form env))))
663 (let ((sym (first assignments)) (val (second assignments)))
664 (unless (symbolp sym)
665 (ip-error "~S is not a symbol" sym))
666 (if sexpr
667 (deferred-setq-1 sym val env sexpr)
668 (immediate-setq-1 sym val env))))))
670 ;;;; Comment from 'full-eval'
671 ;;; The expansion of SB-SYS:WITH-PINNED-OBJECTS on GENCGC uses some
672 ;;; VOPs which can't be reasonably implemented in the interpreter. So
673 ;;; we special-case the macro.
675 ;;; Unlikely to appear at toplevel, so should not occur in :IMMEDIATE mode.
676 ;;; If it does, just dispatch to the deferred handler.
677 (defspecial sb-sys:with-pinned-objects (objects &body forms)
678 :deferred ()
679 (let ((objects (mapcar #'%sexpr objects)) (forms (%progn forms)))
680 (hlambda sb-sys:with-pinned-objects (objects forms) (env)
681 (labels ((recurse (list forms)
682 (if (not list)
683 (dispatch forms env)
684 (sb-sys:with-pinned-objects ((car list))
685 (recurse (cdr list) forms)))))
686 (recurse objects forms)))))
688 ;;; Now for the complicated stuff, starting with the simplest
689 ;;; of the complicated ...
691 (defun digest-locally (env body)
692 (multiple-value-bind (forms decls) (parse-body body nil t)
693 (if (not decls)
694 (digest-progn forms)
695 (let* ((specials (free-specials env decls))
696 (scope (process-typedecls
697 (%make-local-scope decls (new-policy env decls)
698 (%progn forms) specials)
699 env 0 specials)))
700 (hlambda LOCALLY (scope) (env)
701 (enforce-types scope env)
702 (dispatch (local-scope-body scope)
703 (make-basic-env env nil
704 (local-scope-specials scope) scope)))))))
706 (defspecial locally (&body body)
707 :immediate (env)
708 (multiple-value-bind (forms decls) (parse-body body nil t)
709 (let* ((specials (free-specials env decls))
710 (scope (process-typedecls
711 (make-decl-scope decls (new-policy env decls))
712 env 0 specials)))
713 (enforce-types scope env)
714 (eval-progn forms (make-basic-env env nil specials scope))))
715 :deferred (env) (digest-locally env body))
717 (defun parse-symbol-macrolet (env bindings body wrap-fn)
718 (multiple-value-bind (forms decls) (parse-body body nil t)
719 (binding* (((specials n-specials) (declared-specials decls))
720 (n-macros (length bindings))
721 (symbols (make-array (+ n-macros n-specials)))
722 (expansions (make-array n-macros))
723 (checker (sb-c::symbol-macrolet-definitionize-fun :eval))
724 (index -1))
725 (with-package-lock-context (env)
726 (dolist (binding bindings)
727 (let* ((binding (funcall checker binding))
728 (symbol (car binding))
729 (expansion (cddr binding)))
730 (setf (svref symbols (incf index)) (list symbol)
731 (svref expansions index) expansion)))
732 (assert-declarable-as-special env specials))
733 (dolist (symbol specials)
734 (if (find symbol symbols :end n-macros :key #'car)
735 (ip-error "~S can not be both a symbol-macro and special" symbol))
736 (setf (svref symbols (incf index)) (find-special-binding env symbol)))
737 (process-typedecls
738 (%make-symbol-macro-scope decls (new-policy env decls)
739 symbols expansions (funcall wrap-fn forms))
740 env n-macros symbols))))
742 (macrolet ((new-env ()
743 `(make-symbol-macro-env env
744 (symbol-macro-expansions scope)
745 (symbol-macro-symbols scope)
746 scope)))
747 (defspecial symbol-macrolet (defs &rest body)
748 :immediate (env)
749 (let ((scope (parse-symbol-macrolet env defs body #'identity)))
750 (enforce-types scope env)
751 (eval-progn (symbol-macro-body scope) (new-env)))
752 :deferred (env)
753 (if (not defs)
754 (digest-locally env body)
755 (let ((scope (parse-symbol-macrolet env defs body #'%progn)))
756 (hlambda SYMBOL-MACROLET (scope) (env)
757 (enforce-types scope env)
758 (dispatch (symbol-macro-body scope) (new-env)))))))
760 (defun parse-let (maker env bindings body specials-listifier)
761 (multiple-value-bind (forms decls) (parse-body body nil t)
762 (binding* (((declared-specials n-declared) (declared-specials decls))
763 (n-bindings 0)
764 (n-free-specials
765 (let ((boundp 0)) ; mask over declared-specials of bound ones
766 (dolist (binding bindings (- n-declared (logcount boundp)))
767 (let ((p (posq (binding-symbol binding) declared-specials)))
768 (when p (setf (logbitp p boundp) t)))
769 (incf n-bindings))))
770 (symbols (make-array (+ n-bindings n-free-specials)))
771 (values (make-array n-bindings))
772 (index -1))
773 (dolist (binding bindings)
774 (multiple-value-bind (symbol value-form)
775 (if (atom binding)
776 (values binding nil)
777 (with-subforms (symbol &optional value) binding
778 (values symbol value)))
779 (unless (symbolp symbol)
780 (ip-error "~S is not a symbol" symbol))
781 (incf index)
782 (setf (svref symbols index) (list symbol)
783 (svref values index) value-form)))
784 (dolist (sym declared-specials)
785 (unless (find (the symbol sym) symbols :end n-bindings :key #'car)
786 (setf (svref symbols (incf index)) (find-special-binding env sym))))
787 (let ((special-b ; mask over symbols of special ones
788 (mark-bound-specials env declared-specials symbols n-bindings)))
789 (process-typedecls
790 (funcall maker decls (new-policy env decls) symbols special-b
791 values (%progn forms)
792 (funcall specials-listifier
793 (collect-progv-symbols symbols n-bindings
794 special-b)))
795 env n-bindings symbols)))))
797 (defglobal *let-processor* nil)
799 (macrolet
800 ((defspecial* (operator transform-specials)
801 `(defspecial ,operator (bindings &body body)
802 :deferred (env)
803 (unless bindings
804 (return-from ,operator (digest-locally env body)))
805 ;; For 1 binding always use LET which is semantically the same.
806 ;; It is ever-so-slightly more efficient to use LET than LET*.
807 ,@(when (eq operator 'let*)
808 `((when (singleton-p bindings)
809 (return-from let*
810 (funcall *let-processor* `(,bindings ,@body) env)))))
811 ;; FIXME: aren't MAKE-LET*-FRAME and MAKE-LET-FRAME essentially
812 ;; the same now?
813 (let ((frame (parse-let ',(symbolicate "MAKE-" operator "-FRAME")
814 env bindings body ,transform-specials)))
815 (let ((values (frame-values frame)))
816 (map-into values #'%sexpr values))
817 (symbol-macrolet ((symbols (frame-symbols frame)))
818 (cond ((zerop (frame-special-b frame))
819 (hlambda ,operator (frame) (old-env)
820 (let ((values (make-array (frame-size frame))))
821 (eval-it (frame-values frame) dispatch
822 (dispatch (frame-sexpr frame) new-env)
823 :specialp nil))))
824 ((fixnump (frame-special-b frame))
825 (symbol-macrolet
826 ((special-b (the fixnum (frame-special-b frame))))
827 (hlambda ,(sb-int:symbolicate operator "/SPEC")
828 (frame) (old-env)
829 (let ((values (make-array (frame-size frame)))
830 (specials (frame-specials frame)))
831 (eval-it (frame-values frame) dispatch
832 (dispatch (frame-sexpr frame) new-env))))))
833 (t ; a ton of specials
834 (symbol-macrolet ((special-b (frame-special-b frame)))
835 (hlambda ,(sb-int:symbolicate operator "/SPEC")
836 (frame) (old-env)
837 (let ((values (make-array (frame-size frame)))
838 (specials (frame-specials frame)))
839 (eval-it (frame-values frame) dispatch
840 (dispatch (frame-sexpr frame)
841 new-env))))))))))))
842 (macrolet
843 ((eval-it (value-source-v eval-fn eval-body &rest more)
844 `(let ((new-env (make-var-env old-env values symbols frame))
845 (type-restrictions (binding-typechecks frame)))
846 (with-let-bindings
847 (values (length values) ,@more
848 :value (enforce-type
849 (,eval-fn (svref ,value-source-v frame-index) old-env)
850 type-restrictions frame-index symbols)
851 :specials specials)
852 (enforce-types frame env) ; the OLD env
853 ,eval-body))))
854 ;; WITH-LET-BINDINGS accumulates special bindings in reverse
855 ;; so we have to reverse the symbols too.
856 (defspecial* LET #'nreverse))
858 (macrolet
859 ((eval-it (value-source-v eval-fn eval-body &rest more)
860 ;; (length . vector) is a proxy for a vector with fill-pointer
861 `(let* ((symbol-cells (cons 0 symbols))
862 (new-env (make-var-env old-env values symbol-cells frame))
863 (type-restrictions (binding-typechecks frame)))
864 (with-let*-binder
865 (values (car symbol-cells) ,@more
866 :value (enforce-type
867 (,eval-fn (svref ,value-source-v frame-index) new-env)
868 type-restrictions frame-index symbols)
869 :specials (pop specials))
870 ;; expression to start the recursion
871 (let*-bind 0 (length values))
872 ;; post-binding actions
873 ;; FIXME: this step is possibly not thread-safe. Figure it out.
874 ;; Maybe "once a mutable env, always a mutable env"?
875 (setf (env-symbols new-env) symbols)
876 (enforce-types frame env) ; the OLD env
877 ,eval-body))))
878 ;; WITH-LET*-BINDER needs each special in a singleton list
879 (defspecial* LET* (lambda (x) (mapcar #'list x)))))
881 (setq *let-processor* (cdr (!special-form-handler (find-fdefn 'let))))
883 ;;;; Macrolet
885 ;;; Unlike with local functions, this encloses the macro lambda in the
886 ;;; parse-time environment which is why this is EVAL- and not DIGEST.
887 ;;; It also does not go to the trouble of hiding (making inaccessible)
888 ;;; any lexical names that should not be visible.
889 ;;; This is permissible per CLHS in the description of MACROLET:
890 ;;; "the consequences are undefined if the local macro definitions
891 ;;; reference any local variable or function bindings that are
892 ;;; visible in that lexical environment."
893 ;;; This means: you're wrong for doing that; but in this implementation
894 ;;; your macro functions can look at things they shouldn't.
896 (defun eval-local-macros (env defs)
897 ;; Is it necessary to freeze a macro env? You shouldn't look at
898 ;; any lexical constructs except macros anyway.
899 (when (must-freeze-p env) (setq env (freeze-env env)))
900 (map 'vector
901 (lambda (def)
902 (with-subforms (name lambda-list &body body) def
903 (unless (and (symbolp name)
904 (neq (info :function :kind name) :special-form))
905 (ip-error "~S is not a valid macro name" name))
906 (when (fboundp name)
907 (with-package-lock-context (env)
908 (program-assert-symbol-home-package-unlocked
909 :eval name "binding ~S as a local macro")))
910 (make-function
911 (make-proto-fn (make-macro-lambda `(macrolet ,name) lambda-list body
912 'macrolet name))
913 env)))
914 (the list defs)))
916 ;;; MACROLET has an immediate-mode handler since it is common at toplevel.
917 (defspecial macrolet (defs &body body)
918 :immediate (env)
919 (multiple-value-bind (forms decls) (parse-body body nil t)
920 (let* ((specials (free-specials env decls))
921 (scope (process-typedecls
922 (make-decl-scope decls (new-policy env decls))
923 env 0 specials)))
924 (enforce-types scope env)
925 (eval-progn forms
926 (make-macro-env env
927 (eval-local-macros env defs)
928 specials scope))))
929 :deferred (env)
930 (if (not defs)
931 (digest-locally env body)
932 (multiple-value-bind (forms decls) (parse-body body nil t)
933 (let ((scope (make-local-fn-scope decls (eval-local-macros env defs)
934 forms env)))
935 (hlambda MACROLET (scope) (env)
936 (enforce-types scope env)
937 (dispatch
938 (local-fn-scope-body scope)
939 (make-macro-env env
940 (local-fn-scope-funs scope)
941 (local-fn-scope-specials scope)
942 scope)))))))
944 ;;;; FLET and LABELS
946 (define-load-time-global *last-toplevel-env*
947 (make-basic-env nil nil nil (make-decl-scope nil sb-c::**baseline-policy**)))
949 (declaim (inline disabled-locks))
950 ;;; Pull out LIST from `((DECLARE (DISABLE-PACKAGE-LOCKS ,@LIST)))
951 (defun disabled-locks (decls) (cdadar decls))
953 ;;; Immediate mode FUNCTION when evaluated captures the globally
954 ;;; disabled package-locks, so this works:
955 ;;; * (declaim (disable-package-locks read-byte))
956 ;;; * (defun foo () (flet ((read-byte () 42)) (read-byte)))
957 ;;; * (declaim (enable-package-locks read-byte))
958 ;;; * (something-that-calls-foo)
959 ;;; And conversely the lambda should not observe subsequent
960 ;;; changes that globally unlock a symbol.
961 (defun capture-toplevel-env ()
962 (let* ((disabled-locks sb-c::*disabled-package-locks*)
963 (policy sb-c::*policy*)
964 ;; Multiple threads can harmlessly share this global variable.
965 ;; At worst, a new environment is consed every time through here.
966 (last-env *last-toplevel-env*)
967 (contour (env-contour last-env)))
968 ;; The toplevel environment changes only when the user declaims
969 ;; optimization settings or enables/disables per-symbol package-locks.
970 (unless (and (sb-c::policy= (%policy contour) policy)
971 (equal (disabled-locks (declarations contour))
972 disabled-locks))
973 (let ((decls
974 (if disabled-locks
975 `((declare (disable-package-locks ,@disabled-locks))))))
976 (setq last-env (make-basic-env
977 nil nil nil (make-decl-scope decls policy)))
978 ;; Ensure all accessible parts of the new BASIC-ENV
979 ;; are flushed to memory before publishing shared variable.
980 (sb-thread:barrier (:write))
981 (setq *last-toplevel-env* last-env)))
982 last-env))
984 ;;; We have to do some shenanigans with lexical environments that are non-null
985 ;;; but have not captured the toplevel disabled package lock state.
986 ;;; Continuing the example above, suppose we have:
987 ;;; (locally (declare (special ...)) (lambda () (flet ((read-byte ...)))))
988 ;;; This lambda has a non-null environment due to the LOCALLY form.
989 ;;; On account of the interpreter's laziness, it does not decide up front about
990 ;;; whether the lexical binding of #'READ-BYTE is permitted. But to be consistent
991 ;;; with the compiler, it should act like it decides now. To do that, we inject
992 ;;; globally disabled package-locks as if they appeared in a *nested* environment,
993 ;;; carefully ignoring anything global shadowed by a contrary lexical declaration.
994 ;;; The compiler does not have this problem, because compilation isn't lazy.
995 (defun capture-disabled-package-locks (env)
996 (let* ((decls (declarations (env-contour (capture-toplevel-env))))
997 (proclaimed-disabled-locks (disabled-locks decls)))
998 (when proclaimed-disabled-locks ; usually false
999 (let ((decls
1000 (if (every (lambda (name) (lexically-unlocked-symbol-p name env))
1001 proclaimed-disabled-locks)
1002 ;; No local declaration prevailed over the global,
1003 ;; so capture the global list. This is fine even if it
1004 ;; contains a name that is redundant with an explicit
1005 ;; lexically declared unlock. It avoids some consing.
1006 decls
1007 (let (new-list) ; XXX: This code is untested!
1008 (dolist (name proclaimed-disabled-locks)
1009 (when (lexically-unlocked-symbol-p name env)
1010 ;; *assume* it was because of the global unlock,
1011 ;; which is to say, it might be redundant with,
1012 ;; a local unlock but at least it wasn't shadowed
1013 ;; by an explicitly declared lexical re-lock.
1014 (push name new-list)))
1015 (when new-list
1016 `((declare (disable-package-locks ,@new-list))))))))
1017 (when decls
1018 (return-from capture-disabled-package-locks
1019 (make-basic-env env nil nil
1020 (make-decl-scope decls (env-policy env)))))))
1021 ;; There were no applicable global unlocks, meaning either the list
1022 ;; was empty, or everything in it was shadowed by a lexical lock.
1023 env))
1025 (defun capture-toplevel-stuff (env)
1026 (labels ((captured-p (env) ; true if there is already an ancestor lambda
1027 (acond ((lambda-env-p env) t)
1028 ((env-parent env) (captured-p it)))))
1029 (cond ((null env) (capture-toplevel-env))
1030 ((captured-p env) env)
1031 (t (capture-disabled-package-locks env)))))
1033 (defun digest-local-fns (env kind bindings body) ; KIND is FLET or LABELS
1034 (flet ((proto-functionize (def)
1035 (with-subforms (name lambda-list &body body) def
1036 (multiple-value-bind (forms decls docstring) (parse-body body t t)
1037 ;; *** Test LEGAL-FUN-NAME-P before asking for an info-value.
1038 ;; This is because (INFO :FUNCTION :KIND) uses FBOUNDP when it
1039 ;; does not have an entry for NAME. But calling FBOUNDP
1040 ;; might call LEGAL-FUN-NAME-OR-TYPE-ERROR.
1041 ;; This ends up producing a different error message instead
1042 ;; of a consistent message as per the format string below.
1043 (unless (and (legal-fun-name-p name)
1044 (neq (info :function :kind name) :special-form))
1045 (ip-error "~S is not a legal function name" name))
1046 (when (fboundp name)
1047 (with-package-lock-context (env)
1048 (program-assert-symbol-home-package-unlocked
1049 :eval name "binding ~S as a local function")))
1050 ;; Return T if SEXPR contains (RETURN-FROM BLOCK-NAME ...),
1051 ;; or NIL if it definitely does not. While this is an inelegant
1052 ;; kludge, it is extremely effective. Avoiding creation of a
1053 ;; CATCH frame, makes local fun application properly
1054 ;; tail recursive, barring other inhibitors.
1055 ;; FIXME: Macros can be nondeterministic :-( so if any macro
1056 ;; in a non-builtin package is seen, conservatively return T.
1057 (flet ((has-return-p (sexpr env block-name)
1058 (handler-case
1059 (progn
1060 (sb-walker:walk-form
1061 sexpr env
1062 (lambda (subform context env)
1063 (declare (ignore env))
1064 (when (and (eq context :eval)
1065 (typep subform
1066 '(cons (eql return-from) list))
1067 (eq (cadr subform) block-name))
1068 (return-from has-return-p t))
1069 subform))
1070 nil)
1071 (condition () t)))) ; conservative answer
1072 (let* ((block (fun-name-block-name name))
1073 (forms (if (has-return-p `(progn ,@forms) env block)
1074 `((block ,block ,@forms))
1075 forms)))
1076 (%make-proto-fn `(,kind ,name) lambda-list decls forms
1077 docstring)))))))
1078 (multiple-value-bind (forms decls) (parse-body body nil t)
1079 (make-local-fn-scope decls (map 'vector #'proto-functionize bindings)
1080 forms env))))
1082 ;;; There's an improvement that could be made - unless a function name
1083 ;;; appears as the operand to FUNCTION, all internals call could use
1084 ;;; different convention for function application which avoids consing
1085 ;;; a funcallable instance. But you can't now that without walking into the
1086 ;;; body, which means you lose the otherwise nice laziness aspect.
1087 (macrolet ((defspecial* (operator)
1088 `(defspecial ,operator (defs &body body)
1089 :deferred (env)
1090 (cond ((not defs) (digest-locally env body))
1091 ((not body) (return-constant nil))
1093 (let* ((env (capture-toplevel-stuff env))
1094 (frame (digest-local-fns env ',operator defs body)))
1095 (if (must-freeze-p env)
1096 (handler-guts (freeze-env env))
1097 (handler-guts env))))))))
1099 (macrolet ((handler-guts (closed-over-env)
1100 `(hlambda FLET (frame) (env)
1101 (enforce-types frame env)
1102 (let* ((closure-env ,closed-over-env)
1103 (funs
1104 (map 'vector
1105 (lambda (proto-fn)
1106 (make-function proto-fn closure-env))
1107 (local-fn-scope-funs frame))))
1108 (dispatch
1109 (local-fn-scope-body frame)
1110 (make-function-env
1111 env funs (local-fn-scope-specials frame) frame))))))
1112 (defspecial* flet))
1114 (macrolet ((handler-guts (closed-over-env)
1115 `(hlambda LABELS (frame) (env)
1116 (enforce-types frame env)
1117 (let* ((funs (make-array (length (local-fn-scope-funs frame))))
1118 (closure-env (make-function-env ,closed-over-env funs
1119 nil *vacuous-decls*)))
1120 (map-into funs (lambda (proto-fn)
1121 (make-function proto-fn closure-env))
1122 (local-fn-scope-funs frame))
1123 (dispatch
1124 (local-fn-scope-body frame)
1125 ;; In the absence of decls, the env in which the body
1126 ;; is eval'ed is the same as the functions' env.
1127 ;; Otherwise, it is yet another new env.
1128 (if (declarations frame)
1129 (make-basic-env closure-env nil
1130 (local-fn-scope-specials frame) frame)
1131 closure-env))))))
1132 (defspecial* labels)))
1134 (macrolet ((not-a-function (name)
1135 `(ip-error "~S is a macro." ,name)))
1136 (defspecial function (name)
1137 (if (and (symbolp name) (eq (info :function :kind name) :special-form))
1138 (ip-error "~S names a special operator." name))
1139 ;; again it's sad that I can't wrap code around both modes
1140 :immediate (env)
1141 (if (and (listp name) (memq (car name) '(named-lambda lambda)))
1142 (progn
1143 (aver (not (must-freeze-p env)))
1144 (enclose (make-proto-fn name (not (null env)))
1145 (capture-toplevel-stuff env)
1146 nil))
1147 ;; immediate mode calls FDEFINITION as needed, so wil err as it should.
1148 (multiple-value-bind (definition macro-p) (get-function name env)
1149 (if macro-p (not-a-function name) definition)))
1150 :deferred (env)
1151 (if (and (listp name) (memq (car name) '(named-lambda lambda)))
1152 (handler (if (must-freeze-p env) #'enclose-freeze #'enclose)
1153 (make-proto-fn name))
1154 (multiple-value-bind (kind definition frame-ptr)
1155 (find-lexical-fun env name)
1156 (if definition
1157 (if (eq kind :macro)
1158 (not-a-function name)
1159 (hlambda FUNCTION (frame-ptr) (env)
1160 (local-fdefinition frame-ptr env)))
1161 ;; Consider (DEFUN GET-THING () #'THING) - it shouldn't return
1162 ;; THING's error trampoline if THING is redefined after
1163 ;; GET-THING was called once.
1164 (let ((fdefn (find-or-create-fdefn name)))
1165 (if (symbolp name) ; could be a macro
1166 (hlambda FUNCTION (fdefn) (env)
1167 (declare (ignore env))
1168 (let ((fun (sb-c:safe-fdefn-fun fdefn)))
1169 (if (sb-impl::macro/special-guard-fun-p fun)
1170 (not-a-function (fdefn-name fdefn))
1171 fun)))
1172 (hlambda FUNCTION (fdefn) (env) ; could not be a macro
1173 (declare (ignore env))
1174 (sb-c:safe-fdefn-fun fdefn)))))))))
1176 ;;;; some extra handlers
1178 #+nil
1179 (macrolet
1180 ((define-boole (op identity test)
1181 `(defspecial ,op (&rest forms)
1182 :immediate :none ; just recurse
1183 :deferred ()
1184 ;; following the model of PROGN
1185 (case (length forms)
1186 (0 (return-constant ,identity))
1187 (1 (handler #'digest-form (first forms)))
1188 (2 (let ((one (%sexpr (first forms))) (two (%sexpr (second forms))))
1189 (hlambda ,op (one two) (env)
1190 (,op (dispatch one env) (dispatch two env)))))
1192 (let ((forms (nreverse (vector-of-sexpr forms))))
1193 (hlambda ,op (forms) (env)
1194 (declare (simple-vector forms))
1195 (let ((i (1- (length forms))))
1196 (loop (let ((result (dispatch (svref forms i) env))) ,test)
1197 (if (zerop (decf i))
1198 (return (dispatch (svref forms 0) env))))))))))))
1199 (define-boole OR nil (when result (return result)))
1200 (define-boole AND t (unless result (return nil))))
1202 ;;;; CL functions that are handled semi-magically
1204 (flet ((local-dispatch (sexpr env)
1205 (declare #.+handler-optimize+)
1206 (if (%instancep sexpr) (%dispatch sexpr env) sexpr)))
1208 ;; hand-generated lists of useful functions
1209 (setq *unary-functions*
1210 (sb-impl::%stuff-hash-table
1211 (make-hash-table :test #'eq)
1212 (macrolet
1213 ((def-wrapper (&rest input)
1214 (cons 'list
1215 (mapcar
1216 (lambda (f)
1217 `(cons ',f
1218 (named-lambda (EVAL ,f) (arg env sexpr)
1219 (declare (ignore sexpr)
1220 (optimize (sb-c:verify-arg-count 0))
1221 (muffle-conditions compiler-note))
1222 (,f (local-dispatch arg env)))))
1223 input))))
1224 (def-wrapper
1225 ;; non-alphabetic
1226 - / /= 1+ 1- < <= = > >=
1227 ;; CxR
1228 CAR CDR CAAR CADR CDAR CDDR
1229 CAAAR CAADR CADAR CADDR CDAAR CDADR CDDAR CDDDR
1230 CAAAAR CAAADR CAADAR CAADDR CADAAR CADADR CADDAR CADDDR
1231 CDAAAR CDAADR CDADAR CDADDR CDDAAR CDDADR CDDDAR CDDDDR
1232 ;; other list accessors
1233 FIRST REST
1234 SECOND THIRD FOURTH FIFTH SIXTH SEVENTH EIGHTH NINTH TENTH
1235 ;; alphabetical order from here down
1237 ADJUSTABLE-ARRAY-P
1238 ALPHA-CHAR-P ALPHANUMERICP
1239 ;;; Compiling ARRAY-ELEMENT-TYPE refers to the type CLASS
1240 ;;; which isn't defined yet. Why does it?
1241 ARRAY-DIMENSIONS #|ARRAY-ELEMENT-TYPE|# ARRAY-HAS-FILL-POINTER-P
1242 ARRAY-IN-BOUNDS-P ARRAY-RANK ARRAY-TOTAL-SIZE ARRAYP
1243 ATOM
1244 BIT-NOT BIT-VECTOR-P BOTH-CASE-P BOUNDP
1245 BUTLAST BYTE-POSITION BYTE-SIZE
1246 CEILING CHAR-CODE CHAR-DOWNCASE CHAR-EQUAL CHAR-GREATERP
1247 CHAR-INT CHAR-LESSP CHAR-NOT-EQUAL
1248 CHAR-NOT-GREATERP CHAR-NOT-LESSP CHAR-UPCASE
1249 CHAR/= CHAR< CHAR<= CHAR= CHAR> CHAR>=
1250 CHARACTER CHARACTERP
1251 CODE-CHAR COMPILED-FUNCTION-P COMPLEMENT
1252 COMPLEX COMPLEXP CONSP
1253 DENOMINATOR
1254 DIGIT-CHAR DIGIT-CHAR-P
1255 ENDP EVENP FBOUNDP FDEFINITION FIND-SYMBOL
1256 FLOAT FLOATP FLOOR FUNCALL FUNCTIONP
1257 GRAPHIC-CHAR-P
1258 HASH-TABLE-P
1259 IDENTITY
1260 INTEGER-LENGTH
1261 INTEGERP
1262 INTERN
1263 ISQRT
1264 KEYWORDP
1265 LAST LENGTH LIST* LIST-LENGTH LISTP
1266 LOGCOUNT LOGNOT LOWER-CASE-P
1267 MAX MIN MINUSP
1268 NBUTLAST NOT NREVERSE
1269 NSTRING-CAPITALIZE NSTRING-DOWNCASE NSTRING-UPCASE
1270 NULL NUMBERP NUMERATOR
1271 ODDP
1272 PACKAGEP PATHNAMEP PLUSP
1273 REALP REVERSE ROUND
1274 SBIT SIGNUM
1275 SIMPLE-BIT-VECTOR-P SIMPLE-STRING-P SIMPLE-VECTOR-P
1276 SPECIAL-OPERATOR-P SQRT
1277 STANDARD-CHAR-P
1278 STREAMP STRING
1279 STRING-CAPITALIZE STRING-DOWNCASE STRING-UPCASE STRINGP SXHASH
1280 SYMBOL-FUNCTION SYMBOL-NAME SYMBOL-PACKAGE SYMBOL-PLIST
1281 SYMBOL-VALUE SYMBOLP
1282 TRUNCATE
1283 UPPER-CASE-P
1284 VALUES-LIST
1285 VECTOR-POP
1286 VECTORP
1287 ZEROP))))
1289 (setq *binary-functions*
1290 (sb-impl::%stuff-hash-table
1291 (make-hash-table :test #'eq)
1292 (macrolet
1293 ((def-wrapper (&rest input)
1294 (cons 'list
1295 (mapcar
1296 (lambda (f)
1297 `(cons ',f
1298 (named-lambda (.eval. ,(symbolicate "2-ARG-" f))
1299 (data env sexpr)
1300 (declare (ignore sexpr)
1301 (optimize (sb-c:verify-arg-count 0))
1302 (muffle-conditions compiler-note))
1303 (,f (local-dispatch (car data) env)
1304 (local-dispatch (cdr data) env)))))
1305 input))))
1306 (def-wrapper + - * / = < > <= >= min max
1307 string= string< string<= string> string>=
1308 char= char< char<= char> char>=
1309 eq eql equal equalp
1310 cons list list*))))
1311 ) ; end FLET