summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/cl-preloaded.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/cl-preloaded.el')
-rw-r--r--lisp/emacs-lisp/cl-preloaded.el236
1 files changed, 186 insertions, 50 deletions
diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el
index 20e68555578..d23ad3972a9 100644
--- a/lisp/emacs-lisp/cl-preloaded.el
+++ b/lisp/emacs-lisp/cl-preloaded.el
@@ -50,51 +50,16 @@
(apply #'error string (append sargs args))
(signal 'cl-assertion-failed `(,form ,@sargs)))))
-(defconst cl--typeof-types
- ;; Hand made from the source code of `type-of'.
- '((integer number integer-or-marker number-or-marker atom)
- (symbol-with-pos symbol atom) (symbol atom) (string array sequence atom)
- (cons list sequence)
- ;; Markers aren't `numberp', yet they are accepted wherever integers are
- ;; accepted, pretty much.
- (marker integer-or-marker number-or-marker atom)
- (overlay atom) (float number number-or-marker atom)
- (window-configuration atom) (process atom) (window atom)
- ;; FIXME: We'd want to put `function' here, but that's only true
- ;; for those `subr's which aren't special forms!
- (subr atom)
- ;; FIXME: We should probably reverse the order between
- ;; `compiled-function' and `byte-code-function' since arguably
- ;; `subr' is also "compiled functions" but not "byte code functions",
- ;; but it would require changing the value returned by `type-of' for
- ;; byte code objects, which risks breaking existing code, which doesn't
- ;; seem worth the trouble.
- (compiled-function byte-code-function function atom)
- (module-function function atom)
- (buffer atom) (char-table array sequence atom)
- (bool-vector array sequence atom)
- (frame atom) (hash-table atom) (terminal atom)
- (thread atom) (mutex atom) (condvar atom)
- (font-spec atom) (font-entity atom) (font-object atom)
- (vector array sequence atom)
- (user-ptr atom)
- (tree-sitter-parser atom)
- (tree-sitter-node atom)
- (tree-sitter-compiled-query atom)
- ;; Plus, really hand made:
- (null symbol list sequence atom))
- "Alist of supertypes.
-Each element has the form (TYPE . SUPERTYPES) where TYPE is one of
-the symbols returned by `type-of', and SUPERTYPES is the list of its
-supertypes from the most specific to least specific.")
-
-(defconst cl--all-builtin-types
- (delete-dups (copy-sequence (apply #'append cl--typeof-types))))
+(defun cl--builtin-type-p (name)
+ (if (not (fboundp 'built-in-class-p)) ;; Early bootstrap
+ nil
+ (let ((class (and (symbolp name) (get name 'cl--class))))
+ (and class (built-in-class-p class)))))
(defun cl--struct-name-p (name)
"Return t if NAME is a valid structure name for `cl-defstruct'."
(and name (symbolp name) (not (keywordp name))
- (not (memq name cl--all-builtin-types))))
+ (not (cl--builtin-type-p name))))
;; When we load this (compiled) file during pre-loading, the cl--struct-class
;; code below will need to access the `cl-struct' info, since it's considered
@@ -147,7 +112,7 @@ supertypes from the most specific to least specific.")
(defun cl--struct-register-child (parent tag)
;; Can't use (cl-typep parent 'cl-structure-class) at this stage
;; because `cl-structure-class' is defined later.
- (while (recordp parent)
+ (while (cl--struct-class-p parent)
(add-to-list (cl--struct-class-children-sym parent) tag)
;; Only register ourselves as a child of the leftmost parent since structs
;; can only have one parent.
@@ -162,9 +127,14 @@ supertypes from the most specific to least specific.")
(with-suppressed-warnings ((obsolete cl-old-struct-compat-mode))
(message "cl-old-struct-compat-mode is obsolete!")
(cl-old-struct-compat-mode 1)))
- (if (eq type 'record)
- ;; Defstruct using record objects.
- (setq type nil))
+ (when (eq type 'record)
+ ;; Defstruct using record objects.
+ (setq type nil)
+ ;; `cl-structure-class' and `cl-structure-object' are allowed to be
+ ;; defined without specifying the parent, because their parent
+ ;; doesn't exist yet when they're defined.
+ (cl-assert (or parent (memq name '(cl-structure-class
+ cl-structure-object)))))
(cl-assert (or type (not named)))
(if (boundp children-sym)
(add-to-list children-sym tag)
@@ -172,7 +142,9 @@ supertypes from the most specific to least specific.")
(and (null type) (eq (caar slots) 'cl-tag-slot)
;; Hide the tag slot from "standard" (i.e. non-`type'd) structs.
(setq slots (cdr slots)))
- (let* ((parent-class (when parent (cl--struct-get-class parent)))
+ (let* ((parent-class (if parent (cl--struct-get-class parent)
+ (cl--find-class (if (eq type 'list) 'cons
+ (or type 'record)))))
(n (length slots))
(index-table (make-hash-table :test 'eq :size n))
(vslots (let ((v (make-vector n nil))
@@ -195,7 +167,9 @@ supertypes from the most specific to least specific.")
name docstring
(unless (symbolp parent-class) (list parent-class))
type named vslots index-table children-sym tag print)))
- (unless (symbolp parent-class)
+ (cl-assert (or (not (symbolp parent-class))
+ (memq name '(cl-structure-class cl-structure-object))))
+ (when (cl--struct-class-p parent-class)
(let ((pslots (cl--struct-class-slots parent-class)))
(or (>= n (length pslots))
(let ((ok t))
@@ -286,7 +260,7 @@ supertypes from the most specific to least specific.")
(cl-defstruct (cl--class
(:constructor nil)
(:copier nil))
- "Type of descriptors for any kind of structure-like data."
+ "Abstract supertype of all type descriptors."
;; Intended to be shared between defstruct and defclass.
(name nil :type symbol) ;The type name.
(docstring nil :type string)
@@ -327,8 +301,170 @@ supertypes from the most specific to least specific.")
(merge-ordered-lists (mapcar #'cl--class-allparents
(cl--class-parents class)))))
-(eval-and-compile
- (cl-assert (null (cl--class-parents (cl--find-class 'cl-structure-object)))))
+(cl-defstruct (built-in-class
+ (:include cl--class)
+ (:noinline t)
+ (:constructor nil)
+ (:constructor built-in-class--make (name docstring parents))
+ (:copier nil))
+ "Type descriptors for built-in types.
+The `slots' (and hence `index-table') are currently unused."
+ )
+
+(defmacro cl--define-built-in-type (name parents &optional docstring &rest slots)
+ ;; `slots' is currently unused, but we could make it take
+ ;; a list of "slot like properties" together with the corresponding
+ ;; accessor, and then we could maybe even make `slot-value' work
+ ;; on some built-in types :-)
+ (declare (indent 2) (doc-string 3))
+ (unless (listp parents) (setq parents (list parents)))
+ (unless (or parents (eq name t))
+ (error "Missing parents for %S: %S" name parents))
+ (let ((predicate (intern-soft (format
+ (if (string-match "-" (symbol-name name))
+ "%s-p" "%sp")
+ name))))
+ (unless (fboundp predicate) (setq predicate nil))
+ (while (keywordp (car slots))
+ (let ((kw (pop slots)) (val (pop slots)))
+ (pcase kw
+ (:predicate (setq predicate val))
+ (_ (error "Unknown keyword arg: %S" kw)))))
+ `(progn
+ ,(if predicate `(put ',name 'cl-deftype-satisfies #',predicate)
+ ;; (message "Missing predicate for: %S" name)
+ nil)
+ (put ',name 'cl--class
+ (built-in-class--make ',name ,docstring
+ (mapcar (lambda (type)
+ (let ((class (get type 'cl--class)))
+ (unless class
+ (error "Unknown type: %S" type))
+ class))
+ ',parents))))))
+
+;; FIXME: Our type DAG has various quirks:
+;; - Some `keyword's are also `symbol-with-pos' but that's not reflected
+;; in the DAG.
+;; - An OClosure can be an interpreted function or a `byte-code-function',
+;; so the DAG of OClosure types is "orthogonal" to the distinction
+;; 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 atom t "Abstract supertype of anything but cons cells."
+ :predicate 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-parser atom)
+(when (fboundp 'user-ptrp)
+ (cl--define-built-in-type user-ptr atom nil
+ ;; FIXME: Shouldn't it be called `user-ptr-p'?
+ :predicate user-ptrp))
+(cl--define-built-in-type font-object atom)
+(cl--define-built-in-type font-entity atom)
+(cl--define-built-in-type font-spec atom)
+(cl--define-built-in-type condvar atom)
+(cl--define-built-in-type mutex atom)
+(cl--define-built-in-type thread atom)
+(cl--define-built-in-type terminal atom)
+(cl--define-built-in-type hash-table atom)
+(cl--define-built-in-type frame atom)
+(cl--define-built-in-type buffer atom)
+(cl--define-built-in-type window atom)
+(cl--define-built-in-type process atom)
+(cl--define-built-in-type finalizer atom)
+(cl--define-built-in-type window-configuration atom)
+(cl--define-built-in-type overlay atom)
+(cl--define-built-in-type number-or-marker atom
+ "Abstract supertype of both `number's and `marker's.")
+(cl--define-built-in-type symbol atom
+ "Type of symbols."
+ ;; Example of slots we could document. It would be desirable to
+ ;; have some way to extract this from the C code, or somehow keep it
+ ;; in sync (probably not for `cons' and `symbol' but for things like
+ ;; `font-entity').
+ (name symbol-name)
+ (value symbol-value)
+ (function symbol-function)
+ (plist symbol-plist))
+
+(cl--define-built-in-type obarray atom)
+(cl--define-built-in-type native-comp-unit atom)
+
+(cl--define-built-in-type sequence t "Abstract supertype of sequences.")
+(cl--define-built-in-type list sequence)
+(cl--define-built-in-type array (sequence atom) "Abstract supertype of arrays.")
+(cl--define-built-in-type number (number-or-marker)
+ "Abstract supertype of numbers.")
+(cl--define-built-in-type float (number))
+(cl--define-built-in-type integer-or-marker (number-or-marker)
+ "Abstract supertype of both `integer's and `marker's.")
+(cl--define-built-in-type integer (number integer-or-marker))
+(cl--define-built-in-type marker (integer-or-marker))
+(cl--define-built-in-type bignum (integer)
+ "Type of those integers too large to fit in a `fixnum'.")
+(cl--define-built-in-type fixnum (integer)
+ (format "Type of small (fixed-size) integers.
+The size depends on the Emacs version and compilation options.
+For this build of Emacs it's %dbit."
+ (1+ (logb (1+ most-positive-fixnum)))))
+(cl--define-built-in-type boolean (symbol)
+ "Type of the canonical boolean values, i.e. either nil or t.")
+(cl--define-built-in-type symbol-with-pos (symbol)
+ "Type of symbols augmented with source-position information.")
+(cl--define-built-in-type vector (array))
+(cl--define-built-in-type record (atom)
+ "Abstract type of objects with slots.")
+(cl--define-built-in-type bool-vector (array) "Type of bitvectors.")
+(cl--define-built-in-type char-table (array)
+ "Type of special arrays that are indexed by characters.")
+(cl--define-built-in-type string (array))
+(cl--define-built-in-type null (boolean list) ;FIXME: `atom' comes before `list'?
+ "Type of the nil value."
+ :predicate null)
+(cl--define-built-in-type cons (list)
+ "Type of cons cells."
+ ;; Example of slots we could document.
+ (car car) (cdr cdr))
+(cl--define-built-in-type function (atom)
+ "Abstract supertype of function values."
+ ;; FIXME: Historically, (cl-typep FOO 'function) called `functionp',
+ ;; so while `cl-functionp' would be the more correct predicate, it
+ ;; would breaks existing code :-(
+ ;; :predicate cl-functionp
+ )
+(cl--define-built-in-type compiled-function (function)
+ "Abstract type of functions that have been compiled.")
+(cl--define-built-in-type byte-code-function (compiled-function)
+ "Type of functions that have been byte-compiled.")
+(cl--define-built-in-type subr (atom)
+ "Abstract type of functions compiled to machine code.")
+(cl--define-built-in-type module-function (function)
+ "Type of functions provided via the module API.")
+(cl--define-built-in-type interpreted-function (function)
+ "Type of functions that have not been compiled.")
+(cl--define-built-in-type special-form (subr)
+ "Type of the core syntactic elements of the Emacs Lisp language.")
+(cl--define-built-in-type subr-native-elisp (subr compiled-function)
+ "Type of functions that have been compiled by the native compiler.")
+(cl--define-built-in-type primitive-function (subr compiled-function)
+ "Type of functions hand written in C.")
+
+(unless (cl--class-parents (cl--find-class 'cl-structure-object))
+ ;; When `cl-structure-object' is created, built-in classes didn't exist
+ ;; yet, so we couldn't put `record' as the parent.
+ ;; Fix it now to close the recursion.
+ (setf (cl--class-parents (cl--find-class 'cl-structure-object))
+ (list (cl--find-class 'record))))
;; Make sure functions defined with cl-defsubst can be inlined even in
;; packages which do not require CL. We don't put an autoload cookie