aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEshel Yaron2025-10-03 18:00:54 +0200
committerEshel Yaron2025-10-03 18:17:34 +0200
commit22327f58bbfa2d34b3160248ce3bfd1969ef7d0d (patch)
treed6aeeebd6ccc4e42aa18fb9534e0eaacfff99df5
parent5339cf0010752b9695e5f6a848d87aeaea4c549f (diff)
downloademacs-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.el84
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