aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEshel Yaron2025-10-06 10:16:25 +0200
committerEshel Yaron2025-10-06 10:54:21 +0200
commitec7b376dd444d3cff733dcff21dc5fcb0dc56d61 (patch)
treebaa4dabfb385f345cfe65527b54549dcf90b8047
parentdfb10509a45caf90c0832983636292d021c582f6 (diff)
downloademacs-ec7b376dd444d3cff733dcff21dc5fcb0dc56d61.tar.gz
emacs-ec7b376dd444d3cff733dcff21dc5fcb0dc56d61.zip
elisp-scope.el: Unify and generalize local function/macro handling
* lisp/emacs-lisp/elisp-scope.el (elisp-scope-local-definitions): New variable. Replaces... (elisp-scope-flet-alist, elisp-scope-macrolet-alist): these. Removed, no longer used. (elisp-scope-1, elisp-scope--handle-quoted): Update. (elisp-scope-with-local-definition): New macro. (elisp-scope-flet, elisp-scope-labels, elisp-scope-named-let) (elisp-scope-cl-macrolet): Use it.
-rw-r--r--lisp/emacs-lisp/elisp-scope.el86
1 files changed, 49 insertions, 37 deletions
diff --git a/lisp/emacs-lisp/elisp-scope.el b/lisp/emacs-lisp/elisp-scope.el
index 784c165645d..098bc231994 100644
--- a/lisp/emacs-lisp/elisp-scope.el
+++ b/lisp/emacs-lisp/elisp-scope.el
@@ -716,7 +716,13 @@ Optional argument LOCAL is a local context to extend."
716 716
717(defun elisp-scope-setq (args) (elisp-scope-n args elisp-scope-output-spec)) 717(defun elisp-scope-setq (args) (elisp-scope-n args elisp-scope-output-spec))
718 718
719(defvar elisp-scope-flet-alist nil) 719(defvar elisp-scope-local-definitions nil)
720
721(defmacro elisp-scope-with-local-definition (sym def &rest body)
722 (declare (indent 2) (debug t))
723 `(let ((elisp-scope-local-definitions
724 (cons (cons ,sym ,def) elisp-scope-local-definitions)))
725 ,@body))
720 726
721(defun elisp-scope-flet (defs body outspec) 727(defun elisp-scope-flet (defs body outspec)
722 (if defs 728 (if defs
@@ -724,16 +730,21 @@ Optional argument LOCAL is a local context to extend."
724 (func (car def)) 730 (func (car def))
725 (exps (cdr def)) 731 (exps (cdr def))
726 (beg (elisp-scope-sym-pos func)) 732 (beg (elisp-scope-sym-pos func))
727 (bare (bare-symbol func))) 733 (bare (bare-symbol func))
734 (len (length (symbol-name bare))))
728 (when beg 735 (when beg
729 (elisp-scope-report 'function beg (length (symbol-name bare)) beg)) 736 (elisp-scope-report 'function beg len beg))
730 (if (cdr exps) 737 (if (cdr exps)
731 ;; def is (FUNC ARGLIST BODY...) 738 ;; def is (FUNC ARGLIST BODY...)
732 (elisp-scope-cl-lambda (car exps) (cdr exps)) 739 (elisp-scope-cl-lambda (car exps) (cdr exps))
733 ;; def is (FUNC EXP) 740 ;; def is (FUNC EXP)
734 (elisp-scope-1 (car exps))) 741 (elisp-scope-1 (car exps)))
735 (let ((elisp-scope-flet-alist (elisp-scope-local-new bare beg elisp-scope-flet-alist))) 742 (let ((pos (or beg (cons 'gen (incf elisp-scope-counter)))))
736 (elisp-scope-flet (cdr defs) body outspec))) 743 (elisp-scope-with-local-definition bare
744 (lambda (f &rest args)
745 (elisp-scope-report 'function (symbol-with-pos-pos f) len pos)
746 (elisp-scope-n args))
747 (elisp-scope-flet (cdr defs) body outspec))))
737 (elisp-scope-n body outspec))) 748 (elisp-scope-n body outspec)))
738 749
739(defun elisp-scope-labels (defs forms outspec) 750(defun elisp-scope-labels (defs forms outspec)
@@ -743,12 +754,17 @@ Optional argument LOCAL is a local context to extend."
743 (args (cadr def)) 754 (args (cadr def))
744 (body (cddr def)) 755 (body (cddr def))
745 (beg (elisp-scope-sym-pos func)) 756 (beg (elisp-scope-sym-pos func))
746 (bare (bare-symbol func))) 757 (bare (bare-symbol func))
758 (len (length (symbol-name bare))))
747 (when beg 759 (when beg
748 (elisp-scope-report 'function beg (length (symbol-name bare)) beg)) 760 (elisp-scope-report 'function beg len beg))
749 (let ((elisp-scope-flet-alist (elisp-scope-local-new bare beg elisp-scope-flet-alist))) 761 (let ((pos (or beg (cons 'gen (incf elisp-scope-counter)))))
750 (elisp-scope-lambda args body) 762 (elisp-scope-with-local-definition bare
751 (elisp-scope-flet (cdr defs) forms outspec))) 763 (lambda (f &rest args)
764 (elisp-scope-report 'function (symbol-with-pos-pos f) len pos)
765 (elisp-scope-n args))
766 (elisp-scope-lambda args body)
767 (elisp-scope-flet (cdr defs) forms outspec))))
752 (elisp-scope-n forms outspec))) 768 (elisp-scope-n forms outspec)))
753 769
754(defvar elisp-scope-block-alist nil) 770(defvar elisp-scope-block-alist nil)
@@ -777,7 +793,10 @@ Optional argument LOCAL is a local context to extend."
777 ((or (symbol-with-pos-p arg) (symbolp arg)) 793 ((or (symbol-with-pos-p arg) (symbolp arg))
778 (let ((bare (bare-symbol arg))) 794 (let ((bare (bare-symbol arg)))
779 (cond 795 (cond
780 ((or (functionp bare) (memq bare elisp-scope-local-functions) (assq bare elisp-scope-flet-alist) elisp-scope-assume-func) 796 ((or (functionp bare)
797 (memq bare elisp-scope-local-functions)
798 (assq bare elisp-scope-local-definitions)
799 elisp-scope-assume-func)
781 (elisp-scope-report-s arg 'function)) 800 (elisp-scope-report-s arg 'function))
782 (t (elisp-scope-report-s arg 'unknown))))) 801 (t (elisp-scope-report-s arg 'unknown)))))
783 ((consp arg) (elisp-scope-1 arg)))) 802 ((consp arg) (elisp-scope-1 arg))))
@@ -1023,9 +1042,13 @@ Optional argument LOCAL is a local context to extend."
1023 (when-let* ((sym (car (ensure-list binding))) 1042 (when-let* ((sym (car (ensure-list binding)))
1024 (bare (elisp-scope-sym-bare sym))) 1043 (bare (elisp-scope-sym-bare sym)))
1025 (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos sym) l)))) 1044 (setq l (elisp-scope-local-new bare (elisp-scope-sym-pos sym) l))))
1026 (let ((elisp-scope-flet-alist (elisp-scope-local-new bare beg elisp-scope-flet-alist)) 1045 (let ((pos (or beg (cons 'gen (incf elisp-scope-counter))))
1027 (elisp-scope--local l)) 1046 (len (length (symbol-name bare))))
1028 (elisp-scope-n body outspec))))) 1047 (elisp-scope-with-local-definition bare
1048 (lambda (f &rest args)
1049 (elisp-scope-report 'function (symbol-with-pos-pos f) len pos)
1050 (elisp-scope-n args))
1051 (let ((elisp-scope--local l)) (elisp-scope-n body outspec)))))))
1029 1052
1030(defun elisp-scope-rx (regexps) 1053(defun elisp-scope-rx (regexps)
1031 (dolist (regexp regexps) (elisp-scope-rx-1 regexp))) 1054 (dolist (regexp regexps) (elisp-scope-rx-1 regexp)))
@@ -1508,19 +1531,21 @@ Optional argument LOCAL is a local context to extend."
1508 (more (elisp-scope-cl-lambda-1 (car more) (cdr more) body)) 1531 (more (elisp-scope-cl-lambda-1 (car more) (cdr more) body))
1509 (t (elisp-scope-lambda nil body))))))) 1532 (t (elisp-scope-lambda nil body)))))))
1510 1533
1511(defvar elisp-scope-macrolet-alist nil)
1512
1513(defun elisp-scope-cl-macrolet (bindings body outspec) 1534(defun elisp-scope-cl-macrolet (bindings body outspec)
1514 (if-let* ((b (car bindings))) 1535 (if-let* ((b (car bindings)))
1515 (let ((name (car b)) 1536 (let ((name (car b))
1516 (arglist (cadr b)) 1537 (arglist (cadr b))
1517 (mbody (cddr b))) 1538 (mbody (cddr b)))
1518 (elisp-scope-cl-lambda arglist mbody) 1539 (elisp-scope-cl-lambda arglist mbody)
1519 (when-let* ((bare (elisp-scope-sym-bare name))) 1540 (when-let* ((bare (elisp-scope-sym-bare name))
1520 (when-let* ((beg (elisp-scope-sym-pos name))) 1541 (len (length (symbol-name bare))))
1521 (elisp-scope-report 'macro beg (length (symbol-name bare)) beg)) 1542 (let ((beg (elisp-scope-sym-pos name)))
1522 (let ((elisp-scope-macrolet-alist (elisp-scope-local-new bare (elisp-scope-sym-pos name) elisp-scope-macrolet-alist))) 1543 (when beg (elisp-scope-report 'macro beg len beg))
1523 (elisp-scope-cl-macrolet (cdr bindings) body outspec)))) 1544 (let ((pos (or beg (cons 'gen (incf elisp-scope-counter)))))
1545 (elisp-scope-with-local-definition bare
1546 (lambda (f &rest _)
1547 (elisp-scope-report 'macro (symbol-with-pos-pos f) len pos))
1548 (elisp-scope-cl-macrolet (cdr bindings) body outspec))))))
1524 (elisp-scope-n body outspec))) 1549 (elisp-scope-n body outspec)))
1525 1550
1526(defun elisp-scope-define-minor-mode (mode _doc body) 1551(defun elisp-scope-define-minor-mode (mode _doc body)
@@ -2592,9 +2617,8 @@ property, or if the current buffer is trusted (see `trusted-content-p')."
2592(cl-defmethod elisp-scope--handle-quoted ((_spec (eql 'code)) arg) 2617(cl-defmethod elisp-scope--handle-quoted ((_spec (eql 'code)) arg)
2593 (let ((elisp-scope--local nil) 2618 (let ((elisp-scope--local nil)
2594 (elisp-scope-current-let-alist-form nil) 2619 (elisp-scope-current-let-alist-form nil)
2595 (elisp-scope-flet-alist nil) 2620 (elisp-scope-local-definitions nil)
2596 (elisp-scope-block-alist nil) 2621 (elisp-scope-block-alist nil)
2597 (elisp-scope-macrolet-alist nil)
2598 (elisp-scope-label-alist nil) 2622 (elisp-scope-label-alist nil)
2599 (elisp-scope-rx-alist nil) 2623 (elisp-scope-rx-alist nil)
2600 (elisp-scope--quoted t)) 2624 (elisp-scope--quoted t))
@@ -2761,20 +2785,8 @@ are analyzed."
2761 (forms (cdr form)) (this nil)) 2785 (forms (cdr form)) (this nil))
2762 (when bare 2786 (when bare
2763 (cond 2787 (cond
2764 ;; TODO: Collapse `elisp-scope-flet/macrolet/...-alist' into a 2788 ((setq this (or (alist-get bare elisp-scope-local-definitions)
2765 ;; unified "context", associating role+binder position to syms. 2789 (function-get bare 'elisp-scope-analyzer)))
2766 ((setq this (assq bare elisp-scope-flet-alist))
2767 (elisp-scope-report
2768 'function (symbol-with-pos-pos f) (length (symbol-name bare)) (cdr this))
2769 (elisp-scope-n forms))
2770 ((setq this (assq bare elisp-scope-macrolet-alist))
2771 (when (symbol-with-pos-p f)
2772 (elisp-scope-report
2773 'macro (symbol-with-pos-pos f) (length (symbol-name bare)) (cdr this)))
2774 ;; Local macros can be unsafe, so we do not expand them.
2775 ;; Hence we cannot interpret their arguments.
2776 )
2777 ((setq this (function-get bare 'elisp-scope-analyzer))
2778 (let ((elisp-scope-output-spec outspec)) (apply this form))) 2790 (let ((elisp-scope-output-spec outspec)) (apply this form)))
2779 ((special-form-p bare) (elisp-scope-report-s f 'special-form) (elisp-scope-n forms)) 2791 ((special-form-p bare) (elisp-scope-report-s f 'special-form) (elisp-scope-n forms))
2780 ((macrop bare) (elisp-scope-report-s f 'macro) 2792 ((macrop bare) (elisp-scope-report-s f 'macro)