diff options
| author | Stefan Monnier | 2016-05-30 16:33:07 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2016-05-30 16:33:07 -0400 |
| commit | 89cc852af3c7a17684b0d3083eca1ef2731f1f41 (patch) | |
| tree | 46a1b7901bf2b155291cda29a1ad68f35ab47469 | |
| parent | 060026b9162ed5a76e95d98eea4b8f3204f6b941 (diff) | |
| download | emacs-89cc852af3c7a17684b0d3083eca1ef2731f1f41.tar.gz emacs-89cc852af3c7a17684b0d3083eca1ef2731f1f41.zip | |
* lisp/emacs-lisp/pcase.el (pcase-mutually-exclusive-predicates): Add `atom'.
| -rw-r--r-- | lisp/emacs-lisp/pcase.el | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index 7e164c0fe5c..b18472d7e3d 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el | |||
| @@ -105,6 +105,8 @@ | |||
| 105 | specs))))) | 105 | specs))))) |
| 106 | (edebug-match cursor (cons '&or specs)))) | 106 | (edebug-match cursor (cons '&or specs)))) |
| 107 | 107 | ||
| 108 | (fset 'pcase--canon #'identity) | ||
| 109 | |||
| 108 | ;;;###autoload | 110 | ;;;###autoload |
| 109 | (defmacro pcase (exp &rest cases) | 111 | (defmacro pcase (exp &rest cases) |
| 110 | "Evaluate EXP and attempt to match it against structural patterns. | 112 | "Evaluate EXP and attempt to match it against structural patterns. |
| @@ -332,7 +334,8 @@ any kind of error." | |||
| 332 | ;; to a separate function if that number is too high. | 334 | ;; to a separate function if that number is too high. |
| 333 | ;; | 335 | ;; |
| 334 | ;; We've already used this branch. So it is shared. | 336 | ;; We've already used this branch. So it is shared. |
| 335 | (let* ((code (car prev)) (cdrprev (cdr prev)) | 337 | (let* (;; (code (car prev)) |
| 338 | (cdrprev (cdr prev)) | ||
| 336 | (prevvars (car cdrprev)) (cddrprev (cdr cdrprev)) | 339 | (prevvars (car cdrprev)) (cddrprev (cdr cdrprev)) |
| 337 | (res (car cddrprev))) | 340 | (res (car cddrprev))) |
| 338 | (unless (symbolp res) | 341 | (unless (symbolp res) |
| @@ -434,8 +437,10 @@ to this macro." | |||
| 434 | ;; Don't use let*, otherwise macroexp-let* may merge it with some surrounding | 437 | ;; Don't use let*, otherwise macroexp-let* may merge it with some surrounding |
| 435 | ;; let* which might prevent the setcar/setcdr in pcase--expand's fancy | 438 | ;; let* which might prevent the setcar/setcdr in pcase--expand's fancy |
| 436 | ;; codegen from later metamorphosing this let into a funcall. | 439 | ;; codegen from later metamorphosing this let into a funcall. |
| 437 | `(let ,(mapcar (lambda (b) (list (car b) (cdr b))) vars) | 440 | (if vars |
| 438 | ,@code)) | 441 | `(let ,(mapcar (lambda (b) (list (car b) (cdr b))) vars) |
| 442 | ,@code) | ||
| 443 | `(progn ,@code))) | ||
| 439 | 444 | ||
| 440 | (defun pcase--small-branch-p (code) | 445 | (defun pcase--small-branch-p (code) |
| 441 | (and (= 1 (length code)) | 446 | (and (= 1 (length code)) |
| @@ -451,7 +456,36 @@ to this macro." | |||
| 451 | (cond | 456 | (cond |
| 452 | ((eq else :pcase--dontcare) then) | 457 | ((eq else :pcase--dontcare) then) |
| 453 | ((eq then :pcase--dontcare) (debug) else) ;Can/should this ever happen? | 458 | ((eq then :pcase--dontcare) (debug) else) ;Can/should this ever happen? |
| 454 | (t (macroexp-if test then else)))) | 459 | ;; FIXME: The code below shows that there are some opportunities for sharing, |
| 460 | ;; but it's rarely useful to do it here, since almost all sharing found | ||
| 461 | ;; shares a trivial expression. | ||
| 462 | ;; But among the common trivial expressions are those of the form | ||
| 463 | ;; (funcall pcase-0). For this case, there could be a significant payoff | ||
| 464 | ;; if we could find the sharing-opportunity earlier so as to avoid | ||
| 465 | ;; the creation of pcase-0. | ||
| 466 | ;; ((and (eq 'if (car-safe then)) | ||
| 467 | ;; (equal (macroexp-unprogn (macroexp-progn (nthcdr 3 then))) | ||
| 468 | ;; (macroexp-unprogn else))) | ||
| 469 | ;; (let ((res (macroexp-if `(and ,test ,(nth 1 then)) | ||
| 470 | ;; (nth 2 then) else))) | ||
| 471 | ;; (message "if+if => if-and: sharing %S" else) | ||
| 472 | ;; res)) | ||
| 473 | ;; ((and (eq 'if (car-safe else)) | ||
| 474 | ;; (equal (nth 2 else) then)) | ||
| 475 | ;; (let ((res (macroexp-if `(or ,test ,(nth 1 else)) | ||
| 476 | ;; then (macroexp-progn (nthcdr 3 else))))) | ||
| 477 | ;; (message "if+if => if-or: sharing %S" then) | ||
| 478 | ;; res)) | ||
| 479 | (t | ||
| 480 | ;; (cond | ||
| 481 | ;; ((and (eq 'cond (car-safe then)) | ||
| 482 | ;; (equal `(cond ,@(nthcdr 2 then)) else)) | ||
| 483 | ;; (message "if+cond => cond-and: sharing %S" else)) | ||
| 484 | ;; ((and (eq 'cond (car-safe else)) | ||
| 485 | ;; (equal (macroexp-unprogn (macroexp-progn (cdr (nth 1 else)))) | ||
| 486 | ;; (macroexp-unprogn then))) | ||
| 487 | ;; (message "if+cond => cond-or: sharing %S" then))) | ||
| 488 | (macroexp-if test then else)))) | ||
| 455 | 489 | ||
| 456 | ;; Note about MATCH: | 490 | ;; Note about MATCH: |
| 457 | ;; When we have patterns like `(PAT1 . PAT2), after performing the `consp' | 491 | ;; When we have patterns like `(PAT1 . PAT2), after performing the `consp' |
| @@ -509,6 +543,7 @@ MATCH is the pattern that needs to be matched, of the form: | |||
| 509 | (numberp . stringp) | 543 | (numberp . stringp) |
| 510 | (numberp . byte-code-function-p) | 544 | (numberp . byte-code-function-p) |
| 511 | (consp . arrayp) | 545 | (consp . arrayp) |
| 546 | (consp . atom) | ||
| 512 | (consp . vectorp) | 547 | (consp . vectorp) |
| 513 | (consp . stringp) | 548 | (consp . stringp) |
| 514 | (consp . byte-code-function-p) | 549 | (consp . byte-code-function-p) |
| @@ -918,6 +953,14 @@ QPAT can take the following forms: | |||
| 918 | ((or (stringp qpat) (integerp qpat) (symbolp qpat)) `',qpat) | 953 | ((or (stringp qpat) (integerp qpat) (symbolp qpat)) `',qpat) |
| 919 | (t (error "Unknown QPAT: %S" qpat)))) | 954 | (t (error "Unknown QPAT: %S" qpat)))) |
| 920 | 955 | ||
| 956 | ;;; Extra definitions that use pcase. | ||
| 957 | |||
| 958 | (defun pcase--canon (e) | ||
| 959 | (pcase e | ||
| 960 | (`(progn ,e) (pcase--canon e)) | ||
| 961 | (`(cond (,test . ,then) (t . ,else)) | ||
| 962 | `(if ,test ,(macroexp-progn then) ,(macroexp-progn else))))) | ||
| 963 | |||
| 921 | 964 | ||
| 922 | (provide 'pcase) | 965 | (provide 'pcase) |
| 923 | ;;; pcase.el ends here | 966 | ;;; pcase.el ends here |