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.
This commit is contained in:
Stefan Monnier 2011-02-11 17:30:02 -05:00
parent 43e67019df
commit 295fb2ac59
7 changed files with 198 additions and 199 deletions

View file

@ -1,3 +1,23 @@
2011-02-11 Stefan Monnier <monnier@iro.umontreal.ca>
* 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.
* 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):
* emacs-lisp/byte-lexbind.el (byte-compile-maybe-push-heap-environment):
Make sure cconv did its job.
* emacs-lisp/byte-opt.el (byte-optimize-lapcode): Check stack-depth
before using it.
* dired.el (dired-desktop-buffer-misc-data): Don't use a dynamic var as
function argument.
2011-02-11 Stefan Monnier <monnier@iro.umontreal.ca>
* emacs-lisp/bytecomp.el (byte-compile-lambda): Fix `fun' that was not

View file

@ -1,5 +1,4 @@
;;; -*- lexical-binding: t -*-
;;; dired.el --- directory-browsing commands
;;; dired.el --- directory-browsing commands -*- lexical-binding: t -*-
;; Copyright (C) 1985-1986, 1992-1997, 2000-2011
;; 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."
(eval-when-compile (require 'desktop))
(defun dired-desktop-buffer-misc-data (desktop-dirname)
(defun dired-desktop-buffer-misc-data (dirname)
"Auxiliary information to be saved in desktop file."
(cons
;; Value of `dired-directory'.
(if (consp dired-directory)
;; Directory name followed by list of files.
(cons (desktop-file-name (car dired-directory) desktop-dirname)
(cons (desktop-file-name (car dired-directory) dirname)
(cdr dired-directory))
;; Directory name, optionally with shell wildcard.
(desktop-file-name dired-directory desktop-dirname))
(desktop-file-name dired-directory dirname))
;; Subdirectories in `dired-subdir-alist'.
(cdr
(nreverse
(mapcar
(function (lambda (f) (desktop-file-name (car f) desktop-dirname)))
(function (lambda (f) (desktop-file-name (car f) dirname)))
dired-subdir-alist)))))
(defun dired-restore-desktop-buffer (desktop-buffer-file-name

View file

@ -585,6 +585,7 @@ proper scope)."
(= nclosures byte-compile-current-num-closures))
;; No need to push a heap environment.
nil
(error "Should have been handled by cconv")
;; Have to push one. A heap environment is really just a vector, so
;; we emit bytecodes to create a vector. However, the size is not
;; fixed yet (the vector can grow if subforms use it to store

View file

@ -1863,7 +1863,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
;;
;; stack-ref-N --> dup ; where N is TOS
;;
((and (eq (car lap0) 'byte-stack-ref)
((and stack-depth (eq (car lap0) 'byte-stack-ref)
(= (cdr lap0) (1- stack-depth)))
(setcar lap0 'byte-dup)
(setcdr lap0 nil)
@ -2093,7 +2093,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
;; stack-set-M [discard/discardN ...] --> discardN-preserve-tos
;; stack-set-M [discard/discardN ...] --> discardN
;;
((and (eq (car lap0) 'byte-stack-set)
((and stack-depth ;Make sure we know the stack depth.
(eq (car lap0) 'byte-stack-set)
(memq (car lap1) '(byte-discard byte-discardN))
(progn
;; 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."
;; dup return --> return
;; stack-set-N return --> return ; where N is TOS-1
;;
((and (eq (car lap1) 'byte-return)
((and stack-depth ;Make sure we know the stack depth.
(eq (car lap1) 'byte-return)
(or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup))
(and (eq (car lap0) 'byte-stack-set)
(= (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."
;;
;; dup stack-set-N return --> return ; where N is TOS
;;
((and (eq (car lap0) 'byte-dup)
((and stack-depth ;Make sure we know the stack depth.
(eq (car lap0) 'byte-dup)
(eq (car lap1) 'byte-stack-set)
(eq (car (car (cdr (cdr rest)))) 'byte-return)
(= (cdr lap1) (1- stack-depth)))

View file

@ -134,7 +134,7 @@
;; `eval-when-compile' is defined in byte-run.el, so it must come after the
;; preceding load expression.
(provide 'bytecomp-preload)
(eval-when-compile (require 'byte-lexbind))
(eval-when-compile (require 'byte-lexbind nil 'noerror))
;; The feature of compiling in a specific target Emacs version
;; has been turned off because compile time options are a bad idea.
@ -2240,7 +2240,7 @@ list that represents a doc string reference.
bytecomp-handler)
(setq form (macroexpand-all form byte-compile-macro-environment))
(if lexical-binding
(setq form (cconv-closure-convert-toplevel form)))
(setq form (cconv-closure-convert form)))
(cond ((not (consp form))
(byte-compile-keep-pending form))
((and (symbolp (car form))
@ -2592,7 +2592,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(macroexpand-all fun
byte-compile-initial-macro-environment))
(if lexical-binding
(setq fun (cconv-closure-convert-toplevel fun)))
(setq fun (cconv-closure-convert fun)))
;; get rid of the `function' quote added by the `lambda' macro
(setq fun (cadr fun))
(setq fun (if macro
@ -2753,7 +2753,8 @@ If FORM is a lambda or a macro, byte-compile it as a function."
;; containing lexical environment are closed over).
(and lexical-binding
(byte-compile-closure-initial-lexenv-p
byte-compile-lexical-environment)))
byte-compile-lexical-environment)
(error "Should have been handled by cconv")))
(byte-compile-current-heap-environment nil)
(byte-compile-current-num-closures 0)
(compiled
@ -2791,6 +2792,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
(eq (car-safe code) 'closure))
(defun byte-compile-make-closure (code)
(error "Should have been handled by cconv")
;; A real closure requires that the constant be curried with an
;; environment vector to make a closure object.
(if for-effect

View file

@ -87,7 +87,9 @@ Each candidate has the form (VAR INCLOSURE BINDER PARENTFORM).")
(defun cconv-not-lexical-var-p (var)
(or (not (symbolp var)) ; form is not a list
(special-variable-p var)
(if (eval-when-compile (fboundp 'special-variable-p))
(special-variable-p var)
(boundp var))
;; byte-compile-bound-variables normally holds both the
;; dynamic and lexical vars, but the bytecomp.el should
;; only call us at the top-level so there shouldn't be
@ -192,14 +194,8 @@ Returns a list of free variables."
(cons form fvrs)))))
;;;###autoload
(defun cconv-closure-convert (form &optional toplevel)
;; cconv-closure-convert-rec has a lot of parameters that are
;; whether useless for user, whether they should contain
;; specific data like a list of closure mutables or the list
;; of lambdas suitable for lifting.
;;
;; That's why this function exists.
"Main entry point for non-toplevel forms.
(defun cconv-closure-convert (form)
"Main entry point for closure conversion.
-- FORM is a piece of Elisp code after macroexpansion.
-- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST
@ -221,19 +217,21 @@ Returns a form where all lambdas don't have any free variables."
'() ; fvrs initially empty
'() ; envs initially empty
'()
toplevel))) ; true if the tree is a toplevel form
)))
;;;###autoload
(defun cconv-closure-convert-toplevel (form)
"Entry point for toplevel forms.
-- FORM is a piece of Elisp code after macroexpansion.
(defun cconv-lookup-let (table var binder form)
(let ((res nil))
(dolist (elem table)
(when (and (eq (nth 2 elem) binder)
(eq (nth 3 elem) form))
(assert (eq (car elem) var))
(setq res elem)))
res))
Returns a form where all lambdas don't have any free variables."
;; we distinguish toplevel forms to treat def(un|var|const) correctly.
(cconv-closure-convert form t))
(defconst cconv--dummy-var (make-symbol "ignored"))
(defun cconv-closure-convert-rec
(form emvrs fvrs envs lmenvs defs-are-legal)
(form emvrs fvrs envs lmenvs)
;; This function actually rewrites the tree.
"Eliminates all free variables of all lambdas in given forms.
Arguments:
@ -245,8 +243,6 @@ within current environment.
Initially empty.
-- FVRS is a list of variables to substitute in each context.
Initially empty.
-- DEFS-ARE-LEGAL is a boolean variable, true if def(un|var|const)
can be used in this form(e.g. toplevel form)
Returns a form where all lambdas don't have any free variables."
;; What's the difference between fvrs and envs?
@ -261,11 +257,11 @@ Returns a form where all lambdas don't have any free variables."
;; so we never touch it(unless we enter to the other closure).
;;(if (listp form) (print (car form)) form)
(pcase form
(`(,(and letsym (or `let* `let)) ,varsvalues . ,body-forms)
(`(,(and letsym (or `let* `let)) ,binders . ,body-forms)
; let and let* special forms
(let ((body-forms-new '())
(varsvalues-new '())
(binders-new '())
;; next for variables needed for delayed push
;; because we should process <value(s)>
;; before we change any arguments
@ -274,83 +270,58 @@ Returns a form where all lambdas don't have any free variables."
(emvr-push) ;needed only in case of let*
(lmenv-push)) ;needed only in case of let*
(dolist (elm varsvalues) ;begin of dolist over varsvalues
(let (var value elm-new iscandidate ismutated)
(if (consp elm) ; (let (v1) ...) => (let ((v1 nil)) ...)
(progn
(setq var (car elm))
(setq value (cadr elm)))
(setq var elm))
(dolist (binder binders)
(let* ((value nil)
(var (if (not (consp binder))
binder
(setq value (cadr binder))
(car binder)))
(new-val
(cond
;; Check if var is a candidate for lambda lifting.
((cconv-lookup-let cconv-lambda-candidates var binder form)
;; Check if var is a candidate for lambda lifting
(let ((lcandid cconv-lambda-candidates))
(while (and lcandid (not iscandidate))
(when (and (eq (caar lcandid) var)
(eq (caddar lcandid) elm)
(eq (cadr (cddar lcandid)) form))
(setq iscandidate t))
(setq lcandid (cdr lcandid))))
; declared variable is a candidate
; for lambda lifting
(if iscandidate
(let* ((func (cadr elm)) ; function(lambda) itself
; free variables
(fv (delete-dups (cconv-freevars func '())))
(funcvars (append fv (cadadr func))) ;function args
(funcbodies (cddadr func)) ; function bodies
(funcbodies-new '()))
(let* ((fv (delete-dups (cconv-freevars value '())))
(funargs (cadr (cadr value)))
(funcvars (append fv funargs))
(funcbodies (cddadr value)) ; function bodies
(funcbodies-new '()))
; lambda lifting condition
(if (or (not fv) (< cconv-liftwhen (length funcvars)))
(if (or (not fv) (< cconv-liftwhen (length funcvars)))
; do not lift
(setq
elm-new
`(,var
,(cconv-closure-convert-rec
func emvrs fvrs envs lmenvs nil)))
(cconv-closure-convert-rec
value emvrs fvrs envs lmenvs)
; lift
(progn
(dolist (elm2 funcbodies)
(push ; convert function bodies
(cconv-closure-convert-rec
elm2 emvrs nil envs lmenvs nil)
funcbodies-new))
(if (eq letsym 'let*)
(setq lmenv-push (cons var fv))
(push (cons var fv) lmenvs-new))
(progn
(dolist (elm2 funcbodies)
(push ; convert function bodies
(cconv-closure-convert-rec
elm2 emvrs nil envs lmenvs)
funcbodies-new))
(if (eq letsym 'let*)
(setq lmenv-push (cons var fv))
(push (cons var fv) lmenvs-new))
; push lifted function
(setq elm-new
`(,var
(function .
((lambda ,funcvars .
,(reverse funcbodies-new)))))))))
`(function .
((lambda ,funcvars .
,(reverse funcbodies-new))))))))
;declared variable is not a function
(progn
;; Check if var is mutated
(let ((lmutated cconv-captured+mutated))
(while (and lmutated (not ismutated))
(when (and (eq (caar lmutated) var)
(eq (caddar lmutated) elm)
(eq (cadr (cddar lmutated)) form))
(setq ismutated t))
(setq lmutated (cdr lmutated))))
(if ismutated
(progn ; declared variable is mutated
(setq elm-new
`(,var (list ,(cconv-closure-convert-rec
value emvrs
fvrs envs lmenvs nil))))
;; Check if it needs to be turned into a "ref-cell".
((cconv-lookup-let cconv-captured+mutated var binder form)
;; Declared variable is mutated and captured.
(prog1
`(list ,(cconv-closure-convert-rec
value emvrs
fvrs envs lmenvs))
(if (eq letsym 'let*)
(setq emvr-push var)
(push var emvrs-new)))
(progn
(setq
elm-new
`(,var ; else
,(cconv-closure-convert-rec
value emvrs fvrs envs lmenvs nil)))))))
(push var emvrs-new))))
;; Normal default case.
(t
(cconv-closure-convert-rec
value emvrs fvrs envs lmenvs)))))
;; this piece of code below letbinds free
;; variables of a lambda lifted function
@ -384,12 +355,12 @@ Returns a form where all lambdas don't have any free variables."
(when new-lmenv
(setq lmenvs (remq old-lmenv lmenvs))
(push new-lmenv lmenvs)
(push `(,closedsym ,var) varsvalues-new))))
(push `(,closedsym ,var) binders-new))))
;; we push the element after redefined free variables
;; are processes. this is important to avoid the bug
;; when free variable and the function have the same
;; name
(push elm-new varsvalues-new)
(push (list var new-val) binders-new)
(when (eq letsym 'let*) ; update fvrs
(setq fvrs (remq var fvrs))
@ -405,23 +376,23 @@ Returns a form where all lambdas don't have any free variables."
(when lmenv-push
(push lmenv-push lmenvs)
(setq lmenv-push nil)))
)) ; end of dolist over varsvalues
)) ; end of dolist over binders
(when (eq letsym 'let)
(let (var fvrs-1 emvrs-1 lmenvs-1)
;; Here we update emvrs, fvrs and lmenvs lists
(dolist (vr fvrs)
; safely remove
(when (not (assq vr varsvalues-new)) (push vr fvrs-1)))
(when (not (assq vr binders-new)) (push vr fvrs-1)))
(setq fvrs fvrs-1)
(dolist (vr emvrs)
; safely remove
(when (not (assq vr varsvalues-new)) (push vr emvrs-1)))
(when (not (assq vr binders-new)) (push vr emvrs-1)))
(setq emvrs emvrs-1)
; push new
(setq emvrs (append emvrs emvrs-new))
(dolist (vr lmenvs)
(when (not (assq (car vr) varsvalues-new))
(when (not (assq (car vr) binders-new))
(push vr lmenvs-1)))
(setq lmenvs (append lmenvs lmenvs-new)))
@ -432,10 +403,9 @@ Returns a form where all lambdas don't have any free variables."
(let ((new-lmenv)
(var nil)
(closedsym nil)
(letbinds '())
(fvrs-new)) ; list of (closed-var var)
(dolist (elm varsvalues)
(setq var (if (consp elm) (car elm) elm))
(letbinds '()))
(dolist (binder binders)
(setq var (if (consp binder) (car binder) binder))
(let ((lmenvs-1 lmenvs)) ; just to avoid manipulating
(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."
(push new-lmenv lmenvs)
(push `(,closedsym ,var) letbinds)
))))
(setq varsvalues-new (append varsvalues-new letbinds))))
(setq binders-new (append binders-new letbinds))))
(dolist (elm body-forms) ; convert body forms
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs nil)
elm emvrs fvrs envs lmenvs)
body-forms-new))
`(,letsym ,(reverse varsvalues-new) . ,(reverse body-forms-new))))
`(,letsym ,(reverse binders-new) . ,(reverse body-forms-new))))
;end of let let* forms
; first element is lambda expression
@ -468,13 +438,12 @@ Returns a form where all lambdas don't have any free variables."
(let ((other-body-forms-new '()))
(dolist (elm other-body-forms)
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs nil)
elm emvrs fvrs envs lmenvs)
other-body-forms-new))
(cons
(cadr
(cconv-closure-convert-rec
(list 'function fun) emvrs fvrs envs lmenvs nil))
(reverse other-body-forms-new))))
`(funcall
,(cconv-closure-convert-rec
(list 'function fun) emvrs fvrs envs lmenvs)
,@(nreverse other-body-forms-new))))
(`(cond . ,cond-forms) ; cond special form
(let ((cond-forms-new '()))
@ -483,7 +452,7 @@ Returns a form where all lambdas don't have any free variables."
(dolist (elm-2 elm)
(push
(cconv-closure-convert-rec
elm-2 emvrs fvrs envs lmenvs nil)
elm-2 emvrs fvrs envs lmenvs)
elm-new))
(reverse elm-new))
cond-forms-new))
@ -523,7 +492,7 @@ Returns a form where all lambdas don't have any free variables."
(dolist (elm fv)
(push
(cconv-closure-convert-rec
elm (remq elm emvrs) fvrs envs lmenvs nil)
elm (remq elm emvrs) fvrs envs lmenvs)
envector)) ; process vars for closure vector
(setq envector (reverse envector))
(setq envs fv))
@ -539,7 +508,7 @@ Returns a form where all lambdas don't have any free variables."
(push `(,mv (list ,mv)) letbind))))
(dolist (elm body-forms) ; convert function body
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs nil)
elm emvrs fvrs envs lmenvs)
body-forms-new))
(setq body-forms-new
@ -566,83 +535,89 @@ Returns a form where all lambdas don't have any free variables."
;defconst, defvar
(`(,(and sym (or `defconst `defvar)) ,definedsymbol . ,body-forms)
(if defs-are-legal
(let ((body-forms-new '()))
(dolist (elm body-forms)
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs nil)
body-forms-new))
(setq body-forms-new (reverse body-forms-new))
`(,sym ,definedsymbol . ,body-forms-new))
(error "Invalid form: %s inside a function" sym)))
(let ((body-forms-new '()))
(dolist (elm body-forms)
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs)
body-forms-new))
(setq body-forms-new (reverse body-forms-new))
`(,sym ,definedsymbol . ,body-forms-new)))
;defun, defmacro
(`(,(and sym (or `defun `defmacro))
,func ,vars . ,body-forms)
(if defs-are-legal
(let ((body-new '()) ; the whole body
(body-forms-new '()) ; body w\o docstring and interactive
(letbind '()))
(let ((body-new '()) ; the whole body
(body-forms-new '()) ; body w\o docstring and interactive
(letbind '()))
; find mutable arguments
(let ((lmutated cconv-captured+mutated) ismutated)
(dolist (elm vars)
(setq ismutated nil)
(while (and lmutated (not ismutated))
(when (and (eq (caar lmutated) elm)
(eq (cadar lmutated) form))
(setq ismutated t))
(setq lmutated (cdr lmutated)))
(when ismutated
(push elm letbind)
(push elm emvrs))))
(let ((lmutated cconv-captured+mutated) ismutated)
(dolist (elm vars)
(setq ismutated nil)
(while (and lmutated (not ismutated))
(when (and (eq (caar lmutated) elm)
(eq (cadar lmutated) form))
(setq ismutated t))
(setq lmutated (cdr lmutated)))
(when ismutated
(push elm letbind)
(push elm emvrs))))
;transform body-forms
(when (stringp (car body-forms)) ; treat docstring well
(push (car body-forms) body-new)
(setq body-forms (cdr body-forms)))
(when (eq (car-safe (car body-forms)) 'interactive)
(push
(cconv-closure-convert-rec
(car body-forms)
emvrs fvrs envs lmenvs nil) body-new)
(setq body-forms (cdr body-forms)))
(when (stringp (car body-forms)) ; treat docstring well
(push (car body-forms) body-new)
(setq body-forms (cdr body-forms)))
(when (eq (car-safe (car body-forms)) 'interactive)
(push (cconv-closure-convert-rec
(car body-forms)
emvrs fvrs envs lmenvs)
body-new)
(setq body-forms (cdr body-forms)))
(dolist (elm body-forms)
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs nil)
body-forms-new))
(setq body-forms-new (reverse body-forms-new))
(dolist (elm body-forms)
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs)
body-forms-new))
(setq body-forms-new (reverse body-forms-new))
(if letbind
(if letbind
; letbind mutable arguments
(let ((varsvalues-new '()))
(dolist (elm letbind) (push `(,elm (list ,elm))
varsvalues-new))
(push `(let ,(reverse varsvalues-new) .
,body-forms-new) body-new)
(setq body-new (reverse body-new)))
(setq body-new (append (reverse body-new) body-forms-new)))
(let ((binders-new '()))
(dolist (elm letbind) (push `(,elm (list ,elm))
binders-new))
(push `(let ,(reverse binders-new) .
,body-forms-new) body-new)
(setq body-new (reverse body-new)))
(setq body-new (append (reverse body-new) body-forms-new)))
`(,sym ,func ,vars . ,body-new))
`(,sym ,func ,vars . ,body-new)))
(error "Invalid form: defun inside a function")))
;condition-case
(`(condition-case ,var ,protected-form . ,conditions-bodies)
(let ((conditions-bodies-new '()))
(`(condition-case ,var ,protected-form . ,handlers)
(let ((handlers-new '())
(newform (cconv-closure-convert-rec
`(function (lambda () ,protected-form))
emvrs fvrs envs lmenvs)))
(setq fvrs (remq var fvrs))
(dolist (elm conditions-bodies)
(push (let ((elm-new '()))
(dolist (elm-2 (cdr elm))
(push
(cconv-closure-convert-rec
elm-2 emvrs fvrs envs lmenvs nil)
elm-new))
(cons (car elm) (reverse elm-new)))
conditions-bodies-new))
`(condition-case
,var
,(cconv-closure-convert-rec
protected-form emvrs fvrs envs lmenvs nil)
. ,(reverse conditions-bodies-new))))
(dolist (handler handlers)
(push (list (car handler)
(cconv-closure-convert-rec
`(function (lambda (,(or var cconv--dummy-var))
,@(cdr handler)))
emvrs fvrs envs lmenvs))
handlers-new))
`(condition-case :fun-body ,newform
,@(nreverse handlers-new))))
(`(,(and head (or `catch `unwind-protect)) ,form . ,body)
`(,head ,(cconv-closure-convert-rec form emvrs fvrs envs lmenvs)
:fun-body
,(cconv-closure-convert-rec `(function (lambda () ,@body))
emvrs fvrs envs lmenvs)))
(`(,(and head (or `save-window-excursion `track-mouse)) . ,body)
`(,head
:fun-body
,(cconv-closure-convert-rec `(function (lambda () ,@body))
emvrs fvrs envs lmenvs)))
(`(setq . ,forms) ; setq special form
(let (prognlist sym sym-new value)
@ -650,10 +625,10 @@ Returns a form where all lambdas don't have any free variables."
(setq sym (car forms))
(setq sym-new (cconv-closure-convert-rec
sym
(remq sym emvrs) fvrs envs lmenvs nil))
(remq sym emvrs) fvrs envs lmenvs))
(setq value
(cconv-closure-convert-rec
(cadr forms) emvrs fvrs envs lmenvs nil))
(cadr forms) emvrs fvrs envs lmenvs))
(if (memq sym emvrs)
(push `(setcar ,sym-new ,value) prognlist)
(if (symbolp sym-new)
@ -678,21 +653,21 @@ Returns a form where all lambdas don't have any free variables."
(dolist (fvr fv)
(push (cconv-closure-convert-rec
fvr (remq fvr emvrs)
fvrs envs lmenvs nil)
fvrs envs lmenvs)
processed-fv))
(setq processed-fv (reverse processed-fv))
(dolist (elm args)
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs nil)
elm emvrs fvrs envs lmenvs)
args-new))
(setq args-new (append processed-fv (reverse args-new)))
(setq fun (cconv-closure-convert-rec
fun emvrs fvrs envs lmenvs nil))
fun emvrs fvrs envs lmenvs))
`(,callsym ,fun . ,args-new))
(let ((cdr-new '()))
(dolist (elm (cdr form))
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs nil)
elm emvrs fvrs envs lmenvs)
cdr-new))
`(,callsym . ,(reverse cdr-new))))))
@ -703,7 +678,7 @@ Returns a form where all lambdas don't have any free variables."
(let ((body-forms-new '()))
(dolist (elm body-forms)
(push (cconv-closure-convert-rec
elm emvrs fvrs envs lmenvs defs-are-legal)
elm emvrs fvrs envs lmenvs)
body-forms-new))
(setq body-forms-new (reverse body-forms-new))
`(,func . ,body-forms-new)))

View file

@ -1,5 +1,4 @@
;;; -*- lexical-binding: t -*-
;;; mpc.el --- A client for the Music Player Daemon -*- coding: utf-8 -*-
;;; mpc.el --- A client for the Music Player Daemon -*- coding: utf-8; lexical-binding: t -*-
;; Copyright (C) 2006-2011 Free Software Foundation, Inc.