diff options
| author | Stefan Monnier | 2011-02-12 00:53:30 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2011-02-12 00:53:30 -0500 |
| commit | ce5b520a3758e22c6516e0d864d8c1a3512bf457 (patch) | |
| tree | bcf74ea6c4f88995c5630113578632dc4ce2a878 | |
| parent | c530e1c2a3a036d71942c354ba11b30a06341fd7 (diff) | |
| download | emacs-ce5b520a3758e22c6516e0d864d8c1a3512bf457.tar.gz emacs-ce5b520a3758e22c6516e0d864d8c1a3512bf457.zip | |
* lisp/emacs-lisp/byte-lexbind.el: Delete.
* lisp/emacs-lisp/bytecomp.el (byte-compile-current-heap-environment)
(byte-compile-current-num-closures): Remove vars.
(byte-vec-ref, byte-vec-set): Remove byte codes.
(byte-compile-arglist-vars, byte-compile-make-lambda-lexenv): Move from
byte-lexbind.el.
(byte-compile-lambda): Never build a closure.
(byte-compile-closure-code-p, byte-compile-make-closure): Remove.
(byte-compile-closure): Simplify.
(byte-compile-top-level): Don't mess with heap environments.
(byte-compile-dynamic-variable-bind): Always maintain
byte-compile-bound-variables.
(byte-compile-variable-ref, byte-compile-variable-set): Always just use
the stack for lexical vars.
(byte-compile-push-binding-init): Simplify.
(byte-compile-not-lexical-var-p): New function, moved from cconv.el.
(byte-compile-bind, byte-compile-unbind): New functions, moved and
simplified from byte-lexbind.el.
(byte-compile-let, byte-compile-let*): Simplify.
(byte-compile-condition-case): Don't add :fun-body to the bound vars.
(byte-compile-defmacro): Simplify.
* lisp/emacs-lisp/byte-opt.el (byte-compile-side-effect-free-ops)
(byte-optimize-lapcode): Remove byte-vec-ref and byte-vec-set.
* lisp/emacs-lisp/cconv.el (cconv-not-lexical-var-p): Remove.
(cconv-freevars, cconv-analyse-function, cconv-analyse-form):
Use byte-compile-not-lexical-var-p instead.
* src/bytecode.c (Bvec_ref, Bvec_set): Remove.
(exec_byte_code): Don't handle them.
* lisp/help-fns.el (describe-function-1): Fix paren typo.
| -rw-r--r-- | lisp/ChangeLog | 34 | ||||
| -rw-r--r-- | lisp/emacs-lisp/byte-lexbind.el | 699 | ||||
| -rw-r--r-- | lisp/emacs-lisp/byte-opt.el | 4 | ||||
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 553 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cconv.el | 19 | ||||
| -rw-r--r-- | lisp/help-fns.el | 34 | ||||
| -rw-r--r-- | src/ChangeLog | 5 | ||||
| -rw-r--r-- | src/bytecode.c | 23 |
8 files changed, 283 insertions, 1088 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index c3451d9b269..b972f17909a 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,37 @@ | |||
| 1 | 2011-02-12 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * emacs-lisp/byte-lexbind.el: Delete. | ||
| 4 | |||
| 5 | * emacs-lisp/bytecomp.el (byte-compile-current-heap-environment) | ||
| 6 | (byte-compile-current-num-closures): Remove vars. | ||
| 7 | (byte-vec-ref, byte-vec-set): Remove byte codes. | ||
| 8 | (byte-compile-arglist-vars, byte-compile-make-lambda-lexenv): Move from | ||
| 9 | byte-lexbind.el. | ||
| 10 | (byte-compile-lambda): Never build a closure. | ||
| 11 | (byte-compile-closure-code-p, byte-compile-make-closure): Remove. | ||
| 12 | (byte-compile-closure): Simplify. | ||
| 13 | (byte-compile-top-level): Don't mess with heap environments. | ||
| 14 | (byte-compile-dynamic-variable-bind): Always maintain | ||
| 15 | byte-compile-bound-variables. | ||
| 16 | (byte-compile-variable-ref, byte-compile-variable-set): Always just use | ||
| 17 | the stack for lexical vars. | ||
| 18 | (byte-compile-push-binding-init): Simplify. | ||
| 19 | (byte-compile-not-lexical-var-p): New function, moved from cconv.el. | ||
| 20 | (byte-compile-bind, byte-compile-unbind): New functions, moved and | ||
| 21 | simplified from byte-lexbind.el. | ||
| 22 | (byte-compile-let, byte-compile-let*): Simplify. | ||
| 23 | (byte-compile-condition-case): Don't add :fun-body to the bound vars. | ||
| 24 | (byte-compile-defmacro): Simplify. | ||
| 25 | |||
| 26 | * emacs-lisp/cconv.el (cconv-not-lexical-var-p): Remove. | ||
| 27 | (cconv-freevars, cconv-analyse-function, cconv-analyse-form): | ||
| 28 | Use byte-compile-not-lexical-var-p instead. | ||
| 29 | |||
| 30 | * help-fns.el (describe-function-1): Fix paren typo. | ||
| 31 | |||
| 32 | * emacs-lisp/byte-opt.el (byte-compile-side-effect-free-ops) | ||
| 33 | (byte-optimize-lapcode): Remove byte-vec-ref and byte-vec-set. | ||
| 34 | |||
| 1 | 2011-02-11 Stefan Monnier <monnier@iro.umontreal.ca> | 35 | 2011-02-11 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 36 | ||
| 3 | * emacs-lisp/cconv.el (cconv-closure-convert): Drop `toplevel' arg. | 37 | * emacs-lisp/cconv.el (cconv-closure-convert): Drop `toplevel' arg. |
diff --git a/lisp/emacs-lisp/byte-lexbind.el b/lisp/emacs-lisp/byte-lexbind.el deleted file mode 100644 index 06353e2eea8..00000000000 --- a/lisp/emacs-lisp/byte-lexbind.el +++ /dev/null | |||
| @@ -1,699 +0,0 @@ | |||
| 1 | ;;; byte-lexbind.el --- Lexical binding support for byte-compiler | ||
| 2 | ;; | ||
| 3 | ;; Copyright (C) 2001, 2002, 2010, 2011 Free Software Foundation, Inc. | ||
| 4 | ;; | ||
| 5 | ;; Author: Miles Bader <miles@gnu.org> | ||
| 6 | ;; Keywords: lisp, compiler, lexical binding | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 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) | ||
| 13 | ;; any later version. | ||
| 14 | |||
| 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. | ||
| 19 | |||
| 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. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | ;; | ||
| 27 | |||
| 28 | ;;; Code: | ||
| 29 | |||
| 30 | (require 'bytecomp-preload "bytecomp") | ||
| 31 | |||
| 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.") | ||
| 35 | |||
| 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.") | ||
| 39 | |||
| 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))) | ||
| 43 | |||
| 44 | |||
| 45 | ;;; Variable extent analysis. | ||
| 46 | |||
| 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: | ||
| 51 | ;; | ||
| 52 | ;; LFORMINFO : ((LVARINFO ...) . NUM-CLOSURES)" | ||
| 53 | ;; | ||
| 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: | ||
| 57 | ;; | ||
| 58 | ;; LVARINFO : (VAR NUM-REFS NUM-SETS CLOSED-OVER) | ||
| 59 | ;; | ||
| 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" | ||
| 64 | |||
| 65 | ;;; lvarinfo: | ||
| 66 | |||
| 67 | ;; constructor | ||
| 68 | (defsubst byte-compile-make-lvarinfo (var &optional already-set) | ||
| 69 | (list var 0 (if already-set 1 0) 0 nil)) | ||
| 70 | ;; accessors | ||
| 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)) | ||
| 75 | ;; setters | ||
| 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)) | ||
| 82 | |||
| 83 | ;;; lforminfo: | ||
| 84 | |||
| 85 | ;; constructor | ||
| 86 | (defsubst byte-compile-make-lforminfo () | ||
| 87 | (cons nil 0)) | ||
| 88 | ;; accessors | ||
| 89 | (defalias 'byte-compile-lforminfo-vars 'car) | ||
| 90 | (defalias 'byte-compile-lforminfo-num-closures 'cdr) | ||
| 91 | ;; setters | ||
| 92 | (defsubst byte-compile-lforminfo-add-var (finfo var &optional already-set) | ||
| 93 | (setcar finfo (cons (byte-compile-make-lvarinfo var already-set) | ||
| 94 | (car finfo)))) | ||
| 95 | |||
| 96 | (defun byte-compile-lforminfo-make-closure-flag () | ||
| 97 | "Return a new `closure-flag'." | ||
| 98 | (cons nil nil)) | ||
| 99 | |||
| 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'." | ||
| 106 | (when 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)))) | ||
| 111 | |||
| 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). | ||
| 117 | |||
| 118 | The result is an `lforminfo' data structure." | ||
| 119 | (and | ||
| 120 | (consp form) | ||
| 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)))) | ||
| 128 | ;; Analyze the body | ||
| 129 | (unless (null (byte-compile-lforminfo-vars lforminfo)) | ||
| 130 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 131 | special nil))) | ||
| 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 | ||
| 136 | ;; bound variables. | ||
| 137 | (when (and (consp clause) lforminfo) | ||
| 138 | (byte-compile-lforminfo-analyze lforminfo (cadr clause) | ||
| 139 | special nil)) | ||
| 140 | (unless (or (special-variable-p var) (memq var special)) | ||
| 141 | (byte-compile-lforminfo-add-var lforminfo var t)))) | ||
| 142 | ;; Analyze the body | ||
| 143 | (unless (null (byte-compile-lforminfo-vars lforminfo)) | ||
| 144 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 145 | special nil))) | ||
| 146 | ((eq (car form) 'condition-case) | ||
| 147 | ;; `condition-case' currently must dynamically bind the | ||
| 148 | ;; error variable, so do nothing. | ||
| 149 | ) | ||
| 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) | ||
| 158 | lforminfo | ||
| 159 | nil)))) | ||
| 160 | |||
| 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'." | ||
| 165 | ;; Add the arguments | ||
| 166 | (dolist (arg (byte-compile-arglist-vars (cadr lambda))) | ||
| 167 | (byte-compile-lforminfo-add-var lforminfo arg t)) | ||
| 168 | ;; Analyze the body | ||
| 169 | (unless (null (byte-compile-lforminfo-vars lforminfo)) | ||
| 170 | (byte-compile-lforminfo-analyze-forms lforminfo lambda 2 special nil))) | ||
| 171 | |||
| 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 | ||
| 179 | LFORMINFO." | ||
| 180 | (cond ((symbolp form) | ||
| 181 | ;; variable reference | ||
| 182 | (unless (member form ignore) | ||
| 183 | (let ((vinfo (assq form (byte-compile-lforminfo-vars lforminfo)))) | ||
| 184 | (when vinfo | ||
| 185 | (byte-compile-lvarinfo-note-ref vinfo) | ||
| 186 | (byte-compile-lforminfo-note-closure lforminfo vinfo | ||
| 187 | closure-flag))))) | ||
| 188 | ;; function call/special form | ||
| 189 | ((consp form) | ||
| 190 | (let ((fun (car form))) | ||
| 191 | (cond | ||
| 192 | ((eq fun 'setq) | ||
| 193 | (pop form) | ||
| 194 | (while form | ||
| 195 | (let ((var (pop form))) | ||
| 196 | (byte-compile-lforminfo-analyze lforminfo (pop form) | ||
| 197 | ignore closure-flag) | ||
| 198 | (unless (member var ignore) | ||
| 199 | (let ((vinfo | ||
| 200 | (assq var (byte-compile-lforminfo-vars lforminfo)))) | ||
| 201 | (when vinfo | ||
| 202 | (byte-compile-lvarinfo-note-set vinfo) | ||
| 203 | (byte-compile-lforminfo-note-closure lforminfo vinfo | ||
| 204 | closure-flag))))))) | ||
| 205 | ((and (eq fun 'catch) (not (eq :fun-body (nth 2 form)))) | ||
| 206 | ;; tag | ||
| 207 | (byte-compile-lforminfo-analyze lforminfo (cadr form) | ||
| 208 | ignore closure-flag) | ||
| 209 | ;; `catch' uses a closure for the body | ||
| 210 | (byte-compile-lforminfo-analyze-forms | ||
| 211 | lforminfo form 2 | ||
| 212 | ignore | ||
| 213 | (or closure-flag | ||
| 214 | (and (not byte-compile-use-downward-closures) | ||
| 215 | (byte-compile-lforminfo-make-closure-flag))))) | ||
| 216 | ((eq fun 'cond) | ||
| 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))) | ||
| 226 | ;; value form | ||
| 227 | (byte-compile-lforminfo-analyze lforminfo (nth 2 form) | ||
| 228 | ignore closure-flag) | ||
| 229 | ;; the error variable is always bound dynamically (because | ||
| 230 | ;; of the implementation) | ||
| 231 | (when (cadr form) | ||
| 232 | (push (cadr form) ignore)) | ||
| 233 | ;; handlers | ||
| 234 | (byte-compile-lforminfo-analyze-clauses lforminfo | ||
| 235 | (nthcdr 2 form) 1 | ||
| 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)) | ||
| 243 | ((eq fun 'function) | ||
| 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 | ||
| 249 | (setq ignore | ||
| 250 | (append (byte-compile-arglist-vars (cadr (cadr form))) | ||
| 251 | ignore)) | ||
| 252 | ;; analyze body of lambda | ||
| 253 | (byte-compile-lforminfo-analyze-forms | ||
| 254 | lforminfo (cadr form) 2 | ||
| 255 | ignore | ||
| 256 | (or closure-flag | ||
| 257 | (byte-compile-lforminfo-make-closure-flag))))) | ||
| 258 | ((eq fun 'let) | ||
| 259 | ;; analyze variable inits | ||
| 260 | (byte-compile-lforminfo-analyze-clauses lforminfo (cadr form) 1 | ||
| 261 | ignore closure-flag) | ||
| 262 | ;; shadow bound variables | ||
| 263 | (dolist (clause (cadr form)) | ||
| 264 | (push (if (symbolp clause) clause (car clause)) | ||
| 265 | ignore)) | ||
| 266 | ;; analyze body | ||
| 267 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 268 | ignore closure-flag)) | ||
| 269 | ((eq fun 'let*) | ||
| 270 | (dolist (clause (cadr form)) | ||
| 271 | (if (symbolp clause) | ||
| 272 | ;; shadow bound (to nil) variable | ||
| 273 | (push clause ignore) | ||
| 274 | ;; analyze variable init | ||
| 275 | (byte-compile-lforminfo-analyze lforminfo (cadr clause) | ||
| 276 | ignore closure-flag) | ||
| 277 | ;; shadow bound variable | ||
| 278 | (push (car clause) ignore))) | ||
| 279 | ;; analyze body | ||
| 280 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 281 | ignore closure-flag)) | ||
| 282 | ((eq fun 'quote) | ||
| 283 | ;; do nothing | ||
| 284 | ) | ||
| 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 | ||
| 291 | lforminfo form 2 | ||
| 292 | ignore | ||
| 293 | (or closure-flag | ||
| 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'. | ||
| 300 | ;; analyze inits | ||
| 301 | (byte-compile-lforminfo-analyze-forms lforminfo form 2 | ||
| 302 | ignore closure-flag) | ||
| 303 | |||
| 304 | ;; shadow bound variables | ||
| 305 | (setq ignore (nconc (byte-compile-arglist-vars (cadr fun)) | ||
| 306 | ignore)) | ||
| 307 | ;; analyze body | ||
| 308 | (byte-compile-lforminfo-analyze-forms lforminfo fun 2 | ||
| 309 | ignore closure-flag)) | ||
| 310 | (t | ||
| 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))))))) | ||
| 316 | |||
| 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." | ||
| 326 | (when skip | ||
| 327 | (setq forms (nthcdr skip forms))) | ||
| 328 | (while forms | ||
| 329 | (byte-compile-lforminfo-analyze lforminfo (pop forms) | ||
| 330 | ignore closure-flag))) | ||
| 331 | |||
| 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." | ||
| 342 | (while clauses | ||
| 343 | (let ((clause (pop clauses))) | ||
| 344 | (when (consp clause) | ||
| 345 | (byte-compile-lforminfo-analyze-forms lforminfo clause skip | ||
| 346 | ignore closure-flag))))) | ||
| 347 | |||
| 348 | |||
| 349 | ;;; Lexical environments | ||
| 350 | |||
| 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 | ||
| 361 | ;; non-symbol VAR). | ||
| 362 | |||
| 363 | ;; We call a lexical environment a `lexenv', and an entry in it a `lexvar'. | ||
| 364 | |||
| 365 | ;; constructor | ||
| 366 | (defsubst byte-compile-make-lexvar (name offset &optional env) | ||
| 367 | (cons name (cons offset env))) | ||
| 368 | ;; accessors | ||
| 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))) | ||
| 379 | |||
| 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 | ||
| 388 | (let ((closure nil) | ||
| 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) | ||
| 401 | (let ((lexenv nil)) | ||
| 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. | ||
| 405 | (setq closure t) | ||
| 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 | ||
| 410 | ;; one). | ||
| 411 | (unless (byte-compile-lexvar-in-heap-p vinfo) | ||
| 412 | ;; To access the variable from FORM, it must be in the heap. | ||
| 413 | (error | ||
| 414 | "Compiler error: lexical variable `%s' should be heap-allocated but is not" | ||
| 415 | (car vinfo))) | ||
| 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 | ||
| 423 | (let ((stackpos 0)) | ||
| 424 | (when closure | ||
| 425 | ;; Add the magic first argument that holds the environment pointer | ||
| 426 | (push (byte-compile-make-lexvar byte-compile-current-heap-environment | ||
| 427 | 0) | ||
| 428 | lexenv) | ||
| 429 | (setq stackpos (1+ stackpos))) | ||
| 430 | ;; Add entries for each argument | ||
| 431 | (dolist (arg args) | ||
| 432 | (push (byte-compile-make-lexvar arg stackpos) lexenv) | ||
| 433 | (setq stackpos (1+ stackpos))) | ||
| 434 | ;; Return the new lexical environment | ||
| 435 | lexenv)))) | ||
| 436 | |||
| 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)." | ||
| 442 | (let ((closure nil)) | ||
| 443 | (while (and lexenv (not closure)) | ||
| 444 | (when (byte-compile-lexvar-environment-p (pop lexenv)) | ||
| 445 | (setq closure t))) | ||
| 446 | closure)) | ||
| 447 | |||
| 448 | |||
| 449 | ;;; Heap environment vectors | ||
| 450 | |||
| 451 | ;; A `heap environment vector' is heap-allocated vector used to store | ||
| 452 | ;; variable that can't be put onto the stack. | ||
| 453 | ;; | ||
| 454 | ;; They are represented in the compiler by a list of the form | ||
| 455 | ;; | ||
| 456 | ;; (SIZE SIZE-CONST-ID INIT-POSITION . ENVS) | ||
| 457 | ;; | ||
| 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). | ||
| 467 | |||
| 468 | ;; constructor | ||
| 469 | (defsubst byte-compile-make-heapenv (size-const-id init-position) | ||
| 470 | (list 0 size-const-id init-position)) | ||
| 471 | ;; accessors | ||
| 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)) | ||
| 476 | |||
| 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))))) | ||
| 480 | |||
| 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)))) | ||
| 486 | |||
| 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 | ||
| 504 | env-stack-pos))) | ||
| 505 | |||
| 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)))) | ||
| 512 | |||
| 513 | |||
| 514 | ;;; Variable binding/unbinding | ||
| 515 | |||
| 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))) | ||
| 521 | (progn | ||
| 522 | (while (and vars clauses) | ||
| 523 | (when (byte-compile-lvarinfo-closed-over-p (pop vars)) | ||
| 524 | (setq clauses nil))) | ||
| 525 | (not clauses))))) | ||
| 526 | |||
| 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." | ||
| 530 | (or (null clauses) | ||
| 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))))) | ||
| 535 | |||
| 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) | ||
| 546 | (lex-non-stack nil) | ||
| 547 | (dynamic nil)) | ||
| 548 | (while clauses | ||
| 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)))) | ||
| 553 | (cond | ||
| 554 | ((or (and vinfo | ||
| 555 | (not (byte-compile-lvarinfo-closed-over-p vinfo))) | ||
| 556 | (not | ||
| 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)) | ||
| 562 | (vinfo | ||
| 563 | (push clause lex-non-stack)) | ||
| 564 | (t | ||
| 565 | (push clause dynamic))))) | ||
| 566 | (nconc (nreverse unchanged) (nreverse lex-non-stack) (nreverse dynamic)))) | ||
| 567 | |||
| 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 | ||
| 576 | proper scope)." | ||
| 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. | ||
| 581 | (let ((nclosures | ||
| 582 | (and lforminfo (byte-compile-lforminfo-num-closures lforminfo)))) | ||
| 583 | (if (or (null lforminfo) | ||
| 584 | (zerop nclosures) | ||
| 585 | (= nclosures byte-compile-current-num-closures)) | ||
| 586 | ;; No need to push a heap environment. | ||
| 587 | nil | ||
| 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 | ||
| 594 | ;; vector size. | ||
| 595 | (setq byte-compile-current-num-closures nclosures) | ||
| 596 | (list (byte-compile-push-heapenv))))) | ||
| 597 | |||
| 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 | ||
| 607 | ;; vector. | ||
| 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) | ||
| 613 | t) | ||
| 614 | ((null vinfo) | ||
| 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)) | ||
| 624 | nil) | ||
| 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)))) | ||
| 635 | (env-vec-pos | ||
| 636 | ;; Position of VAR in the environment vector | ||
| 637 | (byte-compile-lexvar-offset | ||
| 638 | (assq var byte-compile-lexical-environment))) | ||
| 639 | (env-vec-stack-pos | ||
| 640 | ;; Position of the the environment vector on the stack | ||
| 641 | ;; (the heap-environment must _always_ be available on | ||
| 642 | ;; the stack!) | ||
| 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!")) | ||
| 648 | (when init-stack-pos | ||
| 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) | ||
| 654 | (when init-stack-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))) | ||
| 664 | (t | ||
| 665 | ;; VAR is a simple stack-allocated lexical variable | ||
| 666 | (push (assq var init-lexenv) | ||
| 667 | byte-compile-lexical-environment) | ||
| 668 | nil)))) | ||
| 669 | |||
| 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)) | ||
| 682 | (if lforminfo | ||
| 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. | ||
| 692 | (when init-lexenv | ||
| 693 | ;; INIT-LEXENV contains all init values left on the stack | ||
| 694 | (byte-compile-discard (length init-lexenv) preserve-body-value))) | ||
| 695 | |||
| 696 | |||
| 697 | (provide 'byte-lexbind) | ||
| 698 | |||
| 699 | ;;; byte-lexbind.el ends here | ||
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 97ed6a01c2f..71960ad54dc 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el | |||
| @@ -1483,7 +1483,7 @@ | |||
| 1483 | byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate | 1483 | byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate |
| 1484 | byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax | 1484 | byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax |
| 1485 | byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt | 1485 | byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt |
| 1486 | byte-member byte-assq byte-quo byte-rem byte-vec-ref) | 1486 | byte-member byte-assq byte-quo byte-rem) |
| 1487 | byte-compile-side-effect-and-error-free-ops)) | 1487 | byte-compile-side-effect-and-error-free-ops)) |
| 1488 | 1488 | ||
| 1489 | ;; This crock is because of the way DEFVAR_BOOL variables work. | 1489 | ;; This crock is because of the way DEFVAR_BOOL variables work. |
| @@ -1671,7 +1671,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." | |||
| 1671 | ;; | 1671 | ;; |
| 1672 | ((and (eq 'byte-dup (car lap0)) | 1672 | ((and (eq 'byte-dup (car lap0)) |
| 1673 | (eq 'byte-discard (car lap2)) | 1673 | (eq 'byte-discard (car lap2)) |
| 1674 | (memq (car lap1) '(byte-varset byte-varbind byte-stack-set byte-vec-set))) | 1674 | (memq (car lap1) '(byte-varset byte-varbind byte-stack-set))) |
| 1675 | (byte-compile-log-lap " dup %s discard\t-->\t%s" lap1 lap1) | 1675 | (byte-compile-log-lap " dup %s discard\t-->\t%s" lap1 lap1) |
| 1676 | (setq keep-going t | 1676 | (setq keep-going t |
| 1677 | rest (cdr rest) | 1677 | rest (cdr rest) |
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 33940ec160e..e9beb0c5792 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -126,47 +126,11 @@ | |||
| 126 | ;; This really ought to be loaded already! | 126 | ;; This really ought to be loaded already! |
| 127 | (load "byte-run")) | 127 | (load "byte-run")) |
| 128 | 128 | ||
| 129 | ;; We want to do (require 'byte-lexbind) when compiling, to avoid compilation | ||
| 130 | ;; errors; however that file also wants to do (require 'bytecomp) for the | ||
| 131 | ;; same reason. Since we know it's OK to load byte-lexbind.el second, we | ||
| 132 | ;; have that file require a feature that's provided before at the beginning | ||
| 133 | ;; of this file, to avoid an infinite require loop. | ||
| 134 | ;; `eval-when-compile' is defined in byte-run.el, so it must come after the | ||
| 135 | ;; preceding load expression. | ||
| 136 | (provide 'bytecomp-preload) | ||
| 137 | (eval-when-compile (require 'byte-lexbind nil 'noerror)) | ||
| 138 | |||
| 139 | ;; The feature of compiling in a specific target Emacs version | 129 | ;; The feature of compiling in a specific target Emacs version |
| 140 | ;; has been turned off because compile time options are a bad idea. | 130 | ;; has been turned off because compile time options are a bad idea. |
| 141 | (defmacro byte-compile-single-version () nil) | 131 | (defmacro byte-compile-single-version () nil) |
| 142 | (defmacro byte-compile-version-cond (cond) cond) | 132 | (defmacro byte-compile-version-cond (cond) cond) |
| 143 | 133 | ||
| 144 | ;; The crud you see scattered through this file of the form | ||
| 145 | ;; (or (and (boundp 'epoch::version) epoch::version) | ||
| 146 | ;; (string-lessp emacs-version "19")) | ||
| 147 | ;; is because the Epoch folks couldn't be bothered to follow the | ||
| 148 | ;; normal emacs version numbering convention. | ||
| 149 | |||
| 150 | ;; (if (byte-compile-version-cond | ||
| 151 | ;; (or (and (boundp 'epoch::version) epoch::version) | ||
| 152 | ;; (string-lessp emacs-version "19"))) | ||
| 153 | ;; (progn | ||
| 154 | ;; ;; emacs-18 compatibility. | ||
| 155 | ;; (defvar baud-rate (baud-rate)) ;Define baud-rate if it's undefined | ||
| 156 | ;; | ||
| 157 | ;; (if (byte-compile-single-version) | ||
| 158 | ;; (defmacro byte-code-function-p (x) "Emacs 18 doesn't have these." nil) | ||
| 159 | ;; (defun byte-code-function-p (x) "Emacs 18 doesn't have these." nil)) | ||
| 160 | ;; | ||
| 161 | ;; (or (and (fboundp 'member) | ||
| 162 | ;; ;; avoid using someone else's possibly bogus definition of this. | ||
| 163 | ;; (subrp (symbol-function 'member))) | ||
| 164 | ;; (defun member (elt list) | ||
| 165 | ;; "like memq, but uses equal instead of eq. In v19, this is a subr." | ||
| 166 | ;; (while (and list (not (equal elt (car list)))) | ||
| 167 | ;; (setq list (cdr list))) | ||
| 168 | ;; list)))) | ||
| 169 | |||
| 170 | 134 | ||
| 171 | (defgroup bytecomp nil | 135 | (defgroup bytecomp nil |
| 172 | "Emacs Lisp byte-compiler." | 136 | "Emacs Lisp byte-compiler." |
| @@ -439,24 +403,15 @@ specify different fields to sort on." | |||
| 439 | :type '(choice (const name) (const callers) (const calls) | 403 | :type '(choice (const name) (const callers) (const calls) |
| 440 | (const calls+callers) (const nil))) | 404 | (const calls+callers) (const nil))) |
| 441 | 405 | ||
| 442 | ;(defvar byte-compile-debug nil) | ||
| 443 | (defvar byte-compile-debug t) | 406 | (defvar byte-compile-debug t) |
| 444 | (setq debug-on-error t) | 407 | (setq debug-on-error t) |
| 445 | 408 | ||
| 446 | ;; (defvar byte-compile-overwrite-file t | ||
| 447 | ;; "If nil, old .elc files are deleted before the new is saved, and .elc | ||
| 448 | ;; files will have the same modes as the corresponding .el file. Otherwise, | ||
| 449 | ;; existing .elc files will simply be overwritten, and the existing modes | ||
| 450 | ;; will not be changed. If this variable is nil, then an .elc file which | ||
| 451 | ;; is a symbolic link will be turned into a normal file, instead of the file | ||
| 452 | ;; which the link points to being overwritten.") | ||
| 453 | |||
| 454 | (defvar byte-compile-constants nil | 409 | (defvar byte-compile-constants nil |
| 455 | "List of all constants encountered during compilation of this form.") | 410 | "List of all constants encountered during compilation of this form.") |
| 456 | (defvar byte-compile-variables nil | 411 | (defvar byte-compile-variables nil |
| 457 | "List of all variables encountered during compilation of this form.") | 412 | "List of all variables encountered during compilation of this form.") |
| 458 | (defvar byte-compile-bound-variables nil | 413 | (defvar byte-compile-bound-variables nil |
| 459 | "List of variables bound in the context of the current form. | 414 | "List of dynamic variables bound in the context of the current form. |
| 460 | This list lives partly on the stack.") | 415 | This list lives partly on the stack.") |
| 461 | (defvar byte-compile-const-variables nil | 416 | (defvar byte-compile-const-variables nil |
| 462 | "List of variables declared as constants during compilation of this file.") | 417 | "List of variables declared as constants during compilation of this file.") |
| @@ -512,10 +467,6 @@ but won't necessarily be defined when the compiled file is loaded.") | |||
| 512 | ;; Variables for lexical binding | 467 | ;; Variables for lexical binding |
| 513 | (defvar byte-compile-lexical-environment nil | 468 | (defvar byte-compile-lexical-environment nil |
| 514 | "The current lexical environment.") | 469 | "The current lexical environment.") |
| 515 | (defvar byte-compile-current-heap-environment nil | ||
| 516 | "If non-nil, a descriptor for the current heap-allocated lexical environment.") | ||
| 517 | (defvar byte-compile-current-num-closures 0 | ||
| 518 | "The number of lexical closures that close over `byte-compile-current-heap-environment'.") | ||
| 519 | 470 | ||
| 520 | (defvar byte-compile-tag-number 0) | 471 | (defvar byte-compile-tag-number 0) |
| 521 | (defvar byte-compile-output nil | 472 | (defvar byte-compile-output nil |
| @@ -734,8 +685,6 @@ otherwise pop it") | |||
| 734 | 685 | ||
| 735 | (byte-defop 178 -1 byte-stack-set) ; stack offset in following one byte | 686 | (byte-defop 178 -1 byte-stack-set) ; stack offset in following one byte |
| 736 | (byte-defop 179 -1 byte-stack-set2) ; stack offset in following two bytes | 687 | (byte-defop 179 -1 byte-stack-set2) ; stack offset in following two bytes |
| 737 | (byte-defop 180 1 byte-vec-ref) ; vector offset in following one byte | ||
| 738 | (byte-defop 181 -1 byte-vec-set) ; vector offset in following one byte | ||
| 739 | 688 | ||
| 740 | ;; if (following one byte & 0x80) == 0 | 689 | ;; if (following one byte & 0x80) == 0 |
| 741 | ;; discard (following one byte & 0x7F) stack entries | 690 | ;; discard (following one byte & 0x7F) stack entries |
| @@ -824,68 +773,71 @@ CONST2 may be evaulated multiple times." | |||
| 824 | (dolist (lap-entry lap) | 773 | (dolist (lap-entry lap) |
| 825 | (setq op (car lap-entry) | 774 | (setq op (car lap-entry) |
| 826 | off (cdr lap-entry)) | 775 | off (cdr lap-entry)) |
| 827 | (cond ((not (symbolp op)) | 776 | (cond |
| 828 | (error "Non-symbolic opcode `%s'" op)) | 777 | ((not (symbolp op)) |
| 829 | ((eq op 'TAG) | 778 | (error "Non-symbolic opcode `%s'" op)) |
| 830 | (setcar off pc)) | 779 | ((eq op 'TAG) |
| 831 | ((null op) | 780 | (setcar off pc)) |
| 832 | ;; a no-op added by `byte-compile-delay-out' | 781 | ((null op) |
| 833 | (unless (zerop off) | 782 | ;; a no-op added by `byte-compile-delay-out' |
| 834 | (error | 783 | (unless (zerop off) |
| 835 | "Placeholder added by `byte-compile-delay-out' not filled in.") | 784 | (error |
| 836 | )) | 785 | "Placeholder added by `byte-compile-delay-out' not filled in.") |
| 837 | (t | 786 | )) |
| 838 | (if (eq op 'byte-discardN-preserve-tos) | 787 | (t |
| 839 | ;; byte-discardN-preserve-tos is a psuedo op, which is actually | 788 | (setq opcode |
| 840 | ;; the same as byte-discardN with a modified argument | 789 | (if (eq op 'byte-discardN-preserve-tos) |
| 841 | (setq opcode byte-discardN) | 790 | ;; byte-discardN-preserve-tos is a pseudo op, which |
| 842 | (setq opcode (symbol-value op))) | 791 | ;; is actually the same as byte-discardN |
| 843 | (cond ((memq op byte-goto-ops) | 792 | ;; with a modified argument. |
| 844 | ;; goto | 793 | byte-discardN |
| 845 | (byte-compile-push-bytecodes opcode nil (cdr off) bytes pc) | 794 | (symbol-value op))) |
| 846 | (push bytes patchlist)) | 795 | (cond ((memq op byte-goto-ops) |
| 847 | ((and (consp off) | 796 | ;; goto |
| 848 | ;; Variable or constant reference | 797 | (byte-compile-push-bytecodes opcode nil (cdr off) bytes pc) |
| 849 | (progn (setq off (cdr off)) | 798 | (push bytes patchlist)) |
| 850 | (eq op 'byte-constant))) | 799 | ((and (consp off) |
| 851 | ;; constant ref | 800 | ;; Variable or constant reference |
| 852 | (if (< off byte-constant-limit) | 801 | (progn (setq off (cdr off)) |
| 853 | (byte-compile-push-bytecodes (+ byte-constant off) | 802 | (eq op 'byte-constant))) |
| 854 | bytes pc) | 803 | ;; constant ref |
| 855 | (byte-compile-push-bytecode-const2 byte-constant2 off | 804 | (if (< off byte-constant-limit) |
| 856 | bytes pc))) | 805 | (byte-compile-push-bytecodes (+ byte-constant off) |
| 857 | ((and (= opcode byte-stack-set) | 806 | bytes pc) |
| 858 | (> off 255)) | 807 | (byte-compile-push-bytecode-const2 byte-constant2 off |
| 859 | ;; Use the two-byte version of byte-stack-set if the | 808 | bytes pc))) |
| 860 | ;; offset is too large for the normal version. | 809 | ((and (= opcode byte-stack-set) |
| 861 | (byte-compile-push-bytecode-const2 byte-stack-set2 off | 810 | (> off 255)) |
| 862 | bytes pc)) | 811 | ;; Use the two-byte version of byte-stack-set if the |
| 863 | ((and (>= opcode byte-listN) | 812 | ;; offset is too large for the normal version. |
| 864 | (< opcode byte-discardN)) | 813 | (byte-compile-push-bytecode-const2 byte-stack-set2 off |
| 865 | ;; These insns all put their operand into one extra byte. | 814 | bytes pc)) |
| 866 | (byte-compile-push-bytecodes opcode off bytes pc)) | 815 | ((and (>= opcode byte-listN) |
| 867 | ((= opcode byte-discardN) | 816 | (< opcode byte-discardN)) |
| 868 | ;; byte-discardN is wierd in that it encodes a flag in the | 817 | ;; These insns all put their operand into one extra byte. |
| 869 | ;; top bit of its one-byte argument. If the argument is | 818 | (byte-compile-push-bytecodes opcode off bytes pc)) |
| 870 | ;; too large to fit in 7 bits, the opcode can be repeated. | 819 | ((= opcode byte-discardN) |
| 871 | (let ((flag (if (eq op 'byte-discardN-preserve-tos) #x80 0))) | 820 | ;; byte-discardN is wierd in that it encodes a flag in the |
| 872 | (while (> off #x7f) | 821 | ;; top bit of its one-byte argument. If the argument is |
| 873 | (byte-compile-push-bytecodes opcode (logior #x7f flag) bytes pc) | 822 | ;; too large to fit in 7 bits, the opcode can be repeated. |
| 874 | (setq off (- off #x7f))) | 823 | (let ((flag (if (eq op 'byte-discardN-preserve-tos) #x80 0))) |
| 875 | (byte-compile-push-bytecodes opcode (logior off flag) bytes pc))) | 824 | (while (> off #x7f) |
| 876 | ((null off) | 825 | (byte-compile-push-bytecodes opcode (logior #x7f flag) bytes pc) |
| 877 | ;; opcode that doesn't use OFF | 826 | (setq off (- off #x7f))) |
| 878 | (byte-compile-push-bytecodes opcode bytes pc)) | 827 | (byte-compile-push-bytecodes opcode (logior off flag) bytes pc))) |
| 879 | ;; The following three cases are for the special | 828 | ((null off) |
| 880 | ;; insns that encode their operand into 0, 1, or 2 | 829 | ;; opcode that doesn't use OFF |
| 881 | ;; extra bytes depending on its magnitude. | 830 | (byte-compile-push-bytecodes opcode bytes pc)) |
| 882 | ((< off 6) | 831 | ;; The following three cases are for the special |
| 883 | (byte-compile-push-bytecodes (+ opcode off) bytes pc)) | 832 | ;; insns that encode their operand into 0, 1, or 2 |
| 884 | ((< off 256) | 833 | ;; extra bytes depending on its magnitude. |
| 885 | (byte-compile-push-bytecodes (+ opcode 6) off bytes pc)) | 834 | ((< off 6) |
| 886 | (t | 835 | (byte-compile-push-bytecodes (+ opcode off) bytes pc)) |
| 887 | (byte-compile-push-bytecode-const2 (+ opcode 7) off | 836 | ((< off 256) |
| 888 | bytes pc)))))) | 837 | (byte-compile-push-bytecodes (+ opcode 6) off bytes pc)) |
| 838 | (t | ||
| 839 | (byte-compile-push-bytecode-const2 (+ opcode 7) off | ||
| 840 | bytes pc)))))) | ||
| 889 | ;;(if (not (= pc (length bytes))) | 841 | ;;(if (not (= pc (length bytes))) |
| 890 | ;; (error "Compiler error: pc mismatch - %s %s" pc (length bytes))) | 842 | ;; (error "Compiler error: pc mismatch - %s %s" pc (length bytes))) |
| 891 | 843 | ||
| @@ -1694,7 +1646,7 @@ that already has a `.elc' file." | |||
| 1694 | "Non-nil to prevent byte-compiling of Emacs Lisp code. | 1646 | "Non-nil to prevent byte-compiling of Emacs Lisp code. |
| 1695 | This is normally set in local file variables at the end of the elisp file: | 1647 | This is normally set in local file variables at the end of the elisp file: |
| 1696 | 1648 | ||
| 1697 | ;; Local Variables:\n;; no-byte-compile: t\n;; End: ") | 1649 | \;; Local Variables:\n;; no-byte-compile: t\n;; End: ") ;Backslash for compile-main. |
| 1698 | ;;;###autoload(put 'no-byte-compile 'safe-local-variable 'booleanp) | 1650 | ;;;###autoload(put 'no-byte-compile 'safe-local-variable 'booleanp) |
| 1699 | 1651 | ||
| 1700 | (defun byte-recompile-file (bytecomp-filename &optional bytecomp-force bytecomp-arg load) | 1652 | (defun byte-recompile-file (bytecomp-filename &optional bytecomp-force bytecomp-arg load) |
| @@ -2682,7 +2634,23 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2682 | (setq list (cdr list))))) | 2634 | (setq list (cdr list))))) |
| 2683 | 2635 | ||
| 2684 | 2636 | ||
| 2685 | (autoload 'byte-compile-make-lambda-lexenv "byte-lexbind") | 2637 | (defun byte-compile-arglist-vars (arglist) |
| 2638 | "Return a list of the variables in the lambda argument list ARGLIST." | ||
| 2639 | (remq '&rest (remq '&optional arglist))) | ||
| 2640 | |||
| 2641 | (defun byte-compile-make-lambda-lexenv (form) | ||
| 2642 | "Return a new lexical environment for a lambda expression FORM." | ||
| 2643 | ;; See if this is a closure or not | ||
| 2644 | (let ((args (byte-compile-arglist-vars (cadr form)))) | ||
| 2645 | (let ((lexenv nil)) | ||
| 2646 | ;; Fill in the initial stack contents | ||
| 2647 | (let ((stackpos 0)) | ||
| 2648 | ;; Add entries for each argument | ||
| 2649 | (dolist (arg args) | ||
| 2650 | (push (cons arg stackpos) lexenv) | ||
| 2651 | (setq stackpos (1+ stackpos))) | ||
| 2652 | ;; Return the new lexical environment | ||
| 2653 | lexenv)))) | ||
| 2686 | 2654 | ||
| 2687 | ;; Byte-compile a lambda-expression and return a valid function. | 2655 | ;; Byte-compile a lambda-expression and return a valid function. |
| 2688 | ;; The value is usually a compiled function but may be the original | 2656 | ;; The value is usually a compiled function but may be the original |
| @@ -2700,10 +2668,9 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2700 | (byte-compile-check-lambda-list (nth 1 bytecomp-fun)) | 2668 | (byte-compile-check-lambda-list (nth 1 bytecomp-fun)) |
| 2701 | (let* ((bytecomp-arglist (nth 1 bytecomp-fun)) | 2669 | (let* ((bytecomp-arglist (nth 1 bytecomp-fun)) |
| 2702 | (byte-compile-bound-variables | 2670 | (byte-compile-bound-variables |
| 2703 | (nconc (and (byte-compile-warning-enabled-p 'free-vars) | 2671 | (append (and (not lexical-binding) |
| 2704 | (delq '&rest | 2672 | (byte-compile-arglist-vars bytecomp-arglist)) |
| 2705 | (delq '&optional (copy-sequence bytecomp-arglist)))) | 2673 | byte-compile-bound-variables)) |
| 2706 | byte-compile-bound-variables)) | ||
| 2707 | (bytecomp-body (cdr (cdr bytecomp-fun))) | 2674 | (bytecomp-body (cdr (cdr bytecomp-fun))) |
| 2708 | (bytecomp-doc (if (stringp (car bytecomp-body)) | 2675 | (bytecomp-doc (if (stringp (car bytecomp-body)) |
| 2709 | (prog1 (car bytecomp-body) | 2676 | (prog1 (car bytecomp-body) |
| @@ -2742,42 +2709,27 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2742 | ;; Process the body. | 2709 | ;; Process the body. |
| 2743 | (let* ((byte-compile-lexical-environment | 2710 | (let* ((byte-compile-lexical-environment |
| 2744 | ;; If doing lexical binding, push a new lexical environment | 2711 | ;; If doing lexical binding, push a new lexical environment |
| 2745 | ;; containing the args and any closed-over variables. | 2712 | ;; containing just the args (since lambda expressions |
| 2746 | (and lexical-binding | 2713 | ;; should be closed by now). |
| 2747 | (byte-compile-make-lambda-lexenv | ||
| 2748 | bytecomp-fun | ||
| 2749 | byte-compile-lexical-environment))) | ||
| 2750 | (is-closure | ||
| 2751 | ;; This is true if we should be making a closure instead of | ||
| 2752 | ;; a simple lambda (because some variables from the | ||
| 2753 | ;; containing lexical environment are closed over). | ||
| 2754 | (and lexical-binding | 2714 | (and lexical-binding |
| 2755 | (byte-compile-closure-initial-lexenv-p | 2715 | (byte-compile-make-lambda-lexenv bytecomp-fun))) |
| 2756 | byte-compile-lexical-environment) | ||
| 2757 | (error "Should have been handled by cconv"))) | ||
| 2758 | (byte-compile-current-heap-environment nil) | ||
| 2759 | (byte-compile-current-num-closures 0) | ||
| 2760 | (compiled | 2716 | (compiled |
| 2761 | (byte-compile-top-level (cons 'progn bytecomp-body) nil 'lambda))) | 2717 | (byte-compile-top-level (cons 'progn bytecomp-body) nil 'lambda))) |
| 2762 | ;; Build the actual byte-coded function. | 2718 | ;; Build the actual byte-coded function. |
| 2763 | (if (eq 'byte-code (car-safe compiled)) | 2719 | (if (eq 'byte-code (car-safe compiled)) |
| 2764 | (let ((code | 2720 | (apply 'make-byte-code |
| 2765 | (apply 'make-byte-code | 2721 | (append (list bytecomp-arglist) |
| 2766 | (append (list bytecomp-arglist) | 2722 | ;; byte-string, constants-vector, stack depth |
| 2767 | ;; byte-string, constants-vector, stack depth | 2723 | (cdr compiled) |
| 2768 | (cdr compiled) | 2724 | ;; optionally, the doc string. |
| 2769 | ;; optionally, the doc string. | 2725 | (if (or bytecomp-doc bytecomp-int |
| 2770 | (if (or bytecomp-doc bytecomp-int | 2726 | lexical-binding) |
| 2771 | lexical-binding) | 2727 | (list bytecomp-doc)) |
| 2772 | (list bytecomp-doc)) | 2728 | ;; optionally, the interactive spec. |
| 2773 | ;; optionally, the interactive spec. | 2729 | (if (or bytecomp-int lexical-binding) |
| 2774 | (if (or bytecomp-int lexical-binding) | 2730 | (list (nth 1 bytecomp-int))) |
| 2775 | (list (nth 1 bytecomp-int))) | 2731 | (if lexical-binding |
| 2776 | (if lexical-binding | 2732 | '(t)))) |
| 2777 | '(t)))))) | ||
| 2778 | (if is-closure | ||
| 2779 | (cons 'closure code) | ||
| 2780 | code)) | ||
| 2781 | (setq compiled | 2733 | (setq compiled |
| 2782 | (nconc (if bytecomp-int (list bytecomp-int)) | 2734 | (nconc (if bytecomp-int (list bytecomp-int)) |
| 2783 | (cond ((eq (car-safe compiled) 'progn) (cdr compiled)) | 2735 | (cond ((eq (car-safe compiled) 'progn) (cdr compiled)) |
| @@ -2788,26 +2740,10 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2788 | (bytecomp-body (list nil)))) | 2740 | (bytecomp-body (list nil)))) |
| 2789 | compiled)))))) | 2741 | compiled)))))) |
| 2790 | 2742 | ||
| 2791 | (defun byte-compile-closure-code-p (code) | ||
| 2792 | (eq (car-safe code) 'closure)) | ||
| 2793 | |||
| 2794 | (defun byte-compile-make-closure (code) | ||
| 2795 | (error "Should have been handled by cconv") | ||
| 2796 | ;; A real closure requires that the constant be curried with an | ||
| 2797 | ;; environment vector to make a closure object. | ||
| 2798 | (if for-effect | ||
| 2799 | (setq for-effect nil) | ||
| 2800 | (byte-compile-push-constant 'curry) | ||
| 2801 | (byte-compile-push-constant code) | ||
| 2802 | (byte-compile-lexical-variable-ref byte-compile-current-heap-environment) | ||
| 2803 | (byte-compile-out 'byte-call 2))) | ||
| 2804 | |||
| 2805 | (defun byte-compile-closure (form &optional add-lambda) | 2743 | (defun byte-compile-closure (form &optional add-lambda) |
| 2806 | (let ((code (byte-compile-lambda form add-lambda))) | 2744 | (let ((code (byte-compile-lambda form add-lambda))) |
| 2807 | (if (byte-compile-closure-code-p code) | 2745 | ;; A simple lambda is just a constant. |
| 2808 | (byte-compile-make-closure code) | 2746 | (byte-compile-constant code))) |
| 2809 | ;; A simple lambda is just a constant. | ||
| 2810 | (byte-compile-constant code)))) | ||
| 2811 | 2747 | ||
| 2812 | (defun byte-compile-constants-vector () | 2748 | (defun byte-compile-constants-vector () |
| 2813 | ;; Builds the constants-vector from the current variables and constants. | 2749 | ;; Builds the constants-vector from the current variables and constants. |
| @@ -2867,34 +2803,11 @@ If FORM is a lambda or a macro, byte-compile it as a function." | |||
| 2867 | ;; See how many arguments there are, and set the current stack depth | 2803 | ;; See how many arguments there are, and set the current stack depth |
| 2868 | ;; accordingly | 2804 | ;; accordingly |
| 2869 | (dolist (var byte-compile-lexical-environment) | 2805 | (dolist (var byte-compile-lexical-environment) |
| 2870 | (when (byte-compile-lexvar-on-stack-p var) | 2806 | (setq byte-compile-depth (1+ byte-compile-depth))) |
| 2871 | (setq byte-compile-depth (1+ byte-compile-depth)))) | ||
| 2872 | ;; If there are args, output a tag to record the initial | 2807 | ;; If there are args, output a tag to record the initial |
| 2873 | ;; stack-depth for the optimizer | 2808 | ;; stack-depth for the optimizer |
| 2874 | (when (> byte-compile-depth 0) | 2809 | (when (> byte-compile-depth 0) |
| 2875 | (byte-compile-out-tag (byte-compile-make-tag))) | 2810 | (byte-compile-out-tag (byte-compile-make-tag)))) |
| 2876 | ;; If this is the top-level of a lexically bound lambda expression, | ||
| 2877 | ;; perhaps some parameters on stack need to be copied into a heap | ||
| 2878 | ;; environment, so check for them, and do so if necessary. | ||
| 2879 | (let ((lforminfo (byte-compile-make-lforminfo))) | ||
| 2880 | ;; Add any lexical variable that's on the stack to the analysis set. | ||
| 2881 | (dolist (var byte-compile-lexical-environment) | ||
| 2882 | (when (byte-compile-lexvar-on-stack-p var) | ||
| 2883 | (byte-compile-lforminfo-add-var lforminfo (car var) t))) | ||
| 2884 | ;; Analyze the body | ||
| 2885 | (unless (null (byte-compile-lforminfo-vars lforminfo)) | ||
| 2886 | (byte-compile-lforminfo-analyze lforminfo form nil nil)) | ||
| 2887 | ;; If the analysis revealed some argument need to be in a heap | ||
| 2888 | ;; environment (because they're closed over by an embedded | ||
| 2889 | ;; lambda), put them there. | ||
| 2890 | (setq byte-compile-lexical-environment | ||
| 2891 | (nconc (byte-compile-maybe-push-heap-environment lforminfo) | ||
| 2892 | byte-compile-lexical-environment)) | ||
| 2893 | (dolist (arginfo (byte-compile-lforminfo-vars lforminfo)) | ||
| 2894 | (when (byte-compile-lvarinfo-closed-over-p arginfo) | ||
| 2895 | (byte-compile-bind (car arginfo) | ||
| 2896 | byte-compile-lexical-environment | ||
| 2897 | lforminfo))))) | ||
| 2898 | ;; Now compile FORM | 2811 | ;; Now compile FORM |
| 2899 | (byte-compile-form form for-effect) | 2812 | (byte-compile-form form for-effect) |
| 2900 | (byte-compile-out-toplevel for-effect output-type)))) | 2813 | (byte-compile-out-toplevel for-effect output-type)))) |
| @@ -3044,7 +2957,7 @@ That command is designed for interactive use only" bytecomp-fn)) | |||
| 3044 | (if (memq bytecomp-fn | 2957 | (if (memq bytecomp-fn |
| 3045 | '(custom-declare-group custom-declare-variable | 2958 | '(custom-declare-group custom-declare-variable |
| 3046 | custom-declare-face)) | 2959 | custom-declare-face)) |
| 3047 | (byte-compile-nogroup-warn form)) | 2960 | (byte-compile-nogroup-warn form)) |
| 3048 | (byte-compile-callargs-warn form)) | 2961 | (byte-compile-callargs-warn form)) |
| 3049 | (if (and bytecomp-handler | 2962 | (if (and bytecomp-handler |
| 3050 | ;; Make sure that function exists. This is important | 2963 | ;; Make sure that function exists. This is important |
| @@ -3107,40 +3020,16 @@ If BINDING is non-nil, VAR is being bound." | |||
| 3107 | (defun byte-compile-dynamic-variable-bind (var) | 3020 | (defun byte-compile-dynamic-variable-bind (var) |
| 3108 | "Generate code to bind the lexical variable VAR to the top-of-stack value." | 3021 | "Generate code to bind the lexical variable VAR to the top-of-stack value." |
| 3109 | (byte-compile-check-variable var t) | 3022 | (byte-compile-check-variable var t) |
| 3110 | (when (byte-compile-warning-enabled-p 'free-vars) | 3023 | (push var byte-compile-bound-variables) |
| 3111 | (push var byte-compile-bound-variables)) | ||
| 3112 | (byte-compile-dynamic-variable-op 'byte-varbind var)) | 3024 | (byte-compile-dynamic-variable-op 'byte-varbind var)) |
| 3113 | 3025 | ||
| 3114 | ;; This is used when it's know that VAR _definitely_ has a lexical | ||
| 3115 | ;; binding, and no error-checking should be done. | ||
| 3116 | (defun byte-compile-lexical-variable-ref (var) | ||
| 3117 | "Generate code to push the value of the lexical variable VAR on the stack." | ||
| 3118 | (let ((binding (assq var byte-compile-lexical-environment))) | ||
| 3119 | (when (null binding) | ||
| 3120 | (error "Lexical binding not found for `%s'" var)) | ||
| 3121 | (if (byte-compile-lexvar-on-stack-p binding) | ||
| 3122 | ;; On the stack | ||
| 3123 | (byte-compile-stack-ref (byte-compile-lexvar-offset binding)) | ||
| 3124 | ;; In a heap environment vector; first push the vector on the stack | ||
| 3125 | (byte-compile-lexical-variable-ref | ||
| 3126 | (byte-compile-lexvar-environment binding)) | ||
| 3127 | ;; Now get the value from it | ||
| 3128 | (byte-compile-out 'byte-vec-ref (byte-compile-lexvar-offset binding))))) | ||
| 3129 | |||
| 3130 | (defun byte-compile-variable-ref (var) | 3026 | (defun byte-compile-variable-ref (var) |
| 3131 | "Generate code to push the value of the variable VAR on the stack." | 3027 | "Generate code to push the value of the variable VAR on the stack." |
| 3132 | (byte-compile-check-variable var) | 3028 | (byte-compile-check-variable var) |
| 3133 | (let ((lex-binding (assq var byte-compile-lexical-environment))) | 3029 | (let ((lex-binding (assq var byte-compile-lexical-environment))) |
| 3134 | (if lex-binding | 3030 | (if lex-binding |
| 3135 | ;; VAR is lexically bound | 3031 | ;; VAR is lexically bound |
| 3136 | (if (byte-compile-lexvar-on-stack-p lex-binding) | 3032 | (byte-compile-stack-ref (cdr lex-binding)) |
| 3137 | ;; On the stack | ||
| 3138 | (byte-compile-stack-ref (byte-compile-lexvar-offset lex-binding)) | ||
| 3139 | ;; In a heap environment vector | ||
| 3140 | (byte-compile-lexical-variable-ref | ||
| 3141 | (byte-compile-lexvar-environment lex-binding)) | ||
| 3142 | (byte-compile-out 'byte-vec-ref | ||
| 3143 | (byte-compile-lexvar-offset lex-binding))) | ||
| 3144 | ;; VAR is dynamically bound | 3033 | ;; VAR is dynamically bound |
| 3145 | (unless (or (not (byte-compile-warning-enabled-p 'free-vars)) | 3034 | (unless (or (not (byte-compile-warning-enabled-p 'free-vars)) |
| 3146 | (boundp var) | 3035 | (boundp var) |
| @@ -3156,14 +3045,7 @@ If BINDING is non-nil, VAR is being bound." | |||
| 3156 | (let ((lex-binding (assq var byte-compile-lexical-environment))) | 3045 | (let ((lex-binding (assq var byte-compile-lexical-environment))) |
| 3157 | (if lex-binding | 3046 | (if lex-binding |
| 3158 | ;; VAR is lexically bound | 3047 | ;; VAR is lexically bound |
| 3159 | (if (byte-compile-lexvar-on-stack-p lex-binding) | 3048 | (byte-compile-stack-set (cdr lex-binding)) |
| 3160 | ;; On the stack | ||
| 3161 | (byte-compile-stack-set (byte-compile-lexvar-offset lex-binding)) | ||
| 3162 | ;; In a heap environment vector | ||
| 3163 | (byte-compile-lexical-variable-ref | ||
| 3164 | (byte-compile-lexvar-environment lex-binding)) | ||
| 3165 | (byte-compile-out 'byte-vec-set | ||
| 3166 | (byte-compile-lexvar-offset lex-binding))) | ||
| 3167 | ;; VAR is dynamically bound | 3049 | ;; VAR is dynamically bound |
| 3168 | (unless (or (not (byte-compile-warning-enabled-p 'free-vars)) | 3050 | (unless (or (not (byte-compile-warning-enabled-p 'free-vars)) |
| 3169 | (boundp var) | 3051 | (boundp var) |
| @@ -3795,9 +3677,7 @@ that suppresses all warnings during execution of BODY." | |||
| 3795 | ,condition (list 'boundp 'default-boundp))) | 3677 | ,condition (list 'boundp 'default-boundp))) |
| 3796 | ;; Maybe add to the bound list. | 3678 | ;; Maybe add to the bound list. |
| 3797 | (byte-compile-bound-variables | 3679 | (byte-compile-bound-variables |
| 3798 | (if bound-list | 3680 | (append bound-list byte-compile-bound-variables))) |
| 3799 | (append bound-list byte-compile-bound-variables) | ||
| 3800 | byte-compile-bound-variables))) | ||
| 3801 | (unwind-protect | 3681 | (unwind-protect |
| 3802 | ;; If things not being bound at all is ok, so must them being obsolete. | 3682 | ;; If things not being bound at all is ok, so must them being obsolete. |
| 3803 | ;; Note that we add to the existing lists since Tramp (ab)uses | 3683 | ;; Note that we add to the existing lists since Tramp (ab)uses |
| @@ -3910,14 +3790,7 @@ that suppresses all warnings during execution of BODY." | |||
| 3910 | 3790 | ||
| 3911 | (defun byte-compile-while (form) | 3791 | (defun byte-compile-while (form) |
| 3912 | (let ((endtag (byte-compile-make-tag)) | 3792 | (let ((endtag (byte-compile-make-tag)) |
| 3913 | (looptag (byte-compile-make-tag)) | 3793 | (looptag (byte-compile-make-tag))) |
| 3914 | ;; Heap environments can't be shared between a loop and its | ||
| 3915 | ;; enclosing environment (because any lexical variables bound | ||
| 3916 | ;; inside the loop should have an independent value for each | ||
| 3917 | ;; iteration). Setting `byte-compile-current-num-closures' to | ||
| 3918 | ;; an invalid value causes the code that tries to merge | ||
| 3919 | ;; environments to not do so. | ||
| 3920 | (byte-compile-current-num-closures -1)) | ||
| 3921 | (byte-compile-out-tag looptag) | 3794 | (byte-compile-out-tag looptag) |
| 3922 | (byte-compile-form (car (cdr form))) | 3795 | (byte-compile-form (car (cdr form))) |
| 3923 | (byte-compile-goto-if nil for-effect endtag) | 3796 | (byte-compile-goto-if nil for-effect endtag) |
| @@ -3933,109 +3806,131 @@ that suppresses all warnings during execution of BODY." | |||
| 3933 | 3806 | ||
| 3934 | ;; let binding | 3807 | ;; let binding |
| 3935 | 3808 | ||
| 3936 | ;; All other lexical-binding functions are guarded by a non-nil return | 3809 | (defun byte-compile-push-binding-init (clause) |
| 3937 | ;; value from `byte-compile-compute-lforminfo', so they needn't be | ||
| 3938 | ;; autoloaded. | ||
| 3939 | (autoload 'byte-compile-compute-lforminfo "byte-lexbind") | ||
| 3940 | |||
| 3941 | (defun byte-compile-push-binding-init (clause init-lexenv lforminfo) | ||
| 3942 | "Emit byte-codes to push the initialization value for CLAUSE on the stack. | 3810 | "Emit byte-codes to push the initialization value for CLAUSE on the stack. |
| 3943 | INIT-LEXENV is the lexical environment created for initializations | 3811 | Return the offset in the form (VAR . OFFSET)." |
| 3944 | already done for this form. | 3812 | (let* ((var (if (consp clause) (car clause) clause))) |
| 3945 | LFORMINFO should be information about lexical variables being bound. | 3813 | ;; We record the stack position even of dynamic bindings and |
| 3946 | Return INIT-LEXENV updated to include the newest initialization, or nil | 3814 | ;; variables in non-stack lexical environments; we'll put |
| 3947 | if LFORMINFO is nil (meaning all bindings are dynamic)." | 3815 | ;; them in the proper place below. |
| 3948 | (let* ((var (if (consp clause) (car clause) clause)) | 3816 | (prog1 (cons var byte-compile-depth) |
| 3949 | (vinfo | ||
| 3950 | (and lforminfo (assq var (byte-compile-lforminfo-vars lforminfo)))) | ||
| 3951 | (unused (and vinfo (zerop (cadr vinfo))))) | ||
| 3952 | (unless (and unused (symbolp clause)) | ||
| 3953 | (when (and lforminfo (not unused)) | ||
| 3954 | ;; We record the stack position even of dynamic bindings and | ||
| 3955 | ;; variables in non-stack lexical environments; we'll put | ||
| 3956 | ;; them in the proper place below. | ||
| 3957 | (push (byte-compile-make-lexvar var byte-compile-depth) init-lexenv)) | ||
| 3958 | (if (consp clause) | 3817 | (if (consp clause) |
| 3959 | (byte-compile-form (cadr clause) unused) | 3818 | (byte-compile-form (cadr clause)) |
| 3960 | (byte-compile-push-constant nil)))) | 3819 | (byte-compile-push-constant nil))))) |
| 3961 | init-lexenv) | 3820 | |
| 3821 | (defun byte-compile-not-lexical-var-p (var) | ||
| 3822 | (or (not (symbolp var)) ; form is not a list | ||
| 3823 | (if (eval-when-compile (fboundp 'special-variable-p)) | ||
| 3824 | (special-variable-p var) | ||
| 3825 | (boundp var)) | ||
| 3826 | (memq var byte-compile-bound-variables) | ||
| 3827 | (memq var '(nil t)) | ||
| 3828 | (keywordp var))) | ||
| 3829 | |||
| 3830 | (defun byte-compile-bind (var init-lexenv) | ||
| 3831 | "Emit byte-codes to bind VAR and update `byte-compile-lexical-environment'. | ||
| 3832 | INIT-LEXENV should be a lexical-environment alist describing the | ||
| 3833 | positions of the init value that have been pushed on the stack. | ||
| 3834 | Return non-nil if the TOS value was popped." | ||
| 3835 | ;; The presence of lexical bindings mean that we may have to | ||
| 3836 | ;; juggle things on the stack, either to move them to TOS for | ||
| 3837 | ;; dynamic binding, or to put them in a non-stack environment | ||
| 3838 | ;; vector. | ||
| 3839 | (cond ((not (byte-compile-not-lexical-var-p var)) | ||
| 3840 | ;; VAR is a simple stack-allocated lexical variable | ||
| 3841 | (push (assq var init-lexenv) | ||
| 3842 | byte-compile-lexical-environment) | ||
| 3843 | nil) | ||
| 3844 | ((eq var (caar init-lexenv)) | ||
| 3845 | ;; VAR is dynamic and is on the top of the | ||
| 3846 | ;; stack, so we can just bind it like usual | ||
| 3847 | (byte-compile-dynamic-variable-bind var) | ||
| 3848 | t) | ||
| 3849 | (t | ||
| 3850 | ;; VAR is dynamic, but we have to get its | ||
| 3851 | ;; value out of the middle of the stack | ||
| 3852 | (let ((stack-pos (cdr (assq var init-lexenv)))) | ||
| 3853 | (byte-compile-stack-ref stack-pos) | ||
| 3854 | (byte-compile-dynamic-variable-bind var) | ||
| 3855 | ;; Now we have to store nil into its temporary | ||
| 3856 | ;; stack position to avoid problems with GC | ||
| 3857 | (byte-compile-push-constant nil) | ||
| 3858 | (byte-compile-stack-set stack-pos)) | ||
| 3859 | nil))) | ||
| 3860 | |||
| 3861 | (defun byte-compile-unbind (clauses init-lexenv | ||
| 3862 | &optional preserve-body-value) | ||
| 3863 | "Emit byte-codes to unbind the variables bound by CLAUSES. | ||
| 3864 | CLAUSES is a `let'-style variable binding list. INIT-LEXENV should be a | ||
| 3865 | lexical-environment alist describing the positions of the init value that | ||
| 3866 | have been pushed on the stack. If PRESERVE-BODY-VALUE is true, | ||
| 3867 | then an additional value on the top of the stack, above any lexical binding | ||
| 3868 | slots, is preserved, so it will be on the top of the stack after all | ||
| 3869 | binding slots have been popped." | ||
| 3870 | ;; Unbind dynamic variables | ||
| 3871 | (let ((num-dynamic-bindings 0)) | ||
| 3872 | (dolist (clause clauses) | ||
| 3873 | (unless (assq (if (consp clause) (car clause) clause) | ||
| 3874 | byte-compile-lexical-environment) | ||
| 3875 | (setq num-dynamic-bindings (1+ num-dynamic-bindings)))) | ||
| 3876 | (unless (zerop num-dynamic-bindings) | ||
| 3877 | (byte-compile-out 'byte-unbind num-dynamic-bindings))) | ||
| 3878 | ;; Pop lexical variables off the stack, possibly preserving the | ||
| 3879 | ;; return value of the body. | ||
| 3880 | (when init-lexenv | ||
| 3881 | ;; INIT-LEXENV contains all init values left on the stack | ||
| 3882 | (byte-compile-discard (length init-lexenv) preserve-body-value))) | ||
| 3962 | 3883 | ||
| 3963 | (defun byte-compile-let (form) | 3884 | (defun byte-compile-let (form) |
| 3964 | "Generate code for the `let' form FORM." | 3885 | "Generate code for the `let' form FORM." |
| 3965 | (let ((clauses (cadr form)) | 3886 | ;; First compute the binding values in the old scope. |
| 3966 | (lforminfo (and lexical-binding (byte-compile-compute-lforminfo form))) | 3887 | (let ((varlist (car (cdr form))) |
| 3967 | (init-lexenv nil) | 3888 | (init-lexenv nil)) |
| 3968 | ;; bind these to restrict the scope of any changes | 3889 | (dolist (var varlist) |
| 3969 | (byte-compile-current-heap-environment | 3890 | (push (byte-compile-push-binding-init var) init-lexenv)) |
| 3970 | byte-compile-current-heap-environment) | 3891 | ;; Now do the bindings, execute the body, and undo the bindings. |
| 3971 | (byte-compile-current-num-closures byte-compile-current-num-closures)) | 3892 | (let ((byte-compile-bound-variables byte-compile-bound-variables) ;new scope |
| 3972 | (when (and lforminfo (byte-compile-non-stack-bindings-p clauses lforminfo)) | 3893 | (varlist (reverse (car (cdr form)))) |
| 3973 | ;; Some of the variables we're binding are lexical variables on | 3894 | (byte-compile-lexical-environment byte-compile-lexical-environment)) |
| 3974 | ;; the stack, but not all. As much as we can, rearrange the list | 3895 | (dolist (var varlist) |
| 3975 | ;; so that non-stack lexical variables and dynamically bound | 3896 | (let ((var (if (consp var) (car var) var))) |
| 3976 | ;; variables come last, which allows slightly more optimal | 3897 | (cond ((null lexical-binding) |
| 3977 | ;; byte-code for binding them. | ||
| 3978 | (setq clauses (byte-compile-rearrange-let-clauses clauses lforminfo))) | ||
| 3979 | ;; If necessary, create a new heap environment to hold some of the | ||
| 3980 | ;; variables bound here. | ||
| 3981 | (when lforminfo | ||
| 3982 | (setq init-lexenv (byte-compile-maybe-push-heap-environment lforminfo))) | ||
| 3983 | ;; First compute the binding values in the old scope. | ||
| 3984 | (dolist (clause clauses) | ||
| 3985 | (setq init-lexenv | ||
| 3986 | (byte-compile-push-binding-init clause init-lexenv lforminfo))) | ||
| 3987 | ;; Now do the bindings, execute the body, and undo the bindings | ||
| 3988 | (let ((byte-compile-bound-variables byte-compile-bound-variables) | ||
| 3989 | (byte-compile-lexical-environment byte-compile-lexical-environment) | ||
| 3990 | (preserve-body-value (not for-effect))) | ||
| 3991 | (dolist (clause (reverse clauses)) | ||
| 3992 | (let ((var (if (consp clause) (car clause) clause))) | ||
| 3993 | (cond ((null lforminfo) | ||
| 3994 | ;; If there are no lexical bindings, we can do things simply. | 3898 | ;; If there are no lexical bindings, we can do things simply. |
| 3995 | (byte-compile-dynamic-variable-bind var)) | 3899 | (byte-compile-dynamic-variable-bind var)) |
| 3996 | ((byte-compile-bind var init-lexenv lforminfo) | 3900 | ((byte-compile-bind var init-lexenv) |
| 3997 | (pop init-lexenv))))) | 3901 | (pop init-lexenv))))) |
| 3998 | ;; Emit the body | 3902 | ;; Emit the body. |
| 3999 | (byte-compile-body-do-effect (cdr (cdr form))) | 3903 | (byte-compile-body-do-effect (cdr (cdr form))) |
| 4000 | ;; Unbind the variables | 3904 | ;; Unbind the variables. |
| 4001 | (if lforminfo | 3905 | (if lexical-binding |
| 4002 | ;; Unbind both lexical and dynamic variables | 3906 | ;; Unbind both lexical and dynamic variables. |
| 4003 | (byte-compile-unbind clauses init-lexenv lforminfo preserve-body-value) | 3907 | (byte-compile-unbind varlist init-lexenv t) |
| 4004 | ;; Unbind dynamic variables | 3908 | ;; Unbind dynamic variables. |
| 4005 | (byte-compile-out 'byte-unbind (length clauses)))))) | 3909 | (byte-compile-out 'byte-unbind (length varlist)))))) |
| 4006 | 3910 | ||
| 4007 | (defun byte-compile-let* (form) | 3911 | (defun byte-compile-let* (form) |
| 4008 | "Generate code for the `let*' form FORM." | 3912 | "Generate code for the `let*' form FORM." |
| 4009 | (let ((clauses (cadr form)) | 3913 | (let ((byte-compile-bound-variables byte-compile-bound-variables) ;new scope |
| 4010 | (lforminfo (and lexical-binding (byte-compile-compute-lforminfo form))) | 3914 | (clauses (cadr form)) |
| 4011 | (init-lexenv nil) | 3915 | (init-lexenv nil) |
| 4012 | (preserve-body-value (not for-effect)) | ||
| 4013 | ;; bind these to restrict the scope of any changes | 3916 | ;; bind these to restrict the scope of any changes |
| 4014 | (byte-compile-bound-variables byte-compile-bound-variables) | 3917 | |
| 4015 | (byte-compile-lexical-environment byte-compile-lexical-environment) | 3918 | (byte-compile-lexical-environment byte-compile-lexical-environment)) |
| 4016 | (byte-compile-current-heap-environment | ||
| 4017 | byte-compile-current-heap-environment) | ||
| 4018 | (byte-compile-current-num-closures byte-compile-current-num-closures)) | ||
| 4019 | ;; If necessary, create a new heap environment to hold some of the | ||
| 4020 | ;; variables bound here. | ||
| 4021 | (when lforminfo | ||
| 4022 | (setq init-lexenv (byte-compile-maybe-push-heap-environment lforminfo))) | ||
| 4023 | ;; Bind the variables | 3919 | ;; Bind the variables |
| 4024 | (dolist (clause clauses) | 3920 | (dolist (var clauses) |
| 4025 | (setq init-lexenv | 3921 | (push (byte-compile-push-binding-init var) init-lexenv) |
| 4026 | (byte-compile-push-binding-init clause init-lexenv lforminfo)) | 3922 | (let ((var (if (consp var) (car var) var))) |
| 4027 | (let ((var (if (consp clause) (car clause) clause))) | 3923 | (cond ((null lexical-binding) |
| 4028 | (cond ((null lforminfo) | ||
| 4029 | ;; If there are no lexical bindings, we can do things simply. | 3924 | ;; If there are no lexical bindings, we can do things simply. |
| 4030 | (byte-compile-dynamic-variable-bind var)) | 3925 | (byte-compile-dynamic-variable-bind var)) |
| 4031 | ((byte-compile-bind var init-lexenv lforminfo) | 3926 | ((byte-compile-bind var init-lexenv) |
| 4032 | (pop init-lexenv))))) | 3927 | (pop init-lexenv))))) |
| 4033 | ;; Emit the body | 3928 | ;; Emit the body |
| 4034 | (byte-compile-body-do-effect (cdr (cdr form))) | 3929 | (byte-compile-body-do-effect (cdr (cdr form))) |
| 4035 | ;; Unbind the variables | 3930 | ;; Unbind the variables |
| 4036 | (if lforminfo | 3931 | (if lexical-binding |
| 4037 | ;; Unbind both lexical and dynamic variables | 3932 | ;; Unbind both lexical and dynamic variables |
| 4038 | (byte-compile-unbind clauses init-lexenv lforminfo preserve-body-value) | 3933 | (byte-compile-unbind clauses init-lexenv t) |
| 4039 | ;; Unbind dynamic variables | 3934 | ;; Unbind dynamic variables |
| 4040 | (byte-compile-out 'byte-unbind (length clauses))))) | 3935 | (byte-compile-out 'byte-unbind (length clauses))))) |
| 4041 | 3936 | ||
| @@ -4105,10 +4000,11 @@ if LFORMINFO is nil (meaning all bindings are dynamic)." | |||
| 4105 | 4000 | ||
| 4106 | (defun byte-compile-condition-case (form) | 4001 | (defun byte-compile-condition-case (form) |
| 4107 | (let* ((var (nth 1 form)) | 4002 | (let* ((var (nth 1 form)) |
| 4108 | (byte-compile-bound-variables | 4003 | (fun-bodies (eq var :fun-body)) |
| 4109 | (if var (cons var byte-compile-bound-variables) | 4004 | (byte-compile-bound-variables |
| 4110 | byte-compile-bound-variables)) | 4005 | (if (and var (not fun-bodies)) |
| 4111 | (fun-bodies (eq var :fun-body))) | 4006 | (cons var byte-compile-bound-variables) |
| 4007 | byte-compile-bound-variables))) | ||
| 4112 | (byte-compile-set-symbol-position 'condition-case) | 4008 | (byte-compile-set-symbol-position 'condition-case) |
| 4113 | (unless (symbolp var) | 4009 | (unless (symbolp var) |
| 4114 | (byte-compile-warn | 4010 | (byte-compile-warn |
| @@ -4215,12 +4111,7 @@ if LFORMINFO is nil (meaning all bindings are dynamic)." | |||
| 4215 | (code (byte-compile-lambda (cdr (cdr form)) t)) | 4111 | (code (byte-compile-lambda (cdr (cdr form)) t)) |
| 4216 | (for-effect nil)) | 4112 | (for-effect nil)) |
| 4217 | (byte-compile-push-constant (nth 1 form)) | 4113 | (byte-compile-push-constant (nth 1 form)) |
| 4218 | (if (not (byte-compile-closure-code-p code)) | 4114 | (byte-compile-push-constant (cons 'macro code)) |
| 4219 | ;; simple lambda | ||
| 4220 | (byte-compile-push-constant (cons 'macro code)) | ||
| 4221 | (byte-compile-push-constant 'macro) | ||
| 4222 | (byte-compile-make-closure code) | ||
| 4223 | (byte-compile-out 'byte-cons)) | ||
| 4224 | (byte-compile-out 'byte-fset) | 4115 | (byte-compile-out 'byte-fset) |
| 4225 | (byte-compile-discard)) | 4116 | (byte-compile-discard)) |
| 4226 | (byte-compile-constant (nth 1 form))) | 4117 | (byte-compile-constant (nth 1 form))) |
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index efb9d061b5c..10464047cd3 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el | |||
| @@ -85,19 +85,6 @@ is less than this number.") | |||
| 85 | "List of candidates for lambda lifting. | 85 | "List of candidates for lambda lifting. |
| 86 | Each candidate has the form (VAR INCLOSURE BINDER PARENTFORM).") | 86 | Each candidate has the form (VAR INCLOSURE BINDER PARENTFORM).") |
| 87 | 87 | ||
| 88 | (defun cconv-not-lexical-var-p (var) | ||
| 89 | (or (not (symbolp var)) ; form is not a list | ||
| 90 | (if (eval-when-compile (fboundp 'special-variable-p)) | ||
| 91 | (special-variable-p var) | ||
| 92 | (boundp var)) | ||
| 93 | ;; byte-compile-bound-variables normally holds both the | ||
| 94 | ;; dynamic and lexical vars, but the bytecomp.el should | ||
| 95 | ;; only call us at the top-level so there shouldn't be | ||
| 96 | ;; any lexical vars in it here. | ||
| 97 | (memq var byte-compile-bound-variables) | ||
| 98 | (memq var '(nil t)) | ||
| 99 | (keywordp var))) | ||
| 100 | |||
| 101 | (defun cconv-freevars (form &optional fvrs) | 88 | (defun cconv-freevars (form &optional fvrs) |
| 102 | "Find all free variables of given form. | 89 | "Find all free variables of given form. |
| 103 | Arguments: | 90 | Arguments: |
| @@ -189,7 +176,7 @@ Returns a list of free variables." | |||
| 189 | (dolist (exp body-forms) | 176 | (dolist (exp body-forms) |
| 190 | (setq fvrs (cconv-freevars exp fvrs))) fvrs) | 177 | (setq fvrs (cconv-freevars exp fvrs))) fvrs) |
| 191 | 178 | ||
| 192 | (_ (if (cconv-not-lexical-var-p form) | 179 | (_ (if (byte-compile-not-lexical-var-p form) |
| 193 | fvrs | 180 | fvrs |
| 194 | (cons form fvrs))))) | 181 | (cons form fvrs))))) |
| 195 | 182 | ||
| @@ -704,7 +691,7 @@ Returns a form where all lambdas don't have any free variables." | |||
| 704 | (defun cconv-analyse-function (args body env parentform inclosure) | 691 | (defun cconv-analyse-function (args body env parentform inclosure) |
| 705 | (dolist (arg args) | 692 | (dolist (arg args) |
| 706 | (cond | 693 | (cond |
| 707 | ((cconv-not-lexical-var-p arg) | 694 | ((byte-compile-not-lexical-var-p arg) |
| 708 | (byte-compile-report-error | 695 | (byte-compile-report-error |
| 709 | (format "Argument %S is not a lexical variable" arg))) | 696 | (format "Argument %S is not a lexical variable" arg))) |
| 710 | ((eq ?& (aref (symbol-name arg) 0)) nil) ;Ignore &rest, &optional, ... | 697 | ((eq ?& (aref (symbol-name arg) 0)) nil) ;Ignore &rest, &optional, ... |
| @@ -738,7 +725,7 @@ lambdas if they are suitable for lambda lifting. | |||
| 738 | (cconv-analyse-form value (if (eq letsym 'let*) env orig-env) | 725 | (cconv-analyse-form value (if (eq letsym 'let*) env orig-env) |
| 739 | inclosure)) | 726 | inclosure)) |
| 740 | 727 | ||
| 741 | (unless (cconv-not-lexical-var-p var) | 728 | (unless (byte-compile-not-lexical-var-p var) |
| 742 | (let ((varstruct (list var inclosure binder form))) | 729 | (let ((varstruct (list var inclosure binder form))) |
| 743 | (push varstruct env) ; Push a new one. | 730 | (push varstruct env) ; Push a new one. |
| 744 | 731 | ||
diff --git a/lisp/help-fns.el b/lisp/help-fns.el index ed266c71a59..172a74d8c80 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el | |||
| @@ -529,23 +529,23 @@ suitable file is found, return nil." | |||
| 529 | (high (help-highlight-arguments use doc))) | 529 | (high (help-highlight-arguments use doc))) |
| 530 | (let ((fill-begin (point))) | 530 | (let ((fill-begin (point))) |
| 531 | (insert (car high) "\n") | 531 | (insert (car high) "\n") |
| 532 | (fill-region fill-begin (point)))) | 532 | (fill-region fill-begin (point))) |
| 533 | (setq doc (cdr high)))) | 533 | (setq doc (cdr high)))) |
| 534 | (let* ((obsolete (and | 534 | (let* ((obsolete (and |
| 535 | ;; function might be a lambda construct. | 535 | ;; function might be a lambda construct. |
| 536 | (symbolp function) | 536 | (symbolp function) |
| 537 | (get function 'byte-obsolete-info))) | 537 | (get function 'byte-obsolete-info))) |
| 538 | (use (car obsolete))) | 538 | (use (car obsolete))) |
| 539 | (when obsolete | 539 | (when obsolete |
| 540 | (princ "\nThis function is obsolete") | 540 | (princ "\nThis function is obsolete") |
| 541 | (when (nth 2 obsolete) | 541 | (when (nth 2 obsolete) |
| 542 | (insert (format " since %s" (nth 2 obsolete)))) | 542 | (insert (format " since %s" (nth 2 obsolete)))) |
| 543 | (insert (cond ((stringp use) (concat ";\n" use)) | 543 | (insert (cond ((stringp use) (concat ";\n" use)) |
| 544 | (use (format ";\nuse `%s' instead." use)) | 544 | (use (format ";\nuse `%s' instead." use)) |
| 545 | (t ".")) | 545 | (t ".")) |
| 546 | "\n")) | 546 | "\n")) |
| 547 | (insert "\n" | 547 | (insert "\n" |
| 548 | (or doc "Not documented."))))))) | 548 | (or doc "Not documented.")))))))) |
| 549 | 549 | ||
| 550 | 550 | ||
| 551 | ;; Variables | 551 | ;; Variables |
diff --git a/src/ChangeLog b/src/ChangeLog index f7a3fcc8b1b..6674fb31ca5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2011-02-12 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * bytecode.c (Bvec_ref, Bvec_set): Remove. | ||
| 4 | (exec_byte_code): Don't handle them. | ||
| 5 | |||
| 1 | 2010-12-27 Stefan Monnier <monnier@iro.umontreal.ca> | 6 | 2010-12-27 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 7 | ||
| 3 | * eval.c (Fdefvar): Record specialness before computing initial value. | 8 | * eval.c (Fdefvar): Record specialness before computing initial value. |
diff --git a/src/bytecode.c b/src/bytecode.c index 96d2aa273f2..9bf6ae45ce9 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -231,8 +231,6 @@ extern Lisp_Object Qand_optional, Qand_rest; | |||
| 231 | /* Bstack_ref is code 0. */ | 231 | /* Bstack_ref is code 0. */ |
| 232 | #define Bstack_set 0262 | 232 | #define Bstack_set 0262 |
| 233 | #define Bstack_set2 0263 | 233 | #define Bstack_set2 0263 |
| 234 | #define Bvec_ref 0264 | ||
| 235 | #define Bvec_set 0265 | ||
| 236 | #define BdiscardN 0266 | 234 | #define BdiscardN 0266 |
| 237 | 235 | ||
| 238 | #define Bconstant 0300 | 236 | #define Bconstant 0300 |
| @@ -1722,27 +1720,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1722 | case Bstack_set2: | 1720 | case Bstack_set2: |
| 1723 | stack.bottom[FETCH2] = POP; | 1721 | stack.bottom[FETCH2] = POP; |
| 1724 | break; | 1722 | break; |
| 1725 | case Bvec_ref: | ||
| 1726 | case Bvec_set: | ||
| 1727 | /* These byte-codes used mostly for variable references to | ||
| 1728 | lexically bound variables that are in an environment vector | ||
| 1729 | instead of on the byte-interpreter stack (generally those | ||
| 1730 | variables which might be shared with a closure). */ | ||
| 1731 | { | ||
| 1732 | int index = FETCH; | ||
| 1733 | Lisp_Object vec = POP; | ||
| 1734 | |||
| 1735 | if (! VECTORP (vec)) | ||
| 1736 | wrong_type_argument (Qvectorp, vec); | ||
| 1737 | else if (index < 0 || index >= XVECTOR (vec)->size) | ||
| 1738 | args_out_of_range (vec, make_number (index)); | ||
| 1739 | |||
| 1740 | if (op == Bvec_ref) | ||
| 1741 | PUSH (XVECTOR (vec)->contents[index]); | ||
| 1742 | else | ||
| 1743 | XVECTOR (vec)->contents[index] = POP; | ||
| 1744 | } | ||
| 1745 | break; | ||
| 1746 | case BdiscardN: | 1723 | case BdiscardN: |
| 1747 | op = FETCH; | 1724 | op = FETCH; |
| 1748 | if (op & 0x80) | 1725 | if (op & 0x80) |