aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2011-02-11 17:30:02 -0500
committerStefan Monnier2011-02-11 17:30:02 -0500
commit295fb2ac59b66c0e2470325a42c8e58c135ed044 (patch)
tree79a1ad28fff71252a5d19b49b1d2a6827849039c
parent43e67019dfc4fb7d3474e0fbedcfec60f2300521 (diff)
downloademacs-295fb2ac59b66c0e2470325a42c8e58c135ed044.tar.gz
emacs-295fb2ac59b66c0e2470325a42c8e58c135ed044.zip
Let cconv use :fun-body in special forms that need it.
* lisp/emacs-lisp/cconv.el (cconv-closure-convert): Drop `toplevel' arg. (cconv-closure-convert-toplevel): Remove. (cconv-lookup-let): New fun. (cconv-closure-convert-rec): Don't bother with defs-are-legal. Use :fun-body to handle special forms that require closing their forms. * lisp/emacs-lisp/bytecomp.el (byte-compile-file-form, byte-compile): Use cconv-closure-convert instead of cconv-closure-convert-toplevel. (byte-compile-lambda, byte-compile-make-closure): * lisp/emacs-lisp/byte-lexbind.el (byte-compile-maybe-push-heap-environment): Make sure cconv did its job. * lisp/emacs-lisp/byte-opt.el (byte-optimize-lapcode): Check stack-depth before using it. * lisp/dired.el (dired-desktop-buffer-misc-data): Don't use a dynamic var as function argument.
-rw-r--r--lisp/ChangeLog20
-rw-r--r--lisp/dired.el11
-rw-r--r--lisp/emacs-lisp/byte-lexbind.el1
-rw-r--r--lisp/emacs-lisp/byte-opt.el11
-rw-r--r--lisp/emacs-lisp/bytecomp.el10
-rw-r--r--lisp/emacs-lisp/cconv.el347
-rw-r--r--lisp/mpc.el3
7 files changed, 201 insertions, 202 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 6a47a2626a5..c3451d9b269 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,25 @@
12011-02-11 Stefan Monnier <monnier@iro.umontreal.ca> 12011-02-11 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * emacs-lisp/cconv.el (cconv-closure-convert): Drop `toplevel' arg.
4 (cconv-closure-convert-toplevel): Remove.
5 (cconv-lookup-let): New fun.
6 (cconv-closure-convert-rec): Don't bother with defs-are-legal.
7 Use :fun-body to handle special forms that require closing their forms.
8
9 * emacs-lisp/bytecomp.el (byte-compile-file-form, byte-compile):
10 Use cconv-closure-convert instead of cconv-closure-convert-toplevel.
11 (byte-compile-lambda, byte-compile-make-closure):
12 * emacs-lisp/byte-lexbind.el (byte-compile-maybe-push-heap-environment):
13 Make sure cconv did its job.
14
15 * emacs-lisp/byte-opt.el (byte-optimize-lapcode): Check stack-depth
16 before using it.
17
18 * dired.el (dired-desktop-buffer-misc-data): Don't use a dynamic var as
19 function argument.
20
212011-02-11 Stefan Monnier <monnier@iro.umontreal.ca>
22
3 * emacs-lisp/bytecomp.el (byte-compile-lambda): Fix `fun' that was not 23 * emacs-lisp/bytecomp.el (byte-compile-lambda): Fix `fun' that was not
4 renamed to `bytecomp-fun'. 24 renamed to `bytecomp-fun'.
5 25
diff --git a/lisp/dired.el b/lisp/dired.el
index f98ad641fe3..92cbdd32c8d 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1,5 +1,4 @@
1;;; -*- lexical-binding: t -*- 1;;; dired.el --- directory-browsing commands -*- lexical-binding: t -*-
2;;; dired.el --- directory-browsing commands
3 2
4;; Copyright (C) 1985-1986, 1992-1997, 2000-2011 3;; Copyright (C) 1985-1986, 1992-1997, 2000-2011
5;; Free Software Foundation, Inc. 4;; Free Software Foundation, Inc.
@@ -3507,21 +3506,21 @@ Ask means pop up a menu for the user to select one of copy, move or link."
3507 3506
3508(eval-when-compile (require 'desktop)) 3507(eval-when-compile (require 'desktop))
3509 3508
3510(defun dired-desktop-buffer-misc-data (desktop-dirname) 3509(defun dired-desktop-buffer-misc-data (dirname)
3511 "Auxiliary information to be saved in desktop file." 3510 "Auxiliary information to be saved in desktop file."
3512 (cons 3511 (cons
3513 ;; Value of `dired-directory'. 3512 ;; Value of `dired-directory'.
3514 (if (consp dired-directory) 3513 (if (consp dired-directory)
3515 ;; Directory name followed by list of files. 3514 ;; Directory name followed by list of files.
3516 (cons (desktop-file-name (car dired-directory) desktop-dirname) 3515 (cons (desktop-file-name (car dired-directory) dirname)
3517 (cdr dired-directory)) 3516 (cdr dired-directory))
3518 ;; Directory name, optionally with shell wildcard. 3517 ;; Directory name, optionally with shell wildcard.
3519 (desktop-file-name dired-directory desktop-dirname)) 3518 (desktop-file-name dired-directory dirname))
3520 ;; Subdirectories in `dired-subdir-alist'. 3519 ;; Subdirectories in `dired-subdir-alist'.
3521 (cdr 3520 (cdr
3522 (nreverse 3521 (nreverse
3523 (mapcar 3522 (mapcar
3524 (function (lambda (f) (desktop-file-name (car f) desktop-dirname))) 3523 (function (lambda (f) (desktop-file-name (car f) dirname)))
3525 dired-subdir-alist))))) 3524 dired-subdir-alist)))))
3526 3525
3527(defun dired-restore-desktop-buffer (desktop-buffer-file-name 3526(defun dired-restore-desktop-buffer (desktop-buffer-file-name
diff --git a/lisp/emacs-lisp/byte-lexbind.el b/lisp/emacs-lisp/byte-lexbind.el
index 313c4b6ad0f..06353e2eea8 100644
--- a/lisp/emacs-lisp/byte-lexbind.el
+++ b/lisp/emacs-lisp/byte-lexbind.el
@@ -585,6 +585,7 @@ proper scope)."
585 (= nclosures byte-compile-current-num-closures)) 585 (= nclosures byte-compile-current-num-closures))
586 ;; No need to push a heap environment. 586 ;; No need to push a heap environment.
587 nil 587 nil
588 (error "Should have been handled by cconv")
588 ;; Have to push one. A heap environment is really just a vector, so 589 ;; Have to push one. A heap environment is really just a vector, so
589 ;; we emit bytecodes to create a vector. However, the size is not 590 ;; we emit bytecodes to create a vector. However, the size is not
590 ;; fixed yet (the vector can grow if subforms use it to store 591 ;; fixed yet (the vector can grow if subforms use it to store
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 02107b0e11f..97ed6a01c2f 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1863,7 +1863,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
1863 ;; 1863 ;;
1864 ;; stack-ref-N --> dup ; where N is TOS 1864 ;; stack-ref-N --> dup ; where N is TOS
1865 ;; 1865 ;;
1866 ((and (eq (car lap0) 'byte-stack-ref) 1866 ((and stack-depth (eq (car lap0) 'byte-stack-ref)
1867 (= (cdr lap0) (1- stack-depth))) 1867 (= (cdr lap0) (1- stack-depth)))
1868 (setcar lap0 'byte-dup) 1868 (setcar lap0 'byte-dup)
1869 (setcdr lap0 nil) 1869 (setcdr lap0 nil)
@@ -2093,7 +2093,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2093 ;; stack-set-M [discard/discardN ...] --> discardN-preserve-tos 2093 ;; stack-set-M [discard/discardN ...] --> discardN-preserve-tos
2094 ;; stack-set-M [discard/discardN ...] --> discardN 2094 ;; stack-set-M [discard/discardN ...] --> discardN
2095 ;; 2095 ;;
2096 ((and (eq (car lap0) 'byte-stack-set) 2096 ((and stack-depth ;Make sure we know the stack depth.
2097 (eq (car lap0) 'byte-stack-set)
2097 (memq (car lap1) '(byte-discard byte-discardN)) 2098 (memq (car lap1) '(byte-discard byte-discardN))
2098 (progn 2099 (progn
2099 ;; See if enough discard operations follow to expose or 2100 ;; See if enough discard operations follow to expose or
@@ -2161,7 +2162,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2161 ;; dup return --> return 2162 ;; dup return --> return
2162 ;; stack-set-N return --> return ; where N is TOS-1 2163 ;; stack-set-N return --> return ; where N is TOS-1
2163 ;; 2164 ;;
2164 ((and (eq (car lap1) 'byte-return) 2165 ((and stack-depth ;Make sure we know the stack depth.
2166 (eq (car lap1) 'byte-return)
2165 (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup)) 2167 (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup))
2166 (and (eq (car lap0) 'byte-stack-set) 2168 (and (eq (car lap0) 'byte-stack-set)
2167 (= (cdr lap0) (- stack-depth 2))))) 2169 (= (cdr lap0) (- stack-depth 2)))))
@@ -2174,7 +2176,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2174 ;; 2176 ;;
2175 ;; dup stack-set-N return --> return ; where N is TOS 2177 ;; dup stack-set-N return --> return ; where N is TOS
2176 ;; 2178 ;;
2177 ((and (eq (car lap0) 'byte-dup) 2179 ((and stack-depth ;Make sure we know the stack depth.
2180 (eq (car lap0) 'byte-dup)
2178 (eq (car lap1) 'byte-stack-set) 2181 (eq (car lap1) 'byte-stack-set)
2179 (eq (car (car (cdr (cdr rest)))) 'byte-return) 2182 (eq (car (car (cdr (cdr rest)))) 'byte-return)
2180 (= (cdr lap1) (1- stack-depth))) 2183 (= (cdr lap1) (1- stack-depth)))
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index f37d7489e9a..33940ec160e 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -134,7 +134,7 @@
134;; `eval-when-compile' is defined in byte-run.el, so it must come after the 134;; `eval-when-compile' is defined in byte-run.el, so it must come after the
135;; preceding load expression. 135;; preceding load expression.
136(provide 'bytecomp-preload) 136(provide 'bytecomp-preload)
137(eval-when-compile (require 'byte-lexbind)) 137(eval-when-compile (require 'byte-lexbind nil 'noerror))
138 138
139;; The feature of compiling in a specific target Emacs version 139;; The feature of compiling in a specific target Emacs version
140;; has been turned off because compile time options are a bad idea. 140;; has been turned off because compile time options are a bad idea.
@@ -2240,7 +2240,7 @@ list that represents a doc string reference.
2240 bytecomp-handler) 2240 bytecomp-handler)
2241 (setq form (macroexpand-all form byte-compile-macro-environment)) 2241 (setq form (macroexpand-all form byte-compile-macro-environment))
2242 (if lexical-binding 2242 (if lexical-binding
2243 (setq form (cconv-closure-convert-toplevel form))) 2243 (setq form (cconv-closure-convert form)))
2244 (cond ((not (consp form)) 2244 (cond ((not (consp form))
2245 (byte-compile-keep-pending form)) 2245 (byte-compile-keep-pending form))
2246 ((and (symbolp (car form)) 2246 ((and (symbolp (car form))
@@ -2592,7 +2592,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
2592 (macroexpand-all fun 2592 (macroexpand-all fun
2593 byte-compile-initial-macro-environment)) 2593 byte-compile-initial-macro-environment))
2594 (if lexical-binding 2594 (if lexical-binding
2595 (setq fun (cconv-closure-convert-toplevel fun))) 2595 (setq fun (cconv-closure-convert fun)))
2596 ;; get rid of the `function' quote added by the `lambda' macro 2596 ;; get rid of the `function' quote added by the `lambda' macro
2597 (setq fun (cadr fun)) 2597 (setq fun (cadr fun))
2598 (setq fun (if macro 2598 (setq fun (if macro
@@ -2753,7 +2753,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
2753 ;; containing lexical environment are closed over). 2753 ;; containing lexical environment are closed over).
2754 (and lexical-binding 2754 (and lexical-binding
2755 (byte-compile-closure-initial-lexenv-p 2755 (byte-compile-closure-initial-lexenv-p
2756 byte-compile-lexical-environment))) 2756 byte-compile-lexical-environment)
2757 (error "Should have been handled by cconv")))
2757 (byte-compile-current-heap-environment nil) 2758 (byte-compile-current-heap-environment nil)
2758 (byte-compile-current-num-closures 0) 2759 (byte-compile-current-num-closures 0)
2759 (compiled 2760 (compiled
@@ -2791,6 +2792,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
2791 (eq (car-safe code) 'closure)) 2792 (eq (car-safe code) 'closure))
2792 2793
2793(defun byte-compile-make-closure (code) 2794(defun byte-compile-make-closure (code)
2795 (error "Should have been handled by cconv")
2794 ;; A real closure requires that the constant be curried with an 2796 ;; A real closure requires that the constant be curried with an
2795 ;; environment vector to make a closure object. 2797 ;; environment vector to make a closure object.
2796 (if for-effect 2798 (if for-effect
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index af42a2864c9..efb9d061b5c 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -87,7 +87,9 @@ Each candidate has the form (VAR INCLOSURE BINDER PARENTFORM).")
87 87
88(defun cconv-not-lexical-var-p (var) 88(defun cconv-not-lexical-var-p (var)
89 (or (not (symbolp var)) ; form is not a list 89 (or (not (symbolp var)) ; form is not a list
90 (special-variable-p var) 90 (if (eval-when-compile (fboundp 'special-variable-p))
91 (special-variable-p var)
92 (boundp var))
91 ;; byte-compile-bound-variables normally holds both the 93 ;; byte-compile-bound-variables normally holds both the
92 ;; dynamic and lexical vars, but the bytecomp.el should 94 ;; dynamic and lexical vars, but the bytecomp.el should
93 ;; only call us at the top-level so there shouldn't be 95 ;; only call us at the top-level so there shouldn't be
@@ -192,14 +194,8 @@ Returns a list of free variables."
192 (cons form fvrs))))) 194 (cons form fvrs)))))
193 195
194;;;###autoload 196;;;###autoload
195(defun cconv-closure-convert (form &optional toplevel) 197(defun cconv-closure-convert (form)
196 ;; cconv-closure-convert-rec has a lot of parameters that are 198 "Main entry point for closure conversion.
197 ;; whether useless for user, whether they should contain
198 ;; specific data like a list of closure mutables or the list
199 ;; of lambdas suitable for lifting.
200 ;;
201 ;; That's why this function exists.
202 "Main entry point for non-toplevel forms.
203-- FORM is a piece of Elisp code after macroexpansion. 199-- FORM is a piece of Elisp code after macroexpansion.
204-- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST 200-- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST
205 201
@@ -221,19 +217,21 @@ Returns a form where all lambdas don't have any free variables."
221 '() ; fvrs initially empty 217 '() ; fvrs initially empty
222 '() ; envs initially empty 218 '() ; envs initially empty
223 '() 219 '()
224 toplevel))) ; true if the tree is a toplevel form 220 )))
225 221
226;;;###autoload 222(defun cconv-lookup-let (table var binder form)
227(defun cconv-closure-convert-toplevel (form) 223 (let ((res nil))
228 "Entry point for toplevel forms. 224 (dolist (elem table)
229-- FORM is a piece of Elisp code after macroexpansion. 225 (when (and (eq (nth 2 elem) binder)
226 (eq (nth 3 elem) form))
227 (assert (eq (car elem) var))
228 (setq res elem)))
229 res))
230 230
231Returns a form where all lambdas don't have any free variables." 231(defconst cconv--dummy-var (make-symbol "ignored"))
232 ;; we distinguish toplevel forms to treat def(un|var|const) correctly.
233 (cconv-closure-convert form t))
234 232
235(defun cconv-closure-convert-rec 233(defun cconv-closure-convert-rec
236 (form emvrs fvrs envs lmenvs defs-are-legal) 234 (form emvrs fvrs envs lmenvs)
237 ;; This function actually rewrites the tree. 235 ;; This function actually rewrites the tree.
238 "Eliminates all free variables of all lambdas in given forms. 236 "Eliminates all free variables of all lambdas in given forms.
239Arguments: 237Arguments:
@@ -245,8 +243,6 @@ within current environment.
245Initially empty. 243Initially empty.
246-- FVRS is a list of variables to substitute in each context. 244-- FVRS is a list of variables to substitute in each context.
247Initially empty. 245Initially empty.
248-- DEFS-ARE-LEGAL is a boolean variable, true if def(un|var|const)
249can be used in this form(e.g. toplevel form)
250 246
251Returns a form where all lambdas don't have any free variables." 247Returns a form where all lambdas don't have any free variables."
252 ;; What's the difference between fvrs and envs? 248 ;; What's the difference between fvrs and envs?
@@ -261,11 +257,11 @@ Returns a form where all lambdas don't have any free variables."
261 ;; so we never touch it(unless we enter to the other closure). 257 ;; so we never touch it(unless we enter to the other closure).
262 ;;(if (listp form) (print (car form)) form) 258 ;;(if (listp form) (print (car form)) form)
263 (pcase form 259 (pcase form
264 (`(,(and letsym (or `let* `let)) ,varsvalues . ,body-forms) 260 (`(,(and letsym (or `let* `let)) ,binders . ,body-forms)
265 261
266 ; let and let* special forms 262 ; let and let* special forms
267 (let ((body-forms-new '()) 263 (let ((body-forms-new '())
268 (varsvalues-new '()) 264 (binders-new '())
269 ;; next for variables needed for delayed push 265 ;; next for variables needed for delayed push
270 ;; because we should process <value(s)> 266 ;; because we should process <value(s)>
271 ;; before we change any arguments 267 ;; before we change any arguments
@@ -274,83 +270,58 @@ Returns a form where all lambdas don't have any free variables."
274 (emvr-push) ;needed only in case of let* 270 (emvr-push) ;needed only in case of let*
275 (lmenv-push)) ;needed only in case of let* 271 (lmenv-push)) ;needed only in case of let*
276 272
277 (dolist (elm varsvalues) ;begin of dolist over varsvalues 273 (dolist (binder binders)
278 (let (var value elm-new iscandidate ismutated) 274 (let* ((value nil)
279 (if (consp elm) ; (let (v1) ...) => (let ((v1 nil)) ...) 275 (var (if (not (consp binder))
280 (progn 276 binder
281 (setq var (car elm)) 277 (setq value (cadr binder))
282 (setq value (cadr elm))) 278 (car binder)))
283 (setq var elm)) 279 (new-val
284 280 (cond
285 ;; Check if var is a candidate for lambda lifting 281 ;; Check if var is a candidate for lambda lifting.
286 (let ((lcandid cconv-lambda-candidates)) 282 ((cconv-lookup-let cconv-lambda-candidates var binder form)
287 (while (and lcandid (not iscandidate)) 283
288 (when (and (eq (caar lcandid) var) 284 (let* ((fv (delete-dups (cconv-freevars value '())))
289 (eq (caddar lcandid) elm) 285 (funargs (cadr (cadr value)))
290 (eq (cadr (cddar lcandid)) form)) 286 (funcvars (append fv funargs))
291 (setq iscandidate t)) 287 (funcbodies (cddadr value)) ; function bodies
292 (setq lcandid (cdr lcandid)))) 288 (funcbodies-new '()))
293
294 ; declared variable is a candidate
295 ; for lambda lifting
296 (if iscandidate
297 (let* ((func (cadr elm)) ; function(lambda) itself
298 ; free variables
299 (fv (delete-dups (cconv-freevars func '())))
300 (funcvars (append fv (cadadr func))) ;function args
301 (funcbodies (cddadr func)) ; function bodies
302 (funcbodies-new '()))
303 ; lambda lifting condition 289 ; lambda lifting condition
304 (if (or (not fv) (< cconv-liftwhen (length funcvars))) 290 (if (or (not fv) (< cconv-liftwhen (length funcvars)))
305 ; do not lift 291 ; do not lift
306 (setq 292 (cconv-closure-convert-rec
307 elm-new 293 value emvrs fvrs envs lmenvs)
308 `(,var
309 ,(cconv-closure-convert-rec
310 func emvrs fvrs envs lmenvs nil)))
311 ; lift 294 ; lift
312 (progn 295 (progn
313 (dolist (elm2 funcbodies) 296 (dolist (elm2 funcbodies)
314 (push ; convert function bodies 297 (push ; convert function bodies
315 (cconv-closure-convert-rec 298 (cconv-closure-convert-rec
316 elm2 emvrs nil envs lmenvs nil) 299 elm2 emvrs nil envs lmenvs)
317 funcbodies-new)) 300 funcbodies-new))
318 (if (eq letsym 'let*) 301 (if (eq letsym 'let*)
319 (setq lmenv-push (cons var fv)) 302 (setq lmenv-push (cons var fv))
320 (push (cons var fv) lmenvs-new)) 303 (push (cons var fv) lmenvs-new))
321 ; push lifted function 304 ; push lifted function
322 305
323 (setq elm-new 306 `(function .
324 `(,var 307 ((lambda ,funcvars .
325 (function . 308 ,(reverse funcbodies-new))))))))
326 ((lambda ,funcvars . 309
327 ,(reverse funcbodies-new))))))))) 310 ;; Check if it needs to be turned into a "ref-cell".
328 311 ((cconv-lookup-let cconv-captured+mutated var binder form)
329 ;declared variable is not a function 312 ;; Declared variable is mutated and captured.
330 (progn 313 (prog1
331 ;; Check if var is mutated 314 `(list ,(cconv-closure-convert-rec
332 (let ((lmutated cconv-captured+mutated)) 315 value emvrs
333 (while (and lmutated (not ismutated)) 316 fvrs envs lmenvs))
334 (when (and (eq (caar lmutated) var)
335 (eq (caddar lmutated) elm)
336 (eq (cadr (cddar lmutated)) form))
337 (setq ismutated t))
338 (setq lmutated (cdr lmutated))))
339 (if ismutated
340 (progn ; declared variable is mutated
341 (setq elm-new
342 `(,var (list ,(cconv-closure-convert-rec
343 value emvrs
344 fvrs envs lmenvs nil))))
345 (if (eq letsym 'let*) 317 (if (eq letsym 'let*)
346 (setq emvr-push var) 318 (setq emvr-push var)
347 (push var emvrs-new))) 319 (push var emvrs-new))))
348 (progn 320
349 (setq 321 ;; Normal default case.
350 elm-new 322 (t
351 `(,var ; else 323 (cconv-closure-convert-rec
352 ,(cconv-closure-convert-rec 324 value emvrs fvrs envs lmenvs)))))
353 value emvrs fvrs envs lmenvs nil)))))))
354 325
355 ;; this piece of code below letbinds free 326 ;; this piece of code below letbinds free
356 ;; variables of a lambda lifted function 327 ;; variables of a lambda lifted function
@@ -384,12 +355,12 @@ Returns a form where all lambdas don't have any free variables."
384 (when new-lmenv 355 (when new-lmenv
385 (setq lmenvs (remq old-lmenv lmenvs)) 356 (setq lmenvs (remq old-lmenv lmenvs))
386 (push new-lmenv lmenvs) 357 (push new-lmenv lmenvs)
387 (push `(,closedsym ,var) varsvalues-new)))) 358 (push `(,closedsym ,var) binders-new))))
388 ;; we push the element after redefined free variables 359 ;; we push the element after redefined free variables
389 ;; are processes. this is important to avoid the bug 360 ;; are processes. this is important to avoid the bug
390 ;; when free variable and the function have the same 361 ;; when free variable and the function have the same
391 ;; name 362 ;; name
392 (push elm-new varsvalues-new) 363 (push (list var new-val) binders-new)
393 364
394 (when (eq letsym 'let*) ; update fvrs 365 (when (eq letsym 'let*) ; update fvrs
395 (setq fvrs (remq var fvrs)) 366 (setq fvrs (remq var fvrs))
@@ -405,23 +376,23 @@ Returns a form where all lambdas don't have any free variables."
405 (when lmenv-push 376 (when lmenv-push
406 (push lmenv-push lmenvs) 377 (push lmenv-push lmenvs)
407 (setq lmenv-push nil))) 378 (setq lmenv-push nil)))
408 )) ; end of dolist over varsvalues 379 )) ; end of dolist over binders
409 (when (eq letsym 'let) 380 (when (eq letsym 'let)
410 381
411 (let (var fvrs-1 emvrs-1 lmenvs-1) 382 (let (var fvrs-1 emvrs-1 lmenvs-1)
412 ;; Here we update emvrs, fvrs and lmenvs lists 383 ;; Here we update emvrs, fvrs and lmenvs lists
413 (dolist (vr fvrs) 384 (dolist (vr fvrs)
414 ; safely remove 385 ; safely remove
415 (when (not (assq vr varsvalues-new)) (push vr fvrs-1))) 386 (when (not (assq vr binders-new)) (push vr fvrs-1)))
416 (setq fvrs fvrs-1) 387 (setq fvrs fvrs-1)
417 (dolist (vr emvrs) 388 (dolist (vr emvrs)
418 ; safely remove 389 ; safely remove
419 (when (not (assq vr varsvalues-new)) (push vr emvrs-1))) 390 (when (not (assq vr binders-new)) (push vr emvrs-1)))
420 (setq emvrs emvrs-1) 391 (setq emvrs emvrs-1)
421 ; push new 392 ; push new
422 (setq emvrs (append emvrs emvrs-new)) 393 (setq emvrs (append emvrs emvrs-new))
423 (dolist (vr lmenvs) 394 (dolist (vr lmenvs)
424 (when (not (assq (car vr) varsvalues-new)) 395 (when (not (assq (car vr) binders-new))
425 (push vr lmenvs-1))) 396 (push vr lmenvs-1)))
426 (setq lmenvs (append lmenvs lmenvs-new))) 397 (setq lmenvs (append lmenvs lmenvs-new)))
427 398
@@ -432,10 +403,9 @@ Returns a form where all lambdas don't have any free variables."
432 (let ((new-lmenv) 403 (let ((new-lmenv)
433 (var nil) 404 (var nil)
434 (closedsym nil) 405 (closedsym nil)
435 (letbinds '()) 406 (letbinds '()))
436 (fvrs-new)) ; list of (closed-var var) 407 (dolist (binder binders)
437 (dolist (elm varsvalues) 408 (setq var (if (consp binder) (car binder) binder))
438 (setq var (if (consp elm) (car elm) elm))
439 409
440 (let ((lmenvs-1 lmenvs)) ; just to avoid manipulating 410 (let ((lmenvs-1 lmenvs)) ; just to avoid manipulating
441 (dolist (lmenv lmenvs-1) ; the counter inside the loop 411 (dolist (lmenv lmenvs-1) ; the counter inside the loop
@@ -453,13 +423,13 @@ Returns a form where all lambdas don't have any free variables."
453 (push new-lmenv lmenvs) 423 (push new-lmenv lmenvs)
454 (push `(,closedsym ,var) letbinds) 424 (push `(,closedsym ,var) letbinds)
455 )))) 425 ))))
456 (setq varsvalues-new (append varsvalues-new letbinds)))) 426 (setq binders-new (append binders-new letbinds))))
457 427
458 (dolist (elm body-forms) ; convert body forms 428 (dolist (elm body-forms) ; convert body forms
459 (push (cconv-closure-convert-rec 429 (push (cconv-closure-convert-rec
460 elm emvrs fvrs envs lmenvs nil) 430 elm emvrs fvrs envs lmenvs)
461 body-forms-new)) 431 body-forms-new))
462 `(,letsym ,(reverse varsvalues-new) . ,(reverse body-forms-new)))) 432 `(,letsym ,(reverse binders-new) . ,(reverse body-forms-new))))
463 ;end of let let* forms 433 ;end of let let* forms
464 434
465 ; first element is lambda expression 435 ; first element is lambda expression
@@ -468,13 +438,12 @@ Returns a form where all lambdas don't have any free variables."
468 (let ((other-body-forms-new '())) 438 (let ((other-body-forms-new '()))
469 (dolist (elm other-body-forms) 439 (dolist (elm other-body-forms)
470 (push (cconv-closure-convert-rec 440 (push (cconv-closure-convert-rec
471 elm emvrs fvrs envs lmenvs nil) 441 elm emvrs fvrs envs lmenvs)
472 other-body-forms-new)) 442 other-body-forms-new))
473 (cons 443 `(funcall
474 (cadr 444 ,(cconv-closure-convert-rec
475 (cconv-closure-convert-rec 445 (list 'function fun) emvrs fvrs envs lmenvs)
476 (list 'function fun) emvrs fvrs envs lmenvs nil)) 446 ,@(nreverse other-body-forms-new))))
477 (reverse other-body-forms-new))))
478 447
479 (`(cond . ,cond-forms) ; cond special form 448 (`(cond . ,cond-forms) ; cond special form
480 (let ((cond-forms-new '())) 449 (let ((cond-forms-new '()))
@@ -483,7 +452,7 @@ Returns a form where all lambdas don't have any free variables."
483 (dolist (elm-2 elm) 452 (dolist (elm-2 elm)
484 (push 453 (push
485 (cconv-closure-convert-rec 454 (cconv-closure-convert-rec
486 elm-2 emvrs fvrs envs lmenvs nil) 455 elm-2 emvrs fvrs envs lmenvs)
487 elm-new)) 456 elm-new))
488 (reverse elm-new)) 457 (reverse elm-new))
489 cond-forms-new)) 458 cond-forms-new))
@@ -523,7 +492,7 @@ Returns a form where all lambdas don't have any free variables."
523 (dolist (elm fv) 492 (dolist (elm fv)
524 (push 493 (push
525 (cconv-closure-convert-rec 494 (cconv-closure-convert-rec
526 elm (remq elm emvrs) fvrs envs lmenvs nil) 495 elm (remq elm emvrs) fvrs envs lmenvs)
527 envector)) ; process vars for closure vector 496 envector)) ; process vars for closure vector
528 (setq envector (reverse envector)) 497 (setq envector (reverse envector))
529 (setq envs fv)) 498 (setq envs fv))
@@ -539,7 +508,7 @@ Returns a form where all lambdas don't have any free variables."
539 (push `(,mv (list ,mv)) letbind)))) 508 (push `(,mv (list ,mv)) letbind))))
540 (dolist (elm body-forms) ; convert function body 509 (dolist (elm body-forms) ; convert function body
541 (push (cconv-closure-convert-rec 510 (push (cconv-closure-convert-rec
542 elm emvrs fvrs envs lmenvs nil) 511 elm emvrs fvrs envs lmenvs)
543 body-forms-new)) 512 body-forms-new))
544 513
545 (setq body-forms-new 514 (setq body-forms-new
@@ -566,83 +535,89 @@ Returns a form where all lambdas don't have any free variables."
566 ;defconst, defvar 535 ;defconst, defvar
567 (`(,(and sym (or `defconst `defvar)) ,definedsymbol . ,body-forms) 536 (`(,(and sym (or `defconst `defvar)) ,definedsymbol . ,body-forms)
568 537
569 (if defs-are-legal 538 (let ((body-forms-new '()))
570 (let ((body-forms-new '())) 539 (dolist (elm body-forms)
571 (dolist (elm body-forms) 540 (push (cconv-closure-convert-rec
572 (push (cconv-closure-convert-rec 541 elm emvrs fvrs envs lmenvs)
573 elm emvrs fvrs envs lmenvs nil) 542 body-forms-new))
574 body-forms-new)) 543 (setq body-forms-new (reverse body-forms-new))
575 (setq body-forms-new (reverse body-forms-new)) 544 `(,sym ,definedsymbol . ,body-forms-new)))
576 `(,sym ,definedsymbol . ,body-forms-new))
577 (error "Invalid form: %s inside a function" sym)))
578 545
579 ;defun, defmacro 546 ;defun, defmacro
580 (`(,(and sym (or `defun `defmacro)) 547 (`(,(and sym (or `defun `defmacro))
581 ,func ,vars . ,body-forms) 548 ,func ,vars . ,body-forms)
582 (if defs-are-legal 549 (let ((body-new '()) ; the whole body
583 (let ((body-new '()) ; the whole body 550 (body-forms-new '()) ; body w\o docstring and interactive
584 (body-forms-new '()) ; body w\o docstring and interactive 551 (letbind '()))
585 (letbind '()))
586 ; find mutable arguments 552 ; find mutable arguments
587 (let ((lmutated cconv-captured+mutated) ismutated) 553 (let ((lmutated cconv-captured+mutated) ismutated)
588 (dolist (elm vars) 554 (dolist (elm vars)
589 (setq ismutated nil) 555 (setq ismutated nil)
590 (while (and lmutated (not ismutated)) 556 (while (and lmutated (not ismutated))
591 (when (and (eq (caar lmutated) elm) 557 (when (and (eq (caar lmutated) elm)
592 (eq (cadar lmutated) form)) 558 (eq (cadar lmutated) form))
593 (setq ismutated t)) 559 (setq ismutated t))
594 (setq lmutated (cdr lmutated))) 560 (setq lmutated (cdr lmutated)))
595 (when ismutated 561 (when ismutated
596 (push elm letbind) 562 (push elm letbind)
597 (push elm emvrs)))) 563 (push elm emvrs))))
598 ;transform body-forms 564 ;transform body-forms
599 (when (stringp (car body-forms)) ; treat docstring well 565 (when (stringp (car body-forms)) ; treat docstring well
600 (push (car body-forms) body-new) 566 (push (car body-forms) body-new)
601 (setq body-forms (cdr body-forms))) 567 (setq body-forms (cdr body-forms)))
602 (when (eq (car-safe (car body-forms)) 'interactive) 568 (when (eq (car-safe (car body-forms)) 'interactive)
603 (push 569 (push (cconv-closure-convert-rec
604 (cconv-closure-convert-rec 570 (car body-forms)
605 (car body-forms) 571 emvrs fvrs envs lmenvs)
606 emvrs fvrs envs lmenvs nil) body-new) 572 body-new)
607 (setq body-forms (cdr body-forms))) 573 (setq body-forms (cdr body-forms)))
608 574
609 (dolist (elm body-forms) 575 (dolist (elm body-forms)
610 (push (cconv-closure-convert-rec 576 (push (cconv-closure-convert-rec
611 elm emvrs fvrs envs lmenvs nil) 577 elm emvrs fvrs envs lmenvs)
612 body-forms-new)) 578 body-forms-new))
613 (setq body-forms-new (reverse body-forms-new)) 579 (setq body-forms-new (reverse body-forms-new))
614 580
615 (if letbind 581 (if letbind
616 ; letbind mutable arguments 582 ; letbind mutable arguments
617 (let ((varsvalues-new '())) 583 (let ((binders-new '()))
618 (dolist (elm letbind) (push `(,elm (list ,elm)) 584 (dolist (elm letbind) (push `(,elm (list ,elm))
619 varsvalues-new)) 585 binders-new))
620 (push `(let ,(reverse varsvalues-new) . 586 (push `(let ,(reverse binders-new) .
621 ,body-forms-new) body-new) 587 ,body-forms-new) body-new)
622 (setq body-new (reverse body-new))) 588 (setq body-new (reverse body-new)))
623 (setq body-new (append (reverse body-new) body-forms-new))) 589 (setq body-new (append (reverse body-new) body-forms-new)))
624 590
625 `(,sym ,func ,vars . ,body-new)) 591 `(,sym ,func ,vars . ,body-new)))
626 592
627 (error "Invalid form: defun inside a function")))
628 ;condition-case 593 ;condition-case
629 (`(condition-case ,var ,protected-form . ,conditions-bodies) 594 (`(condition-case ,var ,protected-form . ,handlers)
630 (let ((conditions-bodies-new '())) 595 (let ((handlers-new '())
596 (newform (cconv-closure-convert-rec
597 `(function (lambda () ,protected-form))
598 emvrs fvrs envs lmenvs)))
631 (setq fvrs (remq var fvrs)) 599 (setq fvrs (remq var fvrs))
632 (dolist (elm conditions-bodies) 600 (dolist (handler handlers)
633 (push (let ((elm-new '())) 601 (push (list (car handler)
634 (dolist (elm-2 (cdr elm)) 602 (cconv-closure-convert-rec
635 (push 603 `(function (lambda (,(or var cconv--dummy-var))
636 (cconv-closure-convert-rec 604 ,@(cdr handler)))
637 elm-2 emvrs fvrs envs lmenvs nil) 605 emvrs fvrs envs lmenvs))
638 elm-new)) 606 handlers-new))
639 (cons (car elm) (reverse elm-new))) 607 `(condition-case :fun-body ,newform
640 conditions-bodies-new)) 608 ,@(nreverse handlers-new))))
641 `(condition-case 609
642 ,var 610 (`(,(and head (or `catch `unwind-protect)) ,form . ,body)
643 ,(cconv-closure-convert-rec 611 `(,head ,(cconv-closure-convert-rec form emvrs fvrs envs lmenvs)
644 protected-form emvrs fvrs envs lmenvs nil) 612 :fun-body
645 . ,(reverse conditions-bodies-new)))) 613 ,(cconv-closure-convert-rec `(function (lambda () ,@body))
614 emvrs fvrs envs lmenvs)))
615
616 (`(,(and head (or `save-window-excursion `track-mouse)) . ,body)
617 `(,head
618 :fun-body
619 ,(cconv-closure-convert-rec `(function (lambda () ,@body))
620 emvrs fvrs envs lmenvs)))
646 621
647 (`(setq . ,forms) ; setq special form 622 (`(setq . ,forms) ; setq special form
648 (let (prognlist sym sym-new value) 623 (let (prognlist sym sym-new value)
@@ -650,10 +625,10 @@ Returns a form where all lambdas don't have any free variables."
650 (setq sym (car forms)) 625 (setq sym (car forms))
651 (setq sym-new (cconv-closure-convert-rec 626 (setq sym-new (cconv-closure-convert-rec
652 sym 627 sym
653 (remq sym emvrs) fvrs envs lmenvs nil)) 628 (remq sym emvrs) fvrs envs lmenvs))
654 (setq value 629 (setq value
655 (cconv-closure-convert-rec 630 (cconv-closure-convert-rec
656 (cadr forms) emvrs fvrs envs lmenvs nil)) 631 (cadr forms) emvrs fvrs envs lmenvs))
657 (if (memq sym emvrs) 632 (if (memq sym emvrs)
658 (push `(setcar ,sym-new ,value) prognlist) 633 (push `(setcar ,sym-new ,value) prognlist)
659 (if (symbolp sym-new) 634 (if (symbolp sym-new)
@@ -678,21 +653,21 @@ Returns a form where all lambdas don't have any free variables."
678 (dolist (fvr fv) 653 (dolist (fvr fv)
679 (push (cconv-closure-convert-rec 654 (push (cconv-closure-convert-rec
680 fvr (remq fvr emvrs) 655 fvr (remq fvr emvrs)
681 fvrs envs lmenvs nil) 656 fvrs envs lmenvs)
682 processed-fv)) 657 processed-fv))
683 (setq processed-fv (reverse processed-fv)) 658 (setq processed-fv (reverse processed-fv))
684 (dolist (elm args) 659 (dolist (elm args)
685 (push (cconv-closure-convert-rec 660 (push (cconv-closure-convert-rec
686 elm emvrs fvrs envs lmenvs nil) 661 elm emvrs fvrs envs lmenvs)
687 args-new)) 662 args-new))
688 (setq args-new (append processed-fv (reverse args-new))) 663 (setq args-new (append processed-fv (reverse args-new)))
689 (setq fun (cconv-closure-convert-rec 664 (setq fun (cconv-closure-convert-rec
690 fun emvrs fvrs envs lmenvs nil)) 665 fun emvrs fvrs envs lmenvs))
691 `(,callsym ,fun . ,args-new)) 666 `(,callsym ,fun . ,args-new))
692 (let ((cdr-new '())) 667 (let ((cdr-new '()))
693 (dolist (elm (cdr form)) 668 (dolist (elm (cdr form))
694 (push (cconv-closure-convert-rec 669 (push (cconv-closure-convert-rec
695 elm emvrs fvrs envs lmenvs nil) 670 elm emvrs fvrs envs lmenvs)
696 cdr-new)) 671 cdr-new))
697 `(,callsym . ,(reverse cdr-new)))))) 672 `(,callsym . ,(reverse cdr-new))))))
698 673
@@ -703,7 +678,7 @@ Returns a form where all lambdas don't have any free variables."
703 (let ((body-forms-new '())) 678 (let ((body-forms-new '()))
704 (dolist (elm body-forms) 679 (dolist (elm body-forms)
705 (push (cconv-closure-convert-rec 680 (push (cconv-closure-convert-rec
706 elm emvrs fvrs envs lmenvs defs-are-legal) 681 elm emvrs fvrs envs lmenvs)
707 body-forms-new)) 682 body-forms-new))
708 (setq body-forms-new (reverse body-forms-new)) 683 (setq body-forms-new (reverse body-forms-new))
709 `(,func . ,body-forms-new))) 684 `(,func . ,body-forms-new)))
diff --git a/lisp/mpc.el b/lisp/mpc.el
index 4f21a162c08..548fd17d038 100644
--- a/lisp/mpc.el
+++ b/lisp/mpc.el
@@ -1,5 +1,4 @@
1;;; -*- lexical-binding: t -*- 1;;; mpc.el --- A client for the Music Player Daemon -*- coding: utf-8; lexical-binding: t -*-
2;;; mpc.el --- A client for the Music Player Daemon -*- coding: utf-8 -*-
3 2
4;; Copyright (C) 2006-2011 Free Software Foundation, Inc. 3;; Copyright (C) 2006-2011 Free Software Foundation, Inc.
5 4