diff options
| author | Eshel Yaron | 2025-10-06 10:16:25 +0200 |
|---|---|---|
| committer | Eshel Yaron | 2025-10-06 10:54:21 +0200 |
| commit | ec7b376dd444d3cff733dcff21dc5fcb0dc56d61 (patch) | |
| tree | baa4dabfb385f345cfe65527b54549dcf90b8047 | |
| parent | dfb10509a45caf90c0832983636292d021c582f6 (diff) | |
| download | emacs-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.el | 86 |
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) |