~ubuntu-branches/ubuntu/intrepid/ecl/intrepid

« back to all changes in this revision

Viewing changes to src/clos/boot.lsp

  • Committer: Bazaar Package Importer
  • Author(s): Peter Van Eynde
  • Date: 2006-05-17 02:46:26 UTC
  • Revision ID: james.westby@ubuntu.com-20060517024626-lljr08ftv9g9vefl
Tags: upstream-0.9h-20060510
ImportĀ upstreamĀ versionĀ 0.9h-20060510

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;;;  Copyright (c) 1992, Giuseppe Attardi.
 
2
;;;;
 
3
;;;;    This program is free software; you can redistribute it and/or
 
4
;;;;    modify it under the terms of the GNU Library General Public
 
5
;;;;    License as published by the Free Software Foundation; either
 
6
;;;;    version 2 of the License, or (at your option) any later version.
 
7
;;;;
 
8
;;;;    See file '../Copyright' for full details.
 
9
 
 
10
(in-package "CLOS")
 
11
 
 
12
;;; ----------------------------------------------------------------------
 
13
;;; Building the classes T, CLASS, STANDARD-OBJECT and STANDARD-CLASS.
 
14
;;;
 
15
;;; We cannot use the functions CREATE-STANDARD-CLASS and others because SLOTS,
 
16
;;; DIRECT-SLOTS, etc are empty and therefore SLOT-VALUE does not work.
 
17
 
 
18
(defun make-empty-standard-class (name metaclass)
 
19
  (let ((class (si:allocate-raw-instance nil metaclass #.(length +standard-class-slots+))))
 
20
    (unless metaclass
 
21
      (si:instance-class-set class class))
 
22
    (setf (class-id                  class) name
 
23
          (class-direct-superclasses class) nil
 
24
          (class-direct-subclasses   class) nil
 
25
          (class-slots               class) nil
 
26
          (class-direct-slots        class) nil
 
27
          (class-direct-default-initargs class) nil
 
28
          (class-default-initargs    class) nil
 
29
          (class-precedence-list     class) nil
 
30
          (class-finalized-p         class) t
 
31
          (find-class name) class)
 
32
    (unless (eq name 'T)
 
33
      (setf (slot-table class) (make-hash-table :size 2)))
 
34
    class))
 
35
 
 
36
;; 1) Create the classes
 
37
;;
 
38
;; Notice that, due to circularity in the definition, STANDARD-CLASS has
 
39
;; itself as metaclass. MAKE-EMPTY-CLASS takes care of that.
 
40
;;
 
41
(let* ((standard-class (make-empty-standard-class 'STANDARD-CLASS nil))
 
42
       (standard-object (make-empty-standard-class 'STANDARD-OBJECT standard-class))
 
43
       (the-class (make-empty-standard-class 'CLASS standard-class))
 
44
       (the-t (make-empty-standard-class 'T the-class))
 
45
       ;; It does not matter that we pass NIL instead of a class object,
 
46
       ;; because CANONICAL-SLOT-TO-DIRECT-SLOT will make simple slots.
 
47
       (class-slots (loop for s in (parse-slots '#.+class-slots+)
 
48
                          collect (canonical-slot-to-direct-slot nil s)))
 
49
       (standard-slots (loop for s in (parse-slots '#.+standard-class-slots+)
 
50
                             collect (canonical-slot-to-direct-slot nil s)))
 
51
       (hash-table (make-hash-table :size 24)))
 
52
 
 
53
  ;; 2) STANDARD-CLASS and CLASS are the only classes with slots. Create a
 
54
  ;; hash table for them, so that SLOT-VALUE works. Notice that we
 
55
  ;; make a intentional mistake: CLASS and STANDARD-CLASS share the same
 
56
  ;; hashtable!!
 
57
  (do* ((i 0 (1+ i))
 
58
        (slots standard-slots (cdr slots)))
 
59
       ((endp slots))
 
60
    (let ((slotd (first slots)))
 
61
      (setf (slot-definition-location slotd) i)
 
62
      (setf (gethash (slot-definition-name slotd) hash-table) slotd)))
 
63
  (dolist (slotd class-slots)
 
64
    (setf (slot-definition-location slotd)
 
65
          (slot-definition-location (gethash (slot-definition-name slotd) hash-table))))
 
66
  (setf (class-slots               the-class) (copy-list class-slots)
 
67
        (slot-table                the-class) hash-table
 
68
        (class-direct-slots        the-class) class-slots
 
69
        (class-slots               standard-class) standard-slots
 
70
        (slot-table                standard-class) hash-table
 
71
        (class-direct-slots        standard-class) (set-difference standard-slots class-slots))
 
72
 
 
73
  ;; 3) Fix the class hierarchy
 
74
  (setf (class-direct-superclasses the-t) nil
 
75
        (class-direct-subclasses the-t) (list standard-object)
 
76
        (class-direct-superclasses standard-object) (list the-t)
 
77
        (class-direct-subclasses standard-object) (list the-class)
 
78
        (class-direct-superclasses the-class) (list standard-object)
 
79
        (class-direct-subclasses the-class) (list standard-class)
 
80
        (class-direct-superclasses standard-class) (list the-class))
 
81
 
 
82
  (si::instance-sig-set the-class)
 
83
  (si::instance-sig-set standard-class)
 
84
  (si::instance-sig-set standard-object)
 
85
  (si::instance-sig-set the-t)
 
86
 
 
87
  ;; 4) Fix the class precedence list
 
88
  (let ((cpl (list standard-class the-class standard-object the-t)))
 
89
    (setf (class-precedence-list standard-class) cpl
 
90
          (class-precedence-list the-class) (cdr cpl)
 
91
          (class-precedence-list standard-object) (cddr cpl)
 
92
          (class-precedence-list the-t) nil))
 
93
 
 
94
  ;; 5) Generate accessors (In macros.lsp)
 
95
)
 
96
 
 
97
(defconstant +the-standard-class+ (find-class 'standard nil))
 
98
 
 
99
(defmethod class-prototype ((class class))
 
100
  (unless (slot-boundp class 'prototype)
 
101
    (setf (slot-value class 'prototype) (allocate-instance class)))
 
102
  (slot-value class 'prototype))
 
103
 
 
104
;;; ----------------------------------------------------------------------
 
105
;;; SLOTS READING AND WRITING
 
106
;;;
 
107
;;;
 
108
;;; 1) Functional interface
 
109
;;;
 
110
 
 
111
(defun find-slot-definition (class slot-name)
 
112
  (declare (si::c-local))
 
113
  (if (eq (si:instance-class class) +the-standard-class+)
 
114
      (gethash (class-slot-table class) slot-name nil)
 
115
      (find slot-name (class-slots class) :key #'slot-definition-name)))
 
116
 
 
117
(defun slot-value (self slot-name)
 
118
  (let* ((class (class-of self))
 
119
         (slotd (find-slot-definition class slot-name)))
 
120
    (if slotd
 
121
        (slot-value-using-class class self slotd)
 
122
        (values (slot-missing class self slot-name 'SLOT-VALUE)))))
 
123
 
 
124
(defun slot-boundp (self slot-name)
 
125
  (let* ((class (class-of self))
 
126
         (slotd (find-slot-definition class slot-name)))
 
127
    (if slotd
 
128
        (slot-boundp-using-class class self slotd)
 
129
        (values (slot-missing class self slot-name 'SLOT-BOUNDP)))))
 
130
 
 
131
(defun (setf slot-value) (value self slot-name)
 
132
  (let* ((class (class-of self))
 
133
         (slotd (find-slot-definition class slot-name)))
 
134
    (if slotd
 
135
        (funcall #'(setf slot-value-using-class) value class self slotd)
 
136
        (slot-missing class self slot-name 'SETF value))
 
137
    value))
 
138
 
 
139
(defun slot-makunbound (self slot-name)
 
140
  (let* ((class (class-of self))
 
141
         (slotd (find-slot-definition class slot-name)))
 
142
    (if slotd
 
143
        (slot-makunbound-using-class class self slotd)
 
144
        (slot-missing class self slot-name 'SLOT-MAKUNBOUND))
 
145
    self))
 
146
 
 
147
(defun slot-exists-p (self slot-name)
 
148
  (and (find-slot-definition (class-of self) slot-name)
 
149
       t))
 
150
 
 
151
;;;
 
152
;;; 2) Overloadable methods on which the previous functions are based
 
153
;;;
 
154
 
 
155
(defun standard-instance-get (instance slotd)
 
156
  (ensure-up-to-date-instance instance)
 
157
  (let* ((class (si:instance-class instance))
 
158
         (location (slot-definition-location slotd)))
 
159
    (cond ((si:fixnump location)
 
160
           ;; local slot
 
161
           (si:instance-ref instance (the fixnum location)))
 
162
          ((consp location)
 
163
           ;; shared slot
 
164
           (car location))
 
165
          (t
 
166
           (error "Effective slot definition lacks a valid location:~%~A"
 
167
                  slotd)))))
 
168
 
 
169
(defun standard-instance-set (val instance slotd)
 
170
  (ensure-up-to-date-instance instance)
 
171
  (let* ((class (si:instance-class instance))
 
172
         (location (slot-definition-location slotd)))
 
173
    (cond ((si:fixnump location)
 
174
           ;; local slot
 
175
           (si:instance-set instance (the fixnum location) val))
 
176
          ((consp location)
 
177
           ;; shared slot
 
178
           (setf (car location) val))
 
179
          (t
 
180
           (error "Effective slot definition lacks a valid location:~%~A"
 
181
                  slotd)))
 
182
    val))
 
183
 
 
184
(defmethod slot-value-using-class ((class class) self slotd)
 
185
  (let ((value (standard-instance-get self slotd)))
 
186
    (if (si:sl-boundp value)
 
187
        value
 
188
        (values (slot-unbound class self (slot-definition-name slotd))))))
 
189
 
 
190
(defmethod slot-boundp-using-class ((class class) self slotd)
 
191
  (si::sl-boundp (standard-instance-get self slotd)))
 
192
 
 
193
(defmethod (setf slot-value-using-class) (val (class class) self slotd)
 
194
  (standard-instance-set val self slotd))
 
195
 
 
196
(defmethod slot-makunbound-using-class ((class class) instance slotd)
 
197
  (ensure-up-to-date-instance instance)
 
198
  (let* ((location (slot-definition-location slotd)))
 
199
    (cond ((si:fixnump location)
 
200
           ;; local slot
 
201
           (si:sl-makunbound instance (the fixnum location)))
 
202
          ((consp location)
 
203
           ;; shared slot
 
204
           (setf (car location) (unbound)))
 
205
          (t
 
206
           (error "Effective slot definition lacks a valid location:~%~A"
 
207
                  slotd))))
 
208
  instance)
 
209
 
 
210
;;;
 
211
;;; 3) Error messages related to slot access
 
212
;;;
 
213
 
 
214
(defmethod slot-missing ((class t) object slot-name operation 
 
215
                         &optional new-value)
 
216
  (declare (ignore operation new-value))
 
217
  (error "~A is not a slot of ~A" slot-name object))
 
218
 
 
219
(defmethod slot-unbound ((class t) object slot-name)
 
220
  (error 'unbound-slot :instance object :name slot-name))
 
221
 
 
222
;;;
 
223
;;; For the next accessor we define a method.
 
224
;;;
 
225
 
 
226
(defmethod class-name ((class class))
 
227
  (class-id class))
 
228
 
 
229
(defmethod (setf class-name) (new-value (class class))
 
230
  (setf (class-id class) new-value))