aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2011-02-11 14:48:54 -0500
committerStefan Monnier2011-02-11 14:48:54 -0500
commit43e67019dfc4fb7d3474e0fbedcfec60f2300521 (patch)
treecf67296a599964c895e443024fe4544bcd54f428
parentd779e73c22ae9fedcf6edc6ec286f19cf2e3d89a (diff)
downloademacs-43e67019dfc4fb7d3474e0fbedcfec60f2300521.tar.gz
emacs-43e67019dfc4fb7d3474e0fbedcfec60f2300521.zip
Make cconv-analyse understand the need for closures.
* lisp/emacs-lisp/byte-lexbind.el (byte-compile-lforminfo-analyze): Understand the :fun-body case for catch, save-window-excursion, and condition-case. (byte-compile-maybe-push-heap-environment): No need when nclosures is zero and byte-compile-current-num-closures is -1. * lisp/emacs-lisp/bytecomp.el (byte-compile-lambda): Fix `fun' that was not renamed to `bytecomp-fun'. * lisp/emacs-lisp/cconv.el (cconv-not-lexical-var-p): New function. (cconv-freevars): Use it. (cconv-closure-convert-rec): Avoid `position'. (cconv-analyse-function): New function. (cconv-analyse-form): Use it. `inclosure' can't be nil any more. Check lexical vars at let-binding time rather than when referenced. For defuns to be in an empty environment and lambdas to take lexical args. Pay attention to the need to build closures in catch, unwind-protect, save-window-excursion, condition-case, and track-mouse. Fix defconst/defvar handling.
-rw-r--r--lisp/ChangeLog22
-rw-r--r--lisp/emacs-lisp/byte-lexbind.el18
-rw-r--r--lisp/emacs-lisp/bytecomp.el4
-rw-r--r--lisp/emacs-lisp/cconv.el362
-rw-r--r--lisp/emacs-lisp/macroexp.el13
5 files changed, 214 insertions, 205 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7c920b2eadc..6a47a2626a5 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,25 @@
12011-02-11 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * emacs-lisp/bytecomp.el (byte-compile-lambda): Fix `fun' that was not
4 renamed to `bytecomp-fun'.
5
6 * emacs-lisp/byte-lexbind.el (byte-compile-lforminfo-analyze):
7 Understand the :fun-body case for catch, save-window-excursion, and
8 condition-case.
9 (byte-compile-maybe-push-heap-environment): No need when nclosures is
10 zero and byte-compile-current-num-closures is -1.
11
12 * emacs-lisp/cconv.el (cconv-not-lexical-var-p): New function.
13 (cconv-freevars): Use it.
14 (cconv-closure-convert-rec): Avoid `position'.
15 (cconv-analyse-function): New function.
16 (cconv-analyse-form): Use it. `inclosure' can't be nil any more.
17 Check lexical vars at let-binding time rather than when referenced.
18 For defuns to be in an empty environment and lambdas to take lexical args.
19 Pay attention to the need to build closures in catch, unwind-protect,
20 save-window-excursion, condition-case, and track-mouse.
21 Fix defconst/defvar handling.
22
12011-02-10 Stefan Monnier <monnier@iro.umontreal.ca> 232011-02-10 Stefan Monnier <monnier@iro.umontreal.ca>
2 24
3 * emacs-lisp/cconv.el (cconv-mutated, cconv-captured) 25 * emacs-lisp/cconv.el (cconv-mutated, cconv-captured)
diff --git a/lisp/emacs-lisp/byte-lexbind.el b/lisp/emacs-lisp/byte-lexbind.el
index df463c17549..313c4b6ad0f 100644
--- a/lisp/emacs-lisp/byte-lexbind.el
+++ b/lisp/emacs-lisp/byte-lexbind.el
@@ -1,6 +1,6 @@
1;;; byte-lexbind.el --- Lexical binding support for byte-compiler 1;;; byte-lexbind.el --- Lexical binding support for byte-compiler
2;; 2;;
3;; Copyright (C) 2001, 2002, 2010 Free Software Foundation, Inc. 3;; Copyright (C) 2001, 2002, 2010, 2011 Free Software Foundation, Inc.
4;; 4;;
5;; Author: Miles Bader <miles@gnu.org> 5;; Author: Miles Bader <miles@gnu.org>
6;; Keywords: lisp, compiler, lexical binding 6;; Keywords: lisp, compiler, lexical binding
@@ -202,24 +202,25 @@ LFORMINFO."
202 (byte-compile-lvarinfo-note-set vinfo) 202 (byte-compile-lvarinfo-note-set vinfo)
203 (byte-compile-lforminfo-note-closure lforminfo vinfo 203 (byte-compile-lforminfo-note-closure lforminfo vinfo
204 closure-flag))))))) 204 closure-flag)))))))
205 ((eq fun 'catch) 205 ((and (eq fun 'catch) (not (eq :fun-body (nth 2 form))))
206 ;; tag 206 ;; tag
207 (byte-compile-lforminfo-analyze lforminfo (cadr form) 207 (byte-compile-lforminfo-analyze lforminfo (cadr form)
208 ignore closure-flag) 208 ignore closure-flag)
209 ;; `catch' uses a closure for the body 209 ;; `catch' uses a closure for the body
210 (byte-compile-lforminfo-analyze-forms 210 (byte-compile-lforminfo-analyze-forms
211 lforminfo form 2 211 lforminfo form 2
212 ignore 212 ignore
213 (or closure-flag 213 (or closure-flag
214 (and (not byte-compile-use-downward-closures) 214 (and (not byte-compile-use-downward-closures)
215 (byte-compile-lforminfo-make-closure-flag))))) 215 (byte-compile-lforminfo-make-closure-flag)))))
216 ((eq fun 'cond) 216 ((eq fun 'cond)
217 (byte-compile-lforminfo-analyze-clauses lforminfo (cdr form) 0 217 (byte-compile-lforminfo-analyze-clauses lforminfo (cdr form) 0
218 ignore closure-flag)) 218 ignore closure-flag))
219 ((eq fun 'condition-case) 219 ((eq fun 'condition-case)
220 ;; `condition-case' separates its body/handlers into 220 ;; `condition-case' separates its body/handlers into
221 ;; separate closures. 221 ;; separate closures.
222 (unless (or closure-flag byte-compile-use-downward-closures) 222 (unless (or (eq (nth 1 form) :fun-body)
223 closure-flag byte-compile-use-downward-closures)
223 ;; condition case is implemented by calling a function 224 ;; condition case is implemented by calling a function
224 (setq closure-flag (byte-compile-lforminfo-make-closure-flag))) 225 (setq closure-flag (byte-compile-lforminfo-make-closure-flag)))
225 ;; value form 226 ;; value form
@@ -281,7 +282,8 @@ LFORMINFO."
281 ((eq fun 'quote) 282 ((eq fun 'quote)
282 ;; do nothing 283 ;; do nothing
283 ) 284 )
284 ((eq fun 'save-window-excursion) 285 ((and (eq fun 'save-window-excursion)
286 (not (eq :fun-body (nth 1 form))))
285 ;; `save-window-excursion' currently uses a funny implementation 287 ;; `save-window-excursion' currently uses a funny implementation
286 ;; that requires its body forms be put into a closure (it should 288 ;; that requires its body forms be put into a closure (it should
287 ;; be fixed to work more like `save-excursion' etc., do). 289 ;; be fixed to work more like `save-excursion' etc., do).
@@ -579,6 +581,7 @@ proper scope)."
579 (let ((nclosures 581 (let ((nclosures
580 (and lforminfo (byte-compile-lforminfo-num-closures lforminfo)))) 582 (and lforminfo (byte-compile-lforminfo-num-closures lforminfo))))
581 (if (or (null lforminfo) 583 (if (or (null lforminfo)
584 (zerop nclosures)
582 (= nclosures byte-compile-current-num-closures)) 585 (= nclosures byte-compile-current-num-closures))
583 ;; No need to push a heap environment. 586 ;; No need to push a heap environment.
584 nil 587 nil
@@ -692,5 +695,4 @@ binding slots have been popped."
692 695
693(provide 'byte-lexbind) 696(provide 'byte-lexbind)
694 697
695;;; arch-tag: b8f1dff6-9edb-4430-a96f-323d42a681a9
696;;; byte-lexbind.el ends here 698;;; byte-lexbind.el ends here
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index e14ecc608c7..f37d7489e9a 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2745,7 +2745,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
2745 ;; containing the args and any closed-over variables. 2745 ;; containing the args and any closed-over variables.
2746 (and lexical-binding 2746 (and lexical-binding
2747 (byte-compile-make-lambda-lexenv 2747 (byte-compile-make-lambda-lexenv
2748 fun 2748 bytecomp-fun
2749 byte-compile-lexical-environment))) 2749 byte-compile-lexical-environment)))
2750 (is-closure 2750 (is-closure
2751 ;; This is true if we should be making a closure instead of 2751 ;; This is true if we should be making a closure instead of
@@ -2804,7 +2804,7 @@ If FORM is a lambda or a macro, byte-compile it as a function."
2804 (let ((code (byte-compile-lambda form add-lambda))) 2804 (let ((code (byte-compile-lambda form add-lambda)))
2805 (if (byte-compile-closure-code-p code) 2805 (if (byte-compile-closure-code-p code)
2806 (byte-compile-make-closure code) 2806 (byte-compile-make-closure code)
2807 ;; A simple lambda is just a constant 2807 ;; A simple lambda is just a constant.
2808 (byte-compile-constant code)))) 2808 (byte-compile-constant code))))
2809 2809
2810(defun byte-compile-constants-vector () 2810(defun byte-compile-constants-vector ()
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el
index 60bc906b60c..af42a2864c9 100644
--- a/lisp/emacs-lisp/cconv.el
+++ b/lisp/emacs-lisp/cconv.el
@@ -1,4 +1,4 @@
1;;; cconv.el --- Closure conversion for statically scoped Emacs lisp. -*- lexical-binding: t -*- 1;;; cconv.el --- Closure conversion for statically scoped Emacs lisp. -*- lexical-binding: nil -*-
2 2
3;; Copyright (C) 2011 Free Software Foundation, Inc. 3;; Copyright (C) 2011 Free Software Foundation, Inc.
4 4
@@ -82,8 +82,19 @@ is less than this number.")
82(defvar cconv-captured+mutated nil 82(defvar cconv-captured+mutated nil
83 "An intersection between cconv-mutated and cconv-captured lists.") 83 "An intersection between cconv-mutated and cconv-captured lists.")
84(defvar cconv-lambda-candidates nil 84(defvar cconv-lambda-candidates nil
85 "List of candidates for lambda lifting") 85 "List of candidates for lambda lifting.
86 86Each candidate has the form (VAR INCLOSURE BINDER PARENTFORM).")
87
88(defun cconv-not-lexical-var-p (var)
89 (or (not (symbolp var)) ; form is not a list
90 (special-variable-p var)
91 ;; byte-compile-bound-variables normally holds both the
92 ;; dynamic and lexical vars, but the bytecomp.el should
93 ;; only call us at the top-level so there shouldn't be
94 ;; any lexical vars in it here.
95 (memq var byte-compile-bound-variables)
96 (memq var '(nil t))
97 (keywordp var)))
87 98
88(defun cconv-freevars (form &optional fvrs) 99(defun cconv-freevars (form &optional fvrs)
89 "Find all free variables of given form. 100 "Find all free variables of given form.
@@ -166,24 +177,17 @@ Returns a list of free variables."
166 (append fvrs fvrs-1))) 177 (append fvrs fvrs-1)))
167 178
168 (`(,(and sym (or `defun `defconst `defvar)) . ,_) 179 (`(,(and sym (or `defun `defconst `defvar)) . ,_)
169 ;; we call cconv-freevars only for functions(lambdas) 180 ;; We call cconv-freevars only for functions(lambdas)
170 ;; defun, defconst, defvar are not allowed to be inside 181 ;; defun, defconst, defvar are not allowed to be inside
171 ;; a function(lambda) 182 ;; a function (lambda).
183 ;; FIXME: should be a byte-compile-report-error!
172 (error "Invalid form: %s inside a function" sym)) 184 (error "Invalid form: %s inside a function" sym))
173 185
174 (`(,_ . ,body-forms) ; first element is a function or whatever 186 (`(,_ . ,body-forms) ; First element is (like) a function.
175 (dolist (exp body-forms) 187 (dolist (exp body-forms)
176 (setq fvrs (cconv-freevars exp fvrs))) fvrs) 188 (setq fvrs (cconv-freevars exp fvrs))) fvrs)
177 189
178 (_ (if (or (not (symbolp form)) ; form is not a list 190 (_ (if (cconv-not-lexical-var-p form)
179 (special-variable-p form)
180 ;; byte-compile-bound-variables normally holds both the
181 ;; dynamic and lexical vars, but the bytecomp.el should
182 ;; only call us at the top-level so there shouldn't be
183 ;; any lexical vars in it here.
184 (memq form byte-compile-bound-variables)
185 (memq form '(nil t))
186 (keywordp form))
187 fvrs 191 fvrs
188 (cons form fvrs))))) 192 (cons form fvrs)))))
189 193
@@ -200,12 +204,13 @@ Returns a list of free variables."
200-- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST 204-- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST
201 205
202Returns a form where all lambdas don't have any free variables." 206Returns a form where all lambdas don't have any free variables."
207 (message "Entering cconv-closure-convert...")
203 (let ((cconv-mutated '()) 208 (let ((cconv-mutated '())
204 (cconv-lambda-candidates '()) 209 (cconv-lambda-candidates '())
205 (cconv-captured '()) 210 (cconv-captured '())
206 (cconv-captured+mutated '())) 211 (cconv-captured+mutated '()))
207 ;; Analyse form - fill these variables with new information 212 ;; Analyse form - fill these variables with new information
208 (cconv-analyse-form form '() nil) 213 (cconv-analyse-form form '() 0)
209 ;; Calculate an intersection of cconv-mutated and cconv-captured 214 ;; Calculate an intersection of cconv-mutated and cconv-captured
210 (dolist (mvr cconv-mutated) 215 (dolist (mvr cconv-mutated)
211 (when (memq mvr cconv-captured) ; 216 (when (memq mvr cconv-captured) ;
@@ -271,7 +276,7 @@ Returns a form where all lambdas don't have any free variables."
271 276
272 (dolist (elm varsvalues) ;begin of dolist over varsvalues 277 (dolist (elm varsvalues) ;begin of dolist over varsvalues
273 (let (var value elm-new iscandidate ismutated) 278 (let (var value elm-new iscandidate ismutated)
274 (if (listp elm) ; (let (v1) ...) => (let ((v1 nil)) ...) 279 (if (consp elm) ; (let (v1) ...) => (let ((v1 nil)) ...)
275 (progn 280 (progn
276 (setq var (car elm)) 281 (setq var (car elm))
277 (setq value (cadr elm))) 282 (setq value (cadr elm)))
@@ -430,9 +435,7 @@ Returns a form where all lambdas don't have any free variables."
430 (letbinds '()) 435 (letbinds '())
431 (fvrs-new)) ; list of (closed-var var) 436 (fvrs-new)) ; list of (closed-var var)
432 (dolist (elm varsvalues) 437 (dolist (elm varsvalues)
433 (if (listp elm) 438 (setq var (if (consp elm) (car elm) elm))
434 (setq var (car elm))
435 (setq var elm))
436 439
437 (let ((lmenvs-1 lmenvs)) ; just to avoid manipulating 440 (let ((lmenvs-1 lmenvs)) ; just to avoid manipulating
438 (dolist (lmenv lmenvs-1) ; the counter inside the loop 441 (dolist (lmenv lmenvs-1) ; the counter inside the loop
@@ -490,7 +493,7 @@ Returns a form where all lambdas don't have any free variables."
490 (`(quote . ,_) form) ; quote form 493 (`(quote . ,_) form) ; quote form
491 494
492 (`(function . ((lambda ,vars . ,body-forms))) ; function form 495 (`(function . ((lambda ,vars . ,body-forms))) ; function form
493 (let (fvrs-new) ; we remove vars from fvrs 496 (let (fvrs-new) ; we remove vars from fvrs
494 (dolist (elm fvrs) ;i use such a tricky way to avoid side effects 497 (dolist (elm fvrs) ;i use such a tricky way to avoid side effects
495 (when (not (memq elm vars)) 498 (when (not (memq elm vars))
496 (push elm fvrs-new))) 499 (push elm fvrs-new)))
@@ -577,7 +580,7 @@ Returns a form where all lambdas don't have any free variables."
577 (`(,(and sym (or `defun `defmacro)) 580 (`(,(and sym (or `defun `defmacro))
578 ,func ,vars . ,body-forms) 581 ,func ,vars . ,body-forms)
579 (if defs-are-legal 582 (if defs-are-legal
580 (let ((body-new '()) ; the whole body 583 (let ((body-new '()) ; the whole body
581 (body-forms-new '()) ; body w\o docstring and interactive 584 (body-forms-new '()) ; body w\o docstring and interactive
582 (letbind '())) 585 (letbind '()))
583 ; find mutable arguments 586 ; find mutable arguments
@@ -592,12 +595,11 @@ Returns a form where all lambdas don't have any free variables."
592 (when ismutated 595 (when ismutated
593 (push elm letbind) 596 (push elm letbind)
594 (push elm emvrs)))) 597 (push elm emvrs))))
595 ;transform body-forms 598 ;transform body-forms
596 (when (stringp (car body-forms)) ; treat docstring well 599 (when (stringp (car body-forms)) ; treat docstring well
597 (push (car body-forms) body-new) 600 (push (car body-forms) body-new)
598 (setq body-forms (cdr body-forms))) 601 (setq body-forms (cdr body-forms)))
599 (when (and (listp (car body-forms)) ; treat (interactive) well 602 (when (eq (car-safe (car body-forms)) 'interactive)
600 (eq (caar body-forms) 'interactive))
601 (push 603 (push
602 (cconv-closure-convert-rec 604 (cconv-closure-convert-rec
603 (car body-forms) 605 (car body-forms)
@@ -707,201 +709,171 @@ Returns a form where all lambdas don't have any free variables."
707 `(,func . ,body-forms-new))) 709 `(,func . ,body-forms-new)))
708 710
709 (_ 711 (_
710 (if (memq form fvrs) ;form is a free variable 712 (let ((free (memq form fvrs)))
711 (let* ((numero (position form envs)) 713 (if free ;form is a free variable
712 (var '())) 714 (let* ((numero (- (length fvrs) (length free)))
713 (assert numero) 715 (var '()))
714 (if (null (cdr envs)) 716 (assert numero)
715 (setq var 'env) 717 (if (null (cdr envs))
718 (setq var 'env)
716 ;replace form => 719 ;replace form =>
717 ;(aref env #) 720 ;(aref env #)
718 (setq var `(aref env ,numero))) 721 (setq var `(aref env ,numero)))
719 (if (memq form emvrs) ; form => (car (aref env #)) if mutable 722 (if (memq form emvrs) ; form => (car (aref env #)) if mutable
720 `(car ,var) 723 `(car ,var)
721 var)) 724 var))
722 (if (memq form emvrs) ; if form is a mutable variable 725 (if (memq form emvrs) ; if form is a mutable variable
723 `(car ,form) ; replace form => (car form) 726 `(car ,form) ; replace form => (car form)
724 form))))) 727 form))))))
725 728
726(defun cconv-analyse-form (form vars inclosure) 729(defun cconv-analyse-function (args body env parentform inclosure)
727 730 (dolist (arg args)
731 (cond
732 ((cconv-not-lexical-var-p arg)
733 (byte-compile-report-error
734 (format "Argument %S is not a lexical variable" arg)))
735 ((eq ?& (aref (symbol-name arg) 0)) nil) ;Ignore &rest, &optional, ...
736 (t (push (list arg inclosure parentform) env)))) ;Push vrs to vars.
737 (dolist (form body) ;Analyse body forms.
738 (cconv-analyse-form form env inclosure)))
739
740(defun cconv-analyse-form (form env inclosure)
728 "Find mutated variables and variables captured by closure. Analyse 741 "Find mutated variables and variables captured by closure. Analyse
729lambdas if they are suitable for lambda lifting. 742lambdas if they are suitable for lambda lifting.
730-- FORM is a piece of Elisp code after macroexpansion. 743-- FORM is a piece of Elisp code after macroexpansion.
731-- MLCVRS is a structure that contains captured and mutated variables. 744-- ENV is a list of variables visible in current lexical environment.
732 (first MLCVRS) is a list of mutated variables, (second MLCVRS) is a 745 Each entry has the form (VAR INCLOSURE BINDER PARENTFORM)
733list of candidates for lambda lifting and (third MLCVRS) is a list of 746 for let-bound vars and (VAR INCLOSURE PARENTFORM) for function arguments.
734variables captured by closure. It should be (nil nil nil) initially. 747-- INCLOSURE is the nesting level within lambdas."
735-- VARS is a list of local variables visible in current environment
736 (initially empty).
737-- INCLOSURE is a boolean variable, true if we are in closure.
738Initially false"
739 (pcase form 748 (pcase form
740 ; let special form 749 ; let special form
741 (`(,(and (or `let* `let) letsym) ,varsvalues . ,body-forms) 750 (`(,(and (or `let* `let) letsym) ,binders . ,body-forms)
742
743 (when (eq letsym 'let)
744 (dolist (elm varsvalues) ; analyse values
745 (when (listp elm)
746 (cconv-analyse-form (cadr elm) vars inclosure))))
747 751
748 (let ((v nil) 752 (let ((orig-env env)
749 (var nil) 753 (var nil)
750 (value nil) 754 (value nil))
751 (varstruct nil)) 755 (dolist (binder binders)
752 (dolist (elm varsvalues) 756 (if (not (consp binder))
753 (if (listp elm)
754 (progn 757 (progn
755 (setq var (car elm)) 758 (setq var binder) ; treat the form (let (x) ...) well
756 (setq value (cadr elm))) 759 (setq value nil))
757 (progn 760 (setq var (car binder))
758 (setq var elm) ; treat the form (let (x) ...) well 761 (setq value (cadr binder))
759 (setq value nil))) 762
760 763 (cconv-analyse-form value (if (eq letsym 'let*) env orig-env)
761 (when (eq letsym 'let*) ; analyse value 764 inclosure))
762 (cconv-analyse-form value vars inclosure)) 765
763 766 (unless (cconv-not-lexical-var-p var)
764 (let (vars-new) ; remove the old var 767 (let ((varstruct (list var inclosure binder form)))
765 (dolist (vr vars) 768 (push varstruct env) ; Push a new one.
766 (when (not (eq (car vr) var)) 769
767 (push vr vars-new))) 770 (pcase value
768 (setq vars vars-new)) 771 (`(function (lambda . ,_))
769 772 ;; If var is a function push it to lambda list.
770 (setq varstruct (list var inclosure elm form)) 773 (push varstruct cconv-lambda-candidates)))))))
771 (push varstruct vars) ; push a new one 774
772 775 (dolist (form body-forms) ; Analyse body forms.
773 (when (and (listp value) 776 (cconv-analyse-form form env inclosure)))
774 (eq (car value) 'function) 777
775 (eq (caadr value) 'lambda))
776 ; if var is a function
777 ; push it to lambda list
778 (push varstruct cconv-lambda-candidates))))
779
780 (dolist (elm body-forms) ; analyse body forms
781 (cconv-analyse-form elm vars inclosure))
782 nil)
783 ; defun special form 778 ; defun special form
784 (`(,(or `defun `defmacro) ,func ,vrs . ,body-forms) 779 (`(,(or `defun `defmacro) ,func ,vrs . ,body-forms)
785 (let ((v nil)) 780 (when env
786 (dolist (vr vrs) 781 (byte-compile-log-warning
787 (push (list vr form) vars))) ;push vrs to vars 782 (format "Function %S will ignore its context %S"
788 (dolist (elm body-forms) ; analyse body forms 783 func (mapcar #'car env))
789 (cconv-analyse-form elm vars inclosure)) 784 t :warning))
790 nil) 785 (cconv-analyse-function vrs body-forms nil form 0))
791 786
792 (`(function . ((lambda ,vrs . ,body-forms))) 787 (`(function (lambda ,vrs . ,body-forms))
793 (if inclosure ;we are in closure 788 (cconv-analyse-function vrs body-forms env form (1+ inclosure)))
794 (setq inclosure (+ inclosure 1)) 789
795 (setq inclosure 1)) 790 (`(setq . ,forms)
796 (let (vars-new) ; update vars 791 ;; If a local variable (member of env) is modified by setq then
797 (dolist (vr vars) ; we do that in such a tricky way 792 ;; it is a mutated variable.
798 (when (not (memq (car vr) vrs)) ; to avoid side effects
799 (push vr vars-new)))
800 (dolist (vr vrs)
801 (push (list vr inclosure form) vars-new))
802 (setq vars vars-new))
803
804 (dolist (elm body-forms)
805 (cconv-analyse-form elm vars inclosure))
806 nil)
807
808 (`(setq . ,forms) ; setq
809 ; if a local variable (member of vars)
810 ; is modified by setq
811 ; then it is a mutated variable
812 (while forms 793 (while forms
813 (let ((v (assq (car forms) vars))) ; v = non nil if visible 794 (let ((v (assq (car forms) env))) ; v = non nil if visible
814 (when v 795 (when v
815 (push v cconv-mutated) 796 (push v cconv-mutated)
816 ;; delete from candidate list for lambda lifting 797 ;; Delete from candidate list for lambda lifting.
817 (setq cconv-lambda-candidates (delq v cconv-lambda-candidates)) 798 (setq cconv-lambda-candidates (delq v cconv-lambda-candidates))
818 (when inclosure 799 (unless (eq inclosure (cadr v)) ;Bound in a different closure level.
819 ;; test if v is declared as argument for lambda 800 (push v cconv-captured))))
820 (let* ((thirdv (third v)) 801 (cconv-analyse-form (cadr forms) env inclosure)
821 (isarg (if (listp thirdv) 802 (setq forms (cddr forms))))
822 (eq (car thirdv) 'function) nil))) 803
823 (if isarg 804 (`((lambda . ,_) . ,_) ; first element is lambda expression
824 (when (> inclosure (cadr v)) ; when we are in closure
825 (push v cconv-captured)) ; push it to captured vars
826 ;; FIXME more detailed comments needed
827 (push v cconv-captured))))))
828 (cconv-analyse-form (cadr forms) vars inclosure)
829 (setq forms (cddr forms)))
830 nil)
831
832 (`((lambda . ,_) . ,_) ; first element is lambda expression
833 (dolist (exp `((function ,(car form)) . ,(cdr form))) 805 (dolist (exp `((function ,(car form)) . ,(cdr form)))
834 (cconv-analyse-form exp vars inclosure)) 806 (cconv-analyse-form exp env inclosure)))
835 nil)
836 807
837 (`(cond . ,cond-forms) ; cond special form 808 (`(cond . ,cond-forms) ; cond special form
838 (dolist (exp1 cond-forms) 809 (dolist (forms cond-forms)
839 (dolist (exp2 exp1) 810 (dolist (form forms)
840 (cconv-analyse-form exp2 vars inclosure))) 811 (cconv-analyse-form form env inclosure))))
841 nil)
842 812
843 (`(quote . ,_) nil) ; quote form 813 (`(quote . ,_) nil) ; quote form
844
845 (`(function . ,_) nil) ; same as quote 814 (`(function . ,_) nil) ; same as quote
846 815
847 (`(condition-case ,var ,protected-form . ,conditions-bodies) 816 (`(condition-case ,var ,protected-form . ,handlers)
848 ;condition-case 817 ;; FIXME: The bytecode for condition-case forces us to wrap the
849 (cconv-analyse-form protected-form vars inclosure) 818 ;; form and handlers in closures (for handlers, it's probably
850 (dolist (exp conditions-bodies) 819 ;; unavoidable, but not for the protected form).
851 (cconv-analyse-form (cadr exp) vars inclosure)) 820 (setq inclosure (1+ inclosure))
852 nil) 821 (cconv-analyse-form protected-form env inclosure)
853 822 (push (list var inclosure form) env)
854 (`(,(or `defconst `defvar) ,value) 823 (dolist (handler handlers)
855 (cconv-analyse-form value vars inclosure)) 824 (dolist (form (cdr handler))
825 (cconv-analyse-form form env inclosure))))
826
827 ;; FIXME: The bytecode for catch forces us to wrap the body.
828 (`(,(or `catch `unwind-protect) ,form . ,body)
829 (cconv-analyse-form form env inclosure)
830 (setq inclosure (1+ inclosure))
831 (dolist (form body)
832 (cconv-analyse-form form env inclosure)))
833
834 ;; FIXME: The bytecode for save-window-excursion and the lack of
835 ;; bytecode for track-mouse forces us to wrap the body.
836 (`(,(or `save-window-excursion `track-mouse) . ,body)
837 (setq inclosure (1+ inclosure))
838 (dolist (form body)
839 (cconv-analyse-form form env inclosure)))
840
841 (`(,(or `defconst `defvar) ,var ,value . ,_)
842 (push var byte-compile-bound-variables)
843 (cconv-analyse-form value env inclosure))
856 844
857 (`(,(or `funcall `apply) ,fun . ,args) 845 (`(,(or `funcall `apply) ,fun . ,args)
858 ;; Here we ignore fun because 846 ;; Here we ignore fun because funcall and apply are the only two
859 ;; funcall and apply are the only two 847 ;; functions where we can pass a candidate for lambda lifting as
860 ;; functions where we can pass a candidate 848 ;; argument. So, if we see fun elsewhere, we'll delete it from
861 ;; for lambda lifting as argument. 849 ;; lambda candidate list.
862 ;; So, if we see fun elsewhere, we'll 850 (if (symbolp fun)
863 ;; delete it from lambda candidate list. 851 (let ((lv (assq fun cconv-lambda-candidates)))
864 852 (when lv
865 ;; If this funcall and the definition of fun 853 (unless (eq (cadr lv) inclosure)
866 ;; are in different closures - we delete fun from 854 (push lv cconv-captured)
867 ;; canidate list, because it is too complicated 855 ;; If this funcall and the definition of fun are in
868 ;; to manage free variables in this case. 856 ;; different closures - we delete fun from candidate
869 (let ((lv (assq fun cconv-lambda-candidates))) 857 ;; list, because it is too complicated to manage free
870 (when lv 858 ;; variables in this case.
871 (when (not (eq (cadr lv) inclosure)) 859 (setq cconv-lambda-candidates
872 (setq cconv-lambda-candidates 860 (delq lv cconv-lambda-candidates)))))
873 (delq lv cconv-lambda-candidates))))) 861 (cconv-analyse-form fun env inclosure))
874 862 (dolist (form args)
875 (dolist (elm args) 863 (cconv-analyse-form form env inclosure)))
876 (cconv-analyse-form elm vars inclosure)) 864
877 nil) 865 (`(,_ . ,body-forms) ; First element is a function or whatever.
878 866 (dolist (form body-forms)
879 (`(,_ . ,body-forms) ; first element is a function or whatever 867 (cconv-analyse-form form env inclosure)))
880 (dolist (exp body-forms) 868
881 (cconv-analyse-form exp vars inclosure)) 869 ((pred symbolp)
882 nil) 870 (let ((dv (assq form env))) ; dv = declared and visible
883 871 (when dv
884 (_ 872 (unless (eq inclosure (cadr dv)) ; capturing condition
885 (when (and (symbolp form) 873 (push dv cconv-captured))
886 (not (memq form '(nil t))) 874 ;; Delete lambda if it is found here, since it escapes.
887 (not (keywordp form)) 875 (setq cconv-lambda-candidates
888 (not (special-variable-p form))) 876 (delq dv cconv-lambda-candidates)))))))
889 (let ((dv (assq form vars))) ; dv = declared and visible
890 (when dv
891 (when inclosure
892 ;; test if v is declared as argument of lambda
893 (let* ((thirddv (third dv))
894 (isarg (if (listp thirddv)
895 (eq (car thirddv) 'function) nil)))
896 (if isarg
897 ;; FIXME add detailed comments
898 (when (> inclosure (cadr dv)) ; capturing condition
899 (push dv cconv-captured))
900 (push dv cconv-captured))))
901 ; delete lambda
902 (setq cconv-lambda-candidates ; if it is found here
903 (delq dv cconv-lambda-candidates)))))
904 nil)))
905 877
906(provide 'cconv) 878(provide 'cconv)
907;;; cconv.el ends here 879;;; cconv.el ends here
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index af8047256e2..bccc60a24e0 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -29,6 +29,8 @@
29 29
30;;; Code: 30;;; Code:
31 31
32(eval-when-compile (require 'cl))
33
32;; Bound by the top-level `macroexpand-all', and modified to include any 34;; Bound by the top-level `macroexpand-all', and modified to include any
33;; macros defined by `defmacro'. 35;; macros defined by `defmacro'.
34(defvar macroexpand-all-environment nil) 36(defvar macroexpand-all-environment nil)
@@ -164,6 +166,17 @@ Assumes the caller has bound `macroexpand-all-environment'."
164 (cons (macroexpand-all-1 166 (cons (macroexpand-all-1
165 (list 'function f)) 167 (list 'function f))
166 (macroexpand-all-forms args))))) 168 (macroexpand-all-forms args)))))
169 ;; Macro expand compiler macros.
170 ;; FIXME: Don't depend on CL.
171 (`(,(and (pred symbolp) fun
172 (guard (and (eq (get fun 'byte-compile)
173 'cl-byte-compile-compiler-macro)
174 (functionp 'compiler-macroexpand))))
175 . ,_)
176 (let ((newform (compiler-macroexpand form)))
177 (if (eq form newform)
178 (macroexpand-all-forms form 1)
179 (macroexpand-all-1 newform))))
167 (`(,_ . ,_) 180 (`(,_ . ,_)
168 ;; For every other list, we just expand each argument (for 181 ;; For every other list, we just expand each argument (for
169 ;; setq/setq-default this works alright because the variable names 182 ;; setq/setq-default this works alright because the variable names