summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/bytecomp.el
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2012-06-27 23:31:27 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2012-06-27 23:31:27 -0400
commitc207708c86ab04f4bb1d78789be0d116e77ba9bb (patch)
treead5da6a992628f001c7c5dce39b847a94575c4c4 /lisp/emacs-lisp/bytecomp.el
parent059e4fb5ed71639f16162e559c9f68f8b5889b9c (diff)
downloademacs-c207708c86ab04f4bb1d78789be0d116e77ba9bb.tar.gz
Make inlining of other-mode interpreted functions work.
* lisp/emacs-lisp/bytecomp.el (byte-compile--refiy-function): New fun. (byte-compile): Use it to fix compilation of lexical-binding closures. * lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand): Compile the function, if needed. Fixes: debbugs:11799
Diffstat (limited to 'lisp/emacs-lisp/bytecomp.el')
-rw-r--r--lisp/emacs-lisp/bytecomp.el41
1 files changed, 33 insertions, 8 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 650faec6bf6..af7bc81fef0 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2451,7 +2451,26 @@ If QUOTED is non-nil, print with quoting; otherwise, print without quoting."
(- (position-bytes (point)) (point-min) -1)
(goto-char (point-max))))))
-
+(defun byte-compile--refiy-function (fun)
+ "Return an expression which will evaluate to a function value FUN.
+FUN should be either a `lambda' value or a `closure' value."
+ (pcase-let* (((or (and `(lambda ,args . ,body) (let env nil))
+ `(closure ,env ,args . ,body)) fun)
+ (renv ()))
+ ;; Turn the function's closed vars (if any) into local let bindings.
+ (dolist (binding env)
+ (cond
+ ((consp binding)
+ ;; We check shadowing by the args, so that the `let' can be moved
+ ;; within the lambda, which can then be unfolded. FIXME: Some of those
+ ;; bindings might be unused in `body'.
+ (unless (memq (car binding) args) ;Shadowed.
+ (push `(,(car binding) ',(cdr binding)) renv)))
+ ((eq binding t))
+ (t (push `(defvar ,binding) body))))
+ (if (null renv)
+ `(lambda ,args ,@body)
+ `(lambda ,args (let ,(nreverse renv) ,@body)))))
;;;###autoload
(defun byte-compile (form)
@@ -2459,23 +2478,29 @@ If QUOTED is non-nil, print with quoting; otherwise, print without quoting."
If FORM is a lambda or a macro, byte-compile it as a function."
(displaying-byte-compile-warnings
(byte-compile-close-variables
- (let* ((fun (if (symbolp form)
+ (let* ((lexical-binding lexical-binding)
+ (fun (if (symbolp form)
(and (fboundp form) (symbol-function form))
form))
(macro (eq (car-safe fun) 'macro)))
(if macro
(setq fun (cdr fun)))
- (cond ((eq (car-safe fun) 'lambda)
+ (when (symbolp form)
+ (unless (memq (car-safe fun) '(closure lambda))
+ (error "Don't know how to compile %S" fun))
+ (setq fun (byte-compile--refiy-function fun))
+ (setq lexical-binding (eq (car fun) 'closure)))
+ (unless (eq (car-safe fun) 'lambda)
+ (error "Don't know how to compile %S" fun))
;; Expand macros.
(setq fun (byte-compile-preprocess fun))
;; Get rid of the `function' quote added by the `lambda' macro.
(if (eq (car-safe fun) 'function) (setq fun (cadr fun)))
- (setq fun (if macro
- (cons 'macro (byte-compile-lambda fun))
- (byte-compile-lambda fun)))
+ (setq fun (byte-compile-lambda fun))
+ (if macro (push 'macro fun))
(if (symbolp form)
- (defalias form fun)
- fun)))))))
+ (fset form fun)
+ fun)))))
(defun byte-compile-sexp (sexp)
"Compile and return SEXP."