1 ;;; byte-lexbind.el --- Lexical binding support for byte-compiler
3 ;; Copyright (C) 2001, 2002, 2010, 2011 Free Software Foundation, Inc.
5 ;; Author: Miles Bader <miles@gnu.org>
6 ;; Keywords: lisp, compiler, lexical binding
8 ;; This file is part of GNU Emacs.
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 3, or (at your option)
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
30 (require 'bytecomp-preload
"bytecomp")
32 ;; Downward closures aren't implemented yet, so this should always be nil
33 (defconst byte-compile-use-downward-closures nil
34 "If true, use `downward closures', which are closures that don't cons.")
36 (defconst byte-compile-save-window-excursion-uses-eval t
37 "If true, the bytecode for `save-window-excursion' uses eval.
38 This means that the body of the form must be put into a closure.")
40 (defun byte-compile-arglist-vars (arglist)
41 "Return a list of the variables in the lambda argument list ARGLIST."
42 (remq '&rest
(remq '&optional arglist
)))
45 ;;; Variable extent analysis.
47 ;; A `lforminfo' holds information about lexical bindings in a form, and some
48 ;; other info for analysis. It is a cons-cell, where the car is a list of
49 ;; `lvarinfo' stuctures, which form an alist indexed by variable name, and the
50 ;; cdr is the number of closures found in the form:
52 ;; LFORMINFO : ((LVARINFO ...) . NUM-CLOSURES)"
54 ;; A `lvarinfo' holds information about a single lexical variable. It is a
55 ;; list whose car is the variable name (so an lvarinfo is suitable as an alist
56 ;; entry), and the rest of the of which holds information about the variable:
58 ;; LVARINFO : (VAR NUM-REFS NUM-SETS CLOSED-OVER)
60 ;; NUM-REFS is the number of times the variable's value is used
61 ;; NUM-SETS is the number of times the variable's value is set
62 ;; CLOSED-OVER is non-nil if the variable is referenced
63 ;; anywhere but in its original function-level"
68 (defsubst byte-compile-make-lvarinfo
(var &optional already-set
)
69 (list var
0 (if already-set
1 0) 0 nil
))
71 (defsubst byte-compile-lvarinfo-var
(vinfo) (car vinfo
))
72 (defsubst byte-compile-lvarinfo-num-refs
(vinfo) (cadr vinfo
))
73 (defsubst byte-compile-lvarinfo-num-sets
(vinfo) (nth 3 vinfo
))
74 (defsubst byte-compile-lvarinfo-closed-over-p
(vinfo) (nth 4 vinfo
))
76 (defsubst byte-compile-lvarinfo-note-ref
(vinfo)
77 (setcar (cdr vinfo
) (1+ (cadr vinfo
))))
78 (defsubst byte-compile-lvarinfo-note-set
(vinfo)
79 (setcar (cddr vinfo
) (1+ (nth 3 vinfo
))))
80 (defsubst byte-compile-lvarinfo-note-closure
(vinfo)
81 (setcar (nthcdr 4 vinfo
) t
))
86 (defsubst byte-compile-make-lforminfo
()
89 (defalias 'byte-compile-lforminfo-vars
'car
)
90 (defalias 'byte-compile-lforminfo-num-closures
'cdr
)
92 (defsubst byte-compile-lforminfo-add-var
(finfo var
&optional already-set
)
93 (setcar finfo
(cons (byte-compile-make-lvarinfo var already-set
)
96 (defun byte-compile-lforminfo-make-closure-flag ()
97 "Return a new `closure-flag'."
100 (defsubst byte-compile-lforminfo-note-closure
(lforminfo lvarinfo closure-flag
)
101 "If a variable reference or definition is inside a closure, record that fact.
102 LFORMINFO describes the form currently being analyzed, and LVARINFO
103 describes the variable. CLOSURE-FLAG is either nil, if currently _not_
104 inside a closure, and otherwise a `closure flag' returned by
105 `byte-compile-lforminfo-make-closure-flag'."
107 (byte-compile-lvarinfo-note-closure lvarinfo
)
108 (unless (car closure-flag
)
109 (setcdr lforminfo
(1+ (cdr lforminfo
)))
110 (setcar closure-flag t
))))
112 (defun byte-compile-compute-lforminfo (form &optional special
)
113 "Return information about variables lexically bound by FORM.
114 SPECIAL is a list of variables that are special, and so shouldn't be
115 bound lexically (in addition to variable that are considered special
116 because they are declared with `defvar', et al).
118 The result is an `lforminfo' data structure."
121 (let ((lforminfo (byte-compile-make-lforminfo)))
122 (cond ((eq (car form
) 'let
)
123 ;; Find the bound variables
124 (dolist (clause (cadr form
))
125 (let ((var (if (consp clause
) (car clause
) clause
)))
126 (unless (or (special-variable-p var
) (memq var special
))
127 (byte-compile-lforminfo-add-var lforminfo var t
))))
129 (unless (null (byte-compile-lforminfo-vars lforminfo
))
130 (byte-compile-lforminfo-analyze-forms lforminfo form
2
132 ((eq (car form
) 'let
*)
133 (dolist (clause (cadr form
))
134 (let ((var (if (consp clause
) (car clause
) clause
)))
135 ;; Analyze each initializer based on the previously
137 (when (and (consp clause
) lforminfo
)
138 (byte-compile-lforminfo-analyze lforminfo
(cadr clause
)
140 (unless (or (special-variable-p var
) (memq var special
))
141 (byte-compile-lforminfo-add-var lforminfo var t
))))
143 (unless (null (byte-compile-lforminfo-vars lforminfo
))
144 (byte-compile-lforminfo-analyze-forms lforminfo form
2
146 ((eq (car form
) 'condition-case
)
147 ;; `condition-case' currently must dynamically bind the
148 ;; error variable, so do nothing.
150 ((memq (car form
) '(defun defmacro))
151 (byte-compile-lforminfo-from-lambda lforminfo
(cdr form
) special
))
152 ((eq (car form
) 'lambda
)
153 (byte-compile-lforminfo-from-lambda lforminfo form special
))
154 ((and (consp (car form
)) (eq (caar form
) 'lambda
))
155 ;; An embedded lambda, which is basically just a `let'
156 (byte-compile-lforminfo-from-lambda lforminfo
(cdr form
) special
)))
157 (if (byte-compile-lforminfo-vars lforminfo
)
161 (defun byte-compile-lforminfo-from-lambda (lforminfo lambda special
)
162 "Initialize LFORMINFO from the lambda expression LAMBDA.
163 SPECIAL is a list of variables to ignore.
164 The first element of LAMBDA is ignored; it need not actually be `lambda'."
166 (dolist (arg (byte-compile-arglist-vars (cadr lambda
)))
167 (byte-compile-lforminfo-add-var lforminfo arg t
))
169 (unless (null (byte-compile-lforminfo-vars lforminfo
))
170 (byte-compile-lforminfo-analyze-forms lforminfo lambda
2 special nil
)))
172 (defun byte-compile-lforminfo-analyze (lforminfo form
&optional ignore closure-flag
)
173 "Update variable information in LFORMINFO by analyzing FORM.
174 IGNORE is a list of variables that shouldn't be analyzed (usually because
175 they're special, or because some inner binding shadows the version in
176 LFORMINFO). CLOSURE-FLAG should be either nil or a `closure flag' created
177 with `byte-compile-lforminfo-make-closure-flag'; the latter indicates that
178 FORM is inside a lambda expression that may close over some variable in
180 (cond ((symbolp form
)
181 ;; variable reference
182 (unless (member form ignore
)
183 (let ((vinfo (assq form
(byte-compile-lforminfo-vars lforminfo
))))
185 (byte-compile-lvarinfo-note-ref vinfo
)
186 (byte-compile-lforminfo-note-closure lforminfo vinfo
188 ;; function call/special form
190 (let ((fun (car form
)))
195 (let ((var (pop form
)))
196 (byte-compile-lforminfo-analyze lforminfo
(pop form
)
198 (unless (member var ignore
)
200 (assq var
(byte-compile-lforminfo-vars lforminfo
))))
202 (byte-compile-lvarinfo-note-set vinfo
)
203 (byte-compile-lforminfo-note-closure lforminfo vinfo
205 ((and (eq fun
'catch
) (not (eq :fun-body
(nth 2 form
))))
207 (byte-compile-lforminfo-analyze lforminfo
(cadr form
)
209 ;; `catch' uses a closure for the body
210 (byte-compile-lforminfo-analyze-forms
214 (and (not byte-compile-use-downward-closures
)
215 (byte-compile-lforminfo-make-closure-flag)))))
217 (byte-compile-lforminfo-analyze-clauses lforminfo
(cdr form
) 0
218 ignore closure-flag
))
219 ((eq fun
'condition-case
)
220 ;; `condition-case' separates its body/handlers into
221 ;; separate closures.
222 (unless (or (eq (nth 1 form
) :fun-body
)
223 closure-flag byte-compile-use-downward-closures
)
224 ;; condition case is implemented by calling a function
225 (setq closure-flag
(byte-compile-lforminfo-make-closure-flag)))
227 (byte-compile-lforminfo-analyze lforminfo
(nth 2 form
)
229 ;; the error variable is always bound dynamically (because
230 ;; of the implementation)
232 (push (cadr form
) ignore
))
234 (byte-compile-lforminfo-analyze-clauses lforminfo
236 ignore closure-flag
))
237 ((eq fun
'(defvar defconst
))
238 (byte-compile-lforminfo-analyze lforminfo
(nth 2 form
)
239 ignore closure-flag
))
240 ((memq fun
'(defun defmacro))
241 (byte-compile-lforminfo-analyze-forms lforminfo form
3
242 ignore closure-flag
))
244 ;; Analyze an embedded lambda expression [note: we only recognize
245 ;; it within (function ...) as the (lambda ...) for is actually a
246 ;; macro returning (function (lambda ...))].
247 (when (and (consp (cadr form
)) (eq (car (cadr form
)) 'lambda
))
248 ;; shadow bound variables
250 (append (byte-compile-arglist-vars (cadr (cadr form
)))
252 ;; analyze body of lambda
253 (byte-compile-lforminfo-analyze-forms
254 lforminfo
(cadr form
) 2
257 (byte-compile-lforminfo-make-closure-flag)))))
259 ;; analyze variable inits
260 (byte-compile-lforminfo-analyze-clauses lforminfo
(cadr form
) 1
262 ;; shadow bound variables
263 (dolist (clause (cadr form
))
264 (push (if (symbolp clause
) clause
(car clause
))
267 (byte-compile-lforminfo-analyze-forms lforminfo form
2
268 ignore closure-flag
))
270 (dolist (clause (cadr form
))
272 ;; shadow bound (to nil) variable
274 ;; analyze variable init
275 (byte-compile-lforminfo-analyze lforminfo
(cadr clause
)
277 ;; shadow bound variable
278 (push (car clause
) ignore
)))
280 (byte-compile-lforminfo-analyze-forms lforminfo form
2
281 ignore closure-flag
))
285 ((and (eq fun
'save-window-excursion
)
286 (not (eq :fun-body
(nth 1 form
))))
287 ;; `save-window-excursion' currently uses a funny implementation
288 ;; that requires its body forms be put into a closure (it should
289 ;; be fixed to work more like `save-excursion' etc., do).
290 (byte-compile-lforminfo-analyze-forms
294 (and byte-compile-save-window-excursion-uses-eval
295 (not byte-compile-use-downward-closures
)
296 (byte-compile-lforminfo-make-closure-flag)))))
297 ((and (consp fun
) (eq (car fun
) 'lambda
))
298 ;; Embedded lambda. These are inlined by the compiler, so
299 ;; we don't treat them like a real closure, more like `let'.
301 (byte-compile-lforminfo-analyze-forms lforminfo form
2
304 ;; shadow bound variables
305 (setq ignore
(nconc (byte-compile-arglist-vars (cadr fun
))
308 (byte-compile-lforminfo-analyze-forms lforminfo fun
2
309 ignore closure-flag
))
311 ;; For everything else, we just expand each argument (for
312 ;; setq/setq-default this works alright because the
313 ;; variable names are symbols).
314 (byte-compile-lforminfo-analyze-forms lforminfo form
1
315 ignore closure-flag
)))))))
317 (defun byte-compile-lforminfo-analyze-forms
318 (lforminfo forms skip ignore closure-flag
)
319 "Update variable information in LFORMINFO by analyzing each form in FORMS.
320 The first SKIP elements of FORMS are skipped without analysis. IGNORE
321 is a list of variables that shouldn't be analyzed (usually because
322 they're special, or because some inner binding shadows the version in
323 LFORMINFO). CLOSURE-FLAG should be either nil or a `closure flag' created with
324 `byte-compile-lforminfo-make-closure-flag'; the latter indicates that FORM is
325 inside a lambda expression that may close over some variable in LFORMINFO."
327 (setq forms
(nthcdr skip forms
)))
329 (byte-compile-lforminfo-analyze lforminfo
(pop forms
)
330 ignore closure-flag
)))
332 (defun byte-compile-lforminfo-analyze-clauses
333 (lforminfo clauses skip ignore closure-flag
)
334 "Update variable information in LFORMINFO by analyzing each clause in CLAUSES.
335 Each clause is a list of forms; any clause that's not a list is ignored. The
336 first SKIP elements of each clause are skipped without analysis. IGNORE is a
337 list of variables that shouldn't be analyzed (usually because they're special,
338 or because some inner binding shadows the version in LFORMINFO).
339 CLOSURE-FLAG should be either nil or a `closure flag' created with
340 `byte-compile-lforminfo-make-closure-flag'; the latter indicates that FORM is
341 inside a lambda expression that may close over some variable in LFORMINFO."
343 (let ((clause (pop clauses
)))
345 (byte-compile-lforminfo-analyze-forms lforminfo clause skip
346 ignore closure-flag
)))))
349 ;;; Lexical environments
351 ;; A lexical environment is an alist, where each element is of the form
352 ;; (VAR . (OFFSET . ENV)) where VAR is either a symbol, for normal
353 ;; variables, or an `heapenv' descriptor for references to heap environment
354 ;; vectors. ENV is either an atom, meaning a `stack allocated' variable
355 ;; (the particular atom serves to indicate the particular function context
356 ;; on whose stack it's allocated), or an `heapenv' descriptor (see above),
357 ;; meaning a variable allocated in a heap environment vector. For the
358 ;; later case, an anonymous `variable' holding a pointer to the environment
359 ;; vector may be located by recursively looking up ENV in the environment
360 ;; as if it were a variable (so the entry for that `variable' will have a
363 ;; We call a lexical environment a `lexenv', and an entry in it a `lexvar'.
366 (defsubst byte-compile-make-lexvar
(name offset
&optional env
)
367 (cons name
(cons offset env
)))
369 (defsubst byte-compile-lexvar-name
(lexvar) (car lexvar
))
370 (defsubst byte-compile-lexvar-offset
(lexvar) (cadr lexvar
))
371 (defsubst byte-compile-lexvar-environment
(lexvar) (cddr lexvar
))
372 (defsubst byte-compile-lexvar-variable-p
(lexvar) (symbolp (car lexvar
)))
373 (defsubst byte-compile-lexvar-environment-p
(lexvar)
374 (not (symbolp (car lexvar
))))
375 (defsubst byte-compile-lexvar-on-stack-p
(lexvar)
376 (atom (byte-compile-lexvar-environment lexvar
)))
377 (defsubst byte-compile-lexvar-in-heap-p
(lexvar)
378 (not (byte-compile-lexvar-on-stack-p lexvar
)))
380 (defun byte-compile-make-lambda-lexenv (form closed-over-lexenv
)
381 "Return a new lexical environment for a lambda expression FORM.
382 CLOSED-OVER-LEXENV is the lexical environment in which FORM occurs.
383 The returned lexical environment contains two sets of variables:
384 * Variables that were in CLOSED-OVER-LEXENV and used by FORM
385 (all of these will be `heap' variables)
386 * Arguments to FORM (all of these will be `stack' variables)."
387 ;; See if this is a closure or not
389 (lforminfo (byte-compile-make-lforminfo))
390 (args (byte-compile-arglist-vars (cadr form
))))
391 ;; Add variables from surrounding lexical environment to analysis set
392 (dolist (lexvar closed-over-lexenv
)
393 (when (and (byte-compile-lexvar-in-heap-p lexvar
)
394 (not (memq (car lexvar
) args
)))
395 ;; The variable is located in a heap-allocated environment
396 ;; vector, so FORM may use it. Add it to the set of variables
397 ;; that we'll search for in FORM.
398 (byte-compile-lforminfo-add-var lforminfo
(car lexvar
))))
399 ;; See how FORM uses these potentially closed-over variables.
400 (byte-compile-lforminfo-analyze lforminfo form args
)
402 (dolist (vinfo (byte-compile-lforminfo-vars lforminfo
))
403 (when (> (byte-compile-lvarinfo-num-refs vinfo
) 0)
404 ;; FORM uses VINFO's variable, so it must be a closure.
406 ;; Make sure that the environment in which the variable is
407 ;; located is accessible (since we only ever pass the
408 ;; innermost environment to closures, if it's in some other
409 ;; envionment, there must be path to it from the innermost
411 (unless (byte-compile-lexvar-in-heap-p vinfo
)
412 ;; To access the variable from FORM, it must be in the heap.
414 "Compiler error: lexical variable `%s' should be heap-allocated but is not"
416 (let ((closed-over-lexvar (assq (car vinfo
) closed-over-lexenv
)))
417 (byte-compile-heapenv-ensure-access
418 byte-compile-current-heap-environment
419 (byte-compile-lexvar-environment closed-over-lexvar
))
420 ;; Put this variable in the new lexical environment
421 (push closed-over-lexvar lexenv
))))
422 ;; Fill in the initial stack contents
425 ;; Add the magic first argument that holds the environment pointer
426 (push (byte-compile-make-lexvar byte-compile-current-heap-environment
429 (setq stackpos
(1+ stackpos
)))
430 ;; Add entries for each argument
432 (push (byte-compile-make-lexvar arg stackpos
) lexenv
)
433 (setq stackpos
(1+ stackpos
)))
434 ;; Return the new lexical environment
437 (defun byte-compile-closure-initial-lexenv-p (lexenv)
438 "Return non-nil if LEXENV is the initial lexical environment for a closure.
439 This only works correctly when passed a new lexical environment as
440 returned by `byte-compile-make-lambda-lexenv' (it works by checking to
441 see whether there are any heap-allocated lexical variables in LEXENV)."
443 (while (and lexenv
(not closure
))
444 (when (byte-compile-lexvar-environment-p (pop lexenv
))
449 ;;; Heap environment vectors
451 ;; A `heap environment vector' is heap-allocated vector used to store
452 ;; variable that can't be put onto the stack.
454 ;; They are represented in the compiler by a list of the form
456 ;; (SIZE SIZE-CONST-ID INIT-POSITION . ENVS)
458 ;; SIZE is the current size of the vector (which may be
459 ;; incremented if another variable or environment-reference is added to
460 ;; the end). SIZE-CONST-ID is an `unknown constant id' (as returned by
461 ;; `byte-compile-push-unknown-constant') representing the constant used
462 ;; in the vector initialization code, and INIT-POSITION is a position
463 ;; in the byte-code output (as returned by `byte-compile-delay-out')
464 ;; at which more initialization code can be added.
465 ;; ENVS is a list of other environment vectors accessible form this one,
466 ;; where each element is of the form (ENV . OFFSET).
469 (defsubst byte-compile-make-heapenv
(size-const-id init-position
)
470 (list 0 size-const-id init-position
))
472 (defsubst byte-compile-heapenv-size
(heapenv) (car heapenv
))
473 (defsubst byte-compile-heapenv-size-const-id
(heapenv) (cadr heapenv
))
474 (defsubst byte-compile-heapenv-init-position
(heapenv) (nth 2 heapenv
))
475 (defsubst byte-compile-heapenv-accessible-envs
(heapenv) (nthcdr 3 heapenv
))
477 (defun byte-compile-heapenv-add-slot (heapenv)
478 "Add a slot to the heap environment HEAPENV and return its offset."
479 (prog1 (car heapenv
) (setcar heapenv
(1+ (car heapenv
)))))
481 (defun byte-compile-heapenv-add-accessible-env (heapenv env offset
)
482 "Add to HEAPENV's list of accessible environments, ENV at OFFSET."
483 (setcdr (nthcdr 2 heapenv
)
484 (cons (cons env offset
)
485 (byte-compile-heapenv-accessible-envs heapenv
))))
487 (defun byte-compile-push-heapenv ()
488 "Generate byte-code to push a new heap environment vector.
489 Sets `byte-compile-current-heap-environment' to the compiler descriptor
490 for the new heap environment.
491 Return a `lexvar' descriptor for the new heap environment."
492 (let ((env-stack-pos byte-compile-depth
)
493 size-const-id init-position
)
494 ;; Generate code to push the vector
495 (byte-compile-push-constant 'make-vector
)
496 (setq size-const-id
(byte-compile-push-unknown-constant))
497 (byte-compile-push-constant nil
)
498 (byte-compile-out 'byte-call
2)
499 (setq init-position
(byte-compile-delay-out 3))
500 ;; Now make a heap-environment for the compiler to use
501 (setq byte-compile-current-heap-environment
502 (byte-compile-make-heapenv size-const-id init-position
))
503 (byte-compile-make-lexvar byte-compile-current-heap-environment
506 (defun byte-compile-heapenv-ensure-access (heapenv other-heapenv
)
507 "Make sure that HEAPENV can be used to access OTHER-HEAPENV.
508 If not, then add a new slot to HEAPENV pointing to OTHER-HEAPENV."
509 (unless (memq heapenv
(byte-compile-heapenv-accessible-envs heapenv
))
510 (let ((offset (byte-compile-heapenv-add-slot heapenv
)))
511 (byte-compile-heapenv-add-accessible-env heapenv other-heapenv offset
))))
514 ;;; Variable binding/unbinding
516 (defun byte-compile-non-stack-bindings-p (clauses lforminfo
)
517 "Return non-nil if any lexical bindings in CLAUSES are not stack-allocated.
518 LFORMINFO should be information about lexical variables being bound."
519 (let ((vars (byte-compile-lforminfo-vars lforminfo
)))
520 (or (not (= (length clauses
) (length vars
)))
522 (while (and vars clauses
)
523 (when (byte-compile-lvarinfo-closed-over-p (pop vars
))
527 (defun byte-compile-let-clauses-trivial-init-p (clauses)
528 "Return true if let binding CLAUSES all have a `trivial' init value.
529 Trivial means either a constant value, or a simple variable initialization."
531 (and (or (atom (car clauses
))
532 (atom (cadr (car clauses
)))
533 (eq (car (cadr (car clauses
))) 'quote
))
534 (byte-compile-let-clauses-trivial-init-p (cdr clauses
)))))
536 (defun byte-compile-rearrange-let-clauses (clauses lforminfo
)
537 "Return CLAUSES rearranged so non-stack variables come last if possible.
538 Care is taken to only do so when it's clear that the meaning is the same.
539 LFORMINFO should be information about lexical variables being bound."
540 ;; We currently do a very simple job by only exchanging clauses when
541 ;; one has a constant init, or one has a variable init and the other
542 ;; doesn't have a function call init (because that could change the
543 ;; value of the variable). This could be more clever and actually
544 ;; attempt to analyze which variables could possible be changed, etc.
545 (let ((unchanged nil
)
549 (let* ((clause (pop clauses
))
550 (var (if (consp clause
) (car clause
) clause
))
551 (init (and (consp clause
) (cadr clause
)))
552 (vinfo (assq var
(byte-compile-lforminfo-vars lforminfo
))))
555 (not (byte-compile-lvarinfo-closed-over-p vinfo
)))
557 (or (eq init nil
) (eq init t
)
558 (and (atom init
) (not (symbolp init
)))
559 (and (consp init
) (eq (car init
) 'quote
))
560 (byte-compile-let-clauses-trivial-init-p clauses
))))
561 (push clause unchanged
))
563 (push clause lex-non-stack
))
565 (push clause dynamic
)))))
566 (nconc (nreverse unchanged
) (nreverse lex-non-stack
) (nreverse dynamic
))))
568 (defun byte-compile-maybe-push-heap-environment (&optional lforminfo
)
569 "Push a new heap environment if necessary.
570 LFORMINFO should be information about lexical variables being bound.
571 Return a lexical environment containing only the heap vector (or
572 nil if nothing was pushed).
573 Also, `byte-compile-current-heap-environment' and
574 `byte-compile-current-num-closures' are updated to reflect any change (so they
575 should probably be bound by the caller to ensure that the new values have the
577 ;; We decide whether a new heap environment is required by seeing if
578 ;; the number of closures inside the form described by LFORMINFO is
579 ;; the same as the number inside the binding form that created the
580 ;; currently active heap environment.
582 (and lforminfo
(byte-compile-lforminfo-num-closures lforminfo
))))
583 (if (or (null lforminfo
)
585 (= nclosures byte-compile-current-num-closures
))
586 ;; No need to push a heap environment.
588 (error "Should have been handled by cconv")
589 ;; Have to push one. A heap environment is really just a vector, so
590 ;; we emit bytecodes to create a vector. However, the size is not
591 ;; fixed yet (the vector can grow if subforms use it to store
592 ;; values, and if `access points' to parent heap environments are
593 ;; added), so we use `byte-compile-push-unknown-constant' to push the
595 (setq byte-compile-current-num-closures nclosures
)
596 (list (byte-compile-push-heapenv)))))
598 (defun byte-compile-bind (var init-lexenv
&optional lforminfo
)
599 "Emit byte-codes to bind VAR and update `byte-compile-lexical-environment'.
600 INIT-LEXENV should be a lexical-environment alist describing the
601 positions of the init value that have been pushed on the stack, and
602 LFORMINFO should be information about lexical variables being bound.
603 Return non-nil if the TOS value was popped."
604 ;; The presence of lexical bindings mean that we may have to
605 ;; juggle things on the stack, either to move them to TOS for
606 ;; dynamic binding, or to put them in a non-stack environment
608 (let ((vinfo (assq var
(byte-compile-lforminfo-vars lforminfo
))))
609 (cond ((and (null vinfo
) (eq var
(caar init-lexenv
)))
610 ;; VAR is dynamic and is on the top of the
611 ;; stack, so we can just bind it like usual
612 (byte-compile-dynamic-variable-bind var
)
615 ;; VAR is dynamic, but we have to get its
616 ;; value out of the middle of the stack
617 (let ((stack-pos (cdr (assq var init-lexenv
))))
618 (byte-compile-stack-ref stack-pos
)
619 (byte-compile-dynamic-variable-bind var
)
620 ;; Now we have to store nil into its temporary
621 ;; stack position to avoid problems with GC
622 (byte-compile-push-constant nil
)
623 (byte-compile-stack-set stack-pos
))
625 ((byte-compile-lvarinfo-closed-over-p vinfo
)
626 ;; VAR is lexical, but needs to be in a
627 ;; heap-allocated environment.
628 (unless byte-compile-current-heap-environment
629 (error "No current heap-environment to allocate `%s' in!" var
))
630 (let ((init-stack-pos
631 ;; nil if the init value is on the top of the stack,
632 ;; otherwise the position of the init value on the stack.
633 (and (not (eq var
(caar init-lexenv
)))
634 (byte-compile-lexvar-offset (assq var init-lexenv
))))
636 ;; Position of VAR in the environment vector
637 (byte-compile-lexvar-offset
638 (assq var byte-compile-lexical-environment
)))
640 ;; Position of the the environment vector on the stack
641 ;; (the heap-environment must _always_ be available on
643 (byte-compile-lexvar-offset
644 (assq byte-compile-current-heap-environment
645 byte-compile-lexical-environment
))))
646 (unless env-vec-stack-pos
647 (error "Couldn't find location of current heap environment!"))
649 ;; VAR is not on the top of the stack, so get it
650 (byte-compile-stack-ref init-stack-pos
))
651 (byte-compile-stack-ref env-vec-stack-pos
)
652 ;; Store the variable into the vector
653 (byte-compile-out 'byte-vec-set env-vec-pos
)
655 ;; Store nil into VAR's temporary stack
656 ;; position to avoid problems with GC
657 (byte-compile-push-constant nil
)
658 (byte-compile-stack-set init-stack-pos
))
659 ;; Push a record of VAR's new lexical binding
660 (push (byte-compile-make-lexvar
661 var env-vec-pos byte-compile-current-heap-environment
)
662 byte-compile-lexical-environment
)
663 (not init-stack-pos
)))
665 ;; VAR is a simple stack-allocated lexical variable
666 (push (assq var init-lexenv
)
667 byte-compile-lexical-environment
)
670 (defun byte-compile-unbind (clauses init-lexenv
671 &optional lforminfo preserve-body-value
)
672 "Emit byte-codes to unbind the variables bound by CLAUSES.
673 CLAUSES is a `let'-style variable binding list. INIT-LEXENV should be a
674 lexical-environment alist describing the positions of the init value that
675 have been pushed on the stack, and LFORMINFO should be information about
676 the lexical variables that were bound. If PRESERVE-BODY-VALUE is true,
677 then an additional value on the top of the stack, above any lexical binding
678 slots, is preserved, so it will be on the top of the stack after all
679 binding slots have been popped."
680 ;; Unbind dynamic variables
681 (let ((num-dynamic-bindings 0))
683 (dolist (clause clauses
)
684 (unless (assq (if (consp clause
) (car clause
) clause
)
685 (byte-compile-lforminfo-vars lforminfo
))
686 (setq num-dynamic-bindings
(1+ num-dynamic-bindings
))))
687 (setq num-dynamic-bindings
(length clauses
)))
688 (unless (zerop num-dynamic-bindings
)
689 (byte-compile-out 'byte-unbind num-dynamic-bindings
)))
690 ;; Pop lexical variables off the stack, possibly preserving the
691 ;; return value of the body.
693 ;; INIT-LEXENV contains all init values left on the stack
694 (byte-compile-discard (length init-lexenv
) preserve-body-value
)))
697 (provide 'byte-lexbind
)
699 ;;; byte-lexbind.el ends here