From 2bf2855b57a97387d674799785cf009bbc07c842 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Sun, 8 Feb 2026 16:09:11 +0000 Subject: [PATCH] Restore 'cond' one element clauses to 'cond*' * lisp/emacs-lisp/cond-star.el (cond*-non-exit-clause-p) (cond*-non-exit-clause-substance): Treat only one element clauses beginning with match*/pcase* pseudoforms as non-exit. (cond*-convert-condition): Handle exiting clauses with only one element, that is a regular Lisp expression. (cond*): * doc/lispref/control.texi (cond* Macro): Document the change. --- doc/lispref/control.texi | 5 ++-- lisp/emacs-lisp/cond-star.el | 56 ++++++++++++++++++++++-------------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index 85e13952cfb..e88a7533d89 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -1549,8 +1549,9 @@ becomes the return value of the @code{cond*} construct. @subheading Non-exit clauses -If a clause has only one element, or if its first element is @code{t} or -a @code{bind*} form, or if it ends with the keyword @code{:non-exit}, +If the first element of a clause is @code{t} or a @code{bind*} form, or +if it has only one element and that element is a @code{match*} or +@code{pcase*} form, or if it ends with the keyword @code{:non-exit}, then this clause never exits the @code{cond*} construct. Instead, control falls through to the next clause (if any). Except for a @code{bind-and*} clause, the bindings made in @var{condition} for the diff --git a/lisp/emacs-lisp/cond-star.el b/lisp/emacs-lisp/cond-star.el index 72b58d91151..97a24011bce 100644 --- a/lisp/emacs-lisp/cond-star.el +++ b/lisp/emacs-lisp/cond-star.el @@ -83,12 +83,13 @@ in its body becomes the return value of the `cond*' construct. Non-exit clauses: -If a clause has only one element, or if its first element is t or a -`bind*' form, or if it ends with the keyword `:non-exit', then this -clause never exits the `cond*' construct. Instead, control always falls -through to the next clause (if any). Except for a `bind-and*' clause, -all bindings made in CONDITION for the BODY of the non-exit clause are -passed along to the rest of the clauses in this `cond*' construct. +If the first element of a clause is t or a `bind*' form, or if it has +only one element and that element is a `match*' or `pcase*' form, or if +it ends with the keyword `:non-exit', then this clause never exits the +`cond*' construct. Instead, control always falls through to the next +clause (if any). Except for a `bind-and*' clause, all bindings made in +CONDITION for the BODY of the non-exit clause are passed along to the +rest of the clauses in this `cond*' construct. See `match*' for documentation of the patterns for use in `match*' conditions." @@ -197,22 +198,31 @@ CONDITION of a `cond*' clause. See `cond*' for details." (defun cond*-non-exit-clause-p (clause) "If CLAUSE, a cond* clause, is a non-exit clause, return t." - (or (null (cdr-safe clause)) ;; clause has only one element. - (and (cdr-safe clause) - ;; Starts with t. - (or (eq (car clause) t) - ;; Starts with a `bind*' pseudo-form. - (and (consp (car clause)) - (eq (caar clause) 'bind*)))) - ;; Ends with keyword. - (eq (car (last clause)) :non-exit))) + (or + ;; Starts with t. + (and (cdr-safe clause) + (eq (car clause) t)) + ;; Starts with a `bind*' pseudo-form. + (and (consp (car clause)) + (eq (caar clause) 'bind*)) + ;; Has one element that's a `match*' or `pcase*' pseudo-form. + (and (null (cdr-safe clause)) + (consp (car clause)) + (memq (caar clause) '(match* pcase*))) + ;; Ends with keyword. + (eq (car (last clause)) :non-exit))) (defun cond*-non-exit-clause-substance (clause) "For a non-exit cond* clause CLAUSE, return its substance. This removes a final keyword if that's what makes CLAUSE non-exit." - (cond ((or (null (cdr-safe clause)) ;; either clause has only one element - (and (consp (car clause)) ;; or it starts with `bind*' - (eq (caar clause) 'bind*))) + (cond ((or + ;; Starts with `bind*' pseudo-form. + (and (consp (car clause)) + (eq (caar clause) 'bind*)) + ;; Or has one element that's a `match*'/`pcase*' pseudo-form. + (and (null (cdr-safe clause)) + (consp (car clause)) + (memq (caar clause) '(match* pcase*)))) clause) ;; Starts with t or a keyword. ;; Include t as the first element of the substance @@ -374,12 +384,14 @@ This is used for conditional exit clauses." ;; Ordinary Lisp expression is the condition. (if rest ;; A nonfinal exiting clause. - ;; If condition succeeds, run the TRUE-EXPS. + ;; If condition succeeds, return it or run the TRUE-EXPS. ;; There are following clauses, so run IFFALSE ;; if the condition fails. - `(if ,condition - (progn . ,true-exps) - ,iffalse) + (if true-exps + `(if ,condition + (progn . ,true-exps) + ,iffalse) + `(or ,condition ,iffalse)) (if uncondit-clauses ;; A non-exit clause. ;; If condition succeeds, run the TRUE-EXPS.