diff options
| -rw-r--r-- | lisp/ChangeLog | 15 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-loaddefs.el | 41 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 200 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl.el | 206 | ||||
| -rw-r--r-- | lisp/emacs-lisp/macroexp.el | 4 |
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 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-06-07 Stefan Monnier <monnier@iro.umontreal.ca> | 16 | 2012-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" "\ |
| 487 | Make temporary function definitions. | 486 | Make temporary function definitions. |
| 488 | This is an analogue of `let' that operates on the function cell of FUNC | 487 | Like `cl-labels' but the definitions are not recursive. |
| 489 | rather than its value cell. The FORMs are evaluated with the specified | ||
| 490 | function definitions in place, then the definitions are undone (the FUNCs | ||
| 491 | go 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" "\ |
| 498 | Make temporary function bindings. | 494 | Make temporary function bindings. |
| 499 | This is like `cl-flet', except the bindings are lexical instead of dynamic. | 495 | The bindings can be recursive. Assumes the use of `lexical-binding'. |
| 500 | Unlike `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" "\ | ||
| 524 | Like `let', but lexically scoped. | ||
| 525 | The main visible difference is that lambdas inside BODY will create | ||
| 526 | lexical 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" "\ | ||
| 533 | Like `let*', but lexically scoped. | ||
| 534 | The main visible difference is that lambdas inside BODY, and in | ||
| 535 | successive bindings within BINDINGS, will create lexical closures | ||
| 536 | as in Common Lisp. This is similar to the behavior of `let*' in | ||
| 537 | Common 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" "\ |
| 544 | Collect multiple return values. | 519 | Collect multiple return values. |
| 545 | FORM must return a list; the BODY is then executed with the first N elements | 520 | FORM 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. |
| 1618 | This is an analogue of `let' that operates on the function cell of FUNC | 1637 | Like `cl-labels' but the definitions are not recursive. |
| 1619 | rather than its value cell. The FORMs are evaluated with the specified | ||
| 1620 | function definitions in place, then the definitions are undone (the FUNCs | ||
| 1621 | go 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) |
| 1638 | will 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. |
| 1651 | This is like `cl-flet', except the bindings are lexical instead of dynamic. | 1661 | The bindings can be recursive. Assumes the use of `lexical-binding'. |
| 1652 | Unlike `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). | ||
| 1758 | The 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. | ||
| 1804 | The main visible difference is that lambdas inside BODY will create | ||
| 1805 | lexical 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. | ||
| 1854 | The main visible difference is that lambdas inside BODY, and in | ||
| 1855 | successive bindings within BINDINGS, will create lexical closures | ||
| 1856 | as in Common Lisp. This is similar to the behavior of `let*' in | ||
| 1857 | Common 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). | ||
| 336 | The 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. | ||
| 382 | The main visible difference is that lambdas inside BODY will create | ||
| 383 | lexical 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. | ||
| 431 | The main visible difference is that lambdas inside BODY, and in | ||
| 432 | successive bindings within BINDINGS, will create lexical closures | ||
| 433 | as in Common Lisp. This is similar to the behavior of `let*' in | ||
| 434 | Common 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. | ||
| 447 | This is an analogue of `let' that operates on the function cell of FUNC | ||
| 448 | rather than its value cell. The FORMs are evaluated with the specified | ||
| 449 | function definitions in place, then the definitions are undone (the FUNCs | ||
| 450 | go 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' \ | ||
| 467 | will 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. | ||
| 479 | This is like `flet', except the bindings are lexical instead of dynamic. | ||
| 480 | Unlike `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 |