From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= <mattiase@acm.org> Newsgroups: gmane.emacs.bugs Subject: bug#36139: [PATCH] Make better use of the switch op in cond forms Date: Sat, 8 Jun 2019 16:40:07 +0200 Message-ID: <68467ACF-DA49-4EBA-BA3B-7339DB22A456@acm.org> Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.11\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_6425368A-6F6F-40E3-9751-3E52F91F6248" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="30483"; mail-complaints-to="usenet@blaine.gmane.org" Cc: Stefan Monnier <monnier@iro.umontreal.ca> To: 36139@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Jun 08 17:16:43 2019 Return-path: <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org> Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org>) id 1hZd5G-0007lB-Gy for geb-bug-gnu-emacs@m.gmane.org; Sat, 08 Jun 2019 17:16:42 +0200 Original-Received: from localhost ([::1]:58998 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org>) id 1hZd5F-0007cM-Hb for geb-bug-gnu-emacs@m.gmane.org; Sat, 08 Jun 2019 11:16:41 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:49970) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1hZd4l-0007a7-9g for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 11:16:13 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1hZd4j-0004wA-53 for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 11:16:11 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:39967) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1hZd4c-0004tF-Gk for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 11:16:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from <Debian-debbugs@debbugs.gnu.org>) id 1hZd4c-0003Qf-BA for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 11:16:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= <mattiase@acm.org> Original-Sender: "Debbugs-submit" <debbugs-submit-bounces@debbugs.gnu.org> Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 08 Jun 2019 15:16:02 +0000 Resent-Message-ID: <handler.36139.B.156000695013159@debbugs.gnu.org> Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 36139 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.156000695013159 (code B ref -1); Sat, 08 Jun 2019 15:16:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 8 Jun 2019 15:15:50 +0000 Original-Received: from localhost ([127.0.0.1]:53511 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <debbugs-submit-bounces@debbugs.gnu.org>) id 1hZd4P-0003QB-Cw for submit@debbugs.gnu.org; Sat, 08 Jun 2019 11:15:49 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:56234) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from <mattiase@acm.org>) id 1hZd4O-0003Q4-0d for submit@debbugs.gnu.org; Sat, 08 Jun 2019 11:15:48 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:49805) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from <mattiase@acm.org>) id 1hZd4D-0007UD-GR for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 11:15:44 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <mattiase@acm.org>) id 1hZd43-0004Xq-Pm for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 11:15:33 -0400 Original-Received: from mail1423c50.megamailservers.eu ([91.136.14.23]:58010 helo=mail102c50.megamailservers.eu) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <mattiase@acm.org>) id 1hZd3u-0004Ru-PT for bug-gnu-emacs@gnu.org; Sat, 08 Jun 2019 11:15:21 -0400 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1560004810; bh=q7jFxCHF7YGiYJ2CX4fZBdTgsgWfSDK80UCY2jKuCwY=; h=From:Subject:Date:Cc:To:From; b=ICZlOMpNjru7eAhjAW1n/sL+87zypGBstm0GJu0kegpjCv/+HEXsgnL0TYbfs9mrx 2nAojpCqecINUzHH1t3bnrF23rrWSSV5Tvs/n9eT4CtITp/fXug8tbPiOW3jUk9ORQ Y4lHDHvVtEV96pnVio9f8fVDJYUc6jypHvCK341k= Feedback-ID: mattiase@acm.or Original-Received: from [192.168.0.4] ([188.150.171.71]) (authenticated bits=0) by mail102c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id x58Ee737011987; Sat, 8 Jun 2019 14:40:09 +0000 X-Mailer: Apple Mail (2.3445.104.11) X-CTCH-RefID: str=0001.0A0B0213.5CFBC8CA.0011, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0 X-CTCH-VOD: Unknown X-CTCH-Spam: Unknown X-CTCH-Score: 0.000 X-CTCH-Flags: 0 X-CTCH-ScoreCust: 0.000 X-CSC: 0 X-CHA: v=2.3 cv=F7x5iJpN c=1 sm=1 tr=0 a=SF+I6pRkHZhrawxbOkkvaA==:117 a=SF+I6pRkHZhrawxbOkkvaA==:17 a=6To3NTLLAc8gFo8t5NcA:9 a=7Zwj6sZBwVKJAoWSPKxL6X1jA+E=:19 a=CjuIK1q_8ugA:10 a=E_EwgWnIFQbYCWLjBlUA:9 a=B2y7HmGcmWMA:10 a=mTj2RzUfRsJlQHX1IeMA:9 a=KPFwjdhr0wLR6wY-cI4A:9 a=J5JVcn0FUx--a41e-UEA:9 a=hcRNxtQ6DiqpJ61ql5UA:9 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs.gnu.org> List-Unsubscribe: <https://lists.gnu.org/mailman/options/bug-gnu-emacs>, <mailto:bug-gnu-emacs-request@gnu.org?subject=unsubscribe> List-Archive: <https://lists.gnu.org/archive/html/bug-gnu-emacs> List-Post: <mailto:bug-gnu-emacs@gnu.org> List-Help: <mailto:bug-gnu-emacs-request@gnu.org?subject=help> List-Subscribe: <https://lists.gnu.org/mailman/listinfo/bug-gnu-emacs>, <mailto:bug-gnu-emacs-request@gnu.org?subject=subscribe> Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" <bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org> Xref: news.gmane.org gmane.emacs.bugs:160240 Archived-At: <http://permalink.gmane.org/gmane.emacs.bugs/160240> --Apple-Mail=_6425368A-6F6F-40E3-9751-3E52F91F6248 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Currently, `cond' forms will only use a switch op under very specific = circumstances, which limits their potential utility: every condition = must be a scalar comparison (eq, eql or equal) between a variable and a = constant; the same variable and the same test function must be used = everywhere. These restrictions also limit the generation of switch ops = from `pcase' and `cl-case' constructs. In actual `cond' forms, scalar comparisons are mixed with multi-value = ones (memq, memql, member); different comparisons are mixed, since the = type of values can vary at runtime. There are also non-switch = comparisons thrown into the same `cond' for convenience, typically at = the beginning or end. Occasionally, there are even multiple switch-like = sequences against different variables in the same cond. Attached is a set of patches which gradually eliminate many of these = restrictions. Each patch makes a fixed and hopefully easily-reviewed = improvement. Short overview: * 0001-Compile-list-member-functions-in-cond-to-switch.patch Allow memq, memql and member to be used in switch generation, since = these are idiomatically used for multiple values with the same body. = They are also used by `pcase' and `cl-case'. For example, (cond ((eq x 'a) 11) ((memq x '(b c d)) 22)) will generate a single switch as if the code had been (cond ((eq x 'a) 11) ((eq x 'b) 22) ((eq x 'c) 22) ((eq x 'd) 22)) - that is, the byte code for the body (22) will be generated thrice. * 0002-Share-identical-switch-clause-bodies.patch An improvement of the above to share the body byte code between all = values of the same `cond' clause. This means that the switch jump table = is no longer an injective mapping. * 0003-Tighter-pcase-or-pattern-member-function-selection.patch Make `pcase' use the most specific comparison function (memq instead of = memql, etc) in each case, depending on the values. This patch is technically independent of the other ones, but improves = code generation for `pcase'. * 0004-Compile-cond-with-heterogeneous-tests-into-switch.patch Allow switch generation with a mixture of eq, eql, equal, memq, memql = and member. * 0005-Compile-any-subsequence-of-cond-clauses-to-switch.patch Generalise the code to produce switch ops for any switch-like part of a = `cond' form. These switches can use different variables, and there can = be any number of non-switch clauses before, after and between the switch = clauses. Performance: The patch set is loosely monotonous with the assumptions = already present, in the sense that if the current code generator does = not produce slower code in any case, nor is it expected to do so after = the patches have been applied. In practice, micro-benchmarks naturally = show the expected gains, but I haven't found much real-world code that = is easy enough to benchmark. Some unpublished tree-traversal code = improved about 7 %. --Apple-Mail=_6425368A-6F6F-40E3-9751-3E52F91F6248 Content-Disposition: attachment; filename=0001-Compile-list-member-functions-in-cond-to-switch.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-Compile-list-member-functions-in-cond-to-switch.patch" Content-Transfer-Encoding: quoted-printable =46rom=207ddfbaf4e50f96d0feb05983c4f1d144af774052=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= <mattiase@acm.org>=0ADate:=20Tue,=2021=20May=202019=2011:56:14=20+0200=0A= Subject:=20[PATCH=201/5]=20Compile=20list=20member=20functions=20in=20= cond=20to=20switch=0A=0A*=20lisp/emacs-lisp/bytecomp.el=20= (byte-compile-cond-jump-table-info):=0AExpand=20`memq',=20`memql'=20and=20= `member'=20to=20their=20corresponding=0Aequality=20tests.=0A---=0A=20= lisp/emacs-lisp/bytecomp.el=20|=2046=20= +++++++++++++++++++++++++------------=0A=201=20file=20changed,=2031=20= insertions(+),=2015=20deletions(-)=0A=0Adiff=20--git=20= a/lisp/emacs-lisp/bytecomp.el=20b/lisp/emacs-lisp/bytecomp.el=0Aindex=20= 38cce14fd6..8f089119de=20100644=0A---=20a/lisp/emacs-lisp/bytecomp.el=0A= +++=20b/lisp/emacs-lisp/bytecomp.el=0A@@=20-4117,23=20+4117,39=20@@=20= byte-compile-cond-jump-table-info=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(byte-compile-cond-vars=20= (cadr=20condition)=20(cl-caddr=20condition))))=0A=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(obj1=20(car-safe=20vars))=0A=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(obj2=20= (cdr-safe=20vars))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(body=20(cdr-safe=20clause)))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(body=20(cdr-safe=20clause))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20equality)=0A=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(unless=20prev-var=0A=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(setq=20prev-var=20obj1))=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(unless=20prev-test=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(setq=20prev-test=20test))=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(if=20(and=20obj1=20(memq=20test=20'(eq=20= eql=20equal))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(eq=20test=20prev-test)=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(eq=20obj1=20prev-var))=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20discard=20duplicate=20= clauses=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (unless=20(assoc=20obj2=20cases=20test)=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(push=20(list=20obj2=20body)=20cases))=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(if=20(and=20= (macroexp-const-p=20condition)=20condition)=0A-=09=09=20=20=20=20=20= (progn=20(push=20(list=20byte-compile--default-val=0A-=09=09=09=09=09(or=20= body=20`(,condition)))=0A-=09=09=09=09=20=20cases)=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(throw=20= 'break=20t))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (setq=20ok=20nil)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cond=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((and=20obj1=20(memq=20= test=20'(eq=20eql=20equal))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(eq=20obj1=20prev-var)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(or=20(not=20prev-test)=20(eq=20= test=20prev-test)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (setq=20prev-test=20test)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20;;=20discard=20duplicate=20clauses=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(unless=20(assoc=20obj2=20cases=20test)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(list=20obj2=20= body)=20cases)))=0A+=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ((and=20obj1=20(memq=20test=20'(memq=20memql=20member))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(eq=20obj1=20= prev-var)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(listp=20obj2)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(setq=20equality=20(cdr=20(assq=20test=20'((memq=20=20=20= .=20eq)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(memql=20=20.=20eql)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (member=20.=20equal)))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(or=20(not=20prev-test)=20(eq=20equality=20= prev-test)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= prev-test=20equality)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20;;=20Expand=20to=20individual=20equality=20tests.=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(dolist=20(elem=20obj2)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(unless=20(assoc=20elem=20= cases=20equality)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(push=20(list=20elem=20(or=20body=20`(',(funcall=20test=20elem=20= obj2))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20cases))))=0A+=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20((and=20(macroexp-const-p=20condition)=20condition)=0A+=09=09=20= (push=20(list=20byte-compile--default-val=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(or=20body=20= `(,condition)))=0A+=09=09=20=20=20=20=20=20=20cases)=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(throw=20'break=20t))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(t=20(setq=20ok=20nil)=0A=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(throw=20'break=20nil))))))=0A= =20=20=20=20=20=20=20=20=20=20(list=20(cons=20prev-test=20prev-var)=20= (nreverse=20cases)))))=0A=20=0A--=20=0A2.20.1=20(Apple=20Git-117)=0A=0A= --Apple-Mail=_6425368A-6F6F-40E3-9751-3E52F91F6248 Content-Disposition: attachment; filename=0002-Share-identical-switch-clause-bodies.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0002-Share-identical-switch-clause-bodies.patch" Content-Transfer-Encoding: quoted-printable =46rom=208e3a4317488940adfd58a43e2f66acafba2ea11f=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= <mattiase@acm.org>=0ADate:=20Sun,=2026=20May=202019=2014:04:22=20+0200=0A= Subject:=20[PATCH=202/5]=20Share=20identical=20switch=20clause=20bodies=0A= =0A*=20lisp/emacs-lisp/bytecomp.el=20(byte-compile-cond-jump-table-info)=0A= (byte-compile-cond-jump-table):=0ACases=20now=20have=20multiple=20= values.=0A*=20lisp/emacs-lisp/byte-opt.el=20(byte-decompile-bytecode-1)=0A= (byte-optimize-lapcode):=20Don't=20assume=20switch=20hash=20tables=20to=20= be=20injective.=0A---=0A=20lisp/emacs-lisp/byte-opt.el=20|=2021=20= +++++++--------=0A=20lisp/emacs-lisp/bytecomp.el=20|=2051=20= ++++++++++++++++++++++---------------=0A=202=20files=20changed,=2042=20= insertions(+),=2030=20deletions(-)=0A=0Adiff=20--git=20= a/lisp/emacs-lisp/byte-opt.el=20b/lisp/emacs-lisp/byte-opt.el=0Aindex=20= 44cca6136c..b0aa407c8b=20100644=0A---=20a/lisp/emacs-lisp/byte-opt.el=0A= +++=20b/lisp/emacs-lisp/byte-opt.el=0A@@=20-1376,11=20+1376,15=20@@=20= byte-decompile-bytecode-1=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20do=20(setq=20last-constant=20= (copy-hash-table=20e))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20and=20return=20nil)=0A=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20;;=20Replace=20all=20addresses=20with=20TAGs.=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(maphash=20#'(lambda=20= (value=20tag)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(let=20(newtag)=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= newtag=20(byte-compile-make-tag))=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(cons=20= tag=20newtag)=20tags)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(puthash=20value=20newtag=20= last-constant)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (maphash=20#'(lambda=20(value=20offset)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((match=20= (assq=20offset=20tags)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(puthash=20value=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(if=20match=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(cdr=20match)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(let=20((tag=20(byte-compile-make-tag)))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(cons=20offset=20tag)=20= tags)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20tag))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20last-constant)))=0A=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= last-constant)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= Replace=20the=20hash=20table=20referenced=20in=20the=20lapcode=20with=20= our=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20modified=20= one.=0A@@=20-1722,13=20+1726,10=20@@=20byte-optimize-lapcode=0A=20=09=09=20= =20=20=20=20keep-going=20t)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20;;=20replace=20references=20to=20tag=20in=20jump=20tables,=20if=20any=0A= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(dolist=20(table=20= byte-compile-jump-tables)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(catch=20'break=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(maphash=20#'(lambda=20(value=20tag)=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (when=20(equal=20tag=20lap0)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20each=20= tag=20occurs=20only=20once=20in=20the=20jump=20table=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(puthash=20value=20lap1=20table)=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (throw=20'break=20nil)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20table))))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(puthash=20value=20lap1=20table)))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20table)))=0A=20=09=20= =20=20=20=20=20;;=0A=20=09=20=20=20=20=20=20;;=20unused-TAG:=20-->=20= <deleted>=0A=20=09=20=20=20=20=20=20;;=0Adiff=20--git=20= a/lisp/emacs-lisp/bytecomp.el=20b/lisp/emacs-lisp/bytecomp.el=0Aindex=20= 8f089119de..5930386166=20100644=0A---=20a/lisp/emacs-lisp/bytecomp.el=0A= +++=20b/lisp/emacs-lisp/bytecomp.el=0A@@=20-4105,9=20+4105,10=20@@=20= byte-compile-cond-jump-table-info=0A=20TEST=20and=20VAR=20are=20the=20= same=20throughout=20all=20conditions.=0A=20VALUE=20satisfies=20= `macroexp-const-p'.=0A=20=0A-Return=20a=20list=20of=20the=20form=20= ((TEST=20.=20VAR)=20=20((VALUE=20BODY)=20...))"=0A+Return=20a=20list=20= of=20the=20form=20((TEST=20.=20VAR)=20=20((VALUES=20BODY)=20...))"=0A=20=20= =20(let=20((cases=20'())=0A=20=20=20=20=20=20=20=20=20(ok=20t)=0A+=20=20=20= =20=20=20=20=20(all-keys=20nil)=0A=20=20=20=20=20=20=20=20=20prev-var=20= prev-test)=0A=20=20=20=20=20(and=20(catch=20'break=0A=20=20=20=20=20=20=20= =20=20=20=20=20(dolist=20(clause=20(cdr=20clauses)=20ok)=0A@@=20-4126,23=20= +4127,30=20@@=20byte-compile-cond-jump-table-info=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(eq=20obj1=20prev-var)=0A= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(or=20= (not=20prev-test)=20(eq=20test=20prev-test)))=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(setq=20prev-test=20test)=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20;;=20discard=20duplicate=20clauses=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(unless=20(assoc=20obj2=20= cases=20test)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (push=20(list=20obj2=20body)=20cases)))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20;;=20Discard=20values=20already=20tested=20for.=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(unless=20(member=20obj2=20= all-keys)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (push=20obj2=20all-keys)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(push=20(list=20(list=20obj2)=20body)=20cases)))=0A=20=0A=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((and=20obj1=20(memq=20test=20= '(memq=20memql=20member))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(eq=20obj1=20prev-var)=0A=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(listp=20obj2)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Require=20a=20= non-empty=20body,=20since=20the=20member=20function=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20value=20depends=20= on=20the=20switch=20argument.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20body=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(setq=20equality=20(cdr=20(assq=20test=20= '((memq=20=20=20.=20eq)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(memql=20=20.=20eql)=0A=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(member=20.=20equal)))))=0A=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(or=20(not=20prev-test)=20(eq=20= equality=20prev-test)))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(setq=20prev-test=20equality)=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20;;=20Expand=20to=20individual=20equality=20tests.=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(dolist=20(elem=20obj2)=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(unless=20(assoc=20= elem=20cases=20equality)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(push=20(list=20elem=20(or=20body=20`(',(funcall=20= test=20elem=20obj2))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20cases))))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(let=20((vals=20nil))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20;;=20Discard=20values=20already=20= tested=20for.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (dolist=20(elem=20obj2)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(unless=20(funcall=20test=20elem=20all-keys)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20elem=20= vals)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (when=20vals=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(setq=20all-keys=20(append=20vals=20all-keys))=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(list=20vals=20= body)=20cases))))=0A=20=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20((and=20(macroexp-const-p=20condition)=20condition)=0A=20=09=09=20= (push=20(list=20byte-compile--default-val=0A@@=20-4158,18=20+4166,20=20= @@=20byte-compile-cond-jump-table=0A=20=20=20=20=20=20=20=20=20=20(test=20= (caar=20table-info))=0A=20=20=20=20=20=20=20=20=20=20(var=20(cdar=20= table-info))=0A=20=20=20=20=20=20=20=20=20=20(cases=20(cadr=20= table-info))=0A-=20=20=20=20=20=20=20=20=20jump-table=20test-obj=20body=20= tag=20donetag=20default-tag=20default-case)=0A+=20=20=20=20=20=20=20=20=20= jump-table=20test-objects=20body=20tag=20donetag=20default-tag=20= default-case)=0A=20=20=20=20=20(when=20(and=20cases=20(not=20(=3D=20= (length=20cases)=201)))=0A=20=20=20=20=20=20=20;;=20TODO:=20Once=20= :linear-search=20is=20implemented=20for=20`make-hash-table'=0A=20=20=20=20= =20=20=20;;=20set=20it=20to=20`t'=20for=20cond=20forms=20with=20a=20= small=20number=20of=20cases.=0A-=20=20=20=20=20=20(setq=20jump-table=20= (make-hash-table=0A-=09=09=09:test=20test=0A-=09=09=09:purecopy=20t=0A-=09= =09=09:size=20(if=20(assq=20byte-compile--default-val=20cases)=0A-=09=09=09= =09=20=20(1-=20(length=20cases))=0A-=09=09=09=09(length=20cases)))=0A-=20= =20=20=20=20=20=20=20=20=20=20=20default-tag=20(byte-compile-make-tag)=0A= -=20=20=20=20=20=20=20=20=20=20=20=20donetag=20(byte-compile-make-tag))=0A= +=20=20=20=20=20=20(let=20((nvalues=20(apply=20#'+=20(mapcar=20(lambda=20= (case)=20(length=20(car=20case)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20cases))))=0A+=20=20=20=20=20=20=20=20(setq=20jump-table=20= (make-hash-table=0A+=09=09=09=20=20:test=20test=0A+=09=09=09=20=20= :purecopy=20t=0A+=09=09=09=20=20:size=20(if=20(assq=20= byte-compile--default-val=20cases)=0A+=09=09=09=09=20=20=20=20(1-=20= nvalues)=0A+=09=09=09=09=20=20nvalues))))=0A+=20=20=20=20=20=20(setq=20= default-tag=20(byte-compile-make-tag))=0A+=20=20=20=20=20=20(setq=20= donetag=20(byte-compile-make-tag))=0A=20=20=20=20=20=20=20;;=20The=20= structure=20of=20byte-switch=20code:=0A=20=20=20=20=20=20=20;;=0A=20=20=20= =20=20=20=20;;=20varref=20var=0A@@=20-4206,10=20+4216,11=20@@=20= byte-compile-cond-jump-table=0A=20=0A=20=20=20=20=20=20=20(dolist=20= (case=20cases)=0A=20=20=20=20=20=20=20=20=20(setq=20tag=20= (byte-compile-make-tag)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= test-obj=20(nth=200=20case)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= test-objects=20(nth=200=20case)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20body=20(nth=201=20case))=0A=20=20=20=20=20=20=20=20=20= (byte-compile-out-tag=20tag)=0A-=20=20=20=20=20=20=20=20(puthash=20= test-obj=20tag=20jump-table)=0A+=20=20=20=20=20=20=20=20(dolist=20(value=20= test-objects)=0A+=20=20=20=20=20=20=20=20=20=20(puthash=20value=20tag=20= jump-table))=0A=20=0A=20=20=20=20=20=20=20=20=20(let=20= ((byte-compile-depth=20byte-compile-depth)=0A=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(init-depth=20byte-compile-depth))=0A--=20=0A2.20.1=20= (Apple=20Git-117)=0A=0A= --Apple-Mail=_6425368A-6F6F-40E3-9751-3E52F91F6248 Content-Disposition: attachment; filename=0003-Tighter-pcase-or-pattern-member-function-selection.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0003-Tighter-pcase-or-pattern-member-function-selection.patch" Content-Transfer-Encoding: quoted-printable =46rom=2016e72d20f6a13ff626721ae55b66e1c3848a5813=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= <mattiase@acm.org>=0ADate:=20Tue,=2021=20May=202019=2012:19:38=20+0200=0A= Subject:=20[PATCH=203/5]=20Tighter=20pcase=20or-pattern=20member=20= function=20selection=0A=0A*=20lisp/emacs-lisp/pcase.el=20(pcase--u1):=0A= Use=20the=20most=20specific=20of=20`memq',=20`memql'=20and=20`member'=20= in=20or-patterns=0Awith=20constant=20cases.=20=20This=20improves=20= performance=20and=20may=20help=20the=20byte-code=0Acompiler=20generate=20= a=20switch.=0A*=20test/lisp/emacs-lisp/pcase-tests.el=20= (pcase-tests-member):=0AAdd=20mixed-type=20or-pattern=20test=20cases.=0A= ---=0A=20lisp/emacs-lisp/pcase.el=20=20=20=20=20=20=20=20=20=20=20=20|=20= 15=20++++++++-------=0A=20test/lisp/emacs-lisp/pcase-tests.el=20|=20=206=20= ++++--=0A=202=20files=20changed,=2012=20insertions(+),=209=20= deletions(-)=0A=0Adiff=20--git=20a/lisp/emacs-lisp/pcase.el=20= b/lisp/emacs-lisp/pcase.el=0Aindex=20a644453a94..ae2cf8eb02=20100644=0A= ---=20a/lisp/emacs-lisp/pcase.el=0A+++=20b/lisp/emacs-lisp/pcase.el=0A@@=20= -785,25=20+785,26=20@@=20pcase--u1=0A=20=20=20=20((eq=20'or=20(caar=20= matches))=0A=20=20=20=20=20(let*=20((alts=20(cdar=20matches))=0A=20=20=20= =20=20=20=20=20=20=20=20=20(var=20(if=20(eq=20(caar=20alts)=20'match)=20= (cadr=20(car=20alts))))=0A-=20=20=20=20=20=20=20=20=20=20=20(simples=20= '())=20(others=20'())=20(memql-ok=20t))=0A+=20=20=20=20=20=20=20=20=20=20= =20(simples=20'())=20(others=20'())=20(mem-fun=20'memq))=0A=20=20=20=20=20= =20=20(when=20var=0A=20=20=20=20=20=20=20=20=20(dolist=20(alt=20alts)=0A=20= =20=20=20=20=20=20=20=20=20=20(if=20(and=20(eq=20(car=20alt)=20'match)=20= (eq=20var=20(cadr=20alt))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(let=20((upat=20(cddr=20alt)))=0A=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(eq=20(car-safe=20upat)=20= 'quote)))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((val=20= (cadr=20(cddr=20alt))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (unless=20(or=20(integerp=20val)=20(symbolp=20val))=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(setq=20memql-ok=20nil))=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(cadr=20(cddr=20alt))=20= simples))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cond=20= ((integerp=20val)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(when=20(eq=20mem-fun=20'memq)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20mem-fun=20= 'memql)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20((not=20(symbolp=20val))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(setq=20mem-fun=20'member)))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(push=20val=20simples))=0A=20=20=20=20= =20=20=20=20=20=20=20=20=20(push=20alt=20others))))=0A=20=20=20=20=20=20=20= (cond=0A=20=20=20=20=20=20=20=20((null=20alts)=20(error=20"Please=20= avoid=20it")=20(pcase--u=20rest))=0A=20=20=20=20=20=20=20=20;;=20Yes,=20= we=20can=20use=20`memql'=20(or=20`member')!=0A=20=20=20=20=20=20=20=20= ((>=20(length=20simples)=201)=0A=20=20=20=20=20=20=20=20=20(pcase--u1=20= (cons=20`(match=20,var=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20(pred=20= (pcase--flip=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ,(if=20memql-ok=20#'memql=20#'member)=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20',simples)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20.=20(pred=20= (pcase--flip=20,mem-fun=20',simples)))=0A=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cdr=20matches))=0A=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20code=20vars=0A=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(if=20(null=20others)=20= rest=0Adiff=20--git=20a/test/lisp/emacs-lisp/pcase-tests.el=20= b/test/lisp/emacs-lisp/pcase-tests.el=0Aindex=20af8c9a3f3c..e8c0b8219c=20= 100644=0A---=20a/test/lisp/emacs-lisp/pcase-tests.el=0A+++=20= b/test/lisp/emacs-lisp/pcase-tests.el=0A@@=20-51,9=20+51,11=20@@=20= pcase-tests-grep=0A=20=0A=20(ert-deftest=20pcase-tests-member=20()=0A=20=20= =20(should=20(pcase-tests-grep=0A-=20=20=20=20=20=20=20=20=20=20=20= 'memql=20(macroexpand-all=20'(pcase=20x=20((or=201=202=203)=20body)))))=0A= +=20=20=20=20=20=20=20=20=20=20=20'memq=20(macroexpand-all=20'(pcase=20x=20= ((or=20'a=20'b=20'c)=20body)))))=0A=20=20=20(should=20(pcase-tests-grep=0A= -=20=20=20=20=20=20=20=20=20=20=20'member=20(macroexpand-all=20'(pcase=20= x=20((or=20"a"=202=203)=20body)))))=0A+=20=20=20=20=20=20=20=20=20=20=20= 'memql=20(macroexpand-all=20'(pcase=20x=20((or=201=202=203=20'a)=20= body)))))=0A+=20=20(should=20(pcase-tests-grep=0A+=20=20=20=20=20=20=20=20= =20=20=20'member=20(macroexpand-all=20'(pcase=20x=20((or=20"a"=202=203=20= 'a)=20body)))))=0A=20=20=20(should-not=20(pcase-tests-grep=0A=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20'memq=20(macroexpand-all=20'(pcase=20= x=20((or=20"a"=202=203)=20body)))))=0A=20=20=20(should-not=20= (pcase-tests-grep=0A--=20=0A2.20.1=20(Apple=20Git-117)=0A=0A= --Apple-Mail=_6425368A-6F6F-40E3-9751-3E52F91F6248 Content-Disposition: attachment; filename=0004-Compile-cond-with-heterogeneous-tests-into-switch.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0004-Compile-cond-with-heterogeneous-tests-into-switch.patch" Content-Transfer-Encoding: quoted-printable =46rom=20876f73720ef3274352cf707dbeb1cbb02817cd03=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= <mattiase@acm.org>=0ADate:=20Wed,=2022=20May=202019=2012:36:03=20+0200=0A= Subject:=20[PATCH=204/5]=20Compile=20cond=20with=20heterogeneous=20tests=20= into=20switch=0A=0AAllow=20any=20mixture=20of=20`eq',=20`eql'=20and=20= `equal',=20`memq',=20`memql'=20and=0A`member'=20in=20a=20switch-like=20= `cond'=20to=20be=20compiled=20into=20a=20single=20switch.=0A=0A*=20= lisp/emacs-lisp/bytecomp.el=20(byte-compile--common-test):=20New.=0A= (byte-compile-cond-jump-table-info):=20Use=20most=20specific=20common=20= test.=0A*=20test/lisp/emacs-lisp/bytecomp-tests.el=20= (byte-opt-testsuite-arith-data):=0AAdd=20test=20cases=20for=20= multi-value=20clause=20cond=20forms.=0A---=0A=20= lisp/emacs-lisp/bytecomp.el=20=20=20=20=20=20=20=20=20=20=20=20|=2029=20= +++++++++++++++-----------=0A=20test/lisp/emacs-lisp/bytecomp-tests.el=20= |=2025=20+++++++++++++++++++++-=0A=202=20files=20changed,=2041=20= insertions(+),=2013=20deletions(-)=0A=0Adiff=20--git=20= a/lisp/emacs-lisp/bytecomp.el=20b/lisp/emacs-lisp/bytecomp.el=0Aindex=20= 5930386166..5ee5ceac18=20100644=0A---=20a/lisp/emacs-lisp/bytecomp.el=0A= +++=20b/lisp/emacs-lisp/bytecomp.el=0A@@=20-4098,6=20+4098,12=20@@=20= byte-compile-cond-vars=0A=20=0A=20(defconst=20byte-compile--default-val=20= (cons=20nil=20nil)=20"A=20unique=20object.")=0A=20=0A+(defun=20= byte-compile--common-test=20(test-1=20test-2)=0A+=20=20"Most=20specific=20= common=20test=20of=20`eq',=20`eql'=20and=20`equal'"=0A+=20=20(cond=20= ((or=20(eq=20test-1=20'equal)=20(eq=20test-2=20'equal))=20'equal)=0A+=20=20= =20=20=20=20=20=20((or=20(eq=20test-1=20'eql)=20=20=20(eq=20test-2=20= 'eql))=20=20=20'eql)=0A+=20=20=20=20=20=20=20=20(t=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20'eq)))=0A+=0A=20(defun=20= byte-compile-cond-jump-table-info=20(clauses)=0A=20=20=20"If=20CLAUSES=20= is=20a=20`cond'=20form=20where:=0A=20The=20condition=20for=20each=20= clause=20is=20of=20the=20form=20(TEST=20VAR=20VALUE).=0A@@=20-4109,7=20= +4115,8=20@@=20byte-compile-cond-jump-table-info=0A=20=20=20(let=20= ((cases=20'())=0A=20=20=20=20=20=20=20=20=20(ok=20t)=0A=20=20=20=20=20=20= =20=20=20(all-keys=20nil)=0A-=20=20=20=20=20=20=20=20prev-var=20= prev-test)=0A+=20=20=20=20=20=20=20=20(prev-test=20'eq)=0A+=20=20=20=20=20= =20=20=20prev-var)=0A=20=20=20=20=20(and=20(catch=20'break=0A=20=20=20=20= =20=20=20=20=20=20=20=20(dolist=20(clause=20(cdr=20clauses)=20ok)=0A=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(let*=20((condition=20(car=20= clause))=0A@@=20-4118,15=20+4125,13=20@@=20= byte-compile-cond-jump-table-info=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(byte-compile-cond-vars=20= (cadr=20condition)=20(cl-caddr=20condition))))=0A=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(obj1=20(car-safe=20vars))=0A=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(obj2=20= (cdr-safe=20vars))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(body=20(cdr-safe=20clause))=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20equality)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(body=20(cdr-safe=20clause)))=0A=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(unless=20prev-var=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(setq=20prev-var=20obj1))=0A=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(cond=0A=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20((and=20obj1=20(memq=20test=20'(eq=20eql=20equal))=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(eq=20= obj1=20prev-var)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(or=20(not=20prev-test)=20(eq=20test=20prev-test)))=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20prev-test=20test)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(eq=20= obj1=20prev-var))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (setq=20prev-test=20(byte-compile--common-test=20prev-test=20test))=0A=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Discard=20values=20= already=20tested=20for.=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(unless=20(member=20obj2=20all-keys)=0A=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(push=20obj2=20all-keys)=0A@@=20-4137,12=20= +4142,12=20@@=20byte-compile-cond-jump-table-info=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(listp=20obj2)=0A=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Require=20= a=20non-empty=20body,=20since=20the=20member=20function=0A=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20value=20= depends=20on=20the=20switch=20argument.=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20body=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(setq=20equality=20(cdr=20(assq=20= test=20'((memq=20=20=20.=20eq)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(memql=20=20.=20eql)=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(member=20.=20equal)))))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(or=20(not=20prev-test)=20(eq=20= equality=20prev-test)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(setq=20prev-test=20equality)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20body)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(setq=20prev-test=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(byte-compile--common-test=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20prev-test=20(cdr=20= (assq=20test=20'((memq=20=20=20.=20eq)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(memql=20=20.=20eql)=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(member=20.=20equal))))))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(let=20((vals=20nil))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20;;=20Discard=20values=20already=20tested=20for.=0A=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(dolist=20(elem=20= obj2)=0Adiff=20--git=20a/test/lisp/emacs-lisp/bytecomp-tests.el=20= b/test/lisp/emacs-lisp/bytecomp-tests.el=0Aindex=20= f45c9209c1..87f2c13bf7=20100644=0A---=20= a/test/lisp/emacs-lisp/bytecomp-tests.el=0A+++=20= b/test/lisp/emacs-lisp/bytecomp-tests.el=0A@@=20-311,7=20+311,30=20@@=20= byte-opt-testsuite-arith-data=0A=20=20=20=20=20(let=20((x=20"a"))=20= (cond=20((equal=20x=20"a")=20'correct)=0A=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((equal=20x=20"b")=20= 'incorrect)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20((equal=20x=20"a")=20'incorrect)=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((equal=20x=20"c")=20= 'incorrect))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20((equal=20x=20"c")=20'incorrect)))=0A+=20=20=20=20;;=20= Multi-value=20clauses=0A+=20=20=20=20(mapcar=20(lambda=20(x)=20(cond=20= ((eq=20x=20'a)=2011)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20((memq=20x=20'(b=20a=20c=20d))=20= 22)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20((eq=20x=20'c)=2033)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((eq=20x=20= 'e)=2044)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20((memq=20x=20'(d=20f=20g))=2055)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(t=2099)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20'(a=20b=20c=20d=20= e=20f=20g=20h))=0A+=20=20=20=20(mapcar=20(lambda=20(x)=20(cond=20((eql=20= x=201)=2011)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20((memq=20x=20'(a=20b=20c))=2022)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20((memql=20x=20'(2=201=204=201e-3))=2033)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ((eq=20x=20'd)=2044)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20((eql=20x=20= #x10000000000000000))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20'(1=202=20= 4=201e-3=20a=20b=20c=20d=201.0=20#x10000000000000000))=0A+=20=20=20=20= (mapcar=20(lambda=20(x)=20(cond=20((eq=20x=20'a)=2011)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ((memq=20x=20'(b=20d))=2022)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((equal=20x=20'(a=20.=20= b))=2033)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20((member=20x=20'(b=20c=201.5=202.5=20"X"=20= (d)))=2044)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20((eql=20x=203.14)=2055)=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ((memql=20x=20'(9=200.5=201.5=20q))=2066)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(t=2099)))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20'(a=20b=20c=20d=20(d)=20(a=20.=20b)=20= "X"=200.5=201.5=203.14=209=209.0))=0A+=20=20=20=20)=0A=20=20=20"List=20= of=20expression=20for=20test.=0A=20Each=20element=20will=20be=20executed=20= by=20interpreter=20and=20with=0A=20bytecompiled=20code,=20and=20their=20= results=20compared.")=0A--=20=0A2.20.1=20(Apple=20Git-117)=0A=0A= --Apple-Mail=_6425368A-6F6F-40E3-9751-3E52F91F6248 Content-Disposition: attachment; filename=0005-Compile-any-subsequence-of-cond-clauses-to-switch.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0005-Compile-any-subsequence-of-cond-clauses-to-switch.patch" Content-Transfer-Encoding: quoted-printable =46rom=209822f95ca1c3c92b2097c01b3f209d0155284be2=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= <mattiase@acm.org>=0ADate:=20Fri,=207=20Jun=202019=2017:04:10=20+0200=0A= Subject:=20[PATCH=205/5]=20Compile=20any=20subsequence=20of=20`cond'=20= clauses=20to=20switch=0A=0AA=20single=20`cond'=20form=20can=20how=20be=20= compiled=20to=20any=20number=20of=20switch=20ops,=0Ainterspersed=20with=20= non-switch=20conditions=20in=20arbitrary=20ways.=20=20Previously,=0A= switch=20ops=20would=20only=20be=20used=20for=20whole=20`cond'=20forms=20= containing=20no=0Aother=20tests.=0A=0A*=20lisp/emacs-lisp/bytecomp.el=20= (byte-compile--cond-vars):=0ARename=20from=20`byte-compile-cond-vars'.=0A= (byte-compile--default-val):=20Remove.=0A= (byte-compile--cond-switch-prefix):=0AReplace=20= `byte-compile-cond-jump-table-info';=20now=20also=20returns=0Atrailing=20= non-switch=20clauses.=0A(byte-compile-cond-jump-table):=20New=20= arguments;=20no=20longer=20compiles=0Athe=20default=20case.=0A= (byte-compile-cond):=20Look=20for=20and=20compile=20switches=20at=20any=20= place=20in=20the=0Alist=20of=20clauses.=0A*=20= test/lisp/emacs-lisp/bytecomp-tests.el=20= (byte-opt-testsuite-arith-data):=0AAdd=20test=20expression.=0A---=0A=20= lisp/emacs-lisp/bytecomp.el=20=20=20=20=20=20=20=20=20=20=20=20|=20339=20= ++++++++++++-------------=0A=20test/lisp/emacs-lisp/bytecomp-tests.el=20= |=20=2015=20+-=0A=202=20files=20changed,=20173=20insertions(+),=20181=20= deletions(-)=0A=0Adiff=20--git=20a/lisp/emacs-lisp/bytecomp.el=20= b/lisp/emacs-lisp/bytecomp.el=0Aindex=205ee5ceac18..82e47794e3=20100644=0A= ---=20a/lisp/emacs-lisp/bytecomp.el=0A+++=20= b/lisp/emacs-lisp/bytecomp.el=0A@@=20-4088,7=20+4088,7=20@@=20= byte-compile-if=0A=20=09(byte-compile-out-tag=20donetag))))=0A=20=20=20= (setq=20byte-compile--for-effect=20nil))=0A=20=0A-(defun=20= byte-compile-cond-vars=20(obj1=20obj2)=0A+(defun=20= byte-compile--cond-vars=20(obj1=20obj2)=0A=20=20=20;;=20We=20make=20sure=20= that=20of=20OBJ1=20and=20OBJ2,=20one=20of=20them=20is=20a=20symbol,=0A=20= =20=20;;=20and=20the=20other=20is=20a=20constant=20expression=20whose=20= value=20can=20be=0A=20=20=20;;=20compared=20with=20`eq'=20(with=20= `macroexp-const-p').=0A@@=20-4096,193=20+4096,172=20@@=20= byte-compile-cond-vars=0A=20=20=20=20(and=20(symbolp=20obj1)=20= (macroexp-const-p=20obj2)=20(cons=20obj1=20(eval=20obj2)))=0A=20=20=20=20= (and=20(symbolp=20obj2)=20(macroexp-const-p=20obj1)=20(cons=20obj2=20= (eval=20obj1)))))=0A=20=0A-(defconst=20byte-compile--default-val=20(cons=20= nil=20nil)=20"A=20unique=20object.")=0A-=0A=20(defun=20= byte-compile--common-test=20(test-1=20test-2)=0A=20=20=20"Most=20= specific=20common=20test=20of=20`eq',=20`eql'=20and=20`equal'"=0A=20=20=20= (cond=20((or=20(eq=20test-1=20'equal)=20(eq=20test-2=20'equal))=20= 'equal)=0A=20=20=20=20=20=20=20=20=20((or=20(eq=20test-1=20'eql)=20=20=20= (eq=20test-2=20'eql))=20=20=20'eql)=0A=20=20=20=20=20=20=20=20=20(t=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20'eq)))=0A=20=0A-(defun=20= byte-compile-cond-jump-table-info=20(clauses)=0A-=20=20"If=20CLAUSES=20= is=20a=20`cond'=20form=20where:=0A-The=20condition=20for=20each=20clause=20= is=20of=20the=20form=20(TEST=20VAR=20VALUE).=0A-VAR=20is=20a=20variable.=0A= -TEST=20and=20VAR=20are=20the=20same=20throughout=20all=20conditions.=0A= -VALUE=20satisfies=20`macroexp-const-p'.=0A-=0A-Return=20a=20list=20of=20= the=20form=20((TEST=20.=20VAR)=20=20((VALUES=20BODY)=20...))"=0A-=20=20= (let=20((cases=20'())=0A-=20=20=20=20=20=20=20=20(ok=20t)=0A-=20=20=20=20= =20=20=20=20(all-keys=20nil)=0A-=20=20=20=20=20=20=20=20(prev-test=20= 'eq)=0A-=20=20=20=20=20=20=20=20prev-var)=0A-=20=20=20=20(and=20(catch=20= 'break=0A-=20=20=20=20=20=20=20=20=20=20=20(dolist=20(clause=20(cdr=20= clauses)=20ok)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20(let*=20= ((condition=20(car=20clause))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(test=20(car-safe=20condition))=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(vars=20(when=20(consp=20= condition)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(byte-compile-cond-vars=20(cadr=20condition)=20= (cl-caddr=20condition))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(obj1=20(car-safe=20vars))=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(obj2=20(cdr-safe=20vars))=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(body=20(cdr-safe=20= clause)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(unless=20= prev-var=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= prev-var=20obj1))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cond=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((and=20obj1=20(memq=20= test=20'(eq=20eql=20equal))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(eq=20obj1=20prev-var))=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(setq=20prev-test=20= (byte-compile--common-test=20prev-test=20test))=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20;;=20Discard=20values=20already=20tested=20= for.=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(unless=20= (member=20obj2=20all-keys)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(push=20obj2=20all-keys)=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(push=20(list=20(list=20obj2)=20body)=20cases)))=0A= -=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((and=20obj1=20= (memq=20test=20'(memq=20memql=20member))=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(eq=20obj1=20prev-var)=0A-=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(listp=20obj2)=0A-=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= Require=20a=20non-empty=20body,=20since=20the=20member=20function=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20value=20= depends=20on=20the=20switch=20argument.=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20body)=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(setq=20prev-test=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(byte-compile--common-test=0A-=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20prev-test=20= (cdr=20(assq=20test=20'((memq=20=20=20.=20eq)=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(memql=20=20.=20= eql)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(member=20.=20equal))))))=0A-=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(let=20((vals=20nil))=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20;;=20Discard=20values=20already=20tested=20= for.=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(dolist=20= (elem=20obj2)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(unless=20(funcall=20test=20elem=20all-keys)=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20elem=20vals)))=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(when=20vals=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= all-keys=20(append=20vals=20all-keys))=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(push=20(list=20vals=20body)=20cases))))=0A= -=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((and=20= (macroexp-const-p=20condition)=20condition)=0A-=09=09=20(push=20(list=20= byte-compile--default-val=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(or=20body=20`(,condition)))=0A= -=09=09=20=20=20=20=20=20=20cases)=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(throw=20'break=20t))=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(t=20(setq=20ok=20nil)=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(throw=20'break=20nil))))))=0A-=20=20=20=20=20=20= =20=20=20(list=20(cons=20prev-test=20prev-var)=20(nreverse=20cases)))))=0A= -=0A-(defun=20byte-compile-cond-jump-table=20(clauses)=0A-=20=20(let*=20= ((table-info=20(byte-compile-cond-jump-table-info=20clauses))=0A-=20=20=20= =20=20=20=20=20=20(test=20(caar=20table-info))=0A-=20=20=20=20=20=20=20=20= =20(var=20(cdar=20table-info))=0A-=20=20=20=20=20=20=20=20=20(cases=20= (cadr=20table-info))=0A-=20=20=20=20=20=20=20=20=20jump-table=20= test-objects=20body=20tag=20donetag=20default-tag=20default-case)=0A-=20=20= =20=20(when=20(and=20cases=20(not=20(=3D=20(length=20cases)=201)))=0A-=20= =20=20=20=20=20;;=20TODO:=20Once=20:linear-search=20is=20implemented=20= for=20`make-hash-table'=0A-=20=20=20=20=20=20;;=20set=20it=20to=20`t'=20= for=20cond=20forms=20with=20a=20small=20number=20of=20cases.=0A-=20=20=20= =20=20=20(let=20((nvalues=20(apply=20#'+=20(mapcar=20(lambda=20(case)=20= (length=20(car=20case)))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= cases))))=0A-=20=20=20=20=20=20=20=20(setq=20jump-table=20= (make-hash-table=0A-=09=09=09=20=20:test=20test=0A-=09=09=09=20=20= :purecopy=20t=0A-=09=09=09=20=20:size=20(if=20(assq=20= byte-compile--default-val=20cases)=0A-=09=09=09=09=20=20=20=20(1-=20= nvalues)=0A-=09=09=09=09=20=20nvalues))))=0A-=20=20=20=20=20=20(setq=20= default-tag=20(byte-compile-make-tag))=0A-=20=20=20=20=20=20(setq=20= donetag=20(byte-compile-make-tag))=0A-=20=20=20=20=20=20;;=20The=20= structure=20of=20byte-switch=20code:=0A-=20=20=20=20=20=20;;=0A-=20=20=20= =20=20=20;;=20varref=20var=0A-=20=20=20=20=20=20;;=20constant=20= #s(hash-table=20purecopy=20t=20data=20(val1=20(TAG1)=20val2=20(TAG2)))=0A= -=20=20=20=20=20=20;;=20switch=0A-=20=20=20=20=20=20;;=20goto=20= DEFAULT-TAG=0A-=20=20=20=20=20=20;;=20TAG1=0A-=20=20=20=20=20=20;;=20= <clause=20body>=0A-=20=20=20=20=20=20;;=20goto=20DONETAG=0A-=20=20=20=20=20= =20;;=20TAG2=0A-=20=20=20=20=20=20;;=20<clause=20body>=0A-=20=20=20=20=20= =20;;=20goto=20DONETAG=0A-=20=20=20=20=20=20;;=20DEFAULT-TAG=0A-=20=20=20= =20=20=20;;=20<body=20for=20`t'=20clause,=20if=20any=20(else=20`constant=20= nil')>=0A-=20=20=20=20=20=20;;=20DONETAG=0A-=0A-=20=20=20=20=20=20= (byte-compile-variable-ref=20var)=0A-=20=20=20=20=20=20= (byte-compile-push-constant=20jump-table)=0A-=20=20=20=20=20=20= (byte-compile-out=20'byte-switch)=0A-=0A-=20=20=20=20=20=20;;=20When=20= the=20opcode=20argument=20is=20`byte-goto',=20`byte-compile-goto'=20sets=0A= -=20=20=20=20=20=20;;=20`byte-compile-depth'=20to=20`nil'.=20However,=20= we=20need=20`byte-compile-depth'=0A-=20=20=20=20=20=20;;=20to=20be=20= non-nil=20for=20generating=20tags=20for=20all=20cases.=20Since=0A-=20=20=20= =20=20=20;;=20`byte-compile-depth'=20will=20increase=20by=20at=20most=20= 1=20after=20compiling=0A-=20=20=20=20=20=20;;=20all=20of=20the=20clause=20= (which=20is=20further=20enforced=20by=20cl-assert=20below)=0A-=20=20=20=20= =20=20;;=20it=20should=20be=20safe=20to=20preserve=20its=20value.=0A-=20=20= =20=20=20=20(let=20((byte-compile-depth=20byte-compile-depth))=0A-=20=20=20= =20=20=20=20=20(byte-compile-goto=20'byte-goto=20default-tag))=0A-=0A-=20= =20=20=20=20=20(let=20((default-match=20(assq=20= byte-compile--default-val=20cases)))=0A-=20=20=20=20=20=20=20=20(when=20= default-match=0A-=09=20=20(setq=20default-case=20(cadr=20default-match)=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20cases=20(butlast=20= cases))))=0A-=0A-=20=20=20=20=20=20(dolist=20(case=20cases)=0A-=20=20=20=20= =20=20=20=20(setq=20tag=20(byte-compile-make-tag)=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20test-objects=20(nth=200=20case)=0A-=20=20=20=20=20=20= =20=20=20=20=20=20=20=20body=20(nth=201=20case))=0A-=20=20=20=20=20=20=20= =20(byte-compile-out-tag=20tag)=0A-=20=20=20=20=20=20=20=20(dolist=20= (value=20test-objects)=0A-=20=20=20=20=20=20=20=20=20=20(puthash=20value=20= tag=20jump-table))=0A-=0A-=20=20=20=20=20=20=20=20(let=20= ((byte-compile-depth=20byte-compile-depth)=0A-=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(init-depth=20byte-compile-depth))=0A-=20=20=20=20=20=20=20= =20=20=20;;=20Since=20`byte-compile-body'=20might=20increase=20= `byte-compile-depth'=0A-=20=20=20=20=20=20=20=20=20=20;;=20by=201,=20not=20= preserving=20its=20value=20will=20cause=20it=20to=20potentially=0A-=20=20= =20=20=20=20=20=20=20=20;;=20increase=20by=20one=20for=20every=20clause=20= body=20compiled,=20causing=0A-=20=20=20=20=20=20=20=20=20=20;;=20= depth/tag=20conflicts=20or=20violating=20asserts=20down=20the=20road.=0A= -=20=20=20=20=20=20=20=20=20=20;;=20To=20make=20sure=20= `byte-compile-body'=20itself=20doesn't=20violate=20this,=0A-=20=20=20=20=20= =20=20=20=20=20;;=20we=20use=20`cl-assert'.=0A-=20=20=20=20=20=20=20=20=20= =20(if=20(null=20body)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (byte-compile-form=20t=20byte-compile--for-effect)=0A-=20=20=20=20=20=20=20= =20=20=20=20=20(byte-compile-body=20body=20byte-compile--for-effect))=0A= -=20=20=20=20=20=20=20=20=20=20(cl-assert=20(or=20(=3D=20= byte-compile-depth=20init-depth)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(=3D=20byte-compile-depth=20(1+=20= init-depth))))=0A-=20=20=20=20=20=20=20=20=20=20(byte-compile-goto=20= 'byte-goto=20donetag)=0A-=20=20=20=20=20=20=20=20=20=20(setcdr=20(cdr=20= donetag)=20nil)))=0A-=0A-=20=20=20=20=20=20(byte-compile-out-tag=20= default-tag)=0A-=20=20=20=20=20=20(if=20default-case=0A-=20=20=20=20=20=20= =20=20=20=20(byte-compile-body-do-effect=20default-case)=0A-=20=20=20=20=20= =20=20=20(byte-compile-constant=20nil))=0A-=20=20=20=20=20=20= (byte-compile-out-tag=20donetag)=0A-=20=20=20=20=20=20(push=20jump-table=20= byte-compile-jump-tables))))=0A+(defun=20= byte-compile--cond-switch-prefix=20(clauses)=0A+=20=20"Find=20a=20switch=20= corresponding=20to=20a=20prefix=20of=20CLAUSES,=20or=20nil=20if=20none.=0A= +Return=20(TAIL=20VAR=20TEST=20CASES),=20where:=0A+=20=20TAIL=20is=20the=20= remaining=20part=20of=20CLAUSES=20after=20the=20switch,=20including=0A+=20= =20any=20default=20clause,=0A+=20=20VAR=20is=20the=20variable=20being=20= switched=20on,=0A+=20=20TEST=20is=20the=20equality=20test=20(`eq',=20= `eql'=20or=20`equal'),=0A+=20=20CASES=20is=20a=20list=20of=20(VALUES=20.=20= BODY)=20where=20VALUES=20is=20a=20list=20of=20values=0A+=20=20=20=20= corresponding=20to=20BODY=20(always=20non-empty)."=0A+=20=20(let=20= ((cases=20nil)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;=20= Reversed=20list=20of=20(VALUES=20BODY).=0A+=20=20=20=20=20=20=20=20(keys=20= nil)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;=20Switch=20= keys=20seen=20so=20far.=0A+=20=20=20=20=20=20=20=20(switch-var=20nil)=0A= +=20=20=20=20=20=20=20=20(switch-test=20'eq))=0A+=20=20=20=20(while=20= (pcase=20(car=20clauses)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= (`((,fn=20,expr1=20,expr2)=20.=20,body)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(let*=20((vars=20(byte-compile--cond-vars=20expr1=20expr2))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(var=20= (car=20vars))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(value=20(cdr=20vars)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(and=20var=20(or=20(eq=20var=20switch-var)=20(not=20switch-var))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cond=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ((memq=20fn=20'(eq=20eql=20equal))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(setq=20switch-var=20var)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= switch-test=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(byte-compile--common-test=20switch-test=20= fn))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(unless=20(member=20value=20keys)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20value=20keys)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (push=20(cons=20(list=20value)=20(or=20body=20'(t)))=20cases))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20t)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((and=20(memq=20= fn=20'(memq=20memql=20member))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(listp=20value)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ;;=20Require=20a=20non-empty=20body,=20since=20the=20member=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ;;=20function=20value=20depends=20on=20the=20switch=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= argument.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20body)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(setq=20switch-var=20var)=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20switch-test=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(byte-compile--common-test=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20switch-test=20= (cdr=20(assq=20fn=20'((memq=20=20=20.=20eq)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (memql=20=20.=20eql)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(member=20.=20= equal))))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(let=20((vals=20nil))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(dolist=20(elem=20value)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (unless=20(funcall=20fn=20elem=20keys)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20elem=20= vals)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(when=20vals=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(setq=20keys=20(append=20vals=20= keys))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(push=20(cons=20(nreverse=20vals)=20body)=20cases)))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= t))))))=0A+=20=20=20=20=20=20(setq=20clauses=20(cdr=20clauses)))=0A+=20=20= =20=20(and=20(>=20(length=20cases)=201)=0A+=20=20=20=20=20=20=20=20=20= (list=20clauses=20switch-var=20switch-test=20(nreverse=20cases)))))=0A+=0A= +(defun=20byte-compile-cond-jump-table=20(switch=20donetag)=0A+=20=20= "Generate=20code=20for=20SWITCH,=20ending=20at=20DONETAG."=0A+=20=20= (let*=20((var=20(car=20switch))=0A+=20=20=20=20=20=20=20=20=20(test=20= (nth=201=20switch))=0A+=20=20=20=20=20=20=20=20=20(cases=20(nth=202=20= switch))=0A+=20=20=20=20=20=20=20=20=20jump-table=20test-objects=20body=20= tag=20default-tag)=0A+=20=20=20=20;;=20TODO:=20Once=20:linear-search=20= is=20implemented=20for=20`make-hash-table'=0A+=20=20=20=20;;=20set=20it=20= to=20`t'=20for=20cond=20forms=20with=20a=20small=20number=20of=20cases.=0A= +=20=20=20=20(let=20((nvalues=20(apply=20#'+=20(mapcar=20(lambda=20= (case)=20(length=20(car=20case)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20cases))))=0A+=20=20=20=20=20=20(setq=20jump-table=20(make-hash-table=0A= +=09=09=09:test=20test=0A+=09=09=09:purecopy=20t=0A+=09=09=09:size=20= nvalues)))=0A+=20=20=20=20(setq=20default-tag=20(byte-compile-make-tag))=0A= +=20=20=20=20;;=20The=20structure=20of=20byte-switch=20code:=0A+=20=20=20= =20;;=0A+=20=20=20=20;;=20varref=20var=0A+=20=20=20=20;;=20constant=20= #s(hash-table=20purecopy=20t=20data=20(val1=20(TAG1)=20val2=20(TAG2)))=0A= +=20=20=20=20;;=20switch=0A+=20=20=20=20;;=20goto=20DEFAULT-TAG=0A+=20=20= =20=20;;=20TAG1=0A+=20=20=20=20;;=20<clause=20body>=0A+=20=20=20=20;;=20= goto=20DONETAG=0A+=20=20=20=20;;=20TAG2=0A+=20=20=20=20;;=20<clause=20= body>=0A+=20=20=20=20;;=20goto=20DONETAG=0A+=20=20=20=20;;=20DEFAULT-TAG=0A= +=20=20=20=20;;=20<body=20for=20remaining=20(non-switch)=20clauses>=0A+=20= =20=20=20;;=20DONETAG=0A+=0A+=20=20=20=20(byte-compile-variable-ref=20= var)=0A+=20=20=20=20(byte-compile-push-constant=20jump-table)=0A+=20=20=20= =20(byte-compile-out=20'byte-switch)=0A+=0A+=20=20=20=20;;=20When=20the=20= opcode=20argument=20is=20`byte-goto',=20`byte-compile-goto'=20sets=0A+=20= =20=20=20;;=20`byte-compile-depth'=20to=20`nil'.=20However,=20we=20need=20= `byte-compile-depth'=0A+=20=20=20=20;;=20to=20be=20non-nil=20for=20= generating=20tags=20for=20all=20cases.=20Since=0A+=20=20=20=20;;=20= `byte-compile-depth'=20will=20increase=20by=20at=20most=201=20after=20= compiling=0A+=20=20=20=20;;=20all=20of=20the=20clause=20(which=20is=20= further=20enforced=20by=20cl-assert=20below)=0A+=20=20=20=20;;=20it=20= should=20be=20safe=20to=20preserve=20its=20value.=0A+=20=20=20=20(let=20= ((byte-compile-depth=20byte-compile-depth))=0A+=20=20=20=20=20=20= (byte-compile-goto=20'byte-goto=20default-tag))=0A+=0A+=20=20=20=20= (dolist=20(case=20cases)=0A+=20=20=20=20=20=20(setq=20tag=20= (byte-compile-make-tag)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= test-objects=20(car=20case)=0A+=20=20=20=20=20=20=20=20=20=20=20=20body=20= (cdr=20case))=0A+=20=20=20=20=20=20(byte-compile-out-tag=20tag)=0A+=20=20= =20=20=20=20(dolist=20(value=20test-objects)=0A+=20=20=20=20=20=20=20=20= (puthash=20value=20tag=20jump-table))=0A+=0A+=20=20=20=20=20=20(let=20= ((byte-compile-depth=20byte-compile-depth)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20(init-depth=20byte-compile-depth))=0A+=20=20=20=20=20=20=20=20= ;;=20Since=20`byte-compile-body'=20might=20increase=20= `byte-compile-depth'=0A+=20=20=20=20=20=20=20=20;;=20by=201,=20not=20= preserving=20its=20value=20will=20cause=20it=20to=20potentially=0A+=20=20= =20=20=20=20=20=20;;=20increase=20by=20one=20for=20every=20clause=20body=20= compiled,=20causing=0A+=20=20=20=20=20=20=20=20;;=20depth/tag=20= conflicts=20or=20violating=20asserts=20down=20the=20road.=0A+=20=20=20=20= =20=20=20=20;;=20To=20make=20sure=20`byte-compile-body'=20itself=20= doesn't=20violate=20this,=0A+=20=20=20=20=20=20=20=20;;=20we=20use=20= `cl-assert'.=0A+=20=20=20=20=20=20=20=20(byte-compile-body=20body=20= byte-compile--for-effect)=0A+=20=20=20=20=20=20=20=20(cl-assert=20(or=20= (=3D=20byte-compile-depth=20init-depth)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(=3D=20byte-compile-depth=20(1+=20= init-depth))))=0A+=20=20=20=20=20=20=20=20(byte-compile-goto=20= 'byte-goto=20donetag)=0A+=20=20=20=20=20=20=20=20(setcdr=20(cdr=20= donetag)=20nil)))=0A+=0A+=20=20=20=20(byte-compile-out-tag=20= default-tag)=0A+=20=20=20=20(push=20jump-table=20= byte-compile-jump-tables)))=0A=20=0A=20(defun=20byte-compile-cond=20= (clauses)=0A-=20=20(or=20(and=20byte-compile-cond-use-jump-table=0A-=20=20= =20=20=20=20=20=20=20=20=20(byte-compile-cond-jump-table=20clauses))=0A-=20= =20=20=20(let=20((donetag=20(byte-compile-make-tag))=0A-=20=20=20=20=20=20= =20=20=20=20nexttag=20clause)=0A-=20=20=20=20=20=20(while=20(setq=20= clauses=20(cdr=20clauses))=0A-=20=20=20=20=20=20=20=20(setq=20clause=20= (car=20clauses))=0A-=20=20=20=20=20=20=20=20(cond=20((or=20(eq=20(car=20= clause)=20t)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (and=20(eq=20(car-safe=20(car=20clause))=20'quote)=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(car-safe=20(cdr-safe=20= (car=20clause)))))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= Unconditional=20clause=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (setq=20clause=20(cons=20t=20clause)=0A-=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20clauses=20nil))=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20=20((cdr=20clauses)=0A-=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(byte-compile-form=20(car=20clause))=0A-=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(if=20(null=20(cdr=20clause))=0A-=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20;;=20First=20clause=20is=20a=20= singleton.=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (byte-compile-goto-if=20t=20byte-compile--for-effect=20donetag)=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20nexttag=20= (byte-compile-make-tag))=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(byte-compile-goto=20'byte-goto-if-nil=20nexttag)=0A-=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(byte-compile-maybe-guarded=20(car=20= clause)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (byte-compile-body=20(cdr=20clause)=20byte-compile--for-effect))=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(byte-compile-goto=20= 'byte-goto=20donetag)=0A-=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(byte-compile-out-tag=20nexttag)))))=0A-=20=20=20=20=20=20;;=20Last=20= clause=0A-=20=20=20=20=20=20(let=20((guard=20(car=20clause)))=0A-=20=20=20= =20=20=20=20=20(and=20(cdr=20clause)=20(not=20(eq=20guard=20t))=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20(progn=20(byte-compile-form=20guard)=0A= -=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (byte-compile-goto-if=20nil=20byte-compile--for-effect=20donetag)=0A-=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20clause=20= (cdr=20clause))))=0A-=20=20=20=20=20=20=20=20(byte-compile-maybe-guarded=20= guard=0A-=20=20=20=20=20=20=20=20=20=20(byte-compile-body-do-effect=20= clause)))=0A-=20=20=20=20=20=20(byte-compile-out-tag=20donetag))))=0A+=20= =20(let=20((donetag=20(byte-compile-make-tag))=0A+=20=20=20=20=20=20=20=20= nexttag=20clause)=0A+=20=20=20=20(setq=20clauses=20(cdr=20clauses))=0A+=20= =20=20=20(while=20clauses=0A+=20=20=20=20=20=20(let=20((switch-prefix=20= (and=20byte-compile-cond-use-jump-table=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (byte-compile--cond-switch-prefix=20clauses))))=0A+=20=20=20=20=20=20=20=20= (if=20switch-prefix=0A+=20=20=20=20=20=20=20=20=20=20=20=20(progn=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(byte-compile-cond-jump-table=20(cdr=20= switch-prefix)=20donetag)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (setq=20clauses=20(car=20switch-prefix)))=0A+=20=20=20=20=20=20=20=20=20=20= (setq=20clause=20(car=20clauses))=0A+=20=20=20=20=20=20=20=20=20=20(cond=20= ((or=20(eq=20(car=20clause)=20t)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(and=20(eq=20(car-safe=20(car=20clause))=20= 'quote)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(car-safe=20(cdr-safe=20(car=20clause)))))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Unconditional=20clause=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20clause=20(cons=20= t=20clause)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20clauses=20nil))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20((cdr=20clauses)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (byte-compile-form=20(car=20clause))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(if=20(null=20(cdr=20clause))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20;;=20First=20clause=20is=20a=20= singleton.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(byte-compile-goto-if=20t=20byte-compile--for-effect=20donetag)=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20nexttag=20= (byte-compile-make-tag))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(byte-compile-goto=20'byte-goto-if-nil=20nexttag)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (byte-compile-maybe-guarded=20(car=20clause)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(byte-compile-body=20(cdr=20clause)=20= byte-compile--for-effect))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(byte-compile-goto=20'byte-goto=20donetag)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(byte-compile-out-tag=20= nexttag))))=0A+=20=20=20=20=20=20=20=20=20=20(setq=20clauses=20(cdr=20= clauses)))))=0A+=20=20=20=20;;=20Last=20clause=0A+=20=20=20=20(let=20= ((guard=20(car=20clause)))=0A+=20=20=20=20=20=20(and=20(cdr=20clause)=20= (not=20(eq=20guard=20t))=0A+=20=20=20=20=20=20=20=20=20=20=20(progn=20= (byte-compile-form=20guard)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(byte-compile-goto-if=20nil=20byte-compile--for-effect=20= donetag)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= clause=20(cdr=20clause))))=0A+=20=20=20=20=20=20= (byte-compile-maybe-guarded=20guard=0A+=20=20=20=20=20=20=20=20= (byte-compile-body-do-effect=20clause)))=0A+=20=20=20=20= (byte-compile-out-tag=20donetag)))=0A=20=0A=20(defun=20byte-compile-and=20= (form)=0A=20=20=20(let=20((failtag=20(byte-compile-make-tag))=0Adiff=20= --git=20a/test/lisp/emacs-lisp/bytecomp-tests.el=20= b/test/lisp/emacs-lisp/bytecomp-tests.el=0Aindex=20= 87f2c13bf7..b2a47af63b=20100644=0A---=20= a/test/lisp/emacs-lisp/bytecomp-tests.el=0A+++=20= b/test/lisp/emacs-lisp/bytecomp-tests.el=0A@@=20-334,7=20+334,20=20@@=20= byte-opt-testsuite-arith-data=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((memql=20x=20'(9=20= 0.5=201.5=20q))=2066)=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(t=2099)))=0A=20=20=20=20=20=20= =20=20=20=20=20=20=20'(a=20b=20c=20d=20(d)=20(a=20.=20b)=20"X"=200.5=20= 1.5=203.14=209=209.0))=0A-=20=20=20=20)=0A+=20=20=20=20;;=20Multi-switch=20= cond=20form=0A+=20=20=20=20(mapcar=20(lambda=20(p)=20(let=20((x=20(car=20= p))=20(y=20(cadr=20p)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(cond=20((consp=20x)=2011)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20((eq=20x=20'a)=2022)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((memql=20x=20'(b=207=20= a=20-3))=2033)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20((equal=20y=20"a")=2044)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20((memq=20y=20'(c=20d=20e))=2055)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ((booleanp=20x)=2066)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((eq=20x=20'q)=2077)=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20((memq=20x=20'(r=20s))=2088)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ((eq=20x=20't)=2099)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(t=20999))))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20'((a=20c)=20(b=20c)=20(7=20c)=20(-3=20c)=20(nil=20= nil)=20(t=20c)=20(q=20c)=20(r=20c)=20(s=20c)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(t=20c)=20(x=20"a")=20(x=20"c")=20(x=20c)=20(x=20d)=20(x=20= e))))=0A=20=20=20"List=20of=20expression=20for=20test.=0A=20Each=20= element=20will=20be=20executed=20by=20interpreter=20and=20with=0A=20= bytecompiled=20code,=20and=20their=20results=20compared.")=0A--=20=0A= 2.20.1=20(Apple=20Git-117)=0A=0A= --Apple-Mail=_6425368A-6F6F-40E3-9751-3E52F91F6248--