diff options
| author | Mattias EngdegÄrd | 2019-05-22 12:36:03 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2019-06-19 11:20:59 +0200 |
| commit | 14a81524c27ab54850e0fda736e4ee0c92e447b5 (patch) | |
| tree | 07dae25c695381ab4dc7c5fe70543276b90ace82 /lisp | |
| parent | b8c74742c0238fe15b1cdc9a7f6ee021d038368f (diff) | |
| download | emacs-14a81524c27ab54850e0fda736e4ee0c92e447b5.tar.gz emacs-14a81524c27ab54850e0fda736e4ee0c92e447b5.zip | |
Compile cond with heterogeneous tests into switch (bug#36139)
Allow any mixture of `eq', `eql' and `equal', `memq', `memql' and
`member' in a switch-like `cond' to be compiled into a single switch.
* lisp/emacs-lisp/bytecomp.el (byte-compile--common-test): New.
(byte-compile-cond-jump-table-info): Use most specific common test.
* test/lisp/emacs-lisp/bytecomp-tests.el (byte-opt-testsuite-arith-data):
Add test cases for multi-value clause cond forms.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/emacs-lisp/bytecomp.el | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index ab04c1bf439..3a23543f6a7 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el | |||
| @@ -4132,6 +4132,12 @@ that suppresses all warnings during execution of BODY." | |||
| 4132 | 4132 | ||
| 4133 | (defconst byte-compile--default-val (cons nil nil) "A unique object.") | 4133 | (defconst byte-compile--default-val (cons nil nil) "A unique object.") |
| 4134 | 4134 | ||
| 4135 | (defun byte-compile--common-test (test-1 test-2) | ||
| 4136 | "Most specific common test of `eq', `eql' and `equal'" | ||
| 4137 | (cond ((or (eq test-1 'equal) (eq test-2 'equal)) 'equal) | ||
| 4138 | ((or (eq test-1 'eql) (eq test-2 'eql)) 'eql) | ||
| 4139 | (t 'eq))) | ||
| 4140 | |||
| 4135 | (defun byte-compile-cond-jump-table-info (clauses) | 4141 | (defun byte-compile-cond-jump-table-info (clauses) |
| 4136 | "If CLAUSES is a `cond' form where: | 4142 | "If CLAUSES is a `cond' form where: |
| 4137 | The condition for each clause is of the form (TEST VAR VALUE). | 4143 | The condition for each clause is of the form (TEST VAR VALUE). |
| @@ -4143,7 +4149,8 @@ Return a list of the form ((TEST . VAR) ((VALUES BODY) ...))" | |||
| 4143 | (let ((cases '()) | 4149 | (let ((cases '()) |
| 4144 | (ok t) | 4150 | (ok t) |
| 4145 | (all-keys nil) | 4151 | (all-keys nil) |
| 4146 | prev-var prev-test) | 4152 | (prev-test 'eq) |
| 4153 | prev-var) | ||
| 4147 | (and (catch 'break | 4154 | (and (catch 'break |
| 4148 | (dolist (clause (cdr clauses) ok) | 4155 | (dolist (clause (cdr clauses) ok) |
| 4149 | (let* ((condition (car clause)) | 4156 | (let* ((condition (car clause)) |
| @@ -4152,15 +4159,13 @@ Return a list of the form ((TEST . VAR) ((VALUES BODY) ...))" | |||
| 4152 | (byte-compile-cond-vars (cadr condition) (cl-caddr condition)))) | 4159 | (byte-compile-cond-vars (cadr condition) (cl-caddr condition)))) |
| 4153 | (obj1 (car-safe vars)) | 4160 | (obj1 (car-safe vars)) |
| 4154 | (obj2 (cdr-safe vars)) | 4161 | (obj2 (cdr-safe vars)) |
| 4155 | (body (cdr-safe clause)) | 4162 | (body (cdr-safe clause))) |
| 4156 | equality) | ||
| 4157 | (unless prev-var | 4163 | (unless prev-var |
| 4158 | (setq prev-var obj1)) | 4164 | (setq prev-var obj1)) |
| 4159 | (cond | 4165 | (cond |
| 4160 | ((and obj1 (memq test '(eq eql equal)) | 4166 | ((and obj1 (memq test '(eq eql equal)) |
| 4161 | (eq obj1 prev-var) | 4167 | (eq obj1 prev-var)) |
| 4162 | (or (not prev-test) (eq test prev-test))) | 4168 | (setq prev-test (byte-compile--common-test prev-test test)) |
| 4163 | (setq prev-test test) | ||
| 4164 | ;; Discard values already tested for. | 4169 | ;; Discard values already tested for. |
| 4165 | (unless (member obj2 all-keys) | 4170 | (unless (member obj2 all-keys) |
| 4166 | (push obj2 all-keys) | 4171 | (push obj2 all-keys) |
| @@ -4171,12 +4176,12 @@ Return a list of the form ((TEST . VAR) ((VALUES BODY) ...))" | |||
| 4171 | (listp obj2) | 4176 | (listp obj2) |
| 4172 | ;; Require a non-empty body, since the member function | 4177 | ;; Require a non-empty body, since the member function |
| 4173 | ;; value depends on the switch argument. | 4178 | ;; value depends on the switch argument. |
| 4174 | body | 4179 | body) |
| 4175 | (setq equality (cdr (assq test '((memq . eq) | 4180 | (setq prev-test |
| 4176 | (memql . eql) | 4181 | (byte-compile--common-test |
| 4177 | (member . equal))))) | 4182 | prev-test (cdr (assq test '((memq . eq) |
| 4178 | (or (not prev-test) (eq equality prev-test))) | 4183 | (memql . eql) |
| 4179 | (setq prev-test equality) | 4184 | (member . equal)))))) |
| 4180 | (let ((vals nil)) | 4185 | (let ((vals nil)) |
| 4181 | ;; Discard values already tested for. | 4186 | ;; Discard values already tested for. |
| 4182 | (dolist (elem obj2) | 4187 | (dolist (elem obj2) |