diff options
| author | Eshel Yaron | 2025-10-03 18:00:54 +0200 |
|---|---|---|
| committer | Eshel Yaron | 2025-10-03 18:17:34 +0200 |
| commit | 22327f58bbfa2d34b3160248ce3bfd1969ef7d0d (patch) | |
| tree | d6aeeebd6ccc4e42aa18fb9534e0eaacfff99df5 | |
| parent | 5339cf0010752b9695e5f6a848d87aeaea4c549f (diff) | |
| download | emacs-22327f58bbfa2d34b3160248ce3bfd1969ef7d0d.tar.gz emacs-22327f58bbfa2d34b3160248ce3bfd1969ef7d0d.zip | |
; elisp-scope.el: Improve 'defclass' slots analysis.
Extend the "type" system (to be renamed to "spec" in
subsequent commit) of elisp-scope.el with a plist spec.
This allows us to define a spec for the 'slots' argument of
'eieio-defclass-internal'. Also add a 'cl-type' spec,
describing the type specifications used by 'cl-typep', and
replace the 'equal' spec with a more general 'member' spec,
like we have in 'cl-typep'.
| -rw-r--r-- | lisp/emacs-lisp/elisp-scope.el | 84 |
1 files changed, 56 insertions, 28 deletions
diff --git a/lisp/emacs-lisp/elisp-scope.el b/lisp/emacs-lisp/elisp-scope.el index 6bea0816927..1915609c8df 100644 --- a/lisp/emacs-lisp/elisp-scope.el +++ b/lisp/emacs-lisp/elisp-scope.el | |||
| @@ -1878,23 +1878,9 @@ property, or if the current buffer is trusted (see `trusted-content-p')." | |||
| 1878 | (setq args (cddr args))) | 1878 | (setq args (cddr args))) |
| 1879 | (when args (elisp-scope-n args))) | 1879 | (when args (elisp-scope-n args))) |
| 1880 | 1880 | ||
| 1881 | (defun elisp-scope-typep (type) | ||
| 1882 | (cond | ||
| 1883 | ((or (symbolp type) (symbol-with-pos-p type)) | ||
| 1884 | (unless (booleanp (elisp-scope-sym-bare type)) | ||
| 1885 | (elisp-scope-report-s type 'type))) | ||
| 1886 | ((consp type) | ||
| 1887 | (cond | ||
| 1888 | ((memq (elisp-scope-sym-bare (car type)) '(and or not)) | ||
| 1889 | (mapc #'elisp-scope-typep (cdr type))) | ||
| 1890 | ((eq (elisp-scope-sym-bare (car type)) 'satisfies) | ||
| 1891 | (elisp-scope-report-s (cadr type) 'function)))))) | ||
| 1892 | |||
| 1893 | (elisp-scope-define-function-analyzer cl-typep (val type) | 1881 | (elisp-scope-define-function-analyzer cl-typep (val type) |
| 1894 | (elisp-scope-1 val) | 1882 | (elisp-scope-1 val) |
| 1895 | ;; TODO: Use `elisp-scope-1' with an appropriate outtype. | 1883 | (elisp-scope-1 type 'cl-type)) |
| 1896 | (when-let* ((q (elisp-scope--unquote type))) | ||
| 1897 | (elisp-scope-typep q))) | ||
| 1898 | 1884 | ||
| 1899 | (elisp-scope-define-function-analyzer pulse-momentary-highlight-region (start end &optional face) | 1885 | (elisp-scope-define-function-analyzer pulse-momentary-highlight-region (start end &optional face) |
| 1900 | (elisp-scope-1 start) | 1886 | (elisp-scope-1 start) |
| @@ -2021,7 +2007,20 @@ property, or if the current buffer is trusted (see `trusted-content-p')." | |||
| 2021 | (&optional name superclasses slots options) | 2007 | (&optional name superclasses slots options) |
| 2022 | (elisp-scope-1 name '(symbol . deftype)) | 2008 | (elisp-scope-1 name '(symbol . deftype)) |
| 2023 | (elisp-scope-1 superclasses '(repeat . (symbol . type))) | 2009 | (elisp-scope-1 superclasses '(repeat . (symbol . type))) |
| 2024 | (elisp-scope-1 slots) ;TODO: Specify type of `slots'. | 2010 | (elisp-scope-1 slots |
| 2011 | '(repeat | ||
| 2012 | cons | ||
| 2013 | (symbol . slot) | ||
| 2014 | plist | ||
| 2015 | (:initform . code) | ||
| 2016 | (:initarg . (symbol . constant)) | ||
| 2017 | (:accessor . (symbol . defun)) | ||
| 2018 | (:allocation . code) | ||
| 2019 | (:writer . (symbol . function)) | ||
| 2020 | (:reader . (symbol . function)) | ||
| 2021 | (:type . cl-type) | ||
| 2022 | ;; TODO: add (:custom . custom-type) | ||
| 2023 | )) | ||
| 2025 | (elisp-scope-1 options)) | 2024 | (elisp-scope-1 options)) |
| 2026 | 2025 | ||
| 2027 | (elisp-scope-define-function-analyzer cl-struct-define | 2026 | (elisp-scope-define-function-analyzer cl-struct-define |
| @@ -2591,7 +2590,7 @@ property, or if the current buffer is trusted (see `trusted-content-p')." | |||
| 2591 | (elisp-scope-1 arg))) | 2590 | (elisp-scope-1 arg))) |
| 2592 | 2591 | ||
| 2593 | (cl-defmethod elisp-scope--handle-quoted ((type (head symbol)) arg) | 2592 | (cl-defmethod elisp-scope--handle-quoted ((type (head symbol)) arg) |
| 2594 | (elisp-scope-report-s arg (cdr type))) | 2593 | (when-let* ((role (cdr type))) (elisp-scope-report-s arg role))) |
| 2595 | 2594 | ||
| 2596 | (cl-defmethod elisp-scope--handle-quoted ((type (head list)) arg) | 2595 | (cl-defmethod elisp-scope--handle-quoted ((type (head list)) arg) |
| 2597 | (let ((types (cdr type))) | 2596 | (let ((types (cdr type))) |
| @@ -2610,14 +2609,24 @@ property, or if the current buffer is trusted (see `trusted-content-p')." | |||
| 2610 | (cl-defmethod elisp-scope--match-type-to-arg ((_type (eql 'type)) arg) | 2609 | (cl-defmethod elisp-scope--match-type-to-arg ((_type (eql 'type)) arg) |
| 2611 | (elisp-scope--match-type-to-arg | 2610 | (elisp-scope--match-type-to-arg |
| 2612 | ;; Unfold `type'. | 2611 | ;; Unfold `type'. |
| 2613 | '(or (equal . t) | 2612 | '(or (symbol) |
| 2614 | (equal . code) | 2613 | (cons (member symbol) . (symbol . symbol-role)) |
| 2615 | (equal . type) | 2614 | (cons (member repeat) . type) |
| 2616 | (cons (equal . symbol) . (symbol . symbol-role)) | 2615 | (cons (member or) . (repeat . type)) |
| 2617 | (cons (equal . repeat) . type) | 2616 | (cons (member cons) . (cons type . type)) |
| 2618 | (cons (equal . or) . (repeat . type)) | 2617 | (cons (member member) . t) |
| 2619 | (cons (equal . cons) . (cons type . type)) | 2618 | (cons (member plist) . (repeat . (cons (symbol . constant) . type)))) |
| 2620 | (cons (equal . equal) . t)) | 2619 | arg)) |
| 2620 | |||
| 2621 | (cl-defmethod elisp-scope--match-type-to-arg ((_type (eql 'cl-type)) arg) | ||
| 2622 | (elisp-scope--match-type-to-arg | ||
| 2623 | ;; Unfold `cl-type'. | ||
| 2624 | '(or (member t) | ||
| 2625 | (symbol . type) | ||
| 2626 | (cons (member integer float real number) . t) | ||
| 2627 | (cons (member or and not) . (repeat . cl-type)) | ||
| 2628 | (cons (member member cl-member) . (repeat . t)) | ||
| 2629 | (cons (member satisfies) . (cons (or (symbol . function) code) . t))) | ||
| 2621 | arg)) | 2630 | arg)) |
| 2622 | 2631 | ||
| 2623 | (cl-defmethod elisp-scope--match-type-to-arg ((type (head symbol)) arg) | 2632 | (cl-defmethod elisp-scope--match-type-to-arg ((type (head symbol)) arg) |
| @@ -2645,8 +2654,22 @@ property, or if the current buffer is trusted (see `trusted-content-p')." | |||
| 2645 | (cdr-res (elisp-scope--match-type-to-arg cdr-type (cdr arg)))) | 2654 | (cdr-res (elisp-scope--match-type-to-arg cdr-type (cdr arg)))) |
| 2646 | (cons 'cons (cons car-res cdr-res)))))) | 2655 | (cons 'cons (cons car-res cdr-res)))))) |
| 2647 | 2656 | ||
| 2648 | (cl-defmethod elisp-scope--match-type-to-arg ((type (head equal)) arg) | 2657 | (cl-defmethod elisp-scope--match-type-to-arg ((type (head member)) arg) |
| 2649 | (let ((symbols-with-pos-enabled t)) (equal (cdr type) arg))) | 2658 | (let ((symbols-with-pos-enabled t)) (and (member arg (cdr type)) t))) |
| 2659 | |||
| 2660 | (cl-defmethod elisp-scope--match-type-to-arg ((type (head plist)) arg) | ||
| 2661 | (cond | ||
| 2662 | ((consp arg) | ||
| 2663 | (let ((res nil) (go t)) | ||
| 2664 | (while (and arg go) | ||
| 2665 | (let* ((key (car arg)) | ||
| 2666 | (bkw (elisp-scope-sym-bare key)) | ||
| 2667 | (val (cadr arg))) | ||
| 2668 | (push (if (keywordp bkw) '(symbol . constant) t) res) | ||
| 2669 | (push (setq go (elisp-scope--match-type-to-arg (alist-get bkw (cdr type) t) val)) res)) | ||
| 2670 | (setq arg (cddr arg))) | ||
| 2671 | (when go (cons 'list (nreverse res))))) | ||
| 2672 | ((null arg) t))) | ||
| 2650 | 2673 | ||
| 2651 | (elisp-scope-define-special-form-analyzer catch (&optional tag &rest body) | 2674 | (elisp-scope-define-special-form-analyzer catch (&optional tag &rest body) |
| 2652 | (elisp-scope-1 tag '(symbol . throw-tag)) | 2675 | (elisp-scope-1 tag '(symbol . throw-tag)) |
| @@ -2701,7 +2724,12 @@ OUTTYPE can be one the following: | |||
| 2701 | - (cons CARTYPE . CDRTYPE): FORM evaluates to a cons cell whose `car' | 2724 | - (cons CARTYPE . CDRTYPE): FORM evaluates to a cons cell whose `car' |
| 2702 | has type CARTYPE and whose `cdr' has type CDRTYPE. | 2725 | has type CARTYPE and whose `cdr' has type CDRTYPE. |
| 2703 | 2726 | ||
| 2704 | - (equal . VAL): FORM evaluates to VAL (or something `equal' to VAL). | 2727 | - (member . VALS): FORM evaluates to a `member' of VALS. |
| 2728 | |||
| 2729 | - (plist . VALTYPES): FORM evaluates to a plist. VALTYPES is an alist | ||
| 2730 | associating value types to properties in the plist. For example, an | ||
| 2731 | entry (:face . (symbol . face)) in VALTYPES says that the value of the | ||
| 2732 | property `:face' in the plist is a face name. | ||
| 2705 | 2733 | ||
| 2706 | - (or . TYPES): FORM evaluates to a value that matches one of TYPES. | 2734 | - (or . TYPES): FORM evaluates to a value that matches one of TYPES. |
| 2707 | 2735 | ||