PageRenderTime 79ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/clos-class3.lisp

https://github.com/ynd/clisp-branch--ynd-devel
Lisp | 2716 lines | 1988 code | 132 blank | 596 comment | 48 complexity | 03a0e13ccff506b1a2c2cfd9176a14a2 MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, BSD-3-Clause
  1. ;;;; Common Lisp Object System for CLISP
  2. ;;;; Class metaobjects
  3. ;;;; Part 3: Class definition and redefinition.
  4. ;;;; Bruno Haible 21.8.1993 - 2004
  5. ;;;; Sam Steingold 1998 - 2007
  6. ;;;; German comments translated into English: Stefan Kain 2002-04-08
  7. (in-package "CLOS")
  8. ;; Wipe out all traces of an earlier loaded CLOS.
  9. (eval-when (load eval)
  10. (do-all-symbols (s) (remprop s 'CLOSCLASS)))
  11. ;; CLtL2 28.1.4., ANSI CL 4.3.7. Integrating Types and Classes
  12. (defun subclassp (class1 class2)
  13. (unless (>= (class-initialized class1) 4) (finalize-inheritance class1))
  14. (values
  15. (gethash class2 (class-all-superclasses class1)))) ; T or (default) NIL
  16. ;; Continue bootstrapping.
  17. (%defclos
  18. ;; distinctive marks for CLASS-P
  19. *<standard-class>-class-version*
  20. *<structure-class>-class-version*
  21. *<built-in-class>-class-version*
  22. 'defined-class
  23. 'class
  24. ;; built-in-classes for CLASS-OF
  25. (vector 'array 'bit-vector 'character 'complex 'cons 'float 'function
  26. 'hash-table 'integer 'list 'null 'package 'pathname
  27. #+LOGICAL-PATHNAMES 'logical-pathname
  28. 'random-state 'ratio 'readtable
  29. 'stream 'file-stream 'synonym-stream 'broadcast-stream
  30. 'concatenated-stream 'two-way-stream 'echo-stream 'string-stream
  31. 'string 'symbol 't 'vector))
  32. ;; Bootstrapping support.
  33. (defun replace-class-version (class class-version)
  34. (replace class-version (class-current-version class))
  35. (setf (class-current-version class) class-version))
  36. ;;; -------------------------------- DEFCLASS --------------------------------
  37. (defmacro defclass (&whole whole-form
  38. name superclass-specs slot-specs &rest options)
  39. (unless (symbolp name)
  40. (error-of-type 'ext:source-program-error
  41. :form whole-form
  42. :detail name
  43. (TEXT "~S: class name ~S should be a symbol")
  44. 'defclass name))
  45. (let* ((superclass-forms
  46. (progn
  47. (unless (listp superclass-specs)
  48. (error-of-type 'ext:source-program-error
  49. :form whole-form
  50. :detail superclass-specs
  51. (TEXT "~S ~S: expecting list of superclasses instead of ~S")
  52. 'defclass name superclass-specs))
  53. (mapcar #'(lambda (superclass)
  54. (unless (symbolp superclass)
  55. (error-of-type 'ext:source-program-error
  56. :form whole-form
  57. :detail superclass
  58. (TEXT "~S ~S: superclass name ~S should be a symbol")
  59. 'defclass name superclass))
  60. `',superclass)
  61. superclass-specs)))
  62. (accessor-method-decl-forms '())
  63. (accessor-function-decl-forms '())
  64. (generic-accessors nil) (generic-accessors-arg 'T)
  65. (slot-forms
  66. (let ((slot-names '()))
  67. (unless (listp slot-specs)
  68. (error-of-type 'ext:source-program-error
  69. :form whole-form
  70. :detail slot-specs
  71. (TEXT "~S ~S: expecting list of slot specifications instead of ~S")
  72. 'defclass name slot-specs))
  73. (when (and (oddp (length slot-specs)) (cdr slot-specs)
  74. (do ((l (cdr slot-specs) (cddr l)))
  75. ((endp l) t)
  76. (unless (keywordp (car l))
  77. (return nil))))
  78. ;; Typical beginner error: Omission of the parentheses around the
  79. ;; slot-specs. Probably someone who knows DEFSTRUCT and uses
  80. ;; DEFCLASS for the first time.
  81. (clos-warning (TEXT "~S ~S: Every second slot name is a keyword, and these slots have no options. If you want to define a slot with options, you need to enclose all slot specifications in parentheses: ~S, not ~S.")
  82. 'defclass name (list slot-specs) slot-specs))
  83. (mapcar #'(lambda (slot-spec)
  84. (let ((slot-name slot-spec) (slot-options '()))
  85. (when (consp slot-spec)
  86. (setq slot-name (car slot-spec)
  87. slot-options (cdr slot-spec)))
  88. (unless (symbolp slot-name)
  89. (error-of-type 'ext:source-program-error
  90. :form whole-form
  91. :detail slot-name
  92. (TEXT "~S ~S: slot name ~S should be a symbol")
  93. 'defclass name slot-name))
  94. (if (memq slot-name slot-names)
  95. (error-of-type 'ext:source-program-error
  96. :form whole-form
  97. :detail slot-names
  98. (TEXT "~S ~S: There may be only one direct slot with the name ~S.")
  99. 'defclass name slot-name)
  100. (push slot-name slot-names))
  101. (let ((readers '())
  102. (writers '())
  103. (allocations '())
  104. (initargs '())
  105. (initform nil) (initfunction nil)
  106. (types '())
  107. (documentation nil)
  108. (user-defined-args nil))
  109. (when (oddp (length slot-options))
  110. (error-of-type 'ext:source-program-error
  111. :form whole-form
  112. :detail slot-options
  113. (TEXT "~S ~S: slot options for slot ~S must come in pairs")
  114. 'defclass name slot-name))
  115. (do ((optionsr slot-options (cddr optionsr)))
  116. ((atom optionsr))
  117. (let ((optionkey (first optionsr))
  118. (argument (second optionsr)))
  119. (case optionkey
  120. (:READER
  121. (unless (and (symbolp argument) argument)
  122. (error-of-type 'ext:source-program-error
  123. :form whole-form
  124. :detail argument
  125. (TEXT "~S ~S, slot option for slot ~S: ~S is not a non-NIL symbol")
  126. 'defclass name slot-name argument))
  127. (push argument readers))
  128. (:WRITER
  129. (unless (function-name-p argument)
  130. (error-of-type 'ext:source-program-error
  131. :form whole-form
  132. :detail argument
  133. (TEXT "~S ~S, slot option for slot ~S: ~S is not a function name")
  134. 'defclass name slot-name argument))
  135. (push argument writers))
  136. (:ACCESSOR
  137. (unless (and (symbolp argument) argument)
  138. (error-of-type 'ext:source-program-error
  139. :form whole-form
  140. :detail argument
  141. (TEXT "~S ~S, slot option for slot ~S: ~S is not a non-NIL symbol")
  142. 'defclass name slot-name argument))
  143. (push argument readers)
  144. (push `(SETF ,argument) writers))
  145. (:ALLOCATION
  146. (unless (symbolp argument)
  147. (error-of-type 'ext:source-program-error
  148. :form whole-form
  149. :detail argument
  150. (TEXT "~S ~S, slot option ~S for slot ~S: ~S is not a symbol")
  151. 'defclass name ':allocation slot-name argument))
  152. (when allocations
  153. (error-of-type 'ext:source-program-error
  154. :form whole-form
  155. :detail slot-options
  156. (TEXT "~S ~S, slot option ~S for slot ~S may only be given once")
  157. 'defclass name ':allocation slot-name))
  158. (setq allocations (list argument)))
  159. (:INITARG
  160. (unless (symbolp argument)
  161. (error-of-type 'ext:source-program-error
  162. :form whole-form
  163. :detail argument
  164. (TEXT "~S ~S, slot option for slot ~S: ~S is not a symbol")
  165. 'defclass name slot-name argument))
  166. (push argument initargs))
  167. (:INITFORM
  168. (when initform
  169. (error-of-type 'ext:source-program-error
  170. :form whole-form
  171. :detail slot-options
  172. (TEXT "~S ~S, slot option ~S for slot ~S may only be given once")
  173. 'defclass name ':initform slot-name))
  174. (setq initform `(QUOTE ,argument)
  175. initfunction (make-initfunction-form argument slot-name)))
  176. (:TYPE
  177. (when types
  178. (error-of-type 'ext:source-program-error
  179. :form whole-form
  180. :detail slot-options
  181. (TEXT "~S ~S, slot option ~S for slot ~S may only be given once")
  182. 'defclass name ':type slot-name))
  183. (setq types (list argument)))
  184. (:DOCUMENTATION
  185. (when documentation
  186. (error-of-type 'ext:source-program-error
  187. :form whole-form
  188. :detail slot-options
  189. (TEXT "~S ~S, slot option ~S for slot ~S may only be given once")
  190. 'defclass name ':documentation slot-name))
  191. (unless (stringp argument)
  192. (error-of-type 'ext:source-program-error
  193. :form whole-form
  194. :detail argument
  195. (TEXT "~S ~S, slot option for slot ~S: ~S is not a string")
  196. 'defclass name slot-name argument))
  197. (setq documentation argument))
  198. ((:NAME :READERS :WRITERS :INITARGS :INITFUNCTION)
  199. ;; These are valid initialization keywords for
  200. ;; <direct-slot-definition>, but nevertheless
  201. ;; not valid DEFCLASS slot options.
  202. (error-of-type 'ext:source-program-error
  203. :form whole-form
  204. :detail optionkey
  205. (TEXT "~S ~S, slot option for slot ~S: ~S is not a valid slot option")
  206. 'defclass name slot-name optionkey))
  207. (t
  208. (if (symbolp optionkey)
  209. (let ((acons (assoc optionkey user-defined-args)))
  210. (if acons
  211. (push argument (cdr acons))
  212. (push (list optionkey argument) user-defined-args)))
  213. (error-of-type 'ext:source-program-error
  214. :form whole-form
  215. :detail optionkey
  216. (TEXT "~S ~S, slot option for slot ~S: ~S is not a valid slot option")
  217. 'defclass name slot-name optionkey))))))
  218. (setq readers (nreverse readers))
  219. (setq writers (nreverse writers))
  220. (setq user-defined-args (nreverse user-defined-args))
  221. (let ((type (if types (first types) 'T)))
  222. (dolist (funname readers)
  223. (push `(DECLAIM-METHOD ,funname ((OBJECT ,name)))
  224. accessor-method-decl-forms)
  225. (push `(PROCLAIM '(FUNCTION ,funname (,name) ,type))
  226. accessor-function-decl-forms)
  227. (push `(SYSTEM::EVAL-WHEN-COMPILE (SYSTEM::C-DEFUN ',funname (SYSTEM::LAMBDA-LIST-TO-SIGNATURE '(OBJECT))))
  228. accessor-function-decl-forms))
  229. (dolist (funname writers)
  230. (push `(DECLAIM-METHOD ,funname (NEW-VALUE (OBJECT ,name)))
  231. accessor-method-decl-forms)
  232. (push `(PROCLAIM '(FUNCTION ,funname (,type ,name) ,type))
  233. accessor-function-decl-forms)
  234. (push `(SYSTEM::EVAL-WHEN-COMPILE (SYSTEM::C-DEFUN ',funname (SYSTEM::LAMBDA-LIST-TO-SIGNATURE '(NEW-VALUE OBJECT))))
  235. accessor-function-decl-forms)))
  236. `(LIST
  237. :NAME ',slot-name
  238. ,@(when readers `(:READERS ',readers))
  239. ,@(when writers `(:WRITERS ',writers))
  240. ,@(when allocations `(:ALLOCATION ',(first allocations)))
  241. ,@(when initargs `(:INITARGS ',(nreverse initargs)))
  242. ,@(when initform `(:INITFORM ,initform :INITFUNCTION ,initfunction))
  243. ,@(when types `(:TYPE ',(first types)))
  244. ,@(when documentation `(:DOCUMENTATION ',documentation))
  245. ,@(when user-defined-args
  246. ;; For error-checking purposes:
  247. `('DEFCLASS-FORM ',whole-form))
  248. ,@(mapcan #'(lambda (option)
  249. (list `',(car option)
  250. ;; If there are multiple occurrences
  251. ;; of the same option, the values are
  252. ;; passed as a list. Otherwise a single
  253. ;; value is passed (not a 1-element list)!
  254. `',(if (cddr option)
  255. (nreverse (cdr option))
  256. (cadr option))))
  257. user-defined-args)))))
  258. slot-specs)))
  259. (metaclass nil) (metaclass-arg nil)
  260. (direct-default-initargs nil)
  261. (documentation nil)
  262. (user-defined-args nil))
  263. (dolist (option options)
  264. (block nil
  265. (when (listp option)
  266. (let ((optionkey (first option)))
  267. (when (case optionkey
  268. (:METACLASS metaclass)
  269. (:DEFAULT-INITARGS direct-default-initargs)
  270. (:DOCUMENTATION documentation))
  271. (error-of-type 'ext:source-program-error
  272. :form whole-form
  273. :detail options
  274. (TEXT "~S ~S, option ~S may only be given once")
  275. 'defclass name optionkey))
  276. (case optionkey
  277. (:METACLASS
  278. (when (eql (length option) 2)
  279. (let ((argument (second option)))
  280. (unless (symbolp argument)
  281. (error-of-type 'ext:source-program-error
  282. :form whole-form
  283. :detail argument
  284. (TEXT "~S ~S, option ~S: ~S is not a symbol")
  285. 'defclass name option argument))
  286. (setq metaclass-arg argument)
  287. (setq metaclass `(FIND-CLASS ',argument)))
  288. (return)))
  289. (:DEFAULT-INITARGS
  290. (let ((list (rest option)))
  291. (when (and (consp list) (null (cdr list)) (listp (car list)))
  292. (setq list (car list))
  293. (clos-warning (TEXT "~S ~S: option ~S should be written ~S")
  294. 'defclass name option (cons ':DEFAULT-INITARGS list)))
  295. (when (oddp (length list))
  296. (error-of-type 'ext:source-program-error
  297. :form whole-form
  298. :detail list
  299. (TEXT "~S ~S, option ~S: arguments must come in pairs")
  300. 'defclass name option))
  301. (setq direct-default-initargs
  302. `(:DIRECT-DEFAULT-INITARGS
  303. (LIST
  304. ,@(let ((arglist nil) (formlist nil))
  305. (do ((listr list (cddr listr)))
  306. ((atom listr))
  307. (unless (symbolp (first listr))
  308. (error-of-type 'ext:source-program-error
  309. :form whole-form
  310. :detail (first listr)
  311. (TEXT "~S ~S, option ~S: ~S is not a symbol")
  312. 'defclass name option (first listr)))
  313. (when (member (first listr) arglist)
  314. (error-of-type 'ext:source-program-error
  315. :form whole-form
  316. :detail list
  317. (TEXT "~S ~S, option ~S: ~S may only be given once")
  318. 'defclass name option (first listr)))
  319. (push (first listr) arglist)
  320. (push (second listr) formlist))
  321. (mapcan #'(lambda (arg form)
  322. `((LIST ',arg ',form ,(make-initfunction-form form arg))))
  323. (nreverse arglist) (nreverse formlist)))))))
  324. (return))
  325. (:DOCUMENTATION
  326. (when (eql (length option) 2)
  327. (let ((argument (second option)))
  328. (unless (stringp argument)
  329. (error-of-type 'ext:source-program-error
  330. :form whole-form
  331. :detail argument
  332. (TEXT "~S ~S, option ~S: ~S is not a string")
  333. 'defclass name option argument))
  334. (setq documentation
  335. `(:DOCUMENTATION ',argument)))
  336. (return)))
  337. ((:NAME :DIRECT-SUPERCLASSES :DIRECT-SLOTS :DIRECT-DEFAULT-INITARGS)
  338. ;; These are valid initialization keywords for <defined-class>,
  339. ;; but nevertheless not valid DEFCLASS options.
  340. (error-of-type 'ext:source-program-error
  341. :form whole-form
  342. :detail option
  343. (TEXT "~S ~S: invalid option ~S")
  344. 'defclass name option))
  345. (:GENERIC-ACCESSORS
  346. (when (eql (length option) 2)
  347. (let ((argument (second option)))
  348. (setq generic-accessors-arg argument)
  349. (setq generic-accessors `(:GENERIC-ACCESSORS ',argument))
  350. (return))))
  351. (T
  352. (when (symbolp optionkey)
  353. (when (assoc optionkey user-defined-args)
  354. (error-of-type 'ext:source-program-error
  355. :form whole-form
  356. :detail options
  357. (TEXT "~S ~S, option ~S may only be given once")
  358. 'defclass name optionkey))
  359. (push option user-defined-args)
  360. (return))))))
  361. (error-of-type 'ext:source-program-error
  362. :form whole-form
  363. :detail option
  364. (TEXT "~S ~S: invalid option ~S")
  365. 'defclass name option)))
  366. (setq user-defined-args (nreverse user-defined-args))
  367. (let ((metaclass-var (gensym))
  368. (metaclass-keywords-var (gensym)))
  369. `(LET ()
  370. (EVAL-WHEN (COMPILE LOAD EVAL)
  371. (LET* ((,metaclass-var ,(or metaclass '<STANDARD-CLASS>))
  372. ,@(if user-defined-args
  373. `((,metaclass-keywords-var
  374. ,(cond ((or (null metaclass) (eq metaclass-arg 'STANDARD-CLASS))
  375. '*<STANDARD-CLASS>-VALID-INITIALIZATION-KEYWORDS*)
  376. ((eq metaclass-arg 'FUNCALLABLE-STANDARD-CLASS)
  377. '*<FUNCALLABLE-STANDARD-CLASS>-VALID-INITIALIZATION-KEYWORDS*)
  378. (t `(CLASS-VALID-INITIALIZATION-KEYWORDS ,metaclass-var)))))))
  379. ;; Provide good error messages. The error message from
  380. ;; ENSURE-CLASS (actually MAKE-INSTANCE) later is unintelligible.
  381. ,@(if user-defined-args
  382. `((UNLESS (EQ ,metaclass-keywords-var 'T)
  383. ,@(mapcar #'(lambda (option)
  384. `(UNLESS (MEMBER ',(first option) ,metaclass-keywords-var)
  385. (ERROR-OF-TYPE 'EXT:SOURCE-PROGRAM-ERROR
  386. :FORM ',whole-form
  387. :DETAIL ',option
  388. (TEXT "~S ~S: invalid option ~S")
  389. 'DEFCLASS ',name ',option)))
  390. user-defined-args))))
  391. (APPLY #'ENSURE-CLASS
  392. ',name
  393. :DIRECT-SUPERCLASSES (LIST ,@superclass-forms)
  394. :DIRECT-SLOTS (LIST ,@slot-forms)
  395. :METACLASS ,metaclass-var
  396. ,@direct-default-initargs
  397. ,@documentation
  398. ,@generic-accessors
  399. ;; Pass user-defined initargs of the metaclass.
  400. ,@(mapcan #'(lambda (option)
  401. (list `',(first option) `',(rest option)))
  402. user-defined-args)
  403. (APPEND
  404. ;; Pass the default initargs of the metaclass, in
  405. ;; order to erase leftovers from the previous definition.
  406. ,(if metaclass
  407. `(MAPCAN #'(LAMBDA (X) (LIST (FIRST X) (FUNCALL (THIRD X))))
  408. (CLASS-DEFAULT-INITARGS ,metaclass-var))
  409. `',*<standard-class>-default-initargs*)
  410. (LIST
  411. ;; Here we use (unless ... '(... NIL)) because when a class
  412. ;; is being redefined, passing :DOCUMENTATION NIL to
  413. ;; ENSURE-CLASS means to erase the documentation string,
  414. ;; while nothing means to keep it! See MOP p. 57.
  415. ,@(unless direct-default-initargs '(:DIRECT-DEFAULT-INITARGS NIL))
  416. ,@(unless documentation '(:DOCUMENTATION NIL))
  417. ,@(unless generic-accessors '(:GENERIC-ACCESSORS 'T)))))))
  418. ,@(if generic-accessors-arg
  419. (nreverse accessor-method-decl-forms) ; the DECLAIM-METHODs
  420. (nreverse accessor-function-decl-forms)) ; the C-DEFUNs
  421. (FIND-CLASS ',name)))))
  422. ;; DEFCLASS execution:
  423. ;; The function responsible for a MAKE-INSTANCES-OBSOLETE call.
  424. (defvar *make-instances-obsolete-caller* 'make-instances-obsolete)
  425. (defun ensure-class-using-class-<t> (class name &rest all-keys
  426. &key (metaclass <standard-class>)
  427. (direct-superclasses '())
  428. (direct-slots '())
  429. (direct-default-initargs '())
  430. (documentation nil)
  431. (fixed-slot-locations nil)
  432. &allow-other-keys)
  433. (declare (ignore direct-slots direct-default-initargs documentation
  434. fixed-slot-locations))
  435. ;; Argument checks.
  436. (unless (symbolp name)
  437. (error (TEXT "~S: class name ~S should be a symbol")
  438. 'ensure-class-using-class name))
  439. (unless (defined-class-p metaclass)
  440. (if (symbolp metaclass)
  441. (setq metaclass
  442. (cond ((eq metaclass 'standard-class) <standard-class>) ; for bootstrapping
  443. (t (find-class metaclass))))
  444. (error (TEXT "~S for class ~S: metaclass ~S is neither a class or a symbol")
  445. 'ensure-class-using-class name metaclass)))
  446. (unless (or (eq metaclass <standard-class>) ; for bootstrapping
  447. (subclassp metaclass <defined-class>))
  448. (error (TEXT "~S for class ~S: metaclass ~S is not a subclass of CLASS")
  449. 'ensure-class-using-class name metaclass))
  450. (unless (proper-list-p direct-superclasses)
  451. (error (TEXT "~S for class ~S: The ~S argument should be a proper list, not ~S")
  452. 'ensure-class-using-class name ':direct-superclasses direct-superclasses))
  453. (unless (every #'(lambda (x)
  454. (or (defined-class-p x)
  455. (forward-reference-to-class-p x)
  456. (symbolp x)))
  457. direct-superclasses)
  458. (error (TEXT "~S for class ~S: The direct-superclasses list should consist of classes and symbols, not ~S")
  459. 'ensure-class-using-class name direct-superclasses))
  460. ;; Ignore the old class if the given name is not its "proper name".
  461. ;; (This is an ANSI CL requirement; it's not clear whether it belongs
  462. ;; here or in ENSURE-CLASS.)
  463. (when (and class (not (eq (class-name class) name)))
  464. (return-from ensure-class-using-class-<t>
  465. (apply #'ensure-class-using-class nil name all-keys)))
  466. ;; Decide whether to modify the given class or ignore it.
  467. (let ((a-semi-standard-class-p (or (eq metaclass <standard-class>)
  468. (subclassp metaclass <semi-standard-class>))))
  469. (when class
  470. (cond ((not (eq metaclass (class-of class)))
  471. ;; This can occur when mixing DEFSTRUCT and DEFCLASS.
  472. ;; MOP p. 48 says "If the class of the class argument is not the
  473. ;; same as the class specified by the :metaclass argument, an
  474. ;; error is signalled." But we can do better: ignore the old
  475. ;; class, warn and proceed. The old instances will thus keep
  476. ;; pointing to the old class.
  477. (clos-warning (TEXT "Cannot redefine ~S with a different metaclass ~S")
  478. class metaclass)
  479. (setq class nil))
  480. ((not a-semi-standard-class-p)
  481. ;; This can occur when redefining a class defined through
  482. ;; (DEFCLASS ... (:METACLASS STRUCTURE-CLASS)), which is
  483. ;; equivalent to re-executed DEFSTRUCT.
  484. ;; Only <semi-standard-class> subclasses support making instances
  485. ;; obsolete. Ignore the old class and proceed. The old instances
  486. ;; will thus keep pointing to the old class.
  487. (setq class nil)))
  488. (unless class
  489. (return-from ensure-class-using-class-<t>
  490. (apply #'ensure-class-using-class nil name all-keys))))
  491. ;; Preparation of class initialization arguments.
  492. (setq all-keys (copy-list all-keys))
  493. (remf all-keys ':metaclass)
  494. ;; See which direct superclasses are already defined.
  495. (setq direct-superclasses
  496. (mapcar #'(lambda (c)
  497. (if (defined-class-p c)
  498. c
  499. (let ((cn (if (forward-reference-to-class-p c) (class-name c) c)))
  500. (assert (symbolp cn))
  501. (if a-semi-standard-class-p
  502. ;; Need a class. Allocate a forward-referenced-class
  503. ;; if none is yet allocated.
  504. (or (get cn 'CLOSCLASS)
  505. (setf (get cn 'CLOSCLASS)
  506. (make-instance 'forward-referenced-class
  507. :name cn)))
  508. ;; Need a defined-class.
  509. (find-class cn)))))
  510. direct-superclasses))
  511. (if class
  512. ;; Modify the class and return the modified class.
  513. (apply #'reinitialize-instance ; => #'reinitialize-instance-<defined-class>
  514. class
  515. :direct-superclasses direct-superclasses
  516. all-keys)
  517. (setf (find-class name)
  518. (setq class
  519. (apply (cond ((eq metaclass <standard-class>)
  520. #'make-instance-<standard-class>)
  521. ((eq metaclass <funcallable-standard-class>)
  522. #'make-instance-<funcallable-standard-class>)
  523. ((eq metaclass <built-in-class>)
  524. #'make-instance-<built-in-class>)
  525. ((eq metaclass <structure-class>)
  526. #'make-instance-<structure-class>)
  527. (t #'make-instance))
  528. metaclass
  529. :name name
  530. :direct-superclasses direct-superclasses
  531. all-keys))))
  532. class))
  533. ;; Preliminary.
  534. (predefun ensure-class-using-class (class name &rest args
  535. &key (metaclass <standard-class>)
  536. (direct-superclasses '())
  537. (direct-slots '())
  538. (direct-default-initargs '())
  539. (documentation nil)
  540. (fixed-slot-locations nil)
  541. &allow-other-keys)
  542. (declare (ignore metaclass direct-superclasses direct-slots
  543. direct-default-initargs documentation fixed-slot-locations))
  544. (apply #'ensure-class-using-class-<t> class name args))
  545. ;; MOP p. 46
  546. (defun ensure-class (name &rest args
  547. &key (metaclass <standard-class>)
  548. (direct-superclasses '())
  549. (direct-slots '())
  550. (direct-default-initargs '())
  551. (documentation nil)
  552. (fixed-slot-locations nil)
  553. &allow-other-keys)
  554. (declare (ignore metaclass direct-superclasses direct-slots
  555. direct-default-initargs documentation fixed-slot-locations))
  556. (unless (symbolp name)
  557. (error (TEXT "~S: class name ~S should be a symbol")
  558. 'ensure-class name))
  559. (let ((result
  560. (apply #'ensure-class-using-class (find-class name nil) name args)))
  561. ; A check, to verify that user-defined methods on ensure-class-using-class
  562. ; work as they should.
  563. (unless (defined-class-p result)
  564. (error (TEXT "Wrong ~S result for ~S: not a class: ~S")
  565. 'ensure-class-using-class name result))
  566. result))
  567. ;; Preliminary.
  568. (predefun reader-method-class (class direct-slot &rest initargs)
  569. (declare (ignore class direct-slot initargs))
  570. <standard-reader-method>)
  571. (predefun writer-method-class (class direct-slot &rest initargs)
  572. (declare (ignore class direct-slot initargs))
  573. <standard-writer-method>)
  574. ;; ---------------------------- Class redefinition ----------------------------
  575. ;; When this is true, all safety checks about the metaclasses
  576. ;; of superclasses are omitted.
  577. (defparameter *allow-mixing-metaclasses* nil)
  578. (defun reinitialize-instance-<defined-class> (class &rest all-keys
  579. &key (name nil name-p)
  580. (direct-superclasses '() direct-superclasses-p)
  581. (direct-slots '() direct-slots-p)
  582. (direct-default-initargs '() direct-default-initargs-p)
  583. (documentation nil documentation-p)
  584. (fixed-slot-locations nil fixed-slot-locations-p)
  585. &allow-other-keys
  586. &aux (metaclass (class-of class)))
  587. (if (and (>= (class-initialized class) 4) ; already finalized?
  588. (subclassp class <metaobject>))
  589. ;; Things would go awry when we try to redefine <class> and similar.
  590. (clos-warning (TEXT "Redefining metaobject class ~S has no effect.") class)
  591. (progn
  592. (when direct-superclasses-p
  593. ;; Normalize the (class-direct-superclasses class) in the same way as
  594. ;; the direct-superclasses argument, so that we can compare the two
  595. ;; lists using EQUAL.
  596. (when (and (subclassp metaclass <standard-class>)
  597. (< (class-initialized class) 3))
  598. (do ((l (class-direct-superclasses class) (cdr l)))
  599. ((atom l))
  600. (let ((c (car l)))
  601. (unless (defined-class-p c)
  602. (let ((new-c
  603. (let ((cn (if (forward-reference-to-class-p c) (class-name c) c)))
  604. (assert (symbolp cn))
  605. ;; Need a class. Allocate a forward-referenced-class
  606. ;; if none is yet allocated.
  607. (or (get cn 'CLOSCLASS)
  608. (setf (get cn 'CLOSCLASS)
  609. (make-instance 'forward-referenced-class
  610. :name cn))))))
  611. (unless (eq new-c c)
  612. (when (defined-class-p new-c)
  613. ; changed from forward-referenced-class to defined-class
  614. (check-allowed-superclass class new-c))
  615. (setf (car l) new-c)
  616. (when (or (defined-class-p c) (forward-reference-to-class-p c))
  617. (remove-direct-subclass c class))
  618. (add-direct-subclass new-c class))))))))
  619. (when direct-slots-p
  620. ;; Convert the direct-slots to <direct-slot-definition> instances.
  621. (setq direct-slots (convert-direct-slots class direct-slots)))
  622. (when fixed-slot-locations-p
  623. ;; Convert from list to boolean.
  624. (when (consp fixed-slot-locations)
  625. (setq fixed-slot-locations (car fixed-slot-locations))))
  626. ;; Trivial changes (that can occur when loading the same code twice)
  627. ;; do not require updating the instances:
  628. ;; changed slot-options :initform, :documentation,
  629. ;; changed class-options :name, :default-initargs, :documentation.
  630. (if (or (and direct-superclasses-p
  631. (not (equal (or direct-superclasses (default-direct-superclasses class))
  632. (class-direct-superclasses class))))
  633. (and direct-slots-p
  634. (not (equal-direct-slots direct-slots (class-direct-slots class))))
  635. (and direct-default-initargs-p
  636. (not (equal-default-initargs direct-default-initargs
  637. (class-direct-default-initargs class))))
  638. (and fixed-slot-locations-p
  639. (not (eq fixed-slot-locations (class-fixed-slot-locations class)))))
  640. ;; Instances have to be updated:
  641. (let* ((was-finalized (>= (class-initialized class) 6))
  642. (must-be-finalized
  643. (and was-finalized
  644. (some #'class-instantiated (list-all-finalized-subclasses class))))
  645. (old-direct-superclasses (class-direct-superclasses class))
  646. (old-direct-accessors (class-direct-accessors class))
  647. (old-class-precedence-list (and was-finalized (class-precedence-list class)))
  648. old-class)
  649. ;; ANSI CL 4.3.6. Remove accessor methods created by old DEFCLASS.
  650. (remove-accessor-methods old-direct-accessors)
  651. (setf (class-direct-accessors class) '())
  652. ;; Clear the cached prototype.
  653. (setf (class-prototype class) nil)
  654. ;; Declare all instances as obsolete, and backup the class object.
  655. (let ((old-version (class-current-version class))
  656. (*make-instances-obsolete-caller* 'defclass))
  657. (make-instances-obsolete class)
  658. (setq old-class (cv-class old-version)))
  659. (locally (declare (compile))
  660. (sys::%handler-bind
  661. #'(lambda ()
  662. (apply #'shared-initialize
  663. ; => #'shared-initialize-<built-in-class>
  664. ; #'shared-initialize-<standard-class>
  665. ; #'shared-initialize-<structure-class>
  666. class nil
  667. `(,@(if direct-slots-p
  668. (list 'direct-slots direct-slots) '())
  669. ,@all-keys))
  670. ;; If the class could be finalized (although not a "must"),
  671. ;; keep it finalized and don't unfinalize it.
  672. (when (>= (class-initialized class) 6)
  673. (setq must-be-finalized t))
  674. (update-subclasses-for-redefined-class
  675. class was-finalized must-be-finalized
  676. old-direct-superclasses))
  677. ;; If an error occurs during the class redefinition,
  678. ;; switch back to the old definition, so that existing
  679. ;; instances can continue to be used.
  680. 'ERROR #'(lambda (condition)
  681. (declare (ignore condition))
  682. (let ((tmp-direct-superclasses (class-direct-superclasses class)))
  683. ;; Restore the class using the backup copy.
  684. (let ((new-version (class-current-version class)))
  685. (dotimes (i (sys::%record-length class))
  686. (setf (sys::%record-ref class i) (sys::%record-ref old-class i)))
  687. (setf (class-current-version class) new-version))
  688. ;; Restore the direct-subclasses pointers.
  689. (dolist (super tmp-direct-superclasses)
  690. (remove-direct-subclass-internal super class))
  691. (dolist (super old-direct-superclasses)
  692. (add-direct-subclass-internal super class))
  693. ;; Restore the finalized-direct-subclasses pointers.
  694. (dolist (super tmp-direct-superclasses)
  695. (when (semi-standard-class-p super)
  696. (remove-finalized-direct-subclass super class)))
  697. (when (>= (class-initialized class) 6)
  698. (dolist (super old-direct-superclasses)
  699. (when (semi-standard-class-p super)
  700. (add-finalized-direct-subclass super class))))
  701. ;; Restore the accessor methods.
  702. (add-accessor-methods old-direct-accessors)
  703. (setf (class-direct-accessors class) old-direct-accessors)))))
  704. (let ((new-class-precedence-list
  705. (and (>= (class-initialized class) 6) (class-precedence-list class))))
  706. (unless (equal old-class-precedence-list new-class-precedence-list)
  707. (update-subclass-instance-specializer-generic-functions class)
  708. (update-subclass-cpl-specializer-generic-functions class
  709. old-class-precedence-list new-class-precedence-list)))
  710. (install-class-direct-accessors class))
  711. ;; Instances don't need to be updated:
  712. (progn
  713. (when name-p
  714. ;; Store new name:
  715. (setf (class-classname class) name))
  716. (when direct-slots-p
  717. ;; Store new slot-inits:
  718. (do ((l-old (class-direct-slots class) (cdr l-old))
  719. (l-new direct-slots (cdr l-new)))
  720. ((null l-new))
  721. (let ((old (car l-old))
  722. (new (car l-new)))
  723. (setf (slot-definition-initform old) (slot-definition-initform new))
  724. (setf (slot-definition-initfunction old) (slot-definition-initfunction new))
  725. (setf (slot-definition-documentation old) (slot-definition-documentation new)))))
  726. (when direct-default-initargs-p
  727. ;; Store new default-initargs:
  728. (do ((l-old (class-direct-default-initargs class) (cdr l-old))
  729. (l-new direct-default-initargs (cdr l-new)))
  730. ((null l-new))
  731. (let ((old (cdar l-old))
  732. (new (cdar l-new)))
  733. ;; Move initform and initfunction from new destructively into
  734. ;; the old one:
  735. (setf (car old) (car new))
  736. (setf (cadr old) (cadr new)))))
  737. (when documentation-p
  738. ;; Store new documentation:
  739. (setf (class-documentation class) documentation))
  740. ;; NB: These modifications are automatically inherited by the
  741. ;; subclasses of class! Due to <inheritable-slot-definition-initer>
  742. ;; and <inheritable-slot-definition-doc>.
  743. ;; No need to call (install-class-direct-accessors class) here.
  744. ) )
  745. ;; Try to finalize it (mop-cl-reinit-mo, bug [ 1526448 ])
  746. (unless *allow-mixing-metaclasses* ; for gray.lisp
  747. (when (finalizable-p class)
  748. (finalize-inheritance class)))
  749. ;; Notification of listeners:
  750. (map-dependents class
  751. #'(lambda (dependent)
  752. (apply #'update-dependent class dependent all-keys)))
  753. ) )
  754. class)
  755. (defun equal-direct-slots (slots1 slots2)
  756. (or (and (null slots1) (null slots2))
  757. (and (consp slots1) (consp slots2)
  758. (equal-direct-slot (first slots1) (first slots2))
  759. (equal-direct-slots (rest slots1) (rest slots2)))))
  760. (defun equal-default-initargs (initargs1 initargs2)
  761. (or (and (null initargs1) (null initargs2))
  762. (and (consp initargs1) (consp initargs2)
  763. (eq (car (first initargs1)) (car (first initargs2)))
  764. (equal-default-initargs (cdr initargs1) (cdr initargs2)))))
  765. (defun map-dependents-<defined-class> (class function)
  766. (dolist (dependent (class-listeners class))
  767. (funcall function dependent)))
  768. ;; ------------------- General routines for <defined-class> -------------------
  769. ;; Preliminary.
  770. (predefun class-name (class)
  771. (class-classname class))
  772. ;; Returns the list of implicit direct superclasses when none was specified.
  773. (defun default-direct-superclasses (class)
  774. (cond ((typep class <standard-class>) (list <standard-object>))
  775. ((typep class <funcallable-standard-class>) (list <funcallable-standard-object>))
  776. ((typep class <structure-class>) (list <structure-object>))
  777. (t '())))
  778. (defun check-metaclass-mix (name direct-superclasses metaclass-test metaclass)
  779. (unless *allow-mixing-metaclasses*
  780. (unless (every metaclass-test direct-superclasses)
  781. (error-of-type 'error
  782. (TEXT "(~S ~S): superclass ~S should be of class ~S")
  783. 'DEFCLASS name (find-if-not metaclass-test direct-superclasses)
  784. metaclass))))
  785. ;; Preliminary.
  786. (predefun validate-superclass (class superclass)
  787. (or ;; Green light if class and superclass belong to the same metaclass.
  788. (eq (sys::%record-ref class 0) (sys::%record-ref superclass 0))
  789. ;; Green light also if class is a funcallable-standard-class and
  790. ;; superclass is a standard-class.
  791. (and (eq (sys::%record-ref class 0) *<funcallable-standard-class>-class-version*)
  792. (eq (sys::%record-ref superclass 0) *<standard-class>-class-version*))
  793. ;; Other than that, only <standard-object> and <structure-object> can
  794. ;; inherit from <t> without belonging to the same metaclass.
  795. (and (eq superclass <t>)
  796. (memq (class-classname class) '(standard-object structure-object)))
  797. ;; And only <funcallable-standard-object> can inherit from <function>
  798. ;; without belonging to the same metaclass.
  799. (and (eq superclass <function>)
  800. (eq (class-classname class) 'funcallable-standard-object))))
  801. (defun check-allowed-superclass (class superclass)
  802. (unless (validate-superclass class superclass)
  803. (error (TEXT "(~S ~S) for class ~S: ~S does not allow ~S to become a subclass of ~S. You may define a method on ~S to allow this.")
  804. 'initialize-instance 'class (class-classname class) 'validate-superclass class superclass
  805. 'validate-superclass)))
  806. ;;; The direct-subclasses slot can be either
  807. ;;; - NIL or a weak-list (for saving memory when there are few subclasses), or
  808. ;;; - a weak-hash-table (for speed when there are many subclasses).
  809. #|
  810. ;; Adds a class to the list of direct subclasses.
  811. (defun add-direct-subclass (class subclass) ...)
  812. ;; Removes a class from the list of direct subclasses.
  813. (defun remove-direct-subclass (class subclass) ...)
  814. ;; Returns the currently existing direct subclasses, as a freshly consed list.
  815. (defun list-direct-subclasses (class) ...)
  816. |#
  817. (def-weak-set-accessors class-direct-subclasses-table defined-class
  818. add-direct-subclass-internal
  819. remove-direct-subclass-internal
  820. list-direct-subclasses)
  821. ;; Preliminary.
  822. (predefun add-direct-subclass (class subclass)
  823. (add-direct-subclass-internal class subclass))
  824. (predefun remove-direct-subclass (class subclass)
  825. (remove-direct-subclass-internal class subclass))
  826. (predefun class-direct-subclasses (class)
  827. (list-direct-subclasses class))
  828. (defun checked-class-direct-subclasses (class)
  829. (let ((result (class-direct-subclasses class)))
  830. ; Some checks, to guarantee that user-defined methods on
  831. ; class-direct-subclasses don't break our CLOS.
  832. (unless (proper-list-p result)
  833. (error (TEXT "Wrong ~S result for class ~S: not a proper list: ~S")
  834. 'class-direct-subclasses (class-name class) result))
  835. (dolist (c result)
  836. (unless (defined-class-p c)
  837. (error (TEXT "Wrong ~S result for class ~S: list element is not a class: ~S")
  838. 'class-direct-subclasses (class-name class) c))
  839. (unless (memq class (class-direct-superclasses c))
  840. (error (TEXT "Wrong ~S result for class ~S: ~S is not a direct superclass of ~S")
  841. 'class-direct-subclasses (class-name class) class c)))
  842. result))
  843. (defun update-subclasses-sets (class old-direct-superclasses new-direct-superclasses)
  844. (unless (equal old-direct-superclasses new-direct-superclasses)
  845. (let ((removed-direct-superclasses
  846. (set-difference old-direct-superclasses new-direct-superclasses))
  847. (added-direct-superclasses
  848. (set-difference new-direct-superclasses old-direct-superclasses)))
  849. (dolist (super removed-direct-superclasses)
  850. (remove-direct-subclass super class))
  851. (dolist (super added-direct-superclasses)
  852. (add-direct-subclass super class)))))
  853. ;; ----------------------------------------------------------------------------
  854. ;; CLtL2 28.1.5., ANSI CL 4.3.5. Determining the Class Precedence List
  855. ;; The set of all classes forms a directed graph: Class C is located
  856. ;; below the direct superclasses of C. This graph is acyclic, because
  857. ;; at the moment of definition of the class C all direct superclasses must
  858. ;; already be present.
  859. ;; Hence, one can use Noether Induction (Induction from above to below in
  860. ;; the class graph) .
  861. ;; For a class C let DS(n) be the list of all direct superclasses of C.
  862. ;; The set of all superclasses (incl. C itself) is inductively defined as
  863. ;; S(C) := {C} union union_{D in DS(C)} S(D).
  864. ;; In other words:
  865. ;; S(C) = { C_n : C_n in DS(C_{n-1}), ..., C_1 in DS(C_0), C_0 = C }
  866. ;; Lemma 1: (a) C in S(C).
  867. ;; (b) DS(C) subset S(C).
  868. ;; (c) D in DS(C) ==> S(D) subset S(C).
  869. ;; (d) D in S(C) ==> S(D) subset S(C).
  870. ;; proof: (a) follows from the definition.
  871. ;; (b) from (a) and from the definition.
  872. ;; (c) from the definition.
  873. ;; (d) from (c) with fixed D via induction over C.
  874. ;; The CPL of a class C is one order of set S(C).
  875. ;; If CPL(C) = (... D1 ... D2 ...), one writes D1 < D2.
  876. ;; The relation introduced by this is a total order upon S(C).
  877. ;; The following set of restrictions has to be taken into account:
  878. ;; R(C) := union_{D in S(C)} DR(D) with
  879. ;; DR(C) := { C < C1, C1 < C2, ..., C{n-1} < C_n } if DS(C) = (C1, ..., Cn).
  880. ;; If R(C) contains a cycle, R(C) cannot be completed into a total order,
  881. ;; of course. Then, R(C) is called inconsistent.
  882. ;; CPL(C) is constructed as follows:
  883. ;; L := (), R := R(C).
  884. ;; L := (L | C), remove all (C < ..) from R.
  885. ;; while R /= {}, deal with the set M of all minimal elements of R
  886. ;; (those classes, that can be added to L without violating R(C) ).
  887. ;; If M is empty, then there is a cycle in R(C) and
  888. ;; the algorithm is finished. Else, choose that element among the
  889. ;; elements E of M, which has a D being rightmost in L with
  890. ;; E in DS(D) .
  891. ;; L := (L | E), remove all (E < ..) from R.
  892. ;; CPL(C) := L.
  893. ;; L is lengthened stepwise by one element, R is shortened stepwise,
  894. ;; and R always consists solely of relations between elements
  895. ;; of S(C)\L.
  896. ;; Lemma 2: (a) CPL(C) = (C ...).
  897. ;; (b) If DS(C) = (C1, ..., Cn), then
  898. ;; CPL(C) = (C ... C1 ... C2 ... ... Cn ...).
  899. ;; proof: (a) obvious by construction.
  900. ;; (b) If Ci is added to the CPL, then the restriction
  901. ;; C{i-1} < Ci can no longer be in R, so C{i-1} must already be
  902. ;; in the CPL.
  903. ;; The following statement is wrong:
  904. ;; (*) If D is in DS(C) and CPL(D) = (D1, ..., Dn), then
  905. ;; CPL(C) = (C ... D1 ... D2 ... ... Dn ...).
  906. ;; Example:
  907. ;; z
  908. ;; /|\ CPL(z) = (z)
  909. ;; / | \ CPL(x) = (x z)
  910. ;; x | x CPL(y) = (y z)
  911. ;; | | | CPL(d) = (d x z)
  912. ;; d y e CPL(e) = (e x z)
  913. ;; \/ \/ CPL(b) = (b d x y z)
  914. ;; b c CPL(c) = (c y e x z)
  915. ;; \ / CPL(a) = (a b d c y e x z)
  916. ;; a
  917. ;; CPL(a) does not contain CPL(b) !
  918. #||
  919. (defclass z () ())
  920. (defclass x (z) ())
  921. (defclass y (z) ())
  922. (defclass d (x z) ())
  923. (defclass e (x z) ())
  924. (defclass b (d y) ())
  925. (defclass c (y e) ())
  926. (defclass a (b c) ())
  927. (mapcar #'find-class '(z x y d e b c a))
  928. ||#
  929. (defun std-compute-cpl (class direct-superclasses)
  930. (let* ((superclasses ; list of all superclasses in any order
  931. (remove-duplicates
  932. (mapcap #'class-precedence-list direct-superclasses)))
  933. (L '())
  934. (R1 (list (cons class direct-superclasses)))
  935. (R2 (mapcar #'(lambda (D) (cons D (class-direct-superclasses D)))
  936. superclasses)))
  937. (loop
  938. ;; L is the reversed, so far constructed CPL.
  939. ;; R1 is the list of the so far relevant restrictions, in the form
  940. ;; R1 = (... (Dj ... Dn) ...) if from DR(D) = (D1 ... Dn) only
  941. ;; Dj,...,Dn is left over. The order in R1 corresponds to that in L.
  942. ;; R2 is the list of all so far irrelevant restrictions.
  943. (when (null R1)
  944. (return)) ; R1 = R2 = () -> finished
  945. (let ((M (remove-duplicates (mapcar #'first R1) :from-end t)))
  946. (setq M (remove-if #'(lambda (E)
  947. (or (dolist (r R1 nil)
  948. (when (member E (cdr r)) (return t)))
  949. (dolist (r R2 nil)
  950. (when (member E (cdr r)) (return t)))))
  951. (the list M)))
  952. (when (null M)
  953. (error-of-type 'error
  954. (TEXT "~S ~S: inconsistent precedence graph, cycle ~S")
  955. 'defclass (class-classname class)
  956. ;; find cycle: advance to ever smaller elements
  957. ;; with aid of the restrictions.
  958. (let* ((R0 (append R1 R2))
  959. (cycle (list (car (first R0)))))
  960. (loop
  961. (let* ((last (car cycle))
  962. (next (dolist (r R0 nil)
  963. (when (member last (cdr r))
  964. (return (nth (position last (cdr r)) r))))))
  965. (when (null next)
  966. ;; last is now apparently a minimal element, after all!
  967. (return '??))
  968. (when (member next cycle)
  969. (setf (cdr (member next cycle)) nil)
  970. (return cycle))
  971. (push next cycle))))))
  972. (let ((E (first M)))
  973. (push E L)
  974. (push (assoc E R2) R1)
  975. (setq R2 (delete E R2 :key #'first))
  976. (mapl #'(lambda (r) (when (eq (first (car r)) E) (pop (car r)))) R1)
  977. (setq R1 (delete-if #'null R1)))))
  978. (setq L (nreverse L))
  979. ;; Test, if L is compatible with the CPL(D), D in direct-superclasses:
  980. (mapc #'(lambda (D)
  981. (unless ; Is (class-precedence-list D) sublist of L ?
  982. (do ((CL L)
  983. (DL (class-precedence-list D) (cdr DL)))
  984. ((null DL) t)
  985. (when (null (setq CL (member (car DL) CL))) (return nil)))
  986. (clos-warning (TEXT "(class-precedence-list ~S) and (class-precedence-list ~S) are inconsistent")
  987. class D)))
  988. direct-superclasses)
  989. L))
  990. (defun compute-class-precedence-list-<defined-class> (class)
  991. (std-compute-cpl class (class-direct-superclasses class)))
  992. ;; Preliminary.
  993. (predefun compute-class-precedence-list (class)
  994. (compute-class-precedence-list-<defined-class> class))
  995. (defun checked-compute-class-precedence-list (class)
  996. (let ((cpl (compute-class-precedence-list class))
  997. (name (class-name class)))
  998. ; Some checks, to guarantee that user-defined methods on
  999. ; compute-class-precedence-list don't break our CLOS.
  1000. (unless (proper-list-p cpl)
  1001. (error (TEXT "Wrong ~S result for class ~S: not a proper list: ~S")
  1002. 'compute-class-precedence-list name cpl))
  1003. (dolist (c cpl)
  1004. (unless (defined-class-p c)
  1005. (error (TEXT "Wrong ~S result for class ~S: list element is not a class: ~S")
  1006. 'compute-class-precedence-list name c)))
  1007. (unless (eq (first cpl) class)
  1008. (error (TEXT "Wrong ~S result for class ~S: list doesn't start with the class itself: ~S")
  1009. 'compute-class-precedence-list name cpl))
  1010. (unless (or (eq name 't) ; for bootstrapping
  1011. (eq (car (last cpl)) <t>))
  1012. (error (TEXT "Wrong ~S result for class ~S: list doesn't end with ~S: ~S")
  1013. 'compute-class-precedence-list name <t> cpl))
  1014. (unless (= (length cpl) (length (remove-duplicates cpl :test #'eq)))
  1015. (error (TEXT "Wrong ~S result for class ~S: list contains duplicates: ~S")
  1016. 'compute-class-precedence-list name cpl))
  1017. (let ((superclasses (reduce #'union
  1018. (mapcar #'class-precedence-list
  1019. (class-direct-superclasses class))
  1020. :initial-value '())))
  1021. (let ((forgotten (set-difference superclasses cpl)))
  1022. (when forgotten
  1023. (error (TEXT "Wrong ~S result for class ~S: list doesn't contain the superclass~[~;~:;es~] ~{~S~^, ~}.")
  1024. 'compute-class-precedence-list name (length forgotten) forgotten)))
  1025. (let ((extraneous (set-difference (rest cpl) superclasses)))
  1026. (when extraneous
  1027. (error (TEXT "Wrong ~S result for class ~S: list contains elements that are not superclasses: ~{~S~^, ~}")
  1028. 'compute-class-precedence-list name extraneous))))
  1029. ; Now we've checked the CPL is OK.
  1030. cpl))
  1031. ;; Stuff all superclasses (from the precedence-list) into a hash-table.
  1032. (defun std-compute-superclasses (precedence-list)
  1033. (let ((ht (make-hash-table :key-type 'defined-class :value-type '(eql t)
  1034. :test 'ext:stablehash-eq :warn-if-needs-rehash-after-gc t)))
  1035. (mapc #'(lambda (superclass) (setf (gethash superclass ht) t))
  1036. precedence-list)
  1037. ht))
  1038. ;; Determine whether a class inherits from <standard-stablehash> or
  1039. ;; <structure-stablehash>.
  1040. (defun std-compute-subclass-of-stablehash-p (class)
  1041. (dolist (superclass (class-precedence-list class) nil)
  1042. (let ((superclassname (class-classname superclass)))
  1043. (when (or (eq superclassname 'standard-stablehash)
  1044. (eq superclassname 'structure-stablehash))
  1045. (return t)))))
  1046. ;; ----------------------------------------------------------------------------
  1047. ;; CLtL2 28.1.3.2., ANSI CL 7.5.3. Inheritance of Slots and Slot Options
  1048. (defun compute-effective-slot-definition-initargs-<defined-class> (class directslotdefs)
  1049. (declare (ignore class))
  1050. (unless (and (proper-list-p directslotdefs) (consp directslotdefs))
  1051. (error (TEXT "~S: argument should be a non-empty proper list, not ~S")
  1052. 'compute-effective-slot-definition-initargs directslotdefs))
  1053. (dolist (slot directslotdefs)
  1054. (unless (direct-slot-definition-p slot)
  1055. (error (TEXT "~S: argument list element is not a ~S: ~S")
  1056. 'compute-effective-slot-definition-initargs 'direct-slot-definition
  1057. slot)))
  1058. (let ((name (slot-definition-name (first directslotdefs))))
  1059. (dolist (slot (rest directslotdefs))
  1060. (unless (eql name (slot-definition-name slot))
  1061. (error (TEXT "~S: argument list elements should all have the same name, not ~S and ~S")
  1062. 'compute-effective-slot-definition-initargs name (slot-definition-name slot))))
  1063. `(:name ,name
  1064. ; "The allocation of a slot is controlled by the most
  1065. ; specific slot specifier."
  1066. :allocation ,(slot-definition-allocation (first directslotdefs))
  1067. ; "The set of initialization arguments that initialize a
  1068. ; given slot is the union of the initialization arguments
  1069. ; declared in the :initarg slot options in all the slot
  1070. ; specifiers.
  1071. ,@(let ((initargs
  1072. (remove-duplicates
  1073. (mapcap #'slot-definition-initargs directslotdefs)
  1074. :from-end t)))
  1075. (if initargs `(:initargs ,initargs)))
  1076. ; "The default initial value form for a slot is the value
  1077. ; of the :initform slot option in the most specific slot
  1078. ; specifier that contains one."
  1079. ,@(dolist (slot directslotdefs '())
  1080. (when (slot-definition-initfunction slot)
  1081. (return `(:initform ,(slot-definition-initform slot)
  1082. :initfunction ,(slot-definition-initfunction slot)
  1083. inheritable-initer ,(slot-definition-inheritable-initer slot)))))
  1084. ; "The contents of a slot will always be of type
  1085. ; (and T1 ... Tn) where T1 ...Tn are the values of the
  1086. ; :type slot options contained in all of the slot specifiers."
  1087. ,@(let ((types '()))
  1088. (dolist (slot directslotdefs)
  1089. (push (slot-definition-type slot) types))
  1090. `(:type ,(if types `(AND ,@(nreverse types)) 'T)))
  1091. ; "The documentation string for a slot is the value of the
  1092. ; :documentation slot option in the most specific slot
  1093. ; specifier that contains one."
  1094. ,@(dolist (slot directslotdefs '())
  1095. (when (slot-definition-documentation slot)
  1096. (return `(:documentation ,(slot-definition-documentation slot)
  1097. inheritable-doc ,(slot-definition-inheritable-doc slot)))))
  1098. #|| ; Commented out because <effective-slot-definition>
  1099. ; doesn't have readers and writers.
  1100. ,@(let ((readers (mapcap #'slot-definition-readers directslotdefs)))
  1101. (if readers `(:readers ,readers)))
  1102. ,@(let ((writers (mapcap #'slot-definition-writers directslotdefs)))
  1103. (if writers `(:writers ,writers)))
  1104. ||#
  1105. )))
  1106. ;; Preliminary.
  1107. (predefun compute-effective-slot-definition-initargs (class direct-slot-definitions)
  1108. (compute-effective-slot-definition-initargs-<defined-class> class direct-slot-definitions))
  1109. (defun compute-effective-slot-definition-<defined-class> (class name directslotdefs)
  1110. (let ((args (compute-effective-slot-definition-initargs class directslotdefs)))
  1111. ; Some checks, to guarantee that user-defined primary methods on
  1112. ; compute-effective-slot-definition-initargs don't break our CLOS.
  1113. (unless (and (proper-list-p args) (evenp (length args)))
  1114. (error (TEXT "Wrong ~S result for ~S: not a list of keyword/value pairs: ~S")
  1115. 'compute-effective-slot-definition-initargs class args))
  1116. (let* ((default '#:default)
  1117. (returned-name (getf args ':name '#:default)))
  1118. (unless (eql returned-name name)
  1119. (if (eq returned-name default)
  1120. (error (TEXT "Wrong ~S result for ~S: missing ~S")
  1121. 'compute-effective-slot-definition-initargs class ':name)
  1122. (error (TEXT "Wrong ~S result for ~S: invalid ~S value")
  1123. 'compute-effective-slot-definition-initargs class ':name))))
  1124. (let ((slot-definition-class
  1125. (apply #'effective-slot-definition-class class args)))
  1126. (cond ((semi-standard-class-p class)
  1127. (unless (or ; for bootstrapping
  1128. (eq slot-definition-class 'standard-effective-slot-definition)
  1129. (and (defined-class-p slot-definition-class)
  1130. (subclassp slot-definition-class <standard-effective-slot-definition>)))
  1131. (error (TEXT "Wrong ~S result for class ~S: not a subclass of ~S: ~S")
  1132. 'effective-slot-definition-class (class-name class)
  1133. 'standard-effective-slot-definition slot-definition-class)))
  1134. ((structure-class-p class)
  1135. (unless (and (defined-class-p slot-definition-class)
  1136. (subclassp slot-definition-class <structure-effective-slot-definition>))
  1137. (error (TEXT "Wrong ~S result for class ~S: not a subclass of ~S: ~S")
  1138. 'effective-slot-definition-class (class-name class)
  1139. 'structure-effective-slot-definition slot-definition-class))))
  1140. (apply (cond ((eq slot-definition-class 'standard-effective-slot-definition)
  1141. #'make-instance-<standard-effective-slot-definition>)
  1142. (t #'make-instance))
  1143. slot-definition-class args))))
  1144. ;; Preliminary.
  1145. (predefun compute-effective-slot-definition (class slotname direct-slot-definitions)
  1146. (compute-effective-slot-definition-<defined-class> class slotname direct-slot-definitions))
  1147. (defun compute-slots-<defined-class>-primary (class)
  1148. ;; Gather all slot-specifiers, ordered by precedence:
  1149. (let ((all-slots
  1150. (mapcan #'(lambda (c) (nreverse (copy-list (class-direct-slots c))))
  1151. (class-precedence-list class))))
  1152. ;; Partition by slot-names:
  1153. (setq all-slots
  1154. (let ((ht (make-hash-table :key-type 'symbol :value-type 't
  1155. :test 'ext:stablehash-eql :warn-if-needs-rehash-after-gc t)))
  1156. (dolist (slot all-slots)
  1157. (let ((slot-name (slot-definition-name slot)))
  1158. (push slot (gethash slot-name ht nil))))
  1159. (let ((L nil))
  1160. (maphash #'(lambda (name slot-list)
  1161. (push (cons name (nreverse slot-list)) L))
  1162. ht)
  1163. L))) ; not (nreverse L), because maphash reverses the order
  1164. ;; Bring the slots into final order: Superclass before subclass, and
  1165. ;; inside each class, keeping the same order as in the direct-slots.
  1166. (setq all-slots (nreverse all-slots))
  1167. ;; all-slots is now a list of lists of the form
  1168. ;; (name most-specific-slot ... least-specific-slot).
  1169. (mapcar
  1170. #'(lambda (slotbag)
  1171. (let ((name (car slotbag))
  1172. (directslotdefs (cdr slotbag)))
  1173. ;; Create the effective slot definition in a way that depends
  1174. ;; only on the class, name, and direct-slot-definitions.
  1175. (let ((eff-slot
  1176. (compute-effective-slot-definition class name directslotdefs)))
  1177. ; Some checks, to guarantee that user-defined methods on
  1178. ; compute-effective-slot-definition don't break our CLOS.
  1179. (unless (effective-slot-definition-p eff-slot)
  1180. (error (TEXT "Wrong ~S result for class ~S, slot ~S: not an ~S instance: ~S")
  1181. 'compute-effective-slot-definition class name 'effective-slot-definition eff-slot))
  1182. eff-slot)))
  1183. all-slots)))
  1184. ;; Allocation of local and shared slots.
  1185. ;; Side effects done by this function: The slot-definition-location of the
  1186. ;; slots is determined.
  1187. (defun compute-slots-<slotted-class>-around (class next-method)
  1188. (let ((cpl (class-precedence-list class))
  1189. (slots (funcall next-method class)))
  1190. ; Some checks, to guarantee that user-defined primary methods on
  1191. ; compute-slots don't break our CLOS.
  1192. (unless (proper-list-p slots)
  1193. (error (TEXT "Wrong ~S result for class ~S: not a proper list: ~S")
  1194. 'compute-slots (class-name class) slots))
  1195. (cond ((semi-standard-class-p class)
  1196. (dolist (slot slots)
  1197. (unless (standard-effective-slot-definition-p slot)
  1198. (error (TEXT "Wrong ~S result for class ~S: list element is not a ~S: ~S")
  1199. 'compute-slots (class-name class)
  1200. 'standard-effective-slot-definition slot))))
  1201. ((structure-class-p class)
  1202. (dolist (slot slots)
  1203. (unless (typep-class slot <structure-effective-slot-definition>)
  1204. (error (TEXT "Wrong ~S result for class ~S: list element is not a ~S: ~S")
  1205. 'compute-slots (class-name class)
  1206. 'structure-effective-slot-definition slot)))))
  1207. (unless (= (length slots)
  1208. (length (delete-duplicates (mapcar #'slot-definition-name slots))))
  1209. (error (TEXT "Wrong ~S result for class ~S: list contains duplicate slot names: ~S")
  1210. 'compute-slots (class-name class) slots))
  1211. ;; Implementation of fixed-slot-locations policy.
  1212. (let ((superclasses-with-fixed-slot-locations
  1213. (remove-if-not #'(lambda (c)
  1214. (and (semi-standard-class-p c)
  1215. (class-fixed-slot-locations c)))
  1216. (cdr (class-precedence-list class)))))
  1217. (when superclasses-with-fixed-slot-locations
  1218. (dolist (slot slots)
  1219. (let ((name (slot-definition-name slot))
  1220. (location nil))
  1221. (dolist (superclass superclasses-with-fixed-slot-locations)
  1222. (let ((slot-in-superclass (find name (class-slots superclass)
  1223. :key #'slot-definition-name)))
  1224. (when slot-in-superclass
  1225. (when (eq (slot-definition-allocation slot-in-superclass) ':instance)
  1226. (let ((guaranteed-location
  1227. (slot-definition-location slot-in-superclass)))
  1228. (assert (integerp guaranteed-location))
  1229. (if location
  1230. (unless (equal location guaranteed-location)
  1231. (error (TEXT "In class ~S, the slot ~S is constrained by incompatible constraints inherited from the superclasses.")
  1232. (class-name class) name))
  1233. (setq location guaranteed-location)))))))
  1234. (when location
  1235. (unless (eq (slot-definition-allocation slot) ':instance)
  1236. (error (TEXT "In class ~S, non-local slot ~S is constrained to be a local slot at offset ~S.")
  1237. (class-name class) name location))
  1238. (setf (slot-definition-location slot) location))))))
  1239. (let ((constrained-indices
  1240. (let ((constrained-slots (remove-if-not #'slot-definition-location slots)))
  1241. (setq constrained-slots (copy-list constrained-slots))
  1242. (setq constrained-slots (sort constrained-slots #'< :key #'slot-definition-location))
  1243. (do ((l constrained-slots (cdr l)))
  1244. ((null (cdr l)))
  1245. (when (= (slot-definition-location (car l)) (slot-definition-location (cadr l)))
  1246. (error (TEXT "In class ~S, the slots ~S and ~S are constrained from the superclasses to both be located at offset ~S.")
  1247. (class-name class)
  1248. (slot-definition-name (car l)) (slot-definition-name (cadr l))
  1249. (slot-definition-location (car l)))))
  1250. (mapcar #'slot-definition-location constrained-slots)))
  1251. (local-index (class-instance-size class))
  1252. (shared-index 0))
  1253. ;; Actually the constrained-indices must form a list of consecutive indices
  1254. ;; (1 2 ... n), but we don't need to make use of this.
  1255. ;; Now determine the location of each slot.
  1256. (when (and constrained-indices (< (first constrained-indices) local-index))
  1257. (error (TEXT "In class ~S, a slot constrained from a superclass wants to be located at offset ~S, which is impossible.")
  1258. (class-name class) (first constrained-indices)))
  1259. (flet ((skip-constrained-indices ()
  1260. (loop
  1261. (if (and constrained-indices
  1262. (= (first constrained-indices) local-index))
  1263. (progn (incf local-index) (pop constrained-indices))
  1264. (return)))))
  1265. (skip-constrained-indices)
  1266. (dolist (slot slots)
  1267. (let ((name (slot-definition-name slot))
  1268. (allocation (slot-definition-allocation slot)))
  1269. (setf (slot-definition-location slot)
  1270. (cond ((eq allocation ':instance)
  1271. ;; Local slot.
  1272. (or (slot-definition-location slot)
  1273. (prog1
  1274. local-index
  1275. (incf local-index)
  1276. (skip-constrained-indices))))
  1277. ((eq allocation ':class)
  1278. ;; Shared slot.
  1279. ;; This is a flaw in the compute-slots protocol: the
  1280. ;; primary compute-slots method returns a list of slots,
  1281. ;; without information about the class where the slot
  1282. ;; comes from. So we have to re-scan the direct slots
  1283. ;; lists.
  1284. (let ((origin
  1285. (dolist (superclass cpl class)
  1286. (when (find name (class-direct-slots superclass)
  1287. :key #'slot-definition-name)
  1288. (return superclass)))))
  1289. (if (eq origin class)
  1290. ;; New shared slot.
  1291. (prog1
  1292. (cons (class-current-version class) shared-index)
  1293. (incf shared-index))
  1294. ;; Inherited shared slot.
  1295. (let ((inh-descriptor
  1296. (gethash name (class-slot-location-table origin))))
  1297. (if (effective-slot-definition-p inh-descriptor)
  1298. (slot-definition-location inh-descriptor)
  1299. inh-descriptor)))))
  1300. (t ;; Don't signal an error for user-defined allocation
  1301. ;; types. They can be handled by user-defined around
  1302. ;; methods.
  1303. nil))))))
  1304. ;; Actually the constrained-indices must already have been emptied by
  1305. ;; the first (skip-constrained-indices) call, but we don't need to make
  1306. ;; use of this. Warn if :fixed-slot-locations would cause a waste of
  1307. ;; space.
  1308. (when constrained-indices
  1309. (setq local-index (1+ (car (last constrained-indices))))
  1310. (clos-warning (TEXT "In class ~S, constrained slot locations cause holes to appear.")
  1311. (class-name class)))
  1312. slots)))
  1313. ;; Preliminary.
  1314. (predefun compute-slots (class)
  1315. (compute-slots-<slotted-class>-around class #'compute-slots-<defined-class>-primary))
  1316. (defun checked-compute-slots (class)
  1317. (let ((slots (compute-slots class)))
  1318. ; Some checks, to guarantee that user-defined around methods on
  1319. ; compute-slots don't break our CLOS.
  1320. (unless (proper-list-p slots)
  1321. (error (TEXT "Wrong ~S result for class ~S: not a proper list: ~S")
  1322. 'compute-slots (class-name class) slots))
  1323. (dolist (slot slots)
  1324. (unless (standard-effective-slot-definition-p slot)
  1325. (error (TEXT "Wrong ~S result for class ~S: list element is not a ~S: ~S")
  1326. 'compute-slots (class-name class)
  1327. 'standard-effective-slot-definition slot)))
  1328. (unless (= (length slots)
  1329. (length (delete-duplicates (mapcar #'slot-definition-name slots))))
  1330. (error (TEXT "Wrong ~S result for class ~S: list contains duplicate slot names: ~S")
  1331. 'compute-slots (class-name class) slots))
  1332. (dolist (slot slots)
  1333. (case (slot-definition-allocation slot)
  1334. ((:INSTANCE :CLASS)
  1335. (unless (slot-definition-location slot)
  1336. (error (TEXT "Wrong ~S result for class ~S: no slot location has been assigned to ~S")
  1337. 'compute-slots (class-name class) slot)))))
  1338. slots))
  1339. ;; The MOP lacks a way to customize the instance size as a function of the
  1340. ;; slots. This becomes an issue when you have slots which occupy more than one
  1341. ;; word, and such a slot is the last local slot.
  1342. (defun compute-instance-size (class)
  1343. (let ((size (class-instance-size class))) ; initial size depends on the metaclass
  1344. (dolist (slot (class-slots class))
  1345. (when (eq (slot-definition-allocation slot) ':instance)
  1346. (let ((location (slot-definition-location slot)))
  1347. (assert (integerp location))
  1348. (setq size (max size (+ location 1))))))
  1349. size))
  1350. ;; Similarly, the MOP lacks a way to customize the shared slot values vector's
  1351. ;; size as a function of the slots.
  1352. (defun compute-shared-size (class)
  1353. (let ((shared-size 0))
  1354. (dolist (slot (class-slots class))
  1355. (let ((location (slot-definition-location slot)))
  1356. (when (and (consp location) (eq (cv-newest-class (car location)) class))
  1357. (let ((shared-index (cdr location)))
  1358. (setq shared-size (max shared-size (+ shared-index 1)))))))
  1359. shared-size))
  1360. ;; Creates the shared slot values vector for a class.
  1361. (defun create-shared-slots-vector (class shared-size old-slot-location-table)
  1362. (let ((v (make-array shared-size :initial-element 'DEADBEEF)))
  1363. (dolist (slot (class-slots class))
  1364. (let ((location (slot-definition-location slot)))
  1365. (when (and (consp location)
  1366. (eq (cv-newest-class (car location)) class))
  1367. (let ((shared-index (cdr location)))
  1368. (setf (svref v shared-index)
  1369. (let* ((old-slot-descriptor
  1370. (gethash (slot-definition-name slot) old-slot-location-table))
  1371. (old-slot-location
  1372. (if (effective-slot-definition-p old-slot-descriptor)
  1373. (slot-definition-location old-slot-descriptor)
  1374. old-slot-descriptor)))
  1375. (if (and (consp old-slot-location)
  1376. (eq (cv-newest-class (car old-slot-location)) class))
  1377. ;; The slot was already shared. Retain its value.
  1378. (svref (cv-shared-slots (car old-slot-location))
  1379. (cdr old-slot-location))
  1380. ;; A new shared slot.
  1381. (let ((initfunction (slot-definition-initfunction slot)))
  1382. (if initfunction
  1383. (funcall initfunction)
  1384. (sys::%unbound))))))))))
  1385. v))
  1386. (defun compute-slot-location-table (class)
  1387. (let ((slots (class-slots class)))
  1388. (if slots
  1389. (make-hash-table
  1390. :key-type 'symbol :value-type 't
  1391. :test 'ext:stablehash-eq :warn-if-needs-rehash-after-gc t
  1392. :initial-contents
  1393. (mapcar #'(lambda (slot)
  1394. (cons (slot-definition-name slot)
  1395. (compute-slot-location-table-entry class slot)))
  1396. slots))
  1397. empty-ht)))
  1398. (defun compute-slot-location-table-entry (class slot)
  1399. (let ((location (slot-definition-location slot))
  1400. ;; Compute the effective methods of SLOT-VALUE-USING-CLASS etc.
  1401. ;; Note that we cannot use (class-prototype class) yet.
  1402. ;; Also, SLOT-VALUE-USING-CLASS etc. are not defined on STRUCTURE-CLASS.
  1403. (efm-svuc
  1404. (if (and (semi-standard-class-p class) *classes-finished*)
  1405. (compute-applicable-methods-effective-method-for-set
  1406. |#'slot-value-using-class|
  1407. (list `(EQL ,class) `(INSTANCE-OF-P ,class) `(EQL ,slot))
  1408. (list class '`(CLASS-PROTOTYPE ,class) slot))
  1409. #'%slot-value-using-class))
  1410. (efm-ssvuc
  1411. (if (and (semi-standard-class-p class) *classes-finished*)
  1412. (compute-applicable-methods-effective-method-for-set
  1413. |#'(setf slot-value-using-class)|
  1414. (list `(TYPEP ,<t>) `(EQL ,class) `(INSTANCE-OF-P ,class) `(EQL ,slot))
  1415. (list 'ANY-VALUE class '`(CLASS-PROTOTYPE ,class) slot))
  1416. #'%set-slot-value-using-class))
  1417. (efm-sbuc
  1418. (if (and (semi-standard-class-p class) *classes-finished*)
  1419. (compute-applicable-methods-effective-method-for-set
  1420. |#'slot-boundp-using-class|
  1421. (list `(EQL ,class) `(INSTANCE-OF-P ,class) `(EQL ,slot))
  1422. (list class '`(CLASS-PROTOTYPE ,class) slot))
  1423. #'%slot-boundp-using-class))
  1424. (efm-smuc
  1425. (if (and (semi-standard-class-p class) *classes-finished*)
  1426. (compute-applicable-methods-effective-method-for-set
  1427. |#'slot-makunbound-using-class|
  1428. (list `(EQL ,class) `(INSTANCE-OF-P ,class) `(EQL ,slot))
  1429. (list class '`(CLASS-PROTOTYPE ,class) slot))
  1430. #'%slot-makunbound-using-class)))
  1431. (setf (slot-definition-efm-svuc slot) efm-svuc)
  1432. (setf (slot-definition-efm-ssvuc slot) efm-ssvuc)
  1433. (setf (slot-definition-efm-sbuc slot) efm-sbuc)
  1434. (setf (slot-definition-efm-smuc slot) efm-smuc)
  1435. (if (and (eq efm-svuc #'%slot-value-using-class)
  1436. (eq efm-ssvuc #'%set-slot-value-using-class)
  1437. (eq efm-sbuc #'%slot-boundp-using-class)
  1438. (eq efm-smuc #'%slot-makunbound-using-class))
  1439. location
  1440. slot)))
  1441. ;; ----------------------------------------------------------------------------
  1442. ;; CLtL2 28.1.3.3., ANSI CL 4.3.4.2. Inheritance of Default-Initargs
  1443. (defun compute-default-initargs-<defined-class> (class)
  1444. (remove-duplicates
  1445. (mapcap #'class-direct-default-initargs (class-precedence-list class))
  1446. :key #'car
  1447. :from-end t))
  1448. ;; Preliminary.
  1449. (predefun compute-default-initargs (class)
  1450. (compute-default-initargs-<defined-class> class))
  1451. (defun checked-compute-default-initargs (class)
  1452. (let ((default-initargs (compute-default-initargs class)))
  1453. ; Some checks, to guarantee that user-defined methods on
  1454. ; compute-default-initargs don't break our CLOS.
  1455. (unless (proper-list-p default-initargs)
  1456. (error (TEXT "Wrong ~S result for class ~S: not a proper list: ~S")
  1457. 'compute-default-initargs (class-name class) default-initargs))
  1458. (dolist (di default-initargs)
  1459. (unless (canonicalized-default-initarg-p di)
  1460. (error (TEXT "Wrong ~S result for class ~S: list element is not a canonicalized default initarg: ~S")
  1461. 'compute-default-initargs (class-name class) di)))
  1462. (unless (= (length default-initargs)
  1463. (length (delete-duplicates (mapcar #'first default-initargs))))
  1464. (error (TEXT "Wrong ~S result for class ~S: list contains duplicate initarg names: ~S")
  1465. 'compute-default-initargs (class-name class) default-initargs))
  1466. default-initargs))
  1467. ;; ----------------------------- Accessor Methods -----------------------------
  1468. ;; Flag to avoid bootstrapping issues with the compiler.
  1469. (defvar *compile-accessor-functions* nil)
  1470. (defun check-method-redefinition (funname qualifiers spec-list caller)
  1471. (sys::check-redefinition
  1472. (list* funname qualifiers spec-list) caller
  1473. ;; do not warn about redefinition when no method was defined
  1474. (and (fboundp 'find-method) (fboundp funname)
  1475. (typep-class (fdefinition funname) <generic-function>)
  1476. (not (safe-gf-undeterminedp (fdefinition funname)))
  1477. (eql (sig-req-num (safe-gf-signature (fdefinition funname)))
  1478. (length spec-list))
  1479. (find-method (fdefinition funname) qualifiers spec-list nil)
  1480. (TEXT "method"))))
  1481. ;; Install the accessor methods corresponding to the direct slots of a class.
  1482. (defun install-class-direct-accessors (class)
  1483. (dolist (slot (class-direct-slots class))
  1484. (let ((slot-name (slot-definition-name slot))
  1485. (readers (slot-definition-readers slot))
  1486. (writers (slot-definition-writers slot)))
  1487. (when (or readers writers)
  1488. (let ((generic-p (class-generic-accessors class))
  1489. (access-place
  1490. (let (effective-slot)
  1491. (if (and (semi-standard-class-p class)
  1492. (class-fixed-slot-locations class)
  1493. (setq effective-slot
  1494. (find slot-name (class-slots class)
  1495. :key #'slot-definition-name))
  1496. (eq (slot-definition-allocation effective-slot)
  1497. ':instance))
  1498. (progn
  1499. (assert (typep (slot-definition-location effective-slot) 'integer))
  1500. `(STANDARD-INSTANCE-ACCESS OBJECT ,(slot-definition-location effective-slot)))
  1501. (if (and (structure-class-p class)
  1502. (setq effective-slot
  1503. (find slot-name (class-slots class)
  1504. :key #'slot-definition-name))
  1505. (eq (slot-definition-allocation effective-slot)
  1506. ':instance))
  1507. (progn
  1508. (assert (typep (slot-definition-location effective-slot) 'integer))
  1509. `(SYSTEM::%STRUCTURE-REF ',(class-name class) OBJECT ,(slot-definition-location effective-slot)))
  1510. `(SLOT-VALUE OBJECT ',slot-name))))))
  1511. ;; Generic accessors are defined as methods and listed in the
  1512. ;; direct-accessors list, so they can be removed upon class redefinition.
  1513. ;; Non-generic accessors are defined as plain functions.
  1514. ;; Call CHECK-REDEFINITION appropriately.
  1515. (dolist (funname readers)
  1516. (if generic-p
  1517. (progn
  1518. (check-method-redefinition funname nil (list class) 'defclass)
  1519. (setf (class-direct-accessors class)
  1520. (list* funname
  1521. (do-defmethod funname
  1522. (let* ((args
  1523. (list
  1524. :specializers (list class)
  1525. :qualifiers nil
  1526. :lambda-list '(OBJECT)
  1527. 'signature (sys::memoized (make-signature :req-num 1))
  1528. :slot-definition slot))
  1529. (method-class
  1530. (apply #'reader-method-class
  1531. class slot args)))
  1532. (unless (and (defined-class-p method-class)
  1533. (subclassp method-class <standard-reader-method>))
  1534. (error (TEXT "Wrong ~S result for class ~S: not a subclass of ~S: ~S")
  1535. 'reader-method-class (class-name class) 'standard-reader-method method-class))
  1536. (apply #'make-instance method-class
  1537. (nconc (method-function-initargs
  1538. method-class
  1539. (eval
  1540. `(LOCALLY
  1541. (DECLARE (COMPILE))
  1542. (%OPTIMIZE-FUNCTION-LAMBDA
  1543. (T) (#:CONTINUATION OBJECT)
  1544. (DECLARE (COMPILE))
  1545. ,access-place))))
  1546. args))))
  1547. (class-direct-accessors class))))
  1548. (progn
  1549. (sys::check-redefinition
  1550. funname 'defclass (sys::fbound-string funname))
  1551. (setf (fdefinition funname)
  1552. (eval `(FUNCTION ,funname (LAMBDA (OBJECT)
  1553. ,@(if *compile-accessor-functions* '((DECLARE (COMPILE))))
  1554. (UNLESS (TYPEP OBJECT ',class)
  1555. (ERROR-ACCESSOR-TYPECHECK ',funname OBJECT ',class))
  1556. ,access-place)))))))
  1557. (dolist (funname writers)
  1558. (if generic-p
  1559. (progn
  1560. (check-method-redefinition funname nil (list class) 'defclass)
  1561. (setf (class-direct-accessors class)
  1562. (list* funname
  1563. (do-defmethod funname
  1564. (let* ((args
  1565. (list
  1566. :specializers (list <t> class)
  1567. :qualifiers nil
  1568. :lambda-list '(NEW-VALUE OBJECT)
  1569. 'signature (sys::memoized (make-signature :req-num 2))
  1570. :slot-definition slot))
  1571. (method-class
  1572. (apply #'writer-method-class
  1573. class slot args)))
  1574. (unless (and (defined-class-p method-class)
  1575. (subclassp method-class <standard-writer-method>))
  1576. (error (TEXT "Wrong ~S result for class ~S: not a subclass of ~S: ~S")
  1577. 'writer-method-class
  1578. (class-name class)
  1579. 'standard-writer-method method-class))
  1580. (apply #'make-instance method-class
  1581. (nconc (method-function-initargs
  1582. method-class
  1583. (eval
  1584. `(LOCALLY
  1585. (DECLARE (COMPILE))
  1586. (%OPTIMIZE-FUNCTION-LAMBDA
  1587. (T) (#:CONTINUATION NEW-VALUE OBJECT)
  1588. (DECLARE (COMPILE))
  1589. (SETF ,access-place NEW-VALUE)))))
  1590. args))))
  1591. (class-direct-accessors class))))
  1592. (progn
  1593. (sys::check-redefinition
  1594. funname 'defclass (sys::fbound-string
  1595. (sys::get-funname-symbol funname)))
  1596. (setf (fdefinition funname)
  1597. (eval `(FUNCTION ,funname (LAMBDA (NEW-VALUE OBJECT)
  1598. ,@(if *compile-accessor-functions* '((DECLARE (COMPILE))))
  1599. (UNLESS (TYPEP OBJECT ',class)
  1600. (ERROR-ACCESSOR-TYPECHECK ',funname OBJECT ',class))
  1601. (SETF ,access-place NEW-VALUE)))))))))))))
  1602. ;; Remove a set of accessor methods given as a plist.
  1603. (defun remove-accessor-methods (plist)
  1604. (do ((l plist (cddr l)))
  1605. ((endp l))
  1606. (let ((funname (car l))
  1607. (method (cadr l)))
  1608. (remove-method (fdefinition funname) method))))
  1609. ;; Add a set of accessor methods given as a plist.
  1610. (defun add-accessor-methods (plist)
  1611. (do ((l plist (cddr l)))
  1612. ((endp l))
  1613. (let ((funname (car l))
  1614. (method (cadr l)))
  1615. (add-method (fdefinition funname) method))))
  1616. ;; --------------- Creation of an instance of <built-in-class> ---------------
  1617. (defun make-instance-<built-in-class> (metaclass &rest args
  1618. &key name (direct-superclasses '())
  1619. &allow-other-keys)
  1620. ;; metaclass = <built-in-class>
  1621. ;; Don't add functionality here! This is a preliminary definition that is
  1622. ;; replaced with #'make-instance later.
  1623. (declare (ignore metaclass name direct-superclasses))
  1624. (let ((class (allocate-metaobject-instance *<built-in-class>-class-version*
  1625. *<built-in-class>-instance-size*)))
  1626. (apply #'initialize-instance-<built-in-class> class args)))
  1627. (defun initialize-instance-<built-in-class> (class &rest args
  1628. &key &allow-other-keys)
  1629. ;; Don't add functionality here! This is a preliminary definition that is
  1630. ;; replaced with #'initialize-instance later.
  1631. (apply #'shared-initialize-<built-in-class> class 't args)
  1632. (install-class-direct-accessors class)
  1633. class)
  1634. (defun shared-initialize-<built-in-class> (class situation &rest args
  1635. &key (name nil name-p)
  1636. (direct-superclasses '() direct-superclasses-p)
  1637. ((prototype prototype) nil prototype-p)
  1638. &allow-other-keys)
  1639. (when (or (eq situation 't) direct-superclasses-p)
  1640. (check-metaclass-mix (if name-p name (class-classname class))
  1641. direct-superclasses
  1642. #'built-in-class-p 'built-in-class))
  1643. (apply #'shared-initialize-<defined-class> class situation args)
  1644. ; Initialize the remaining <defined-class> slots:
  1645. (when (or (eq situation 't) direct-superclasses-p)
  1646. (setf (class-precedence-list class)
  1647. (checked-compute-class-precedence-list class))
  1648. (when (eq situation 't)
  1649. (setf (class-initialized class) 3))
  1650. (setf (class-all-superclasses class)
  1651. (std-compute-superclasses (class-precedence-list class)))
  1652. (when (eq situation 't)
  1653. (setf (class-initialized class) 4)))
  1654. (when (eq situation 't)
  1655. (setf (class-slots class) '())
  1656. (setf (class-initialized class) 5)
  1657. (setf (class-default-initargs class) '())
  1658. (setf (class-initialized class) 6))
  1659. (when (or (eq situation 't) prototype-p)
  1660. (setf (sys::%record-ref class *<built-in-class>-prototype-location*) prototype))
  1661. ; Done.
  1662. class)
  1663. ;; --------------- Creation of an instance of <structure-class> ---------------
  1664. (defun make-instance-<structure-class> (metaclass &rest args
  1665. &key name (direct-superclasses '())
  1666. ;; The following keys come from ENSURE-CLASS.
  1667. ((:direct-slots direct-slots-as-lists) '())
  1668. (direct-default-initargs '()) (documentation nil)
  1669. ;; The following keys come from DEFINE-STRUCTURE-CLASS.
  1670. ((names names) nil)
  1671. ((kconstructor kconstructor) nil)
  1672. ((boa-constructors boa-constructors) '())
  1673. ((copier copier) nil)
  1674. ((predicate predicate) nil)
  1675. ((direct-slots direct-slots-as-metaobjects) '())
  1676. ((slots slots) '()) ((size size) 1)
  1677. &allow-other-keys)
  1678. ;; metaclass = <structure-class>
  1679. ;; Don't add functionality here! This is a preliminary definition that is
  1680. ;; replaced with #'make-instance later.
  1681. (declare (ignore metaclass name direct-superclasses direct-slots-as-lists
  1682. direct-default-initargs documentation
  1683. names kconstructor boa-constructors copier predicate
  1684. direct-slots-as-metaobjects slots size))
  1685. (let ((class (allocate-metaobject-instance *<structure-class>-class-version*
  1686. *<structure-class>-instance-size*)))
  1687. (apply #'initialize-instance-<structure-class> class args)))
  1688. (defun initialize-instance-<structure-class> (class &rest args
  1689. &key &allow-other-keys)
  1690. ;; Don't add functionality here! This is a preliminary definition that is
  1691. ;; replaced with #'initialize-instance later.
  1692. (apply #'shared-initialize-<structure-class> class 't args)
  1693. ;; avoid slot accessor redefinition warning
  1694. ;; (install-class-direct-accessors class)
  1695. class)
  1696. (defun shared-initialize-<structure-class> (class situation &rest args
  1697. &key (name nil name-p)
  1698. (direct-superclasses '() direct-superclasses-p)
  1699. (generic-accessors t generic-accessors-p)
  1700. ;; The following keys come from ENSURE-CLASS.
  1701. ((:direct-slots direct-slots-as-lists) '() direct-slots-as-lists-p)
  1702. (direct-default-initargs '() direct-default-initargs-p)
  1703. (documentation nil documentation-p)
  1704. ;; The following keys come from DEFINE-STRUCTURE-CLASS.
  1705. ((names names) nil names-p)
  1706. ((kconstructor kconstructor) nil kconstructor-p)
  1707. ((boa-constructors boa-constructors) '() boa-constructors-p)
  1708. ((copier copier) nil copier-p)
  1709. ((predicate predicate) nil predicate-p)
  1710. ((direct-slots direct-slots-as-metaobjects) '() direct-slots-as-metaobjects-p)
  1711. ((slots slots) '())
  1712. ((size size) 1)
  1713. &allow-other-keys)
  1714. ;; metaclass ⊆ <structure-class>
  1715. (declare (ignore generic-accessors generic-accessors-p direct-slots-as-lists
  1716. direct-slots-as-metaobjects direct-default-initargs
  1717. documentation documentation-p))
  1718. (when (or (eq situation 't) direct-superclasses-p)
  1719. (check-metaclass-mix (if name-p name (class-classname class))
  1720. direct-superclasses
  1721. #'structure-class-p 'STRUCTURE-CLASS))
  1722. (apply #'shared-initialize-<slotted-class> class situation args)
  1723. (setq direct-superclasses (class-direct-superclasses class)) ; augmented
  1724. ; Initialize the remaining <defined-class> slots:
  1725. (when (or (eq situation 't) direct-superclasses-p)
  1726. (setf (class-precedence-list class)
  1727. (checked-compute-class-precedence-list class))
  1728. (when (eq situation 't)
  1729. (setf (class-initialized class) 3))
  1730. (setf (class-all-superclasses class)
  1731. (std-compute-superclasses (class-precedence-list class)))
  1732. (when (eq situation 't)
  1733. (setf (class-initialized class) 4)))
  1734. (when (or (eq situation 't) direct-superclasses-p
  1735. direct-slots-as-lists-p direct-slots-as-metaobjects-p)
  1736. (setf (class-slots class) slots)
  1737. (when (eq situation 't)
  1738. (setf (class-initialized class) 5))
  1739. (setf (class-slot-location-table class) (compute-slot-location-table class))
  1740. (setf (class-instance-size class) size)
  1741. (unless names
  1742. (setf (class-instance-size class) 1)
  1743. (setf (class-slots class)
  1744. (compute-slots-<slotted-class>-around class #'compute-slots-<defined-class>-primary))
  1745. (setf (class-instance-size class) (max size (compute-instance-size class)))
  1746. (when (class-slots class)
  1747. (let ((ht (class-slot-location-table class)))
  1748. (when (eq ht empty-ht) ; avoid clobbering empty-ht!
  1749. (setq ht (setf (class-slot-location-table class)
  1750. (make-hash-table
  1751. :key-type 'symbol :value-type 't
  1752. :test 'ext:stablehash-eq :warn-if-needs-rehash-after-gc t))))
  1753. (dolist (slot (class-slots class))
  1754. (setf (gethash (slot-definition-name slot) ht)
  1755. (slot-definition-location slot)))))
  1756. (when (plusp (compute-shared-size class))
  1757. (error-of-type 'error
  1758. (TEXT "(~S ~S): metaclass ~S does not support shared slots")
  1759. 'DEFCLASS name 'STRUCTURE-CLASS))))
  1760. (when (or (eq situation 't) direct-superclasses-p direct-default-initargs-p)
  1761. (setf (class-default-initargs class)
  1762. (checked-compute-default-initargs class)))
  1763. (when (eq situation 't)
  1764. (setf (class-initialized class) 6))
  1765. ; Initialize the remaining <slotted-class> slots:
  1766. (when (or (eq situation 't) direct-superclasses-p)
  1767. (setf (class-subclass-of-stablehash-p class)
  1768. (std-compute-subclass-of-stablehash-p class)))
  1769. (when (or (eq situation 't) direct-superclasses-p
  1770. direct-slots-as-lists-p direct-slots-as-metaobjects-p)
  1771. (setf (class-valid-initargs-from-slots class)
  1772. (remove-duplicates (mapcap #'slot-definition-initargs (class-slots class)))))
  1773. ; Initialize the remaining <structure-class> slots:
  1774. (when (or (eq situation 't) direct-superclasses-p names-p)
  1775. (unless names
  1776. (setq names
  1777. (cons name
  1778. (if direct-superclasses
  1779. (class-names (first direct-superclasses))
  1780. '()))))
  1781. (setf (class-names class) names))
  1782. (when (or (eq situation 't) kconstructor-p)
  1783. (setf (class-kconstructor class) kconstructor))
  1784. (when (or (eq situation 't) boa-constructors-p)
  1785. (setf (class-boa-constructors class) boa-constructors))
  1786. (when (or (eq situation 't) copier-p)
  1787. (setf (class-copier class) copier))
  1788. (when (or (eq situation 't) predicate-p)
  1789. (setf (class-predicate class) predicate))
  1790. (when (eq situation 't)
  1791. (setf (sys::%record-ref class *<structure-class>-prototype-location*) nil))
  1792. ; Done.
  1793. (when (eq situation 't)
  1794. (system::note-new-structure-class))
  1795. class)
  1796. ;; DEFSTRUCT-Hook
  1797. (defun define-structure-class (name names keyword-constructor boa-constructors copier predicate all-slots direct-slots) ; ABI
  1798. (setf (find-class name)
  1799. (make-instance-<structure-class> <structure-class>
  1800. :name name
  1801. :direct-superclasses
  1802. (if (cdr names) (list (find-class (second names))) '())
  1803. 'names names
  1804. 'kconstructor keyword-constructor
  1805. 'boa-constructors boa-constructors
  1806. 'copier copier
  1807. 'predicate predicate
  1808. 'direct-slots direct-slots
  1809. 'slots all-slots
  1810. 'size (if all-slots
  1811. (1+ (slot-definition-location (car (last all-slots))))
  1812. 1)
  1813. :generic-accessors nil
  1814. 'clos::defclass-form 'defstruct)))
  1815. (defun undefine-structure-class (name) ; ABI
  1816. (setf (find-class name) nil))
  1817. ;; ------------- Creation of an instance of <semi-standard-class> -------------
  1818. (defun shared-initialize-<semi-standard-class> (class situation &rest args
  1819. &key (direct-superclasses '() direct-superclasses-p)
  1820. ((:direct-slots direct-slots-as-lists) '() direct-slots-as-lists-p)
  1821. ((direct-slots direct-slots-as-metaobjects) '() direct-slots-as-metaobjects-p)
  1822. (direct-default-initargs '() direct-default-initargs-p)
  1823. (documentation nil documentation-p)
  1824. (generic-accessors t generic-accessors-p)
  1825. (fixed-slot-locations nil fixed-slot-locations-p)
  1826. &allow-other-keys)
  1827. (declare (ignore direct-superclasses direct-superclasses-p
  1828. direct-slots-as-lists direct-slots-as-lists-p
  1829. direct-slots-as-metaobjects direct-slots-as-metaobjects-p
  1830. direct-default-initargs direct-default-initargs-p
  1831. documentation documentation-p generic-accessors
  1832. generic-accessors-p))
  1833. (apply #'shared-initialize-<slotted-class> class situation args)
  1834. (when (eq situation 't)
  1835. (setf (class-current-version class)
  1836. (make-class-version :newest-class class
  1837. :class class
  1838. :serial 0))
  1839. (unless *classes-finished*
  1840. ; Bootstrapping: Simulate the effect of #'%shared-initialize.
  1841. (setf (class-instantiated class) nil)
  1842. (setf (class-direct-instance-specializers-table class) '())
  1843. (setf (class-finalized-direct-subclasses-table class) '())))
  1844. ; Initialize the remaining <defined-class> slots:
  1845. (setf (class-initialized class) 2) ; mark as not yet finalized
  1846. (setf (class-precedence-list class) nil) ; mark as not yet finalized
  1847. (setf (class-all-superclasses class) nil) ; mark as not yet finalized
  1848. ; Initialize the remaining <slotted-class> slots:
  1849. ; Initialize the remaining <semi-standard-class> slots:
  1850. (when (or (eq situation 't) fixed-slot-locations-p)
  1851. ;; Convert from list to boolean.
  1852. (when (consp fixed-slot-locations)
  1853. (setq fixed-slot-locations (car fixed-slot-locations)))
  1854. (setf (class-fixed-slot-locations class) fixed-slot-locations))
  1855. (setf (class-prototype class) nil)
  1856. ; Try to finalize it.
  1857. (when (finalizable-p class)
  1858. (finalize-inheritance class))
  1859. ; Done.
  1860. class)
  1861. ;; ------------- Finalizing an instance of <semi-standard-class> -------------
  1862. ;; Tests whether a class can be finalized, by recursing on the
  1863. ;; direct-superclasses list. May call finalize-inheritance on some of the
  1864. ;; superclasses.
  1865. ;; Returns T if all the direct-superclasses could be finalized.
  1866. ;; Returns NIL if this is not possible, and as second value a list from the
  1867. ;; direct-superclass that couldn't be finalized up to the forward-reference
  1868. ;; that is not yet defined.
  1869. (defun finalizable-p (class &optional (stack nil))
  1870. (assert (defined-class-p class))
  1871. (when (memq class stack)
  1872. (error-of-type 'program-error
  1873. (TEXT "~S: class definition circularity: ~S depends on itself")
  1874. 'defclass class))
  1875. (let ((stack (cons class stack)))
  1876. (do ((superclassesr (class-direct-superclasses class) (cdr superclassesr)))
  1877. ((endp superclassesr))
  1878. (let ((superclass (car superclassesr)))
  1879. (unless (defined-class-p superclass)
  1880. (unless (forward-reference-to-class-p superclass)
  1881. (error (TEXT "~S has a direct-superclasses element ~S, which is invalid.")
  1882. class superclass))
  1883. (let ((real-superclass
  1884. (or (find-class (class-name superclass) nil)
  1885. (return-from finalizable-p (values nil (list superclass))))))
  1886. ;; Changed from forward-reference-to-class to defined-class.
  1887. (check-allowed-superclass class real-superclass)
  1888. (setf (car superclassesr) real-superclass)
  1889. (remove-direct-subclass superclass class)
  1890. (add-direct-subclass real-superclass class)
  1891. (setq superclass real-superclass)))
  1892. (assert (defined-class-p superclass))
  1893. (unless (>= (class-initialized superclass) 6) ; not already finalized?
  1894. ;; Here we get only for instances of STANDARD-CLASS, since instances
  1895. ;; of BUILT-IN-CLASS and STRUCTURE-CLASS are already finalized when
  1896. ;; they are constructed.
  1897. (multiple-value-bind (done failure-cause) (finalizable-p superclass stack)
  1898. (unless done
  1899. ;; Finalization of a superclass was impossible.
  1900. (return-from finalizable-p (values nil (cons superclass failure-cause)))))
  1901. ;; Now finalize the superclass. (We could also do this later, from
  1902. ;; inside finalize-inheritance, but then we would need some extra
  1903. ;; bookkeeping to ensure that the running time for a class hierarchy
  1904. ;; like this
  1905. ;; A1
  1906. ;; / \
  1907. ;; B1 C1
  1908. ;; \ /
  1909. ;; A2
  1910. ;; / \
  1911. ;; B2 C2
  1912. ;; \ /
  1913. ;; A3
  1914. ;; ....
  1915. ;; A(n-1)
  1916. ;; / \
  1917. ;; B(n-1) C(n-1)
  1918. ;; \ /
  1919. ;; An
  1920. ;; is linear, not exponential, in the number of classes.)
  1921. (finalize-inheritance superclass)))))
  1922. t)
  1923. ;; Preliminary.
  1924. (predefun finalize-inheritance (class)
  1925. (finalize-inheritance-<semi-standard-class> class))
  1926. (defun finalize-inheritance-<semi-standard-class> (class)
  1927. (multiple-value-bind (done failure-cause) (finalizable-p class)
  1928. (unless done
  1929. (let ((pretty-cause (mapcar #'class-pretty (cons class failure-cause))))
  1930. (error (TEXT "~S: Cannot finalize class ~S. ~:{Class ~S inherits from class ~S. ~}Class ~S is not yet defined.")
  1931. 'finalize-inheritance (first pretty-cause)
  1932. (mapcar #'list pretty-cause (rest pretty-cause))
  1933. (car (last pretty-cause))))))
  1934. ;; Now we know that all direct superclasses are finalized.
  1935. (when (boundp 'class-finalized-p)
  1936. (assert (every #'class-finalized-p (class-direct-superclasses class))))
  1937. ;; Now compute the class-precedence-list.
  1938. (finalize-instance-semi-standard-class class)
  1939. class)
  1940. (defun finalize-instance-semi-standard-class (class
  1941. &aux (direct-superclasses (class-direct-superclasses class))
  1942. (name (class-name class))
  1943. (old-slot-location-table (class-slot-location-table class)))
  1944. ;; metaclass ⊆ <semi-standard-class>
  1945. (if (standard-class-p class)
  1946. (check-metaclass-mix name direct-superclasses
  1947. #'standard-class-p 'STANDARD-CLASS)
  1948. (check-metaclass-mix name direct-superclasses
  1949. #'semi-standard-class-p 'SEMI-STANDARD-CLASS))
  1950. (setf (class-precedence-list class)
  1951. (checked-compute-class-precedence-list class))
  1952. (when (< (class-initialized class) 3)
  1953. (setf (class-initialized class) 3))
  1954. (setf (class-all-superclasses class)
  1955. (std-compute-superclasses (class-precedence-list class)))
  1956. (when (< (class-initialized class) 4)
  1957. (setf (class-initialized class) 4))
  1958. (dolist (super direct-superclasses)
  1959. (when (semi-standard-class-p super)
  1960. (add-finalized-direct-subclass super class)))
  1961. (setf (class-subclass-of-stablehash-p class)
  1962. (std-compute-subclass-of-stablehash-p class))
  1963. (setf (class-funcallablep class)
  1964. ; <funcallable-standard-object> or a subclass of it?
  1965. (if (gethash <function> (class-all-superclasses class)) t nil))
  1966. (setf (class-instance-size class)
  1967. (if (class-funcallablep class)
  1968. 3 ; see comments in clos-genfun1.lisp
  1969. 1)) ; slot 0 is the class_version pointer
  1970. (setf (class-slots class) (checked-compute-slots class))
  1971. (when (< (class-initialized class) 5)
  1972. (setf (class-initialized class) 5))
  1973. (setf (class-instance-size class) (compute-instance-size class))
  1974. (setf (class-slot-location-table class) (compute-slot-location-table class))
  1975. (let ((shared-size (compute-shared-size class)))
  1976. (when (plusp shared-size)
  1977. (setf (cv-shared-slots (class-current-version class))
  1978. (create-shared-slots-vector class shared-size old-slot-location-table))))
  1979. ;; CLtL2 28.1.3.3., ANSI CL 4.3.4.2. Inheritance of Class Options
  1980. (setf (class-default-initargs class) (checked-compute-default-initargs class))
  1981. (setf (class-valid-initargs-from-slots class)
  1982. (remove-duplicates (mapcap #'slot-definition-initargs (class-slots class))))
  1983. (when (< (class-initialized class) 6)
  1984. (setf (class-initialized class) 6))
  1985. (system::note-new-standard-class))
  1986. ;; ------------- Redefining an instance of <semi-standard-class> -------------
  1987. ;; Preliminary definition.
  1988. (predefun make-instances-obsolete (class)
  1989. (make-instances-obsolete-<semi-standard-class> class))
  1990. (defun make-instances-obsolete-<semi-standard-class> (class)
  1991. (when (>= (class-initialized class) 6) ; nothing to do if not yet finalized
  1992. ;; Recurse to the subclasses. (Even if there are no direct instances of
  1993. ;; this class: the subclasses may have instances.)
  1994. (mapc #'make-instances-obsolete-<semi-standard-class>-nonrecursive
  1995. (list-all-finalized-subclasses class))))
  1996. (defun make-instances-obsolete-<semi-standard-class>-nonrecursive (class)
  1997. (if (and (>= (class-initialized class) 4) ; already finalized?
  1998. (subclassp class <metaobject>))
  1999. ; Don't obsolete metaobject instances.
  2000. (let ((name (class-name class))
  2001. (caller *make-instances-obsolete-caller*)
  2002. ;; Rebind *make-instances-obsolete-caller* because WARN may enter a
  2003. ;; nested REP-loop.
  2004. (*make-instances-obsolete-caller* 'make-instances-obsolete))
  2005. (clos-warning (TEXT "~S: Class ~S (or one of its ancestors) is being redefined, but its instances cannot be made obsolete")
  2006. caller name))
  2007. (progn
  2008. (when (class-instantiated class) ; don't warn if there are no instances
  2009. (let ((name (class-name class))
  2010. (caller *make-instances-obsolete-caller*)
  2011. ;; Rebind *make-instances-obsolete-caller* because WARN may enter a
  2012. ;; nested REP-loop.
  2013. (*make-instances-obsolete-caller* 'make-instances-obsolete))
  2014. (if (eq caller 'defclass)
  2015. (clos-warning (TEXT "~S: Class ~S (or one of its ancestors) is being redefined, instances are obsolete")
  2016. caller name)
  2017. (clos-warning (TEXT "~S: instances of class ~S are made obsolete")
  2018. caller name))))
  2019. ;; Create a new class-version. (Even if there are no instances: the
  2020. ;; shared-slots may need change.)
  2021. (let* ((copy (copy-standard-class class))
  2022. (old-version (class-current-version copy))
  2023. (new-version
  2024. (make-class-version :newest-class class
  2025. :class class
  2026. :serial (1+ (cv-serial old-version)))))
  2027. (setf (cv-class old-version) copy)
  2028. (setf (cv-next old-version) new-version)
  2029. (setf (class-current-version class) new-version)))))
  2030. ;; After a class redefinition, finalize the subclasses so that the instances
  2031. ;; can be updated.
  2032. (defun update-subclasses-for-redefined-class (class was-finalized must-be-finalized old-direct-superclasses)
  2033. (when was-finalized ; nothing to do if not finalized before the redefinition
  2034. ;; Handle the class itself specially, because its superclasses list now is
  2035. ;; not the same as before.
  2036. (setf (class-initialized class) 2) ; mark as not yet finalized
  2037. (setf (class-precedence-list class) nil) ; mark as not yet finalized
  2038. (setf (class-all-superclasses class) nil) ; mark as not yet finalized
  2039. (if must-be-finalized
  2040. ;; The class remains finalized.
  2041. (progn
  2042. (finalize-inheritance class)
  2043. (let ((new-direct-superclasses (class-direct-superclasses class)))
  2044. (unless (equal old-direct-superclasses new-direct-superclasses)
  2045. (let ((removed-direct-superclasses
  2046. (set-difference old-direct-superclasses new-direct-superclasses))
  2047. (added-direct-superclasses
  2048. (set-difference new-direct-superclasses old-direct-superclasses)))
  2049. (dolist (super removed-direct-superclasses)
  2050. (when (semi-standard-class-p super)
  2051. (remove-finalized-direct-subclass super class)))
  2052. (dolist (super added-direct-superclasses)
  2053. (when (semi-standard-class-p super)
  2054. (add-finalized-direct-subclass super class)))))))
  2055. ;; The class becomes unfinalized.
  2056. (dolist (super old-direct-superclasses)
  2057. (when (semi-standard-class-p super)
  2058. (remove-finalized-direct-subclass super class))))
  2059. ;; Now handle the true subclasses.
  2060. (mapc #'update-subclasses-for-redefined-class-nonrecursive
  2061. (rest (list-all-finalized-subclasses class)))))
  2062. (defun update-subclasses-for-redefined-class-nonrecursive (class)
  2063. (when (>= (class-initialized class) 6) ; nothing to do if not yet finalized
  2064. (setf (class-initialized class) 2) ; mark as not yet finalized
  2065. (setf (class-precedence-list class) nil) ; mark as not yet finalized
  2066. (setf (class-all-superclasses class) nil) ; mark as not yet finalized
  2067. (if (class-instantiated class)
  2068. ;; The class remains finalized.
  2069. (finalize-inheritance class)
  2070. ;; The class becomes unfinalized. If it has an instantiated subclass, the
  2071. ;; subclass' finalize-inheritance invocation will re-finalize this one.
  2072. (dolist (super (class-direct-superclasses class))
  2073. (when (semi-standard-class-p super)
  2074. (remove-finalized-direct-subclass super class))))))
  2075. ;; After a class redefinition that changed the class-precedence-list,
  2076. ;; update the generic functions that use specializers whose object is a
  2077. ;; direct instance of this class or of a subclass.
  2078. (defun update-subclass-instance-specializer-generic-functions (class)
  2079. (dolist (subclass (list-all-finalized-subclasses class))
  2080. ;; Since the CPL of the class has changed, the CPL of the subclass has
  2081. ;; most likely changed as well. It is not worth testing whether it has
  2082. ;; really changed.
  2083. (dolist (specializer (list-direct-instance-specializers subclass))
  2084. ;; specializer's location in the type hierarchy has now changed.
  2085. (dolist (gf (specializer-direct-generic-functions specializer))
  2086. (when (typep-class gf <standard-generic-function>)
  2087. ;; Clear the discriminating function.
  2088. ;; The effective method cache does not need to be invalidated.
  2089. #|(setf (std-gf-effective-method-cache gf) '())|#
  2090. (finalize-fast-gf gf))))))
  2091. ;; After a class redefinition that changed the class-precedence-list,
  2092. ;; update the generic functions that could be affected.
  2093. (defun update-subclass-cpl-specializer-generic-functions (class old-cpl new-cpl)
  2094. ;; Class definitions change the type hierarchy, therefore the discriminating
  2095. ;; function of some generic functions has to be invalidated and recomputed
  2096. ;; later.
  2097. ;; The effective method cache does not need to be invalidated, since it takes
  2098. ;; a sorted method list as input and compute-effective-method-as-function
  2099. ;; doesn't do computations in the type hierarchy.
  2100. ;;
  2101. ;; Now, which generic functions are affected? The discriminating function of
  2102. ;; a generic depends on the following. (x denotes an object occurring as
  2103. ;; argument, and x-class means (class-of x).)
  2104. ;; 1. The computation of the applicable method list for given arguments x
  2105. ;; depends on
  2106. ;; (subclassp x-class specializer)
  2107. ;; for all specializers occurring in methods of the GF.
  2108. ;; 2. The discriminating function is also free to exploit the result of
  2109. ;; (subclassp specializer1 specializer2)
  2110. ;; for any two specializer1, specializer2 occurring in methods of the GF.
  2111. ;; 3. The sorting of the applicable method list for given arguments x
  2112. ;; depends on the relative order of specializer1 and specializer2 in
  2113. ;; (cpl x-class), for any two specializer1, specializer2 occurring in
  2114. ;; methods of the GF.
  2115. ;;
  2116. ;; What effects can a change of (cpl class) = old-cpl -> new-cpl have?
  2117. ;; Assume that some classes S+ are added, some classes S- are removed from
  2118. ;; the CPL, and some classes S* are reordered in the CPL. What effects does
  2119. ;; this have on (cpl o-class), where o-class is any other class?
  2120. ;; - If o-class is not a subclass of class, (cpl o-class) doesn't change.
  2121. ;; - If o-class if subclass of class,
  2122. ;; the elements of S+ are added or, if already present, possibly
  2123. ;; reordered,
  2124. ;; the elements of S- are possibly removed or reordered,
  2125. ;; the elements of S* are possibly reordered.
  2126. ;; ("Possibly" because o-class can also inherit from other classes that
  2127. ;; are not under the given class but under elements of S+, S-, S*.)
  2128. ;;
  2129. ;; Now back to the problem of finding the affected generic functions.
  2130. ;; 1. (subclassp x-class specializer) == (member specializer (cpl x-class))
  2131. ;; - doesn't change if x-class is not a subclass of class,
  2132. ;; - doesn't change if specializer is not an element of S+ or S-.
  2133. ;; Because of the implicit "for all x", we cannot exploit the first
  2134. ;; statement. But the second statement tells us that we have to go
  2135. ;; from the elements of S+ and S- to the methods and generic functions
  2136. ;; using these classes as specializers.
  2137. ;; 2. (subclassp specializer1 specializer2)
  2138. ;; == (member specializer2 (cpl specializer1))
  2139. ;; - doesn't change if specializer1 is not a subclass of class,
  2140. ;; - doesn't change if specializer2 is not an element of S+ or S-.
  2141. ;; So we have to intersect
  2142. ;; - the set of GFs using a subclass of class as specializer,
  2143. ;; - the set of GFs using an element of S+ or S- as specializer.
  2144. ;; This is a subset of the one we got in point 1. It is redundant.
  2145. ;; 3. We know that if
  2146. ;; old (cpl x-class) = (... specializer1 ... specializer2 ...)
  2147. ;; and new (cpl x-class) = (... specializer2 ... specializer1 ...)
  2148. ;; then x-class is a subclass of the given class, and one of
  2149. ;; specializer1, specializer2 (at least) is a member of S+, S- or S*.
  2150. ;; Because of the implicit "for all x", the first condition is hard to
  2151. ;; exploit: we need to recurse through all x-class that are subclasses
  2152. ;; the given class. It is easier to exploit the second condition:
  2153. ;; Go from the elements of S+, S-, S* to the methods and generic functions
  2154. ;; using these classes as specializers.
  2155. ;;
  2156. ;; Cf. MOP p. 41 compute-discriminating-function item (iv). This says that
  2157. ;; all generic functions which use a specializer whose class precedence list
  2158. ;; has changed (i.e. essentially a specializer which is a subclass of the
  2159. ;; given class) should invalidate their discriminating function. This is not
  2160. ;; needed!
  2161. ;;
  2162. ;; Cf. MOP p. 41 compute-discriminating-function item (v). This says that
  2163. ;; all generic functions which have a cache entry containing a class whose
  2164. ;; class precedence list has changed (i.e. essentially a subclass of the
  2165. ;; given class) should invalidate their discriminating function. This is
  2166. ;; also far more than is needed; all that's needed is 1. and 3.
  2167. ;;
  2168. (declare (ignore class))
  2169. (let* ((added-superclasses (set-difference new-cpl old-cpl))
  2170. (removed-superclasses (set-difference old-cpl new-cpl))
  2171. (permuted-superclasses
  2172. (let ((common-superclasses-in-old-order
  2173. (remove-if #'(lambda (x) (memq x removed-superclasses))
  2174. (the list old-cpl)))
  2175. (common-superclasses-in-new-order
  2176. (remove-if #'(lambda (x) (memq x added-superclasses))
  2177. (the list new-cpl))))
  2178. (assert (= (length common-superclasses-in-old-order)
  2179. (length common-superclasses-in-new-order)))
  2180. (subseq common-superclasses-in-old-order
  2181. 0
  2182. (or (mismatch common-superclasses-in-old-order
  2183. common-superclasses-in-new-order
  2184. :test #'eq
  2185. :from-end t)
  2186. 0)))))
  2187. ;; Build the set of affected generic functions.
  2188. (let ((gf-set
  2189. (make-hash-table :key-type 'generic-function :value-type '(eql t)
  2190. :test 'ext:fasthash-eq)))
  2191. (dolist (specializer (append added-superclasses removed-superclasses
  2192. permuted-superclasses))
  2193. (dolist (gf (specializer-direct-generic-functions specializer))
  2194. (setf (gethash gf gf-set) t)))
  2195. #|
  2196. (format *debug-io* "~&added = ~:S, removed = ~:S, permuted = ~:S, affected = ~:S~%"
  2197. added-superclasses removed-superclasses permuted-superclasses
  2198. (let ((l '()))
  2199. (maphash #'(lambda (gf ignored)
  2200. (declare (ignore ignored))
  2201. (push gf l))
  2202. gf-set)
  2203. l))
  2204. |#
  2205. ;; Clear their discriminating function.
  2206. (maphash #'(lambda (gf ignored)
  2207. (declare (ignore ignored))
  2208. (when (typep-class gf <standard-generic-function>)
  2209. (finalize-fast-gf gf)))
  2210. gf-set))))
  2211. ;; Store the information needed by the update of obsolete instances in a
  2212. ;; class-version object. Invoked when an instance needs to be updated.
  2213. (defun class-version-compute-slotlists (old-version)
  2214. (let ((old-class (cv-class old-version))
  2215. (new-class (cv-class (cv-next old-version)))
  2216. ; old-class is already finalized - otherwise no instance could exist.
  2217. ; new-class is already finalized, because ensure-class guarantees it.
  2218. (kept2 '())
  2219. (added '())
  2220. (discarded '())
  2221. (discarded2 '()))
  2222. (dolist (old-slot (class-slots old-class))
  2223. (let* ((name (slot-definition-name old-slot))
  2224. (new-slot (find name (class-slots new-class)
  2225. :test #'eq :key #'slot-definition-name)))
  2226. (if (and new-slot (atom (slot-definition-location new-slot)))
  2227. ;; Local slot remains local, or shared slot becomes local.
  2228. (setq kept2 (list* (slot-definition-location old-slot)
  2229. (slot-definition-location new-slot)
  2230. kept2))
  2231. (if (atom (slot-definition-location old-slot))
  2232. ;; Local slot is discarded or becomes shared.
  2233. (setq discarded (cons name discarded)
  2234. discarded2 (list* name (slot-definition-location old-slot) discarded2))))))
  2235. (dolist (new-slot (class-slots new-class))
  2236. (let* ((name (slot-definition-name new-slot))
  2237. (old-slot (find name (class-slots old-class)
  2238. :test #'eq :key #'slot-definition-name)))
  2239. (unless old-slot
  2240. ;; Newly added local slot.
  2241. (setq added (cons name added)))))
  2242. (setf (cv-kept-slot-locations old-version) kept2)
  2243. (setf (cv-added-slots old-version) added)
  2244. (setf (cv-discarded-slots old-version) discarded)
  2245. (setf (cv-discarded-slot-locations old-version) discarded2)
  2246. (setf (cv-slotlists-valid-p old-version) t)))
  2247. ;; -------------- Auxiliary functions for <semi-standard-class> --------------
  2248. ;;; Maintaining the list of eql-specializers of direct instances that are or
  2249. ;;; were used in a method. (We need this for notifying the generic functions
  2250. ;;; to which these methods belong, when the class or a superclass of it is
  2251. ;;; redefined in a way that changes the class-precedence-list.)
  2252. #|
  2253. ;; Adds a class to the list of direct instance specializers.
  2254. (defun add-direct-instance-specializer (class eql-specializer) ...)
  2255. ;; Removes a class from the list of direct instance specializers.
  2256. (defun remove-direct-instance-specializer (class eql-specializer) ...)
  2257. ;; Returns the currently existing direct instance specializers, as a freshly
  2258. ;; consed list.
  2259. (defun list-direct-instance-specializers (class) ...)
  2260. |#
  2261. (def-weak-set-accessors class-direct-instance-specializers-table eql-specializer
  2262. add-direct-instance-specializer
  2263. remove-direct-instance-specializer
  2264. list-direct-instance-specializers)
  2265. ;;; Maintaining the weak references to the finalized direct subclasses.
  2266. ;;; (We need only the finalized subclasses, because:
  2267. ;;; - The only use of these references is for make-instances-obsolete and for
  2268. ;;; update-subclasses-for-redefined-class.
  2269. ;;; - A non-finalized class cannot have instances.
  2270. ;;; - Without an instance one cannot even access the shared slots.)
  2271. ;;; The finalized-direct-subclasses slot can be either
  2272. ;;; - NIL or a weak-list (for saving memory when there are few subclasses), or
  2273. ;;; - a weak-hash-table (for speed when there are many subclasses).
  2274. #|
  2275. ;; Adds a class to the list of direct subclasses.
  2276. (defun add-finalized-direct-subclass (class subclass) ...)
  2277. ;; Removes a class from the list of direct subclasses.
  2278. (defun remove-finalized-direct-subclass (class subclass) ...)
  2279. ;; Returns the currently existing direct subclasses, as a freshly consed list.
  2280. (defun list-finalized-direct-subclasses (class) ...)
  2281. |#
  2282. (def-weak-set-accessors class-finalized-direct-subclasses-table class
  2283. add-finalized-direct-subclass
  2284. remove-finalized-direct-subclass
  2285. list-finalized-direct-subclasses)
  2286. ;; Returns the currently existing finalized subclasses, in top-down order,
  2287. ;; including the class itself as first element.
  2288. (defun list-all-finalized-subclasses (class)
  2289. ; Use a breadth-first search which removes duplicates.
  2290. (let ((as-list '())
  2291. (as-set (make-hash-table :key-type 'defined-class :value-type '(eql t)
  2292. :test 'ext:stablehash-eq :warn-if-needs-rehash-after-gc t
  2293. :rehash-size 2s0))
  2294. (pending (list class)))
  2295. (loop
  2296. (unless pending (return))
  2297. (let ((new-pending '()))
  2298. (dolist (class pending)
  2299. (unless (gethash class as-set)
  2300. (push class as-list)
  2301. (setf (gethash class as-set) t)
  2302. (setq new-pending
  2303. (nreconc (if (semi-standard-class-p class)
  2304. ; <semi-standard-class> stores the finalized direct-subclasses.
  2305. (list-finalized-direct-subclasses class)
  2306. ; <defined-class> stores only the complete direct-subclasses list.
  2307. (remove-if-not #'(lambda (c) (= (class-initialized c) 6))
  2308. (checked-class-direct-subclasses class)))
  2309. new-pending))))
  2310. (setq pending (nreverse new-pending))))
  2311. ;; Now reorder the list so that superclasses come before, not after, a
  2312. ;; class. This is needed by update-subclasses-for-redefined-class. (It's
  2313. ;; a "topological sorting" algorithm w.r.t. to the superclass relation.)
  2314. (let ((tsorted-list '()))
  2315. (labels ((add-with-superclasses-first (cls)
  2316. (when (gethash cls as-set)
  2317. (remhash cls as-set)
  2318. (dolist (supercls (class-direct-superclasses cls))
  2319. (add-with-superclasses-first supercls))
  2320. (push cls tsorted-list))))
  2321. (mapc #'add-with-superclasses-first as-list))
  2322. (setq tsorted-list (nreverse tsorted-list))
  2323. (assert (eq (first tsorted-list) class))
  2324. tsorted-list)))
  2325. ;; --------------- Creation of an instance of <standard-class> ---------------
  2326. (defun make-instance-<standard-class> (metaclass &rest args
  2327. &key name
  2328. (direct-superclasses '())
  2329. (direct-slots '())
  2330. (direct-default-initargs '())
  2331. &allow-other-keys)
  2332. ;; metaclass = <standard-class>
  2333. ;; Don't add functionality here! This is a preliminary definition that is
  2334. ;; replaced with #'make-instance later.
  2335. (declare (ignore metaclass name direct-superclasses direct-slots
  2336. direct-default-initargs))
  2337. (let ((class (allocate-metaobject-instance *<standard-class>-class-version*
  2338. *<standard-class>-instance-size*)))
  2339. (apply #'initialize-instance-<standard-class> class args)))
  2340. (defun initialize-instance-<standard-class> (class &rest args
  2341. &key &allow-other-keys)
  2342. ;; Don't add functionality here! This is a preliminary definition that is
  2343. ;; replaced with #'initialize-instance later.
  2344. (apply #'shared-initialize-<standard-class> class 't args)
  2345. (install-class-direct-accessors class)
  2346. class)
  2347. (defun shared-initialize-<standard-class> (class situation &rest args
  2348. &key (direct-superclasses '() direct-superclasses-p)
  2349. ((:direct-slots direct-slots-as-lists) '() direct-slots-as-lists-p)
  2350. ((direct-slots direct-slots-as-metaobjects) '() direct-slots-as-metaobjects-p)
  2351. (direct-default-initargs '() direct-default-initargs-p)
  2352. (documentation nil documentation-p)
  2353. (generic-accessors t generic-accessors-p)
  2354. (fixed-slot-locations nil fixed-slot-locations-p)
  2355. &allow-other-keys)
  2356. (declare (ignore direct-superclasses direct-superclasses-p
  2357. direct-slots-as-lists direct-slots-as-lists-p
  2358. direct-slots-as-metaobjects direct-slots-as-metaobjects-p
  2359. direct-default-initargs direct-default-initargs-p
  2360. documentation documentation-p generic-accessors
  2361. generic-accessors-p fixed-slot-locations
  2362. fixed-slot-locations-p))
  2363. (apply #'shared-initialize-<semi-standard-class> class situation args)
  2364. class)
  2365. ;; ---------------------------------------------------------------------------
  2366. ;; Bootstrapping
  2367. (progn
  2368. (setq <function> nil)
  2369. ;; 1. Define the class <t>.
  2370. (setq <t>
  2371. (make-instance-<built-in-class> nil
  2372. :name 't
  2373. :direct-superclasses '()
  2374. 'prototype (byte 1 0)))
  2375. (setf (find-class 't) <t>)
  2376. ;; 2. Define the class <standard-object>.
  2377. (setq <standard-object>
  2378. (let ((*allow-mixing-metaclasses* t))
  2379. (make-instance-<standard-class> nil
  2380. :name 'standard-object
  2381. :direct-superclasses `(,<t>)
  2382. :direct-slots '()
  2383. :slots '()
  2384. :slot-location-table empty-ht
  2385. :instance-size 1
  2386. :direct-default-initargs '()
  2387. :default-initargs '())))
  2388. (setf (find-class 'standard-object) <standard-object>)
  2389. ;; 3. Define the class <metaobject>.
  2390. (setq <metaobject>
  2391. (macrolet ((form () *<metaobject>-defclass*))
  2392. (form)))
  2393. ;; 4. Define the class <standard-stablehash>.
  2394. (macrolet ((form () *<standard-stablehash>-defclass*))
  2395. (form))
  2396. ;; 5. Define the class <specializer>.
  2397. (macrolet ((form () *<specializer>-defclass*))
  2398. (form))
  2399. ;; 6. Define the classes <super-class>, <potential-class>.
  2400. (macrolet ((form () *<super-class>-defclass*))
  2401. (form))
  2402. (setq <potential-class>
  2403. (macrolet ((form () *<potential-class>-defclass*))
  2404. (form)))
  2405. ;; 7. Define the class <defined-class>.
  2406. (setq <defined-class>
  2407. (macrolet ((form () *<defined-class>-defclass*))
  2408. (form)))
  2409. ;; 8. Define the class <built-in-class>.
  2410. (setq <built-in-class>
  2411. (macrolet ((form () *<built-in-class>-defclass*))
  2412. (form)))
  2413. (replace-class-version <built-in-class>
  2414. *<built-in-class>-class-version*)
  2415. ;; 9. Define the classes <slotted-class>, <semi-standard-class>,
  2416. ;; <standard-class>, <structure-class>.
  2417. (macrolet ((form () *<slotted-class>-defclass*))
  2418. (form))
  2419. (setq <semi-standard-class>
  2420. (macrolet ((form () *<semi-standard-class>-defclass*))
  2421. (form)))
  2422. (setq <standard-class>
  2423. (macrolet ((form () *<standard-class>-defclass*))
  2424. (form)))
  2425. (replace-class-version <standard-class>
  2426. *<standard-class>-class-version*)
  2427. (setq <structure-class>
  2428. (macrolet ((form () *<structure-class>-defclass*))
  2429. (form)))
  2430. (replace-class-version <structure-class>
  2431. *<structure-class>-class-version*)
  2432. ;; 10. Define the class <structure-object>.
  2433. (setq <structure-object>
  2434. (let ((*allow-mixing-metaclasses* t))
  2435. (make-instance-<structure-class> <structure-class>
  2436. :name 'structure-object
  2437. :direct-superclasses `(,<t>)
  2438. :direct-slots '()
  2439. :direct-default-initargs '()
  2440. 'names (list 'structure-object))))
  2441. (setf (find-class 'structure-object) <structure-object>)
  2442. ;; 11. Define other classes whose definition was delayed.
  2443. ;; Define the class <slot-definition>.
  2444. (macrolet ((form () *<slot-definition>-defclass*))
  2445. (form))
  2446. ;; Define the class <direct-slot-definition>.
  2447. (setq <direct-slot-definition>
  2448. (macrolet ((form () *<direct-slot-definition>-defclass*))
  2449. (form)))
  2450. ;; Define the class <effective-slot-definition>.
  2451. (setq <effective-slot-definition>
  2452. (macrolet ((form () *<effective-slot-definition>-defclass*))
  2453. (form)))
  2454. ;; Define the class <standard-slot-definition>.
  2455. (macrolet ((form () *<standard-slot-definition>-defclass*))
  2456. (form))
  2457. ;; Define the class <standard-direct-slot-definition>.
  2458. (setq <standard-direct-slot-definition>
  2459. (macrolet ((form () *<standard-direct-slot-definition>-defclass*))
  2460. (form)))
  2461. (replace-class-version (find-class 'standard-direct-slot-definition)
  2462. *<standard-direct-slot-definition>-class-version*)
  2463. ;; Define the class <standard-effective-slot-definition>.
  2464. (setq <standard-effective-slot-definition>
  2465. (macrolet ((form () *<standard-effective-slot-definition>-defclass*))
  2466. (form)))
  2467. (replace-class-version (find-class 'standard-effective-slot-definition)
  2468. *<standard-effective-slot-definition>-class-version*)
  2469. ;; Define the class <structure-direct-slot-definition>.
  2470. (setq <structure-direct-slot-definition>
  2471. (macrolet ((form () *<structure-direct-slot-definition>-defclass*))
  2472. (form)))
  2473. (replace-class-version (find-class 'structure-direct-slot-definition)
  2474. *<structure-direct-slot-definition>-class-version*)
  2475. ;; Define the class <structure-effective-slot-definition>.
  2476. (setq <structure-effective-slot-definition>
  2477. (macrolet ((form () *<structure-effective-slot-definition>-defclass*))
  2478. (form)))
  2479. (replace-class-version (find-class 'structure-effective-slot-definition)
  2480. *<structure-effective-slot-definition>-class-version*)
  2481. ;; Define the class <eql-specializer>.
  2482. (setq <eql-specializer>
  2483. (macrolet ((form () *<eql-specializer>-defclass*))
  2484. (form)))
  2485. (replace-class-version (find-class 'eql-specializer)
  2486. *<eql-specializer>-class-version*)
  2487. ;; Define the classes <forward-reference-to-class>,
  2488. ;; <misdesigned-forward-referenced-class>.
  2489. (setq <forward-reference-to-class>
  2490. (macrolet ((form () *<forward-reference-to-class>-defclass*))
  2491. (form)))
  2492. (setq <misdesigned-forward-referenced-class>
  2493. (macrolet ((form () *<misdesigned-forward-referenced-class>-defclass*))
  2494. (form)))
  2495. );progn
  2496. ;;; Install built-in classes:
  2497. ;; See CLtL2 p. 783 table 28-1, ANSI CL 4.3.7.
  2498. (macrolet ((def (&rest classes)
  2499. (setq classes (reverse classes))
  2500. (let* ((prototype-form (pop classes))
  2501. (new (pop classes))
  2502. (name (intern (string-trim "<>" (symbol-name new)))))
  2503. `(setf (find-class ',name)
  2504. (setq ,new
  2505. (make-instance-<built-in-class> <built-in-class>
  2506. :name ',name
  2507. :direct-superclasses (list ,@classes)
  2508. ,@(unless (eq prototype-form '-+-ABSTRACT-+-)
  2509. `('prototype ,prototype-form))))))))
  2510. ;(def <t> (byte 1 0))
  2511. (def <t> <character> #\Space)
  2512. (def <t> <function> #'cons)
  2513. (def <t> <hash-table> empty-ht)
  2514. (def <t> <package> (find-package "KEYWORD"))
  2515. (def <t> <pathname> (make-pathname))
  2516. #+LOGICAL-PATHNAMES
  2517. (def <pathname> <logical-pathname> (logical-pathname ":"))
  2518. (def <t> <random-state> *random-state*)
  2519. (def <t> <readtable> *readtable*)
  2520. (def <t> <stream> -+-ABSTRACT-+-)
  2521. (def <stream> <file-stream> (open *load-pathname* :direction :probe))
  2522. (def <stream> <synonym-stream> (make-synonym-stream '*terminal-io*))
  2523. (def <stream> <broadcast-stream> (make-broadcast-stream))
  2524. (def <stream> <concatenated-stream> (make-concatenated-stream))
  2525. (def <stream> <two-way-stream> (make-two-way-stream (make-concatenated-stream) (make-broadcast-stream)))
  2526. (def <stream> <echo-stream> (make-echo-stream (make-concatenated-stream) (make-broadcast-stream)))
  2527. (def <stream> <string-stream> (make-string-output-stream))
  2528. (def <t> <symbol> 't)
  2529. (def <t> <sequence> -+-ABSTRACT-+-)
  2530. (def <sequence> <list> -+-ABSTRACT-+-)
  2531. (def <list> <cons> '(t))
  2532. (def <list> <symbol> <null> 'nil)
  2533. (def <t> <array> '#2A())
  2534. (def <sequence> <array> <vector> '#())
  2535. (def <vector> <bit-vector> '#*)
  2536. (def <vector> <string> "")
  2537. (def <t> <number> -+-ABSTRACT-+-)
  2538. (def <number> <complex> #c(3 4))
  2539. (def <number> <real> -+-ABSTRACT-+-)
  2540. (def <real> <float> 1.0s0)
  2541. (def <real> <rational> -+-ABSTRACT-+-)
  2542. (def <rational> <ratio> 1/2)
  2543. (def <rational> <integer> 0)
  2544. )
  2545. ;; Continue bootstrapping.
  2546. (%defclos
  2547. ;; distinctive marks for CLASS-P
  2548. *<standard-class>-class-version*
  2549. *<structure-class>-class-version*
  2550. *<built-in-class>-class-version*
  2551. <defined-class>
  2552. <potential-class>
  2553. ;; built-in-classes for CLASS-OF
  2554. (vector <array> <bit-vector> <character> <complex> <cons> <float> <function>
  2555. <hash-table> <integer> <list> <null> <package> <pathname>
  2556. #+LOGICAL-PATHNAMES <logical-pathname>
  2557. <random-state> <ratio> <readtable>
  2558. <stream> <file-stream> <synonym-stream> <broadcast-stream>
  2559. <concatenated-stream> <two-way-stream> <echo-stream> <string-stream>
  2560. <string> <symbol> <t> <vector>))
  2561. ;;; Intersection of two built-in-classes:
  2562. ;; Deviations from the single-inheritance are only
  2563. ;; (AND <sequence> <array>) = <vector> and (AND <list> <symbol>) = <null>.
  2564. (defun bc-p (class)
  2565. (or (built-in-class-p class)
  2566. (eq class <standard-object>)
  2567. (eq class <structure-object>)))
  2568. (defun bc-and (class1 class2) ; returns (AND class1 class2)
  2569. (cond ((subclassp class1 class2) class1)
  2570. ((subclassp class2 class1) class2)
  2571. ((or (and (subclassp <sequence> class1) (subclassp <array> class2))
  2572. (and (subclassp <sequence> class2) (subclassp <array> class1)))
  2573. <vector>)
  2574. ((or (and (subclassp <list> class1) (subclassp <symbol> class2))
  2575. (and (subclassp <list> class2) (subclassp <symbol> class1)))
  2576. <null>)
  2577. (t nil)))
  2578. (defun bc-and-not (class1 class2) ; returns a class c with
  2579. ; (AND class1 (NOT class2)) <= c <= class1
  2580. (cond ((subclassp class1 class2) nil)
  2581. ((and (eq class1 <sequence>) (subclassp <vector> class2)) <list>)
  2582. ((and (eq class1 <sequence>) (subclassp <list> class2)) <vector>)
  2583. ((and (eq class1 <list>) (subclassp <null> class2)) <cons>)
  2584. (t class1)))