mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
cl-preloaded.el: Fix the type lattice
We generally want types to form not just a DAG but a lattice. If objects can be both `keyword` and `symbol-with-pos`, this means there should be a more precise type describing this intersection. If we ever find the need for such a refinement, we could add such a `keyword-with-pos` type, but here I took the simpler route of treating `keyword` not as a proper built-in type but as a second-class type like `natnum`. While fixing this problem, also fix the problem we had where `functionp` was not quite adequate to characterize objects of type `function`, by introducing a new predicate `cl-functionp` for that. * lisp/emacs-lisp/cl-preloaded.el (cl-functionp): New function. (function): Use it. (keyword): Don't declare it as a built-in type. (user-ptrp): Remove redundant declaration. * lisp/emacs-lisp/cl-generic.el (cl--generic--unreachable-types): Delete constant. (cl-generic-generalizers): Remove corresponding test. * lisp/emacs-lisp/cl-macs.el (cl-deftype-satisfies): Add entry for `keyword` type. * lisp/emacs-lisp/comp.el (comp-known-predicates): Fix type for negative result of `characterp`. Remove duplicate `numberp` entry. Fix types for `keywordp` now that `keyword` is not a built-in type any more. * test/src/data-tests.el (data-tests--cl-type-of): Add a few cases. Remove workaround for `function`.
This commit is contained in:
parent
351d98535d
commit
004f2493a5
6 changed files with 37 additions and 36 deletions
8
etc/NEWS
8
etc/NEWS
|
|
@ -1700,9 +1700,11 @@ This function is like 'type-of' except that it sometimes returns
|
||||||
a more precise type. For example, for nil and t it returns 'null'
|
a more precise type. For example, for nil and t it returns 'null'
|
||||||
and 'boolean' respectively, instead of just 'symbol'.
|
and 'boolean' respectively, instead of just 'symbol'.
|
||||||
|
|
||||||
** New function `primitive-function-p`.
|
** New functions `primitive-function-p` and `cl-functionp`.
|
||||||
This is like `subr-primitive-p` except that it returns t only if the
|
`primitive-function-p` is like `subr-primitive-p` except that it returns
|
||||||
argument is a function rather than a special-form.
|
t only if the argument is a function rather than a special-form,
|
||||||
|
and `cl-functionp` is like `functionp` except it return nil
|
||||||
|
for lists and symbols.
|
||||||
|
|
||||||
** Built-in types have now corresponding classes.
|
** Built-in types have now corresponding classes.
|
||||||
At the Lisp level, this means that things like (cl-find-class 'integer)
|
At the Lisp level, this means that things like (cl-find-class 'integer)
|
||||||
|
|
|
||||||
|
|
@ -1332,11 +1332,6 @@ These match if the argument is `eql' to VAL."
|
||||||
|
|
||||||
;;; Dispatch on "normal types".
|
;;; Dispatch on "normal types".
|
||||||
|
|
||||||
(defconst cl--generic--unreachable-types
|
|
||||||
;; FIXME: Try to make that list empty?
|
|
||||||
'(keyword)
|
|
||||||
"Built-in classes on which we cannot dispatch for technical reasons.")
|
|
||||||
|
|
||||||
(defun cl--generic-type-specializers (tag &rest _)
|
(defun cl--generic-type-specializers (tag &rest _)
|
||||||
(and (symbolp tag)
|
(and (symbolp tag)
|
||||||
(let ((class (cl--find-class tag)))
|
(let ((class (cl--find-class tag)))
|
||||||
|
|
@ -1350,14 +1345,12 @@ These match if the argument is `eql' to VAL."
|
||||||
(cl-defmethod cl-generic-generalizers :extra "typeof" (type)
|
(cl-defmethod cl-generic-generalizers :extra "typeof" (type)
|
||||||
"Support for dispatch on types.
|
"Support for dispatch on types.
|
||||||
This currently works for built-in types and types built on top of records."
|
This currently works for built-in types and types built on top of records."
|
||||||
;; FIXME: Add support for other types accepted by `cl-typep' such
|
;; FIXME: Add support for other "types" accepted by `cl-typep' such
|
||||||
;; as `character', `face', `function', ...
|
;; as `character', `face', `keyword', ...?
|
||||||
(or
|
(or
|
||||||
(and (symbolp type)
|
(and (symbolp type)
|
||||||
(not (eq type t)) ;; Handled by the `t-generalizer'.
|
(not (eq type t)) ;; Handled by the `t-generalizer'.
|
||||||
(let ((class (cl--find-class type)))
|
(let ((class (cl--find-class type)))
|
||||||
(when (memq type cl--generic--unreachable-types)
|
|
||||||
(error "Dispatch on %S is currently not supported" type))
|
|
||||||
(memq (type-of class)
|
(memq (type-of class)
|
||||||
'(built-in-class cl-structure-class eieio--class)))
|
'(built-in-class cl-structure-class eieio--class)))
|
||||||
(list cl--generic-typeof-generalizer))
|
(list cl--generic-typeof-generalizer))
|
||||||
|
|
|
||||||
|
|
@ -3467,6 +3467,7 @@ Of course, we really can't know that for sure, so it's just a heuristic."
|
||||||
'((base-char . characterp) ;Could be subtype of `fixnum'.
|
'((base-char . characterp) ;Could be subtype of `fixnum'.
|
||||||
(character . natnump) ;Could be subtype of `fixnum'.
|
(character . natnump) ;Could be subtype of `fixnum'.
|
||||||
(command . commandp) ;Subtype of closure & subr.
|
(command . commandp) ;Subtype of closure & subr.
|
||||||
|
(keyword . keywordp) ;Would need `keyword-with-pos`.
|
||||||
(natnum . natnump) ;Subtype of fixnum & bignum.
|
(natnum . natnump) ;Subtype of fixnum & bignum.
|
||||||
(real . numberp) ;Not clear where it would fit.
|
(real . numberp) ;Not clear where it would fit.
|
||||||
))
|
))
|
||||||
|
|
|
||||||
|
|
@ -349,6 +349,14 @@ The `slots' (and hence `index-table') are currently unused."
|
||||||
;; so the DAG of OClosure types is "orthogonal" to the distinction
|
;; so the DAG of OClosure types is "orthogonal" to the distinction
|
||||||
;; between interpreted and compiled functions.
|
;; between interpreted and compiled functions.
|
||||||
|
|
||||||
|
(defun cl-functionp (object)
|
||||||
|
"Return non-nil if OBJECT is a member of type `function'.
|
||||||
|
This is like `functionp' except that it returns nil for all lists and symbols,
|
||||||
|
regardless if `funcall' would accept to call them."
|
||||||
|
(memq (cl-type-of object)
|
||||||
|
'(primitive-function subr-native-elisp module-function
|
||||||
|
interpreted-function byte-code-function)))
|
||||||
|
|
||||||
(cl--define-built-in-type t nil "Abstract supertype of everything.")
|
(cl--define-built-in-type t nil "Abstract supertype of everything.")
|
||||||
(cl--define-built-in-type atom t "Abstract supertype of anything but cons cells."
|
(cl--define-built-in-type atom t "Abstract supertype of anything but cons cells."
|
||||||
:predicate atom)
|
:predicate atom)
|
||||||
|
|
@ -356,11 +364,9 @@ The `slots' (and hence `index-table') are currently unused."
|
||||||
(cl--define-built-in-type tree-sitter-compiled-query atom)
|
(cl--define-built-in-type tree-sitter-compiled-query atom)
|
||||||
(cl--define-built-in-type tree-sitter-node atom)
|
(cl--define-built-in-type tree-sitter-node atom)
|
||||||
(cl--define-built-in-type tree-sitter-parser atom)
|
(cl--define-built-in-type tree-sitter-parser atom)
|
||||||
(declare-function user-ptrp "data.c")
|
|
||||||
(when (fboundp 'user-ptrp)
|
(when (fboundp 'user-ptrp)
|
||||||
(cl--define-built-in-type user-ptr atom nil
|
(cl--define-built-in-type user-ptr atom nil
|
||||||
;; FIXME: Shouldn't it be called
|
;; FIXME: Shouldn't it be called `user-ptr-p'?
|
||||||
;; `user-ptr-p'?
|
|
||||||
:predicate user-ptrp))
|
:predicate user-ptrp))
|
||||||
(cl--define-built-in-type font-object atom)
|
(cl--define-built-in-type font-object atom)
|
||||||
(cl--define-built-in-type font-entity atom)
|
(cl--define-built-in-type font-entity atom)
|
||||||
|
|
@ -410,8 +416,6 @@ The `slots' (and hence `index-table') are currently unused."
|
||||||
The size depends on the Emacs version and compilation options.
|
The size depends on the Emacs version and compilation options.
|
||||||
For this build of Emacs it's %dbit."
|
For this build of Emacs it's %dbit."
|
||||||
(1+ (logb (1+ most-positive-fixnum)))))
|
(1+ (logb (1+ most-positive-fixnum)))))
|
||||||
(cl--define-built-in-type keyword (symbol)
|
|
||||||
"Type of those symbols whose first char is `:'.")
|
|
||||||
(cl--define-built-in-type boolean (symbol)
|
(cl--define-built-in-type boolean (symbol)
|
||||||
"Type of the canonical boolean values, i.e. either nil or t.")
|
"Type of the canonical boolean values, i.e. either nil or t.")
|
||||||
(cl--define-built-in-type symbol-with-pos (symbol)
|
(cl--define-built-in-type symbol-with-pos (symbol)
|
||||||
|
|
@ -431,7 +435,8 @@ For this build of Emacs it's %dbit."
|
||||||
;; Example of slots we could document.
|
;; Example of slots we could document.
|
||||||
(car car) (cdr cdr))
|
(car car) (cdr cdr))
|
||||||
(cl--define-built-in-type function (atom)
|
(cl--define-built-in-type function (atom)
|
||||||
"Abstract supertype of function values.")
|
"Abstract supertype of function values."
|
||||||
|
:predicate cl-functionp)
|
||||||
(cl--define-built-in-type compiled-function (function)
|
(cl--define-built-in-type compiled-function (function)
|
||||||
"Abstract type of functions that have been compiled.")
|
"Abstract type of functions that have been compiled.")
|
||||||
(cl--define-built-in-type byte-code-function (compiled-function)
|
(cl--define-built-in-type byte-code-function (compiled-function)
|
||||||
|
|
|
||||||
|
|
@ -193,13 +193,14 @@ Useful to hook into pass checkers.")
|
||||||
;; cl-macs.el. We can't use `cl-deftype-satisfies' directly as the
|
;; cl-macs.el. We can't use `cl-deftype-satisfies' directly as the
|
||||||
;; relation type <-> predicate is not bijective (bug#45576).
|
;; relation type <-> predicate is not bijective (bug#45576).
|
||||||
(defconst comp-known-predicates
|
(defconst comp-known-predicates
|
||||||
|
;; FIXME: Auto-generate (most of) it from `cl-deftype-satifies'?
|
||||||
'((arrayp array)
|
'((arrayp array)
|
||||||
(atom atom)
|
(atom atom)
|
||||||
(bool-vector-p bool-vector)
|
(bool-vector-p bool-vector)
|
||||||
(booleanp boolean)
|
(booleanp boolean)
|
||||||
(bufferp buffer)
|
(bufferp buffer)
|
||||||
(char-table-p char-table)
|
(char-table-p char-table)
|
||||||
(characterp fixnum)
|
(characterp fixnum t)
|
||||||
(consp cons)
|
(consp cons)
|
||||||
(floatp float)
|
(floatp float)
|
||||||
(framep frame)
|
(framep frame)
|
||||||
|
|
@ -207,14 +208,13 @@ Useful to hook into pass checkers.")
|
||||||
(hash-table-p hash-table)
|
(hash-table-p hash-table)
|
||||||
(integer-or-marker-p integer-or-marker)
|
(integer-or-marker-p integer-or-marker)
|
||||||
(integerp integer)
|
(integerp integer)
|
||||||
(keywordp keyword)
|
(keywordp symbol t)
|
||||||
(listp list)
|
(listp list)
|
||||||
(markerp marker)
|
(markerp marker)
|
||||||
(natnump (integer 0 *))
|
(natnump (integer 0 *))
|
||||||
(null null)
|
(null null)
|
||||||
(number-or-marker-p number-or-marker)
|
(number-or-marker-p number-or-marker)
|
||||||
(numberp number)
|
(numberp number)
|
||||||
(numberp number)
|
|
||||||
(obarrayp obarray)
|
(obarrayp obarray)
|
||||||
(overlayp overlay)
|
(overlayp overlay)
|
||||||
(processp process)
|
(processp process)
|
||||||
|
|
|
||||||
|
|
@ -845,10 +845,12 @@ comparing the subr with a much slower Lisp implementation."
|
||||||
;; Note: This doesn't work for list/vector structs since those types
|
;; Note: This doesn't work for list/vector structs since those types
|
||||||
;; are too difficult/unreliable to detect (so `cl-type-of' only says
|
;; are too difficult/unreliable to detect (so `cl-type-of' only says
|
||||||
;; it's a `cons' or a `vector').
|
;; it's a `cons' or a `vector').
|
||||||
(dolist (val (list -2 10 (expt 2 128) nil t 'car
|
(dolist (val (list -2 10 (expt 2 128) nil t 'car :car
|
||||||
(symbol-function 'car)
|
(symbol-function 'car)
|
||||||
(symbol-function 'progn)
|
(symbol-function 'progn)
|
||||||
(position-symbol 'car 7)))
|
(eval '(lambda (x) (+ x 1)) t)
|
||||||
|
(position-symbol 'car 7)
|
||||||
|
(position-symbol :car 7)))
|
||||||
(let* ((type (cl-type-of val))
|
(let* ((type (cl-type-of val))
|
||||||
(class (cl-find-class type))
|
(class (cl-find-class type))
|
||||||
(alltypes (cl--class-allparents class))
|
(alltypes (cl--class-allparents class))
|
||||||
|
|
@ -858,19 +860,17 @@ comparing the subr with a much slower Lisp implementation."
|
||||||
(dolist (parent alltypes)
|
(dolist (parent alltypes)
|
||||||
(should (cl-typep val parent))
|
(should (cl-typep val parent))
|
||||||
(dolist (subtype (cl--class-children (cl-find-class parent)))
|
(dolist (subtype (cl--class-children (cl-find-class parent)))
|
||||||
(unless (memq subtype alltypes)
|
(when (and (not (memq subtype alltypes))
|
||||||
(unless (memq subtype
|
(built-in-class-p (cl-find-class subtype))
|
||||||
;; FIXME: Some types don't have any associated
|
(not (memq subtype
|
||||||
;; predicate,
|
;; FIXME: Some types don't have any associated
|
||||||
'( font-spec font-entity font-object
|
;; predicate,
|
||||||
finalizer condvar terminal
|
'( font-spec font-entity font-object
|
||||||
native-comp-unit interpreted-function
|
finalizer condvar terminal
|
||||||
tree-sitter-compiled-query
|
native-comp-unit interpreted-function
|
||||||
tree-sitter-node tree-sitter-parser
|
tree-sitter-compiled-query
|
||||||
;; `functionp' also matches things of type
|
tree-sitter-node tree-sitter-parser))))
|
||||||
;; `symbol' and `cons'.
|
(should-not (cl-typep val subtype))))))))
|
||||||
function))
|
|
||||||
(should-not (cl-typep val subtype)))))))))
|
|
||||||
|
|
||||||
|
|
||||||
;;; data-tests.el ends here
|
;;; data-tests.el ends here
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue