summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2021-01-27 18:51:09 -0500
committerStefan Monnier <monnier@iro.umontreal.ca>2021-01-27 18:51:09 -0500
commitd93bca019713e98228aca9f4d1a4838a72b1cf92 (patch)
tree3dd984c34b1e55e81975a1b55db17e0b4fcbb239 /lisp
parentd168110a322389a9f991d7a5bdd1cf777642c990 (diff)
downloademacs-d93bca019713e98228aca9f4d1a4838a72b1cf92.tar.gz
emacs-d93bca019713e98228aca9f4d1a4838a72b1cf92.tar.bz2
emacs-d93bca019713e98228aca9f4d1a4838a72b1cf92.zip
* lisp/emacs-lisp/pcase.el (pcase--split-pred): Handle `memq` pred.
Improve handling of the `member` tests generated from (or 'a 'b 'c). This will expand (pcase EXP ((and (or 1 2 3) (guard (FOO))) EXP1) (1 EXP2) (6 EXP3)) to (cond ((memql '(3 2 1) EXP) (cond ((FOO) EXP1) ((eql EXP 1) EXP2))) ((eql EXP 6) EXP3)) rather than to (cond ((memql '(3 2 1) EXP) (cond ((FOO) EXP1) ((eql EXP 1) EXP2) ((eql EXP 6) EXP3))) ((eql EXP 1) EXP2) ((eql EXP 6) EXP3))
Diffstat (limited to 'lisp')
-rw-r--r--lisp/emacs-lisp/pcase.el44
1 files changed, 27 insertions, 17 deletions
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index bfd577c5d14..cf129c453ec 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -683,11 +683,6 @@ A and B can be one of:
;; and catch at least the easy cases such as (bug#14773).
(not (macroexp--fgrep (mapcar #'car vars) (cadr upat)))))
'(:pcase--succeed . :pcase--fail))
- ;; In case UPAT is of the form (pred (not PRED))
- ((and (eq 'pred (car upat)) (eq 'not (car-safe (cadr upat))))
- (let* ((test (cadr (cadr upat)))
- (res (pcase--split-pred vars `(pred ,test) pat)))
- (cons (cdr res) (car res))))
;; In case PAT is of the form (pred (not PRED))
((and (eq 'pred (car-safe pat)) (eq 'not (car-safe (cadr pat))))
(let* ((test (cadr (cadr pat)))
@@ -696,19 +691,34 @@ A and B can be one of:
((eq x :pcase--fail) :pcase--succeed)))))
(cons (funcall reverse (car res))
(funcall reverse (cdr res)))))
- ((and (eq 'pred (car upat))
- (let ((otherpred
- (cond ((eq 'pred (car-safe pat)) (cadr pat))
- ((not (eq 'quote (car-safe pat))) nil)
- ((consp (cadr pat)) #'consp)
- ((stringp (cadr pat)) #'stringp)
- ((vectorp (cadr pat)) #'vectorp)
- ((byte-code-function-p (cadr pat))
- #'byte-code-function-p))))
- (pcase--mutually-exclusive-p (cadr upat) otherpred)))
+ ;; All the rest below presumes UPAT is of the form (pred ...).
+ ((not (eq 'pred (car upat))) nil)
+ ;; In case UPAT is of the form (pred (not PRED))
+ ((eq 'not (car-safe (cadr upat)))
+ (let* ((test (cadr (cadr upat)))
+ (res (pcase--split-pred vars `(pred ,test) pat)))
+ (cons (cdr res) (car res))))
+ ((let ((otherpred
+ (cond ((eq 'pred (car-safe pat)) (cadr pat))
+ ((not (eq 'quote (car-safe pat))) nil)
+ ((consp (cadr pat)) #'consp)
+ ((stringp (cadr pat)) #'stringp)
+ ((vectorp (cadr pat)) #'vectorp)
+ ((byte-code-function-p (cadr pat))
+ #'byte-code-function-p))))
+ (pcase--mutually-exclusive-p (cadr upat) otherpred))
'(:pcase--fail . nil))
- ((and (eq 'pred (car upat))
- (eq 'quote (car-safe pat))
+ ;; Since we turn (or 'a 'b 'c) into (pred (pcase--flip (memq '(a b c))))
+ ;; try and preserve the info we get from that memq test.
+ ((and (eq 'pcase--flip (car-safe (cadr upat)))
+ (memq (cadr (cadr upat)) '(memq member memql))
+ (eq 'quote (car-safe (nth 2 (cadr upat))))
+ (eq 'quote (car-safe pat)))
+ (let ((set (cadr (nth 2 (cadr upat)))))
+ (if (member (cadr pat) set)
+ '(nil . :pcase--fail)
+ '(:pcase--fail . nil))))
+ ((and (eq 'quote (car-safe pat))
(symbolp (cadr upat))
(or (symbolp (cadr pat)) (stringp (cadr pat)) (numberp (cadr pat)))
(get (cadr upat) 'side-effect-free)