aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2012-06-07 22:54:35 -0400
committerStefan Monnier2012-06-07 22:54:35 -0400
commitde7e2b368752bfc3cef17a8c82f6b3aec72bc649 (patch)
tree744eda5cd46648391762c68625e97958ce2cc7f5
parent4f18a4ed84d7268090a92a194dcda40cae1197dd (diff)
downloademacs-de7e2b368752bfc3cef17a8c82f6b3aec72bc649.tar.gz
emacs-de7e2b368752bfc3cef17a8c82f6b3aec72bc649.zip
Get rid of cl-lexical-let, keeping only lexical-let for compatibility.
* lisp/emacs-lisp/cl-macs.el: Provide itself. (cl--labels-convert-cache): New var. (cl--labels-convert): New function. (cl-flet, cl-labels): New implementation with new semantics, relying on lexical-binding. * lisp/emacs-lisp/cl.el: Mark compatibility aliases as obsolete. (cl-closure-vars, cl--function-convert-cache) (cl--function-convert): Move from cl-macs.el. (lexical-let, lexical-let*, flet, labels): Move from cl-macs.el and rename by removing the "cl-" prefix. * lisp/emacs-lisp/macroexp.el (macroexp-unprogn): New function.
-rw-r--r--lisp/ChangeLog15
-rw-r--r--lisp/emacs-lisp/cl-loaddefs.el41
-rw-r--r--lisp/emacs-lisp/cl-macs.el200
-rw-r--r--lisp/emacs-lisp/cl.el206
-rw-r--r--lisp/emacs-lisp/macroexp.el4
5 files changed, 264 insertions, 202 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 07b330a3e6e..3085da7ee79 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,18 @@
12012-06-08 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 Get rid of cl-lexical-let, keeping only lexical-let for compatibility.
4 * emacs-lisp/cl-macs.el: Provide itself.
5 (cl--labels-convert-cache): New var.
6 (cl--labels-convert): New function.
7 (cl-flet, cl-labels): New implementation with new semantics, relying on
8 lexical-binding.
9 * emacs-lisp/cl.el: Mark compatibility aliases as obsolete.
10 (cl-closure-vars, cl--function-convert-cache)
11 (cl--function-convert): Move from cl-macs.el.
12 (lexical-let, lexical-let*, flet, labels): Move from cl-macs.el and
13 rename by removing the "cl-" prefix.
14 * emacs-lisp/macroexp.el (macroexp-unprogn): New function.
15
12012-06-07 Stefan Monnier <monnier@iro.umontreal.ca> 162012-06-07 Stefan Monnier <monnier@iro.umontreal.ca>
2 17
3 * emacs-lisp/cl.el (cl-macroexpand, cl-macro-environment) 18 * emacs-lisp/cl.el (cl-macroexpand, cl-macro-environment)
diff --git a/lisp/emacs-lisp/cl-loaddefs.el b/lisp/emacs-lisp/cl-loaddefs.el
index 2d7c9153318..95716ae2e29 100644
--- a/lisp/emacs-lisp/cl-loaddefs.el
+++ b/lisp/emacs-lisp/cl-loaddefs.el
@@ -258,13 +258,12 @@ Remove from SYMBOL's plist the property PROPNAME and its value.
258;;;;;; cl-letf cl-rotatef cl-shiftf cl-remf cl-do-pop cl-psetf cl-setf 258;;;;;; cl-letf cl-rotatef cl-shiftf cl-remf cl-do-pop cl-psetf cl-setf
259;;;;;; cl-get-setf-method cl-defsetf cl-define-setf-expander cl-declare 259;;;;;; cl-get-setf-method cl-defsetf cl-define-setf-expander cl-declare
260;;;;;; cl-the cl-locally cl-multiple-value-setq cl-multiple-value-bind 260;;;;;; cl-the cl-locally cl-multiple-value-setq cl-multiple-value-bind
261;;;;;; cl-lexical-let* cl-lexical-let cl-symbol-macrolet cl-macrolet 261;;;;;; cl-symbol-macrolet cl-macrolet cl-labels cl-flet cl-progv
262;;;;;; cl-labels cl-flet cl-progv cl-psetq cl-do-all-symbols cl-do-symbols 262;;;;;; cl-psetq cl-do-all-symbols cl-do-symbols cl-dotimes cl-dolist
263;;;;;; cl-dotimes cl-dolist cl-do* cl-do cl-loop cl-return-from 263;;;;;; cl-do* cl-do cl-loop cl-return-from cl-return cl-block cl-etypecase
264;;;;;; cl-return cl-block cl-etypecase cl-typecase cl-ecase cl-case 264;;;;;; cl-typecase cl-ecase cl-case cl-load-time-value cl-eval-when
265;;;;;; cl-load-time-value cl-eval-when cl-destructuring-bind cl-function 265;;;;;; cl-destructuring-bind cl-function cl-defmacro cl-defun cl-gentemp
266;;;;;; cl-defmacro cl-defun cl-gentemp cl-gensym) "cl-macs" "cl-macs.el" 266;;;;;; cl-gensym) "cl-macs" "cl-macs.el" "4c0f605e3c7454488cc9d498b611f422")
267;;;;;; "c1e8e5391e374630452ab3d78e527086")
268;;; Generated autoloads from cl-macs.el 267;;; Generated autoloads from cl-macs.el
269 268
270(autoload 'cl-gensym "cl-macs" "\ 269(autoload 'cl-gensym "cl-macs" "\
@@ -485,10 +484,7 @@ a `let' form, except that the list of symbols can be computed at run-time.
485 484
486(autoload 'cl-flet "cl-macs" "\ 485(autoload 'cl-flet "cl-macs" "\
487Make temporary function definitions. 486Make temporary function definitions.
488This is an analogue of `let' that operates on the function cell of FUNC 487Like `cl-labels' but the definitions are not recursive.
489rather than its value cell. The FORMs are evaluated with the specified
490function definitions in place, then the definitions are undone (the FUNCs
491go back to their previous definitions, or lack thereof).
492 488
493\(fn ((FUNC ARGLIST BODY...) ...) FORM...)" nil t) 489\(fn ((FUNC ARGLIST BODY...) ...) FORM...)" nil t)
494 490
@@ -496,8 +492,7 @@ go back to their previous definitions, or lack thereof).
496 492
497(autoload 'cl-labels "cl-macs" "\ 493(autoload 'cl-labels "cl-macs" "\
498Make temporary function bindings. 494Make temporary function bindings.
499This is like `cl-flet', except the bindings are lexical instead of dynamic. 495The bindings can be recursive. Assumes the use of `lexical-binding'.
500Unlike `cl-flet', this macro is fully compliant with the Common Lisp standard.
501 496
502\(fn ((FUNC ARGLIST BODY...) ...) FORM...)" nil t) 497\(fn ((FUNC ARGLIST BODY...) ...) FORM...)" nil t)
503 498
@@ -520,26 +515,6 @@ by EXPANSION, and (setq NAME ...) will act like (cl-setf EXPANSION ...).
520 515
521(put 'cl-symbol-macrolet 'lisp-indent-function '1) 516(put 'cl-symbol-macrolet 'lisp-indent-function '1)
522 517
523(autoload 'cl-lexical-let "cl-macs" "\
524Like `let', but lexically scoped.
525The main visible difference is that lambdas inside BODY will create
526lexical closures as in Common Lisp.
527
528\(fn BINDINGS BODY)" nil t)
529
530(put 'cl-lexical-let 'lisp-indent-function '1)
531
532(autoload 'cl-lexical-let* "cl-macs" "\
533Like `let*', but lexically scoped.
534The main visible difference is that lambdas inside BODY, and in
535successive bindings within BINDINGS, will create lexical closures
536as in Common Lisp. This is similar to the behavior of `let*' in
537Common Lisp.
538
539\(fn BINDINGS BODY)" nil t)
540
541(put 'cl-lexical-let* 'lisp-indent-function '1)
542
543(autoload 'cl-multiple-value-bind "cl-macs" "\ 518(autoload 'cl-multiple-value-bind "cl-macs" "\
544Collect multiple return values. 519Collect multiple return values.
545FORM must return a list; the BODY is then executed with the first N elements 520FORM must return a list; the BODY is then executed with the first N elements
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 91d7c211483..4d8e4f39214 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -1611,63 +1611,70 @@ a `let' form, except that the list of symbols can be computed at run-time."
1611 (progn (cl-progv-before ,symbols ,values) ,@body) 1611 (progn (cl-progv-before ,symbols ,values) ,@body)
1612 (cl-progv-after)))) 1612 (cl-progv-after))))
1613 1613
1614(defvar cl--labels-convert-cache nil)
1615
1616(defun cl--labels-convert (f)
1617 "Special macro-expander to rename (function F) references in `cl-labels'."
1618 (cond
1619 ;; ¡¡Big Ugly Hack!! We can't use a compiler-macro because those are checked
1620 ;; *after* handling `function', but we want to stop macroexpansion from
1621 ;; being applied infinitely, so we use a cache to return the exact `form'
1622 ;; being expanded even though we don't receive it.
1623 ((eq f (car cl--labels-convert-cache)) (cdr cl--labels-convert-cache))
1624 (t
1625 (let ((found (assq f macroexpand-all-environment)))
1626 (if (and found (ignore-errors
1627 (eq (cadr (cl-caddr found)) 'cl-labels-args)))
1628 (cadr (cl-caddr (cl-cadddr found)))
1629 (let ((res `(function ,f)))
1630 (setq cl--labels-convert-cache (cons f res))
1631 res))))))
1632
1614;;; This should really have some way to shadow 'byte-compile properties, etc. 1633;;; This should really have some way to shadow 'byte-compile properties, etc.
1615;;;###autoload 1634;;;###autoload
1616(defmacro cl-flet (bindings &rest body) 1635(defmacro cl-flet (bindings &rest body)
1617 "Make temporary function definitions. 1636 "Make temporary function definitions.
1618This is an analogue of `let' that operates on the function cell of FUNC 1637Like `cl-labels' but the definitions are not recursive.
1619rather than its value cell. The FORMs are evaluated with the specified
1620function definitions in place, then the definitions are undone (the FUNCs
1621go back to their previous definitions, or lack thereof).
1622 1638
1623\(fn ((FUNC ARGLIST BODY...) ...) FORM...)" 1639\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
1624 (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body))) 1640 (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body)))
1625 `(cl-letf* ,(mapcar 1641 (let ((binds ()) (newenv macroexpand-all-environment))
1626 (lambda (x) 1642 (dolist (binding bindings)
1627 (if (or (and (fboundp (car x)) 1643 (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
1628 (eq (car-safe (symbol-function (car x))) 'macro)) 1644 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds)
1629 (cdr (assq (car x) macroexpand-all-environment))) 1645 (push (cons (car binding)
1630 (error "Use `cl-labels', not `cl-flet', to rebind macro names")) 1646 `(lambda (&rest cl-labels-args)
1631 (let ((func `(cl-function 1647 (cl-list* 'funcall ',var
1632 (lambda ,(cadr x) 1648 cl-labels-args)))
1633 (cl-block ,(car x) ,@(cddr x)))))) 1649 newenv)))
1634 (when (cl-compiling-file) 1650 `(let ,(nreverse binds)
1635 ;; Bug#411. It would be nice to fix this. 1651 ,@(macroexp-unprogn
1636 (and (get (car x) 'byte-compile) 1652 (macroexpand-all
1637 (error "Byte-compiling a redefinition of `%s' \ 1653 `(progn ,@body)
1638will not work - use `cl-labels' instead" (symbol-name (car x)))) 1654 ;; Don't override lexical-let's macro-expander.
1639 ;; FIXME This affects the rest of the file, when it 1655 (if (assq 'function newenv) newenv
1640 ;; should be restricted to the cl-flet body. 1656 (cons (cons 'function #'cl--labels-convert) newenv)))))))
1641 (and (boundp 'byte-compile-function-environment)
1642 (push (cons (car x) (eval func))
1643 byte-compile-function-environment)))
1644 (list `(symbol-function ',(car x)) func)))
1645 bindings)
1646 ,@body))
1647 1657
1648;;;###autoload 1658;;;###autoload
1649(defmacro cl-labels (bindings &rest body) 1659(defmacro cl-labels (bindings &rest body)
1650 "Make temporary function bindings. 1660 "Make temporary function bindings.
1651This is like `cl-flet', except the bindings are lexical instead of dynamic. 1661The bindings can be recursive. Assumes the use of `lexical-binding'.
1652Unlike `cl-flet', this macro is fully compliant with the Common Lisp standard.
1653 1662
1654\(fn ((FUNC ARGLIST BODY...) ...) FORM...)" 1663\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
1655 (declare (indent 1) (debug cl-flet)) 1664 (declare (indent 1) (debug cl-flet))
1656 (let ((vars nil) (sets nil) (newenv macroexpand-all-environment)) 1665 (let ((binds ()) (newenv macroexpand-all-environment))
1657 (while bindings 1666 (dolist (binding bindings)
1658 ;; Use `cl-gensym' rather than `make-symbol'. It's important that 1667 (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
1659 ;; (not (eq (symbol-name var1) (symbol-name var2))) because these 1668 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds)
1660 ;; vars get added to the cl-macro-environment. 1669 (push (cons (car binding)
1661 (let ((var (cl-gensym "--cl-var--")))
1662 (push var vars)
1663 (push `(cl-function (lambda . ,(cdar bindings))) sets)
1664 (push var sets)
1665 (push (cons (car (pop bindings))
1666 `(lambda (&rest cl-labels-args) 1670 `(lambda (&rest cl-labels-args)
1667 (cl-list* 'funcall ',var 1671 (cl-list* 'funcall ',var
1668 cl-labels-args))) 1672 cl-labels-args)))
1669 newenv))) 1673 newenv)))
1670 (macroexpand-all `(cl-lexical-let ,vars (setq ,@sets) ,@body) newenv))) 1674 (macroexpand-all `(letrec ,(nreverse binds) ,@body)
1675 ;; Don't override lexical-let's macro-expander.
1676 (if (assq 'function newenv) newenv
1677 (cons (cons 'function #'cl--labels-convert) newenv)))))
1671 1678
1672;; The following ought to have a better definition for use with newer 1679;; The following ought to have a better definition for use with newer
1673;; byte compilers. 1680;; byte compilers.
@@ -1750,119 +1757,6 @@ by EXPANSION, and (setq NAME ...) will act like (cl-setf EXPANSION ...).
1750 macroexpand-all-environment))) 1757 macroexpand-all-environment)))
1751 (fset 'macroexpand previous-macroexpand)))))) 1758 (fset 'macroexpand previous-macroexpand))))))
1752 1759
1753(defvar cl-closure-vars nil)
1754(defvar cl--function-convert-cache nil)
1755
1756(defun cl--function-convert (f)
1757 "Special macro-expander for special cases of (function F).
1758The two cases that are handled are:
1759- closure-conversion of lambda expressions for `cl-lexical-let'.
1760- renaming of F when it's a function defined via `cl-labels'."
1761 (cond
1762 ;; ¡¡Big Ugly Hack!! We can't use a compiler-macro because those are checked
1763 ;; *after* handling `function', but we want to stop macroexpansion from
1764 ;; being applied infinitely, so we use a cache to return the exact `form'
1765 ;; being expanded even though we don't receive it.
1766 ((eq f (car cl--function-convert-cache)) (cdr cl--function-convert-cache))
1767 ((eq (car-safe f) 'lambda)
1768 (let ((body (mapcar (lambda (f)
1769 (macroexpand-all f macroexpand-all-environment))
1770 (cddr f))))
1771 (if (and cl-closure-vars
1772 (cl--expr-contains-any body cl-closure-vars))
1773 (let* ((new (mapcar 'cl-gensym cl-closure-vars))
1774 (sub (cl-pairlis cl-closure-vars new)) (decls nil))
1775 (while (or (stringp (car body))
1776 (eq (car-safe (car body)) 'interactive))
1777 (push (list 'quote (pop body)) decls))
1778 (put (car (last cl-closure-vars)) 'used t)
1779 `(list 'lambda '(&rest --cl-rest--)
1780 ,@(cl-sublis sub (nreverse decls))
1781 (list 'apply
1782 (list 'quote
1783 #'(lambda ,(append new (cadr f))
1784 ,@(cl-sublis sub body)))
1785 ,@(nconc (mapcar (lambda (x) `(list 'quote ,x))
1786 cl-closure-vars)
1787 '((quote --cl-rest--))))))
1788 (let* ((newf `(lambda ,(cadr f) ,@body))
1789 (res `(function ,newf)))
1790 (setq cl--function-convert-cache (cons newf res))
1791 res))))
1792 (t
1793 (let ((found (assq f macroexpand-all-environment)))
1794 (if (and found (ignore-errors
1795 (eq (cadr (cl-caddr found)) 'cl-labels-args)))
1796 (cadr (cl-caddr (cl-cadddr found)))
1797 (let ((res `(function ,f)))
1798 (setq cl--function-convert-cache (cons f res))
1799 res))))))
1800
1801;;;###autoload
1802(defmacro cl-lexical-let (bindings &rest body)
1803 "Like `let', but lexically scoped.
1804The main visible difference is that lambdas inside BODY will create
1805lexical closures as in Common Lisp.
1806\n(fn BINDINGS BODY)"
1807 (declare (indent 1) (debug let))
1808 (let* ((cl-closure-vars cl-closure-vars)
1809 (vars (mapcar (function
1810 (lambda (x)
1811 (or (consp x) (setq x (list x)))
1812 (push (make-symbol (format "--cl-%s--" (car x)))
1813 cl-closure-vars)
1814 (set (car cl-closure-vars) [bad-lexical-ref])
1815 (list (car x) (cadr x) (car cl-closure-vars))))
1816 bindings))
1817 (ebody
1818 (macroexpand-all
1819 `(cl-symbol-macrolet
1820 ,(mapcar (lambda (x)
1821 `(,(car x) (symbol-value ,(cl-caddr x))))
1822 vars)
1823 ,@body)
1824 (cons (cons 'function #'cl--function-convert)
1825 macroexpand-all-environment))))
1826 (if (not (get (car (last cl-closure-vars)) 'used))
1827 ;; Turn (let ((foo (cl-gensym)))
1828 ;; (set foo <val>) ...(symbol-value foo)...)
1829 ;; into (let ((foo <val>)) ...(symbol-value 'foo)...).
1830 ;; This is good because it's more efficient but it only works with
1831 ;; dynamic scoping, since with lexical scoping we'd need
1832 ;; (let ((foo <val>)) ...foo...).
1833 `(progn
1834 ,@(mapcar (lambda (x) `(defvar ,(cl-caddr x))) vars)
1835 (let ,(mapcar (lambda (x) (list (cl-caddr x) (cadr x))) vars)
1836 ,(cl-sublis (mapcar (lambda (x)
1837 (cons (cl-caddr x)
1838 `',(cl-caddr x)))
1839 vars)
1840 ebody)))
1841 `(let ,(mapcar (lambda (x)
1842 (list (cl-caddr x)
1843 `(make-symbol ,(format "--%s--" (car x)))))
1844 vars)
1845 (cl-setf ,@(apply #'append
1846 (mapcar (lambda (x)
1847 (list `(symbol-value ,(cl-caddr x)) (cadr x)))
1848 vars)))
1849 ,ebody))))
1850
1851;;;###autoload
1852(defmacro cl-lexical-let* (bindings &rest body)
1853 "Like `let*', but lexically scoped.
1854The main visible difference is that lambdas inside BODY, and in
1855successive bindings within BINDINGS, will create lexical closures
1856as in Common Lisp. This is similar to the behavior of `let*' in
1857Common Lisp.
1858\n(fn BINDINGS BODY)"
1859 (declare (indent 1) (debug let))
1860 (if (null bindings) (cons 'progn body)
1861 (setq bindings (reverse bindings))
1862 (while bindings
1863 (setq body (list `(cl-lexical-let (,(pop bindings)) ,@body))))
1864 (car body)))
1865
1866;;; Multiple values. 1760;;; Multiple values.
1867 1761
1868;;;###autoload 1762;;;###autoload
@@ -3211,4 +3105,6 @@ surrounded by (cl-block NAME ...).
3211;; generated-autoload-file: "cl-loaddefs.el" 3105;; generated-autoload-file: "cl-loaddefs.el"
3212;; End: 3106;; End:
3213 3107
3108(provide 'cl-macs)
3109
3214;;; cl-macs.el ends here 3110;;; cl-macs.el ends here
diff --git a/lisp/emacs-lisp/cl.el b/lisp/emacs-lisp/cl.el
index b4be63f2bb1..d162a377f9b 100644
--- a/lisp/emacs-lisp/cl.el
+++ b/lisp/emacs-lisp/cl.el
@@ -28,6 +28,7 @@
28;;; Code: 28;;; Code:
29 29
30(require 'cl-lib) 30(require 'cl-lib)
31(require 'macroexp)
31 32
32;; (defun cl--rename () 33;; (defun cl--rename ()
33;; (let ((vdefs ()) 34;; (let ((vdefs ())
@@ -226,11 +227,8 @@
226 locally 227 locally
227 multiple-value-setq 228 multiple-value-setq
228 multiple-value-bind 229 multiple-value-bind
229 lexical-let*
230 lexical-let
231 symbol-macrolet 230 symbol-macrolet
232 macrolet 231 macrolet
233 labels
234 flet 232 flet
235 progv 233 progv
236 psetq 234 psetq
@@ -330,12 +328,181 @@
330 (if (get new prop) 328 (if (get new prop)
331 (put fun prop (get new prop)))))) 329 (put fun prop (get new prop))))))
332 330
331(defvar cl-closure-vars nil)
332(defvar cl--function-convert-cache nil)
333
334(defun cl--function-convert (f)
335 "Special macro-expander for special cases of (function F).
336The two cases that are handled are:
337- closure-conversion of lambda expressions for `lexical-let'.
338- renaming of F when it's a function defined via `cl-labels' or `labels'."
339 (require 'cl-macs)
340 (cond
341 ;; ¡¡Big Ugly Hack!! We can't use a compiler-macro because those are checked
342 ;; *after* handling `function', but we want to stop macroexpansion from
343 ;; being applied infinitely, so we use a cache to return the exact `form'
344 ;; being expanded even though we don't receive it.
345 ((eq f (car cl--function-convert-cache)) (cdr cl--function-convert-cache))
346 ((eq (car-safe f) 'lambda)
347 (let ((body (mapcar (lambda (f)
348 (macroexpand-all f macroexpand-all-environment))
349 (cddr f))))
350 (if (and cl-closure-vars
351 (cl--expr-contains-any body cl-closure-vars))
352 (let* ((new (mapcar 'cl-gensym cl-closure-vars))
353 (sub (cl-pairlis cl-closure-vars new)) (decls nil))
354 (while (or (stringp (car body))
355 (eq (car-safe (car body)) 'interactive))
356 (push (list 'quote (pop body)) decls))
357 (put (car (last cl-closure-vars)) 'used t)
358 `(list 'lambda '(&rest --cl-rest--)
359 ,@(cl-sublis sub (nreverse decls))
360 (list 'apply
361 (list 'quote
362 #'(lambda ,(append new (cadr f))
363 ,@(cl-sublis sub body)))
364 ,@(nconc (mapcar (lambda (x) `(list 'quote ,x))
365 cl-closure-vars)
366 '((quote --cl-rest--))))))
367 (let* ((newf `(lambda ,(cadr f) ,@body))
368 (res `(function ,newf)))
369 (setq cl--function-convert-cache (cons newf res))
370 res))))
371 (t
372 (let ((found (assq f macroexpand-all-environment)))
373 (if (and found (ignore-errors
374 (eq (cadr (cl-caddr found)) 'cl-labels-args)))
375 (cadr (cl-caddr (cl-cadddr found)))
376 (let ((res `(function ,f)))
377 (setq cl--function-convert-cache (cons f res))
378 res))))))
379
380(defmacro lexical-let (bindings &rest body)
381 "Like `let', but lexically scoped.
382The main visible difference is that lambdas inside BODY will create
383lexical closures as in Common Lisp.
384\n(fn BINDINGS BODY)"
385 (declare (indent 1) (debug let))
386 (let* ((cl-closure-vars cl-closure-vars)
387 (vars (mapcar (function
388 (lambda (x)
389 (or (consp x) (setq x (list x)))
390 (push (make-symbol (format "--cl-%s--" (car x)))
391 cl-closure-vars)
392 (set (car cl-closure-vars) [bad-lexical-ref])
393 (list (car x) (cadr x) (car cl-closure-vars))))
394 bindings))
395 (ebody
396 (macroexpand-all
397 `(cl-symbol-macrolet
398 ,(mapcar (lambda (x)
399 `(,(car x) (symbol-value ,(cl-caddr x))))
400 vars)
401 ,@body)
402 (cons (cons 'function #'cl--function-convert)
403 macroexpand-all-environment))))
404 (if (not (get (car (last cl-closure-vars)) 'used))
405 ;; Turn (let ((foo (cl-gensym)))
406 ;; (set foo <val>) ...(symbol-value foo)...)
407 ;; into (let ((foo <val>)) ...(symbol-value 'foo)...).
408 ;; This is good because it's more efficient but it only works with
409 ;; dynamic scoping, since with lexical scoping we'd need
410 ;; (let ((foo <val>)) ...foo...).
411 `(progn
412 ,@(mapcar (lambda (x) `(defvar ,(cl-caddr x))) vars)
413 (let ,(mapcar (lambda (x) (list (cl-caddr x) (cadr x))) vars)
414 ,(cl-sublis (mapcar (lambda (x)
415 (cons (cl-caddr x)
416 `',(cl-caddr x)))
417 vars)
418 ebody)))
419 `(let ,(mapcar (lambda (x)
420 (list (cl-caddr x)
421 `(make-symbol ,(format "--%s--" (car x)))))
422 vars)
423 (cl-setf ,@(apply #'append
424 (mapcar (lambda (x)
425 (list `(symbol-value ,(cl-caddr x)) (cadr x)))
426 vars)))
427 ,ebody))))
428
429(defmacro lexical-let* (bindings &rest body)
430 "Like `let*', but lexically scoped.
431The main visible difference is that lambdas inside BODY, and in
432successive bindings within BINDINGS, will create lexical closures
433as in Common Lisp. This is similar to the behavior of `let*' in
434Common Lisp.
435\n(fn BINDINGS BODY)"
436 (declare (indent 1) (debug let))
437 (if (null bindings) (cons 'progn body)
438 (setq bindings (reverse bindings))
439 (while bindings
440 (setq body (list `(lexical-let (,(pop bindings)) ,@body))))
441 (car body)))
442
443;; This should really have some way to shadow 'byte-compile properties, etc.
444;;;###autoload
445(defmacro flet (bindings &rest body)
446 "Make temporary function definitions.
447This is an analogue of `let' that operates on the function cell of FUNC
448rather than its value cell. The FORMs are evaluated with the specified
449function definitions in place, then the definitions are undone (the FUNCs
450go back to their previous definitions, or lack thereof).
451
452\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
453 (declare (indent 1) (debug cl-flet))
454 `(cl-letf* ,(mapcar
455 (lambda (x)
456 (if (or (and (fboundp (car x))
457 (eq (car-safe (symbol-function (car x))) 'macro))
458 (cdr (assq (car x) macroexpand-all-environment)))
459 (error "Use `labels', not `flet', to rebind macro names"))
460 (let ((func `(cl-function
461 (lambda ,(cadr x)
462 (cl-block ,(car x) ,@(cddr x))))))
463 (when (cl-compiling-file)
464 ;; Bug#411. It would be nice to fix this.
465 (and (get (car x) 'byte-compile)
466 (error "Byte-compiling a redefinition of `%s' \
467will not work - use `labels' instead" (symbol-name (car x))))
468 ;; FIXME This affects the rest of the file, when it
469 ;; should be restricted to the flet body.
470 (and (boundp 'byte-compile-function-environment)
471 (push (cons (car x) (eval func))
472 byte-compile-function-environment)))
473 (list `(symbol-function ',(car x)) func)))
474 bindings)
475 ,@body))
476
477(defmacro labels (bindings &rest body)
478 "Make temporary function bindings.
479This is like `flet', except the bindings are lexical instead of dynamic.
480Unlike `flet', this macro is fully compliant with the Common Lisp standard.
481
482\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
483 (declare (indent 1) (debug cl-flet))
484 (let ((vars nil) (sets nil) (newenv macroexpand-all-environment))
485 (dolist (binding bindings)
486 ;; It's important that (not (eq (symbol-name var1) (symbol-name var2)))
487 ;; because these var's *names* get added to the macro-environment.
488 (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
489 (push var vars)
490 (push `(cl-function (lambda . ,(cdr binding))) sets)
491 (push var sets)
492 (push (cons (car binding)
493 `(lambda (&rest cl-labels-args)
494 (cl-list* 'funcall ',var
495 cl-labels-args)))
496 newenv)))
497 (macroexpand-all `(lexical-let ,vars (setq ,@sets) ,@body) newenv)))
498
333;;; Additional compatibility code 499;;; Additional compatibility code
334;; For names that were clean but really aren't needed any more. 500;; For names that were clean but really aren't needed any more.
335 501
336(defalias 'cl-macroexpand 'macroexpand) 502(define-obsolete-function-alias 'cl-macroexpand 'macroexpand "24.2")
337(defvaralias 'cl-macro-environment 'macroexpand-all-environment) 503(define-obsolete-variable-alias 'cl-macro-environment
338(defalias 'cl-macroexpand-all 'macroexpand-all) 504 'macroexpand-all-environment "24.2")
505(define-obsolete-function-alias 'cl-macroexpand-all 'macroexpand-all "24.2")
339 506
340;;; Hash tables. 507;;; Hash tables.
341;; This is just kept for compatibility with code byte-compiled by Emacs-20. 508;; This is just kept for compatibility with code byte-compiled by Emacs-20.
@@ -343,24 +510,29 @@
343;; No idea if this might still be needed. 510;; No idea if this might still be needed.
344(defun cl-not-hash-table (x &optional y &rest z) 511(defun cl-not-hash-table (x &optional y &rest z)
345 (signal 'wrong-type-argument (list 'cl-hash-table-p (or y x)))) 512 (signal 'wrong-type-argument (list 'cl-hash-table-p (or y x))))
513(make-obsolete 'cl-not-hash-table nil "24.2")
346 514
347(defvar cl-builtin-gethash (symbol-function 'gethash)) 515(defvar cl-builtin-gethash (symbol-function 'gethash))
516(make-obsolete-variable 'cl-builtin-gethash nil "24.2")
348(defvar cl-builtin-remhash (symbol-function 'remhash)) 517(defvar cl-builtin-remhash (symbol-function 'remhash))
518(make-obsolete-variable 'cl-builtin-remhash nil "24.2")
349(defvar cl-builtin-clrhash (symbol-function 'clrhash)) 519(defvar cl-builtin-clrhash (symbol-function 'clrhash))
520(make-obsolete-variable 'cl-builtin-clrhash nil "24.2")
350(defvar cl-builtin-maphash (symbol-function 'maphash)) 521(defvar cl-builtin-maphash (symbol-function 'maphash))
351 522
352(defalias 'cl-map-keymap 'map-keymap) 523(make-obsolete-variable 'cl-builtin-maphash nil "24.2")
353(defalias 'cl-copy-tree 'copy-tree) 524(define-obsolete-function-alias 'cl-map-keymap 'map-keymap "24.2")
354(defalias 'cl-gethash 'gethash) 525(define-obsolete-function-alias 'cl-copy-tree 'copy-tree "24.2")
355(defalias 'cl-puthash 'puthash) 526(define-obsolete-function-alias 'cl-gethash 'gethash "24.2")
356(defalias 'cl-remhash 'remhash) 527(define-obsolete-function-alias 'cl-puthash 'puthash "24.2")
357(defalias 'cl-clrhash 'clrhash) 528(define-obsolete-function-alias 'cl-remhash 'remhash "24.2")
358(defalias 'cl-maphash 'maphash) 529(define-obsolete-function-alias 'cl-clrhash 'clrhash "24.2")
359(defalias 'cl-make-hash-table 'make-hash-table) 530(define-obsolete-function-alias 'cl-maphash 'maphash "24.2")
360(defalias 'cl-hash-table-p 'hash-table-p) 531(define-obsolete-function-alias 'cl-make-hash-table 'make-hash-table "24.2")
361(defalias 'cl-hash-table-count 'hash-table-count) 532(define-obsolete-function-alias 'cl-hash-table-p 'hash-table-p "24.2")
533(define-obsolete-function-alias 'cl-hash-table-count 'hash-table-count "24.2")
362 534
363;; FIXME: More candidates: define-modify-macro, define-setf-expander, lexical-let. 535;; FIXME: More candidates: define-modify-macro, define-setf-expander.
364 536
365(provide 'cl) 537(provide 'cl)
366;;; cl.el ends here 538;;; cl.el ends here
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index 115af33fb6c..ca6a04d605b 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -231,6 +231,10 @@ definitions to shadow the loaded ones for use in file byte-compilation."
231 "Return an expression equivalent to `(progn ,@EXPS)." 231 "Return an expression equivalent to `(progn ,@EXPS)."
232 (if (cdr exps) `(progn ,@exps) (car exps))) 232 (if (cdr exps) `(progn ,@exps) (car exps)))
233 233
234(defun macroexp-unprogn (exp)
235 "Turn EXP into a list of expressions to execute in sequence."
236 (if (eq (car-safe exp) 'progn) (cdr exp) (list exp)))
237
234(defun macroexp-let* (bindings exp) 238(defun macroexp-let* (bindings exp)
235 "Return an expression equivalent to `(let* ,bindings ,exp)." 239 "Return an expression equivalent to `(let* ,bindings ,exp)."
236 (cond 240 (cond