ecl/src/clos/boot.lsp
Daniel Kochmański f1bc883ed6 clos: introduce class stamps for marking instances obsolete
We should call make-instances-obsolete from finalize-inheritance if we
want to be conforming, because user may have added their own auxiliary
methods.

This change while being last in a serie of commits was locally the
first change which solved problems. It will enable us to implement the
fast generic dispatch after the release.
2020-04-19 17:04:41 +02:00

135 lines
5.9 KiB
Common Lisp

;;;; -*- Mode: Lisp; Syntax: Common-Lisp; indent-tabs-mode: nil; Package: CLOS -*-
;;;; vim: set filetype=lisp tabstop=8 shiftwidth=2 expandtab:
;;;;
;;;; Copyright (c) 1992, Giuseppe Attardi.o
;;;; Copyright (c) 2001, Juan Jose Garcia Ripoll.
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Library General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 2 of the License, or (at your option) any later version.
;;;;
;;;; See file '../Copyright' for full details.
(in-package "CLOS")
(defconstant +builtin-classes-pre-array+
(make-array (1+ #.(length +builtin-classes-list+))))
;;; ----------------------------------------------------------------------
;;; Building the classes T, CLASS, STANDARD-OBJECT and STANDARD-CLASS.
;;;
;;; We cannot use the functions CREATE-STANDARD-CLASS and others because SLOTS,
;;; DIRECT-SLOTS, etc are empty and therefore SLOT-VALUE does not work.
(defun make-empty-standard-class (name &key (metaclass 'standard-class)
direct-superclasses direct-slots index)
(declare (optimize speed (safety 0)))
(let* ((the-metaclass (and metaclass (gethash metaclass si::*class-name-hash-table*)))
(class (or (gethash name si::*class-name-hash-table*)
(si:allocate-raw-instance nil the-metaclass
#.(length +standard-class-slots+)))))
(with-early-accessors (+standard-class-slots+)
(when (eq name 'standard-class)
(defconstant +the-standard-class+ class)
(si:instance-class-set class class))
(setf (class-id class) name
(class-direct-subclasses class) nil
(class-direct-default-initargs class) nil
(class-default-initargs class) nil
(class-finalized-p class) t
(eql-specializer-flag class) nil
(specializer-method-holder class) (cons nil nil)
(gethash name si::*class-name-hash-table*) class
(class-sealedp class) nil
(class-dependents class) nil
(class-valid-initargs class) nil
)
(add-slots class direct-slots)
(let ((superclasses (loop for name in direct-superclasses
for parent = (find-class name)
do (push class (class-direct-subclasses parent))
collect parent)))
(setf (class-direct-superclasses class) superclasses
(class-precedence-list class)
(compute-clos-class-precedence-list class superclasses)))
(when index
(setf (aref +builtin-classes-pre-array+ index) class))
(si:instance-new-stamp class)
class)))
(defun remove-accessors (slotds)
(declare (optimize speed (safety 0)))
(loop for i in slotds
for j = (copy-list i)
do (remf (cdr j) :accessor)
collect j))
(defun add-slots (class slots)
(declare (si::c-local)
(optimize speed (safety 0)))
;; It does not matter that we pass NIL instead of a class object,
;; because CANONICAL-SLOT-TO-DIRECT-SLOT will make simple slots.
(with-early-accessors (+standard-class-slots+
+slot-definition-slots+)
(let* ((table (make-hash-table :size (if slots 24 0)))
(location-table (make-hash-table :size (if slots 24 0)))
(slots (parse-slots slots))
(direct-slots (loop for slotd in slots
collect (apply #'make-simple-slotd
(find-class 'standard-direct-slot-definition)
slotd)))
(effective-slots (loop for i from 0
for slotd in slots
for name = (getf slotd :name)
for s = (apply #'make-simple-slotd
(find-class 'standard-effective-slot-definition)
slotd)
do (setf (slot-definition-location s) i
(gethash name location-table) i
(gethash name table) s)
collect s)))
(setf (class-slots class) effective-slots
(class-direct-slots class) direct-slots
(class-size class) (length slots)
(slot-table class) table
(class-location-table class) location-table))))
;; 1) Create the classes
;;
;; Notice that, due to circularity in the definition, STANDARD-CLASS has
;; itself as metaclass. MAKE-EMPTY-STANDARD-CLASS takes care of that.
;;
(let* ((class-hierarchy '#.+class-hierarchy+))
(let ((all-classes (loop for c in class-hierarchy
for class = (apply #'make-empty-standard-class c)
collect class)))
(defconstant +the-t-class+ (find-class 't nil))
(defconstant +the-class+ (find-class 'class nil))
(defconstant +the-std-class+ (find-class 'std-class nil))
(defconstant +the-funcallable-standard-class+
(find-class 'funcallable-standard-class nil))
;;
;; 2) Class T had its metaclass wrong. Fix it.
;;
(si:instance-class-set (find-class 't) (find-class 'built-in-class))
;;
;; 3) Finalize
;;
(mapc #'si::instance-sig-set all-classes)
;;
;; 4) This is needed for further optimization
;;
(setf (slot-value (find-class 'method-combination) 'sealedp) t)
;;
;; 5) This is needed so that slot-definition objects are not marked
;; obsolete and need to be updated
;;
(with-early-accessors (+standard-class-slots+)
(loop for c in all-classes
do (loop for s in (class-direct-slots c)
do (si::instance-sig-set s))
do (loop for s in (class-slots c)
do (si::instance-sig-set s))))
))