* lisp/emacs-lisp/cl-macs.el (cl--sm-macroexpand): Handle lambda!
(cl--old-macroexpand): Remove. (cl--sm-macroexpand): Change its calling convention, so it can use advice-add. Extend re-binding treatment of vars so it applies to all var-introducing forms rather than only to 'let'. (cl-symbol-macrolet): Use advice-add rather than fset.
This commit is contained in:
parent
d34dbc0b69
commit
6b183f85e0
2 changed files with 59 additions and 26 deletions
|
@ -2089,23 +2089,15 @@ This is like `cl-flet', but for macros instead of functions.
|
||||||
(eval `(cl-function (lambda ,@(cdr res))) t))
|
(eval `(cl-function (lambda ,@(cdr res))) t))
|
||||||
macroexpand-all-environment))))))
|
macroexpand-all-environment))))))
|
||||||
|
|
||||||
(defconst cl--old-macroexpand
|
(defun cl--sm-macroexpand (orig-fun exp &optional env)
|
||||||
(if (and (boundp 'cl--old-macroexpand)
|
"Special macro expander advice used inside `cl-symbol-macrolet'.
|
||||||
(eq (symbol-function 'macroexpand)
|
This function extends `macroexpand' during macro expansion
|
||||||
#'cl--sm-macroexpand))
|
of `cl-symbol-macrolet' to additionally expand symbol macros."
|
||||||
cl--old-macroexpand
|
|
||||||
(symbol-function 'macroexpand)))
|
|
||||||
|
|
||||||
(defun cl--sm-macroexpand (exp &optional env)
|
|
||||||
"Special macro expander used inside `cl-symbol-macrolet'.
|
|
||||||
This function replaces `macroexpand' during macro expansion
|
|
||||||
of `cl-symbol-macrolet', and does the same thing as `macroexpand'
|
|
||||||
except that it additionally expands symbol macros."
|
|
||||||
(let ((macroexpand-all-environment env)
|
(let ((macroexpand-all-environment env)
|
||||||
(venv (alist-get :cl-symbol-macros env)))
|
(venv (alist-get :cl-symbol-macros env)))
|
||||||
(while
|
(while
|
||||||
(progn
|
(progn
|
||||||
(setq exp (funcall cl--old-macroexpand exp env))
|
(setq exp (funcall orig-fun exp env))
|
||||||
(pcase exp
|
(pcase exp
|
||||||
((pred symbolp)
|
((pred symbolp)
|
||||||
;; Perform symbol-macro expansion.
|
;; Perform symbol-macro expansion.
|
||||||
|
@ -2114,7 +2106,7 @@ except that it additionally expands symbol macros."
|
||||||
(setq exp (cadr symval)))))
|
(setq exp (cadr symval)))))
|
||||||
(`(setq . ,_)
|
(`(setq . ,_)
|
||||||
;; Convert setq to setf if required by symbol-macro expansion.
|
;; Convert setq to setf if required by symbol-macro expansion.
|
||||||
(let* ((args (mapcar (lambda (f) (cl--sm-macroexpand f env))
|
(let* ((args (mapcar (lambda (f) (macroexpand f env))
|
||||||
(cdr exp)))
|
(cdr exp)))
|
||||||
(p args))
|
(p args))
|
||||||
(while (and p (symbolp (car p))) (setq p (cddr p)))
|
(while (and p (symbolp (car p))) (setq p (cddr p)))
|
||||||
|
@ -2160,10 +2152,10 @@ except that it additionally expands symbol macros."
|
||||||
(list (macroexpand-all (cadr binding)
|
(list (macroexpand-all (cadr binding)
|
||||||
env)))))
|
env)))))
|
||||||
(push (if (assq var venv)
|
(push (if (assq var venv)
|
||||||
;; This binding should hide its symbol-macro,
|
;; This binding should hide "its" surrounding
|
||||||
;; but given the way macroexpand-all works
|
;; symbol-macro, but given the way macroexpand-all
|
||||||
;; (i.e. the `env' we receive as input will be
|
;; works (i.e. the `env' we receive as input will
|
||||||
;; (re)applied to the code we return), we can't
|
;; be (re)applied to the code we return), we can't
|
||||||
;; prevent application of `env' to the
|
;; prevent application of `env' to the
|
||||||
;; sub-expressions, so we need to α-rename this
|
;; sub-expressions, so we need to α-rename this
|
||||||
;; variable instead.
|
;; variable instead.
|
||||||
|
@ -2181,6 +2173,43 @@ except that it additionally expands symbol macros."
|
||||||
(macroexpand-all (macroexp-progn body)
|
(macroexpand-all (macroexp-progn body)
|
||||||
env)))))
|
env)))))
|
||||||
nil))
|
nil))
|
||||||
|
;; Do the same as for `let' but for variables introduced
|
||||||
|
;; via other means, such as `lambda' and `condition-case'.
|
||||||
|
(`(function (lambda ,args . ,body))
|
||||||
|
(let ((nargs ()) (found nil))
|
||||||
|
(dolist (var args)
|
||||||
|
(push (cond
|
||||||
|
((memq var '(&optional &rest)) var)
|
||||||
|
((assq var venv)
|
||||||
|
(let ((nvar (make-symbol (symbol-name var))))
|
||||||
|
(setq found t)
|
||||||
|
(push (list var nvar) venv)
|
||||||
|
(push (cons :cl-symbol-macros venv) env)
|
||||||
|
nvar))
|
||||||
|
(t var))
|
||||||
|
nargs))
|
||||||
|
(when found
|
||||||
|
(setq exp `(function
|
||||||
|
(lambda ,(nreverse nargs)
|
||||||
|
. ,(mapcar (lambda (exp)
|
||||||
|
(macroexpand-all exp env))
|
||||||
|
body)))))
|
||||||
|
nil))
|
||||||
|
((and `(condition-case ,var ,exp . ,clauses)
|
||||||
|
(guard (assq var venv)))
|
||||||
|
(let ((nvar (make-symbol (symbol-name var))))
|
||||||
|
(push (list var nvar) venv)
|
||||||
|
(push (cons :cl-symbol-macros venv) env)
|
||||||
|
(setq exp
|
||||||
|
`(condition-case ,nvar ,(macroexpand-all exp env)
|
||||||
|
. ,(mapcar
|
||||||
|
(lambda (clause)
|
||||||
|
`(,(car clause)
|
||||||
|
. ,(mapcar (lambda (exp)
|
||||||
|
(macroexpand-all exp env))
|
||||||
|
(cdr clause))))
|
||||||
|
clauses)))
|
||||||
|
nil))
|
||||||
)))
|
)))
|
||||||
exp))
|
exp))
|
||||||
|
|
||||||
|
@ -2192,16 +2221,18 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
|
||||||
|
|
||||||
\(fn ((NAME EXPANSION) ...) FORM...)"
|
\(fn ((NAME EXPANSION) ...) FORM...)"
|
||||||
(declare (indent 1) (debug ((&rest (symbolp sexp)) cl-declarations body)))
|
(declare (indent 1) (debug ((&rest (symbolp sexp)) cl-declarations body)))
|
||||||
(let ((previous-macroexpand (symbol-function 'macroexpand))
|
(let ((malformed-bindings nil)
|
||||||
(malformed-bindings nil))
|
(advised (advice-member-p #'cl--sm-macroexpand 'macroexpand)))
|
||||||
(dolist (binding bindings)
|
(dolist (binding bindings)
|
||||||
(unless (and (consp binding) (symbolp (car binding))
|
(unless (and (consp binding) (symbolp (car binding))
|
||||||
(consp (cdr binding)) (null (cddr binding)))
|
(consp (cdr binding)) (null (cddr binding)))
|
||||||
(push binding malformed-bindings)))
|
(push binding malformed-bindings)))
|
||||||
(unwind-protect
|
(unwind-protect
|
||||||
(progn
|
(progn
|
||||||
(fset 'macroexpand #'cl--sm-macroexpand)
|
(unless advised
|
||||||
(let* ((venv (cdr (assq :cl-symbol-macros macroexpand-all-environment)))
|
(advice-add 'macroexpand :around #'cl--sm-macroexpand))
|
||||||
|
(let* ((venv (cdr (assq :cl-symbol-macros
|
||||||
|
macroexpand-all-environment)))
|
||||||
(expansion
|
(expansion
|
||||||
(macroexpand-all (macroexp-progn body)
|
(macroexpand-all (macroexp-progn body)
|
||||||
(cons (cons :cl-symbol-macros
|
(cons (cons :cl-symbol-macros
|
||||||
|
@ -2213,7 +2244,8 @@ by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
|
||||||
(nreverse malformed-bindings))
|
(nreverse malformed-bindings))
|
||||||
expansion)
|
expansion)
|
||||||
expansion)))
|
expansion)))
|
||||||
(fset 'macroexpand previous-macroexpand))))
|
(unless advised
|
||||||
|
(advice-remove 'macroexpand #'cl--sm-macroexpand)))))
|
||||||
|
|
||||||
;;; Multiple values.
|
;;; Multiple values.
|
||||||
|
|
||||||
|
|
|
@ -518,13 +518,14 @@
|
||||||
|
|
||||||
|
|
||||||
(ert-deftest cl-lib-symbol-macrolet-hide ()
|
(ert-deftest cl-lib-symbol-macrolet-hide ()
|
||||||
;; bug#26325
|
;; bug#26325, bug#26073
|
||||||
(should (equal (let ((y 5))
|
(should (equal (let ((y 5))
|
||||||
(cl-symbol-macrolet ((x y))
|
(cl-symbol-macrolet ((x y))
|
||||||
(list x
|
(list x
|
||||||
(let ((x 6)) (list x y))
|
(let ((x 6)) (list x y))
|
||||||
(cl-letf ((x 6)) (list x y)))))
|
(cl-letf ((x 6)) (list x y))
|
||||||
'(5 (6 5) (6 6)))))
|
(apply (lambda (x) (+ x 1)) (list 8)))))
|
||||||
|
'(5 (6 5) (6 6) 9))))
|
||||||
|
|
||||||
(defun cl-lib-tests--dummy-function ()
|
(defun cl-lib-tests--dummy-function ()
|
||||||
;; Dummy function to see if the file is compiled.
|
;; Dummy function to see if the file is compiled.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue