cl-preloaded.el 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. ;;; cl-preloaded.el --- Preloaded part of the CL library -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2015-2017 Free Software Foundation, Inc
  3. ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
  4. ;; Package: emacs
  5. ;; This file is part of GNU Emacs.
  6. ;; GNU Emacs is free software: you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation, either version 3 of the License, or
  9. ;; (at your option) any later version.
  10. ;; GNU Emacs is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  16. ;;; Commentary:
  17. ;; The cl-defstruct macro is full of circularities, since it uses the
  18. ;; cl-structure-class type (and its accessors) which is defined with itself,
  19. ;; and it setups a default parent (cl-structure-object) which is also defined
  20. ;; with cl-defstruct, and to make things more interesting, the class of
  21. ;; cl-structure-object is of course an object of type cl-structure-class while
  22. ;; cl-structure-class's parent is cl-structure-object.
  23. ;; Furthermore, the code generated by cl-defstruct generally assumes that the
  24. ;; parent will be loaded when the child is loaded. But at the same time, the
  25. ;; expectation is that structs defined with cl-defstruct do not need cl-lib at
  26. ;; run-time, which means that the `cl-structure-object' parent can't be in
  27. ;; cl-lib but should be preloaded. So here's this preloaded circular setup.
  28. ;;; Code:
  29. (eval-when-compile (require 'cl-lib))
  30. (eval-when-compile (require 'cl-macs)) ;For cl--struct-class.
  31. ;; The `assert' macro from the cl package signals
  32. ;; `cl-assertion-failed' at runtime so always define it.
  33. (define-error 'cl-assertion-failed (purecopy "Assertion failed"))
  34. (defun cl--assertion-failed (form &optional string sargs args)
  35. (if debug-on-error
  36. (funcall debugger 'error `(cl-assertion-failed (,form ,string ,@sargs)))
  37. (if string
  38. (apply #'error string (append sargs args))
  39. (signal 'cl-assertion-failed `(,form ,@sargs)))))
  40. ;; When we load this (compiled) file during pre-loading, the cl--struct-class
  41. ;; code below will need to access the `cl-struct' info, since it's considered
  42. ;; already as its parent (because `cl-struct' was defined while the file was
  43. ;; compiled). So let's temporarily setup a fake.
  44. (defvar cl-struct-cl-structure-object-tags nil)
  45. (unless (cl--find-class 'cl-structure-object)
  46. (setf (cl--find-class 'cl-structure-object) 'dummy))
  47. (fset 'cl--make-slot-desc
  48. ;; To break circularity, we pre-define the slot constructor by hand.
  49. ;; It's redefined a bit further down as part of the cl-defstruct of
  50. ;; cl--slot-descriptor.
  51. ;; BEWARE: Obviously, it's important to keep the two in sync!
  52. (lambda (name &optional initform type props)
  53. (record 'cl-slot-descriptor
  54. name initform type props)))
  55. (defun cl--struct-get-class (name)
  56. (or (if (not (symbolp name)) name)
  57. (cl--find-class name)
  58. (if (not (get name 'cl-struct-type))
  59. ;; FIXME: Add a conversion for `eieio--class' so we can
  60. ;; create a cl-defstruct that inherits from an eieio class?
  61. (error "%S is not a struct name" name)
  62. ;; Backward compatibility with a defstruct compiled with a version
  63. ;; cl-defstruct from Emacs<25. Convert to new format.
  64. (let ((tag (intern (format "cl-struct-%s" name)))
  65. (type-and-named (get name 'cl-struct-type))
  66. (descs (get name 'cl-struct-slots)))
  67. (cl-struct-define name nil (get name 'cl-struct-include)
  68. (unless (and (eq (car type-and-named) 'vector)
  69. (null (cadr type-and-named))
  70. (assq 'cl-tag-slot descs))
  71. (car type-and-named))
  72. (cadr type-and-named)
  73. descs
  74. (intern (format "cl-struct-%s-tags" name))
  75. tag
  76. (get name 'cl-struct-print))
  77. (cl--find-class name)))))
  78. (defun cl--plist-remove (plist member)
  79. (cond
  80. ((null plist) nil)
  81. ((null member) plist)
  82. ((eq plist member) (cddr plist))
  83. (t `(,(car plist) ,(cadr plist) ,@(cl--plist-remove (cddr plist) member)))))
  84. (defun cl--struct-register-child (parent tag)
  85. ;; Can't use (cl-typep parent 'cl-structure-class) at this stage
  86. ;; because `cl-structure-class' is defined later.
  87. (while (recordp parent)
  88. (add-to-list (cl--struct-class-children-sym parent) tag)
  89. ;; Only register ourselves as a child of the leftmost parent since structs
  90. ;; can only only have one parent.
  91. (setq parent (car (cl--struct-class-parents parent)))))
  92. ;;;###autoload
  93. (defun cl-struct-define (name docstring parent type named slots children-sym
  94. tag print)
  95. (unless type
  96. ;; Legacy defstruct, using tagged vectors. Enable backward compatibility.
  97. (cl-old-struct-compat-mode 1))
  98. (if (eq type 'record)
  99. ;; Defstruct using record objects.
  100. (setq type nil))
  101. (cl-assert (or type (not named)))
  102. (if (boundp children-sym)
  103. (add-to-list children-sym tag)
  104. (set children-sym (list tag)))
  105. (and (null type) (eq (caar slots) 'cl-tag-slot)
  106. ;; Hide the tag slot from "standard" (i.e. non-`type'd) structs.
  107. (setq slots (cdr slots)))
  108. (let* ((parent-class (when parent (cl--struct-get-class parent)))
  109. (n (length slots))
  110. (index-table (make-hash-table :test 'eq :size n))
  111. (vslots (let ((v (make-vector n nil))
  112. (i 0)
  113. (offset (if type 0 1)))
  114. (dolist (slot slots)
  115. (let* ((props (cddr slot))
  116. (typep (plist-member props :type))
  117. (type (if typep (cadr typep) t)))
  118. (aset v i (cl--make-slot-desc
  119. (car slot) (nth 1 slot)
  120. type (cl--plist-remove props typep))))
  121. (puthash (car slot) (+ i offset) index-table)
  122. (cl-incf i))
  123. v))
  124. (class (cl--struct-new-class
  125. name docstring
  126. (unless (symbolp parent-class) (list parent-class))
  127. type named vslots index-table children-sym tag print)))
  128. (unless (symbolp parent-class)
  129. (let ((pslots (cl--struct-class-slots parent-class)))
  130. (or (>= n (length pslots))
  131. (let ((ok t))
  132. (dotimes (i (length pslots))
  133. (unless (eq (cl--slot-descriptor-name (aref pslots i))
  134. (cl--slot-descriptor-name (aref vslots i)))
  135. (setq ok nil)))
  136. ok)
  137. (error "Included struct %S has changed since compilation of %S"
  138. parent name))))
  139. (add-to-list 'current-load-list `(define-type . ,name))
  140. (cl--struct-register-child parent-class tag)
  141. (unless (or (eq named t) (eq tag name))
  142. ;; We used to use `defconst' instead of `set' but that
  143. ;; has a side-effect of purecopying during the dump, so that the
  144. ;; class object stored in the tag ends up being a *copy* of the
  145. ;; one stored in the `cl--class' property! We could have fixed
  146. ;; this needless duplication by using the purecopied object, but
  147. ;; that then breaks down a bit later when we modify the
  148. ;; cl-structure-class class object to close the recursion
  149. ;; between cl-structure-object and cl-structure-class (because
  150. ;; modifying purecopied objects is not allowed. Since this is
  151. ;; done during dumping, we could relax this rule and allow the
  152. ;; modification, but it's cumbersome).
  153. ;; So in the end, it's easier to just avoid the duplication by
  154. ;; avoiding the use of the purespace here.
  155. (set tag class)
  156. ;; In the cl-generic support, we need to be able to check
  157. ;; if a vector is a cl-struct object, without knowing its particular type.
  158. ;; So we use the (otherwise) unused function slots of the tag symbol
  159. ;; to put a special witness value, to make the check easy and reliable.
  160. (fset tag :quick-object-witness-check))
  161. (setf (cl--find-class name) class)))
  162. (cl-defstruct (cl-structure-class
  163. (:conc-name cl--struct-class-)
  164. (:predicate cl--struct-class-p)
  165. (:constructor nil)
  166. (:constructor cl--struct-new-class
  167. (name docstring parents type named slots index-table
  168. children-sym tag print))
  169. (:copier nil))
  170. "The type of CL structs descriptors."
  171. ;; The first few fields here are actually inherited from cl--class, but we
  172. ;; have to define this one before, to break the circularity, so we manually
  173. ;; list the fields here and later "backpatch" cl--class as the parent.
  174. ;; BEWARE: Obviously, it's indispensable to keep these two structs in sync!
  175. (name nil :type symbol) ;The type name.
  176. (docstring nil :type string)
  177. (parents nil :type (list-of cl--class)) ;The included struct.
  178. (slots nil :type (vector cl--slot-descriptor))
  179. (index-table nil :type hash-table)
  180. (tag nil :type symbol) ;Placed in cl-tag-slot. Holds the struct-class object.
  181. (type nil :type (memq (vector list)))
  182. (named nil :type bool)
  183. (print nil :type bool)
  184. (children-sym nil :type symbol) ;This sym's value holds the tags of children.
  185. )
  186. (cl-defstruct (cl-structure-object
  187. (:predicate cl-struct-p)
  188. (:constructor nil)
  189. (:copier nil))
  190. "The root parent of all \"normal\" CL structs")
  191. (setq cl--struct-default-parent 'cl-structure-object)
  192. (cl-defstruct (cl-slot-descriptor
  193. (:conc-name cl--slot-descriptor-)
  194. (:constructor nil)
  195. (:constructor cl--make-slot-descriptor
  196. (name &optional initform type props))
  197. (:copier cl--copy-slot-descriptor-1))
  198. ;; FIXME: This is actually not used yet, for circularity reasons!
  199. "Descriptor of structure slot."
  200. name ;Attribute name (symbol).
  201. initform
  202. type
  203. ;; Extra properties, kept in an alist, can include:
  204. ;; :documentation, :protection, :custom, :label, :group, :printer.
  205. (props nil :type alist))
  206. (defun cl--copy-slot-descriptor (slot)
  207. (let ((new (cl--copy-slot-descriptor-1 slot)))
  208. (cl-callf copy-alist (cl--slot-descriptor-props new))
  209. new))
  210. (cl-defstruct (cl--class
  211. (:constructor nil)
  212. (:copier nil))
  213. "Type of descriptors for any kind of structure-like data."
  214. ;; Intended to be shared between defstruct and defclass.
  215. (name nil :type symbol) ;The type name.
  216. (docstring nil :type string)
  217. ;; For structs there can only be one parent, but when EIEIO classes inherit
  218. ;; from cl--class, we'll need this to hold a list.
  219. (parents nil :type (list-of cl--class))
  220. (slots nil :type (vector cl-slot-descriptor))
  221. (index-table nil :type hash-table))
  222. (cl-assert
  223. (let ((sc-slots (cl--struct-class-slots (cl--find-class 'cl-structure-class)))
  224. (c-slots (cl--struct-class-slots (cl--find-class 'cl--class)))
  225. (eq t))
  226. (dotimes (i (length c-slots))
  227. (let ((sc-slot (aref sc-slots i))
  228. (c-slot (aref c-slots i)))
  229. (unless (eq (cl--slot-descriptor-name sc-slot)
  230. (cl--slot-descriptor-name c-slot))
  231. (setq eq nil))))
  232. eq))
  233. ;; Close the recursion between cl-structure-object and cl-structure-class.
  234. (setf (cl--struct-class-parents (cl--find-class 'cl-structure-class))
  235. (list (cl--find-class 'cl--class)))
  236. (cl--struct-register-child
  237. (cl--find-class 'cl--class)
  238. (cl--struct-class-tag (cl--find-class 'cl-structure-class)))
  239. (cl-assert (cl--find-class 'cl-structure-class))
  240. (cl-assert (cl--find-class 'cl-structure-object))
  241. (cl-assert (cl-struct-p (cl--find-class 'cl-structure-class)))
  242. (cl-assert (cl-struct-p (cl--find-class 'cl-structure-object)))
  243. (cl-assert (cl--class-p (cl--find-class 'cl-structure-class)))
  244. (cl-assert (cl--class-p (cl--find-class 'cl-structure-object)))
  245. ;; Make sure functions defined with cl-defsubst can be inlined even in
  246. ;; packages which do not require CL. We don't put an autoload cookie
  247. ;; directly on that function, since those cookies only go to cl-loaddefs.
  248. (autoload 'cl--defsubst-expand "cl-macs")
  249. ;; Autoload, so autoload.el and font-lock can use it even when CL
  250. ;; is not loaded.
  251. (put 'cl-defun 'doc-string-elt 3)
  252. (put 'cl-defmacro 'doc-string-elt 3)
  253. (put 'cl-defsubst 'doc-string-elt 3)
  254. (put 'cl-defstruct 'doc-string-elt 2)
  255. (provide 'cl-preloaded)
  256. ;;; cl-preloaded.el ends here