aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2014-09-22 11:04:12 -0400
committerStefan Monnier2014-09-22 11:04:12 -0400
commit536cda1f84f3be1959e5a475e51dbecaa2253bfd (patch)
treeb6dfd400c6f4b13d5a8ce9442c52f26df948986b
parent13b1840d23f1f214bec11a3c6823d675cbd82f28 (diff)
downloademacs-536cda1f84f3be1959e5a475e51dbecaa2253bfd.tar.gz
emacs-536cda1f84f3be1959e5a475e51dbecaa2253bfd.zip
* lisp/emacs-lisp/pcase.el (pcase-defmacro): New macro.
(pcase--macroexpand): New function. (pcase--expand): Use it.
-rw-r--r--etc/NEWS1
-rw-r--r--lisp/ChangeLog4
-rw-r--r--lisp/emacs-lisp/pcase.el27
3 files changed, 31 insertions, 1 deletions
diff --git a/etc/NEWS b/etc/NEWS
index cbad7c5b54b..397b8866f6b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -104,6 +104,7 @@ performance improvements when pasting large amounts of text.
104 104
105** pcase 105** pcase
106*** New UPatterns `quote' and `app'. 106*** New UPatterns `quote' and `app'.
107*** New UPatterns can be defined with `pcase-defmacro'.
107 108
108** Lisp mode 109** Lisp mode
109*** Strings after `:documentation' are highlighted as docstrings. 110*** Strings after `:documentation' are highlighted as docstrings.
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 1aad2004d6a..32843569eda 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,9 @@
12014-09-22 Stefan Monnier <monnier@iro.umontreal.ca> 12014-09-22 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * emacs-lisp/pcase.el (pcase-defmacro): New macro.
4 (pcase--macroexpand): New function.
5 (pcase--expand): Use it.
6
3 Add support for `quote' and `app'. 7 Add support for `quote' and `app'.
4 * emacs-lisp/pcase.el (pcase--app-subst-match, pcase--app-subst-rest): 8 * emacs-lisp/pcase.el (pcase--app-subst-match, pcase--app-subst-rest):
5 New optimization functions. 9 New optimization functions.
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index fbe241b6fc8..2d5f19fe5f7 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -284,7 +284,7 @@ of the form (UPAT EXP)."
284 (main 284 (main
285 (pcase--u 285 (pcase--u
286 (mapcar (lambda (case) 286 (mapcar (lambda (case)
287 `((match ,val . ,(car case)) 287 `((match ,val . ,(pcase--macroexpand (car case)))
288 ,(lambda (vars) 288 ,(lambda (vars)
289 (unless (memq case used-cases) 289 (unless (memq case used-cases)
290 ;; Keep track of the cases that are used. 290 ;; Keep track of the cases that are used.
@@ -303,6 +303,31 @@ of the form (UPAT EXP)."
303 (message "Redundant pcase pattern: %S" (car case)))) 303 (message "Redundant pcase pattern: %S" (car case))))
304 (macroexp-let* defs main)))) 304 (macroexp-let* defs main))))
305 305
306(defun pcase--macroexpand (pat)
307 "Expands all macro-patterns in PAT."
308 (let ((head (car-safe pat)))
309 (cond
310 ((memq head '(nil pred guard quote)) pat)
311 ((memq head '(or and)) `(,head ,@(mapcar #'pcase--macroexpand (cdr pat))))
312 ((eq head 'let) `(let ,(pcase--macroexpand (cadr pat)) ,@(cddr pat)))
313 ((eq head 'app) `(app ,(nth 1 pat) ,(pcase--macroexpand (nth 2 pat))))
314 (t
315 (let* ((expander (get head 'pcase-macroexpander))
316 (npat (if expander (apply expander (cdr pat)))))
317 (if (null npat)
318 (error (if expander
319 "Unexpandable %s pattern: %S"
320 "Unknown %s pattern: %S")
321 head pat)
322 (pcase--macroexpand npat)))))))
323
324;;;###autoload
325(defmacro pcase-defmacro (name args &rest body)
326 "Define a pcase UPattern macro."
327 (declare (indent 2) (debug (def-name sexp def-body)) (doc-string 3))
328 `(put ',name 'pcase-macroexpander
329 (lambda ,args ,@body)))
330
306(defun pcase-codegen (code vars) 331(defun pcase-codegen (code vars)
307 ;; Don't use let*, otherwise macroexp-let* may merge it with some surrounding 332 ;; Don't use let*, otherwise macroexp-let* may merge it with some surrounding
308 ;; let* which might prevent the setcar/setcdr in pcase--expand's fancy 333 ;; let* which might prevent the setcar/setcdr in pcase--expand's fancy