From: akater <nuclearspace@gmail.com>
To: emacs-devel@gnu.org
Subject: [PATCH] Improve detection of local function calls in methods
Date: Fri, 27 Aug 2021 21:41:05 +0000 [thread overview]
Message-ID: <878s0mva4u.fsf@gmail.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 145 bytes --]
Instead of using unreliale and expensive macroexp--fgrep, we record the
relevant calls in the macroexpansion, as suggested in the FIXME entry.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 865 bytes --]
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cl--generic-lambda fix --]
[-- Type: text/x-diff, Size: 4091 bytes --]
From 099c63eb1c107531252fde859dee7466de05f210 Mon Sep 17 00:00:00 2001
From: akater <nuclearspace@gmail.com>
Date: Thu, 26 Aug 2021 06:09:07 +0000
Subject: [PATCH] Improve detection of local function calls in methods
* lisp/emacs-lisp/cl-generic.el (cl--generic-lambda):
Rather than `grep' after the fact,
the macroexpansion records directly
when cl-call-next-method or cl-next-method-p are used.
---
lisp/emacs-lisp/cl-generic.el | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 4a69df15bc..d5d77fe553 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -361,6 +361,14 @@ defun cl--generic-split-args (args)
(cons (nreverse specializers)
(nreverse (delq nil plain-args)))))
+ (defvar cl-generic--uses-cnm nil
+ ;; It would be better to declare the variable special
+ ;; locally where it's used
+ ;; but there is no support for local special declarations in Elisp.
+ "In a runtime environment, keeps a list of flags that indicate
+the presence of `cl-call-next-method' or `cl-next-method-p'
+in a method body.")
+
(defun cl--generic-lambda (args body)
"Make the lambda expression for a method with ARGS and BODY."
(pcase-let* ((`(,spec-args . ,plain-args)
@@ -369,7 +377,7 @@ defun cl--generic-lambda (args body)
(macroenv (cons `(cl-generic-current-method-specializers
. ,(lambda () spec-args))
macroexpand-all-environment)))
- (require 'cl-lib) ;Needed to expand `cl-flet' and `cl-function'.
+ (require 'cl-lib) ;Needed to expand `cl-function', `cl-macrolet'.
(when (interactive-form (cadr fun))
(message "Interactive forms unsupported in generic functions: %S"
(interactive-form (cadr fun))))
@@ -380,21 +388,29 @@ defun cl--generic-lambda (args body)
(let* ((parsed-body (macroexp-parse-body body))
(cnm (make-symbol "cl--cnm"))
(nmp (make-symbol "cl--nmp"))
+ (cl-generic--uses-cnm)
(nbody (macroexpand-all
- `(cl-flet ((cl-call-next-method ,cnm)
- (cl-next-method-p ,nmp))
+ `(cl-macrolet ((cl-call-next-method
+ (&rest args)
+ (prog1 `(funcall ,',cnm ,@args)
+ (cl-pushnew
+ ',cnm cl-generic--uses-cnm
+ :test #'eq)))
+ (cl-next-method-p
+ ()
+ (prog1 `(funcall ,',nmp)
+ (cl-pushnew
+ ',nmp cl-generic--uses-cnm
+ :test #'eq))))
,@(cdr parsed-body))
macroenv))
- ;; FIXME: Rather than `grep' after the fact, the
- ;; macroexpansion should directly set some flag when cnm
- ;; is used.
- ;; FIXME: Also, optimize the case where call-next-method is
+ ;; FIXME: Optimize the case where call-next-method is
;; only called with explicit arguments.
- (uses-cnm (macroexp--fgrep `((,cnm) (,nmp)) nbody)))
+ (uses-cnm cl-generic--uses-cnm))
(cons (not (not uses-cnm))
`#'(lambda (,@(if uses-cnm (list cnm)) ,@args)
,@(car parsed-body)
- ,(if (not (assq nmp uses-cnm))
+ ,(if (not (memq nmp uses-cnm))
nbody
`(let ((,nmp (lambda ()
(cl--generic-isnot-nnm-p ,cnm))))
--
2.31.1
next reply other threads:[~2021-08-27 21:41 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-27 21:41 akater [this message]
2021-08-27 22:59 ` [PATCH] Improve detection of local function calls in methods Stefan Monnier
2021-08-29 11:25 ` akater
2021-09-02 18:34 ` Stefan Monnier
2021-09-10 6:25 ` akater
2021-09-10 15:49 ` Stefan Monnier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=878s0mva4u.fsf@gmail.com \
--to=nuclearspace@gmail.com \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).