1 |
6 |
jlechner |
; Cgen's Object System.
|
2 |
|
|
; Copyright (C) 2000, 2009 Red Hat, Inc.
|
3 |
|
|
; This file is part of CGEN.
|
4 |
|
|
; See file COPYING.CGEN for details.
|
5 |
|
|
;
|
6 |
|
|
; When Guile has an official object implementation that is stable, things will
|
7 |
|
|
; be switched over then. Until such time, there's no point in getting hyper
|
8 |
|
|
; (although doing so is certainly fun, but only to a point).
|
9 |
|
|
; If the Guile team decides there won't be any official object system
|
10 |
|
|
; (which isn't unreasonable) then we'll pick the final object system then.
|
11 |
|
|
; Until such time, there are better things to do than trying to build a
|
12 |
|
|
; better object system. If this is important enough to you, help the Guile
|
13 |
|
|
; team finish the module(/object?) system.
|
14 |
|
|
;
|
15 |
|
|
; Classes look like:
|
16 |
|
|
;
|
17 |
|
|
; #(class-tag
|
18 |
|
|
; class-name
|
19 |
|
|
; parent-name-list
|
20 |
|
|
; elm-alist
|
21 |
|
|
; method-alist
|
22 |
|
|
; full-elm-initial-list
|
23 |
|
|
; full-method-alist ; ??? not currently used
|
24 |
|
|
; class-descriptor)
|
25 |
|
|
;
|
26 |
|
|
; PARENT-NAME-LIST is a list of the names of parent classes (the inheritance
|
27 |
|
|
; tree).
|
28 |
|
|
;
|
29 |
|
|
; ELM-ALIST is an alist of (symbol private? vector-index . initial-value)
|
30 |
|
|
; for this class only.
|
31 |
|
|
; Values can be looked up by name, via elm-make-[gs]etter routines, or
|
32 |
|
|
; methods can use elm-get/set! for speed.
|
33 |
|
|
; Various Lisp (or Lisp-like) OOP systems (e.g. CLOS, Dylan) call these
|
34 |
|
|
; "slots". Maybe for consistency "slot" would be a better name. Some might
|
35 |
|
|
; confuse that with intentions at directions. Given that something better
|
36 |
|
|
; will eventually happen, being deliberately different is useful.
|
37 |
|
|
;
|
38 |
|
|
; METHOD-ALIST is an alist of (symbol . (virtual? . procedure)) for this
|
39 |
|
|
; class only.
|
40 |
|
|
;
|
41 |
|
|
; FULL-ELM-INITIAL-LIST is the elements of the flattened inheritance tree.
|
42 |
|
|
; Initially it is #f meaning it hasn't been computed yet.
|
43 |
|
|
; It is computed when the class is first instantiated. During development,
|
44 |
|
|
; it can be reset to #f after some module has been reloaded (requires all
|
45 |
|
|
; object instantiation happens later of course).
|
46 |
|
|
;
|
47 |
|
|
; FULL-METHOD-ALIST is an alist of the methods of the flattened inheritance
|
48 |
|
|
; tree. Each element is (symbol . (parent-list-entry . method)).
|
49 |
|
|
; Initially it is #f meaning it hasn't been computed yet.
|
50 |
|
|
; It is computed when the class is first instantiated. During development,
|
51 |
|
|
; it can be reset to #f after some module has been reloaded (requires all
|
52 |
|
|
; object instantiation happens later of course).
|
53 |
|
|
;
|
54 |
|
|
; CLASS-DESCRIPTOR is the processed form of parent-name-list.
|
55 |
|
|
; There is an entry for the class and one for each parent (recursively):
|
56 |
|
|
; (class mi? (base-offset . delta) child-backpointer (parent1-entry) ...).
|
57 |
|
|
; mi? is #t if the class or any parent class has multiple inheritance.
|
58 |
|
|
; This is used by the element access routines.
|
59 |
|
|
; base-offset is the offset in the element vector of the baseclass (or first
|
60 |
|
|
; baseclass in the mi case).
|
61 |
|
|
; delta is the offset from base-offset of the class's own elements
|
62 |
|
|
; (as opposed to elements in any parent class).
|
63 |
|
|
; child-backpointer is #f in the top level object.
|
64 |
|
|
; ??? child->subclass, parent->superclass?
|
65 |
|
|
; Initially the class-descriptor is #f meaning it hasn't been computed yet.
|
66 |
|
|
; It is computed when the class is first instantiated. During development,
|
67 |
|
|
; it can be reset to #f after some module has been reloaded (requires all
|
68 |
|
|
; object instantiation to happen later of course).
|
69 |
|
|
;
|
70 |
|
|
; An object is a vector of 2 elements: #(object-elements class-descriptor).
|
71 |
|
|
; ??? Things would be simpler if objects were a pair but that makes eval'ing
|
72 |
|
|
; them trickier. Vectors are nice in that they're self-evaluating, though
|
73 |
|
|
; due to the self-referencing, which Guile 1.2 can't handle, apps have to
|
74 |
|
|
; be careful.
|
75 |
|
|
; ??? We could use smobs/records/whatever but the difference isn't big enough
|
76 |
|
|
; for me to care at this point in time.
|
77 |
|
|
;
|
78 |
|
|
; `object-elements' looks like:
|
79 |
|
|
;
|
80 |
|
|
; #(object-tag
|
81 |
|
|
; class
|
82 |
|
|
; element1
|
83 |
|
|
; element2
|
84 |
|
|
; ...)
|
85 |
|
|
;
|
86 |
|
|
; CLASS is the class the object is an instance of.
|
87 |
|
|
;
|
88 |
|
|
; User visible procs:
|
89 |
|
|
;
|
90 |
|
|
; (class-make name parents elements methods) -> class
|
91 |
|
|
;
|
92 |
|
|
; Create a class. The result is then passed back by procedures requiring
|
93 |
|
|
; a class argument. Note however that PARENTS is a list of class names,
|
94 |
|
|
; not the class data type. This allows reloading the definition of a
|
95 |
|
|
; parent class without having to reload any subclasses. To implement this
|
96 |
|
|
; classes are recorded internally, and `object-init!' must be called if any
|
97 |
|
|
; class has been redefined.
|
98 |
|
|
;
|
99 |
|
|
; (class-list) -> list of all defined classes
|
100 |
|
|
;
|
101 |
|
|
; (class-name class) -> name of CLASS
|
102 |
|
|
;
|
103 |
|
|
; (class-lookup class-name) -> class
|
104 |
|
|
;
|
105 |
|
|
; (class-instance? class object) -> #t if OBJECT is an instance of CLASS
|
106 |
|
|
;
|
107 |
|
|
; (object-class object) -> class of OBJECT
|
108 |
|
|
;
|
109 |
|
|
; (object-class-name object) -> class name of OBJECT
|
110 |
|
|
;
|
111 |
|
|
; (send object method-name . args) -> result of invoking METHOD-NAME
|
112 |
|
|
;
|
113 |
|
|
; (send-next object method-name . args) -> result of invoking next METHOD-NAME
|
114 |
|
|
;
|
115 |
|
|
; (new class) -> instantiate CLASS
|
116 |
|
|
;
|
117 |
|
|
; The object is initialized with values specified when CLASS
|
118 |
|
|
; (and its parent classes) was defined.
|
119 |
|
|
;
|
120 |
|
|
; (vmake class . args) -> instantiate class and initialize it with 'vmake!
|
121 |
|
|
;
|
122 |
|
|
; This is shorthand for (send (new class) 'vmake! args).
|
123 |
|
|
; ARGS is a list of option names and arguments (a la CLOS).
|
124 |
|
|
; ??? Not implemented yet.
|
125 |
|
|
;
|
126 |
|
|
; (method-vmake! object . args) -> modify OBJECT from ARGS
|
127 |
|
|
;
|
128 |
|
|
; This is the standard 'vmake! method, available for use by user-written
|
129 |
|
|
; 'vmake! methods.
|
130 |
|
|
; ??? Not implemented yet.
|
131 |
|
|
;
|
132 |
|
|
; (make class . args) -> instantiate CLASS and initialize it with 'make!
|
133 |
|
|
;
|
134 |
|
|
; This is shorthand for (send (new class) 'make! arg1 ...).
|
135 |
|
|
; This is a positional form of `new'.
|
136 |
|
|
;
|
137 |
|
|
; (method-make-make! class elm1-name elm2-name ...) -> unspecified
|
138 |
|
|
;
|
139 |
|
|
; Create a 'make! method that sets the specified elements.
|
140 |
|
|
;
|
141 |
|
|
; (object-copy object) -> copy of OBJ
|
142 |
|
|
;
|
143 |
|
|
; ??? Whether to discard the parent or keep it and retain specialization
|
144 |
|
|
; is undecided.
|
145 |
|
|
;
|
146 |
|
|
; (object-copy-top object) -> copy of OBJECT with spec'n discarded
|
147 |
|
|
;
|
148 |
|
|
; (object-parent object parent-path) -> parent object in OBJECT via PARENT-PATH
|
149 |
|
|
;
|
150 |
|
|
; (class? foo) -> return #t if FOO is a class
|
151 |
|
|
;
|
152 |
|
|
; (object? foo) -> return #t if FOO is an object
|
153 |
|
|
;
|
154 |
|
|
; (method-make! class name lambda) -> unspecified
|
155 |
|
|
;
|
156 |
|
|
; Add method NAME to CLASS.
|
157 |
|
|
;
|
158 |
|
|
; (method-make-virtual! class name lambda) -> unspecified
|
159 |
|
|
;
|
160 |
|
|
; Add virtual method NAME to CLASS.
|
161 |
|
|
;
|
162 |
|
|
; (method-make-forward! class elm-name methods) -> unspecified
|
163 |
|
|
;
|
164 |
|
|
; Add METHODS to CLASS that pass the "message" onto the object in element
|
165 |
|
|
; ELM-NAME.
|
166 |
|
|
;
|
167 |
|
|
; (method-make-virtual-forward! class elm-name methods) -> unspecified
|
168 |
|
|
;
|
169 |
|
|
; Add virtual METHODS to CLASS that pass the "message" onto the object in
|
170 |
|
|
; element ELM-NAME.
|
171 |
|
|
;
|
172 |
|
|
; (elm-get object elm-name) -> value of element ELM-NAME in OBJ
|
173 |
|
|
;
|
174 |
|
|
; Can only be used in methods.
|
175 |
|
|
;
|
176 |
|
|
; (elm-set! object elm-name new-value) -> unspecified
|
177 |
|
|
;
|
178 |
|
|
; Set element ELM-NAME in OBJECT to NEW-VALUE.
|
179 |
|
|
; Can only be used in methods.
|
180 |
|
|
;
|
181 |
|
|
; (elm-make-getter class elm-name) -> lambda
|
182 |
|
|
;
|
183 |
|
|
; Return lambda to get the value of ELM-NAME in CLASS.
|
184 |
|
|
;
|
185 |
|
|
; (elm-make-setter class elm-name) -> lambda
|
186 |
|
|
;
|
187 |
|
|
; Return lambda to set the value of ELM-NAME in CLASS.
|
188 |
|
|
;
|
189 |
|
|
; Conventions used in this file:
|
190 |
|
|
; - procs/vars internal to this file are prefixed with "-"
|
191 |
|
|
; [Of course this could all be put in a module; later if ever since
|
192 |
|
|
; once Guile has its own official object system we'll convert. Note that
|
193 |
|
|
; it currently does not.]
|
194 |
|
|
; - except for a few exceptions, public procs begin with one of
|
195 |
|
|
; class-, object-, elm-, method-.
|
196 |
|
|
; The exceptions are make, new, parent, send.
|
197 |
|
|
|
198 |
|
|
; ??? Were written as a procedures for Hobbit's sake (I think).
|
199 |
|
|
; Associative list of classes to be traced.
|
200 |
|
|
|
201 |
|
|
; Associative list of messages to be traced.
|
202 |
|
|
|
203 |
|
|
; Cover fn to set verbosity.
|
204 |
|
|
|
205 |
|
|
"not a class""not an object"; X is any arbitrary Scheme data.
|
206 |
|
|
": "" (class: "", name: """")"""""; Low level class operations.
|
207 |
|
|
; Return boolean indicating if X is a class.
|
208 |
|
|
|
209 |
|
|
; Make a class.
|
210 |
|
|
|
211 |
|
|
; Lookup a class given its name.
|
212 |
|
|
|
213 |
|
|
; Return a list of all direct parent classes of CLASS.
|
214 |
|
|
|
215 |
|
|
; The proc name we pass here is made up as we don't
|
216 |
|
|
|
217 |
|
|
"class""not a class"; Cover proc of -class-name for the outside world to use.
|
218 |
|
|
|
219 |
|
|
; We could issue an error here, but to be consistent with object-class-name
|
220 |
|
|
|
221 |
|
|
; Return a boolean indicating if CLASS or any parent class has
|
222 |
|
|
|
223 |
|
|
; Class descriptor utilities.
|
224 |
|
|
|
225 |
|
|
; (class mi? (base-offset . delta) child-backpointer (parent1-entry) ...)
|
226 |
|
|
|
227 |
|
|
; (append (list class offset bkptr) parents)
|
228 |
|
|
;)
|
229 |
|
|
; Note that this is an assq on the classes themselves, not their names.
|
230 |
|
|
|
231 |
|
|
; Compute the class descriptor of CLASS.
|
232 |
|
|
|
233 |
|
|
; We can assume the parents of CLASS have already been initialized.
|
234 |
|
|
;
|
235 |
|
|
; A class-descriptor is:
|
236 |
|
|
; (class mi? (base-offset . delta) child-backpointer (parent1-entry) ...)
|
237 |
|
|
; MI? is a boolean indicating if multiple inheritance is present.
|
238 |
|
|
; BASE-OFFSET is the offset into the object vector of the baseclass's elements
|
239 |
|
|
; (or first baseclass in the mi case).
|
240 |
|
|
; DELTA is the offset from BASE-OFFSET of the class's own elements.
|
241 |
|
|
; CHILD is the backlink to the direct child class or #f for the top class.
|
242 |
|
|
; ??? Is the use of `top' backwards from traditional usage?
|
243 |
|
|
; OFFSET must be global to the calculation because it is continually
|
244 |
|
|
; incremented as we recurse down through the hierarchy (actually, as we
|
245 |
|
|
; traverse back up). At any point in time it is the offset from the start
|
246 |
|
|
; of the element vector of the next class's elements.
|
247 |
|
|
; Object elements are laid out using a depth first traversal of the
|
248 |
|
|
; inheritance tree.
|
249 |
|
|
; Build the result first, then build our parents so that our parents have
|
250 |
|
|
; the right value for the CHILD-BACKPOINTER field.
|
251 |
|
|
; Use a bogus value for mi? and offset for the moment.
|
252 |
|
|
; The correct values are set later.
|
253 |
|
|
|
254 |
|
|
; We use `append!' here as the location of `result' is now fixed so
|
255 |
|
|
; that our parent's child-backpointer remains stable.
|
256 |
|
|
; The proc name we pass here is made up as we don't
|
257 |
|
|
; want it to be the name of an internal proc.
|
258 |
|
|
"class""not a class"; Return the top level class-descriptor of CLASS-DESC.
|
259 |
|
|
; Pretty print a class descriptor.
|
260 |
|
|
"Class: "" mi?: "" base offset: "" delta: "" child: ""-top-""Top level class: "; Low level object utilities.
|
261 |
|
|
; Make an object.
|
262 |
|
|
; All elements get initial (or unbound) values.
|
263 |
|
|
; Make an object using VALUES.
|
264 |
|
|
; VALUES must specify all elements in the class (and parent classes).
|
265 |
|
|
; Copy an object.
|
266 |
|
|
; If TOP?, the copy is of the top level object with any specialization
|
267 |
|
|
; discarded.
|
268 |
|
|
; WARNING: A shallow copy is currently done on the elements!
|
269 |
|
|
|
270 |
|
|
; The result is the same object, but with a different view (confined to
|
271 |
|
|
|
272 |
|
|
; Accessors.
|
273 |
|
|
|
274 |
|
|
; Return boolean indicating if X is an object.
|
275 |
|
|
; Return the class of an object.
|
276 |
|
|
"object-class"; Cover proc of -object-class-name for the outside world to use.
|
277 |
|
|
|
278 |
|
|
; Class operations.
|
279 |
|
|
|
280 |
|
|
; The result does not include parent classes.
|
281 |
|
|
; Initialize class if not already done.
|
282 |
|
|
; FIXME: Need circularity check. Later.
|
283 |
|
|
; This should be fast the second time through, so don't do any
|
284 |
|
|
; computation until we know it's necessary.
|
285 |
|
|
; First pass ensures all parents are initialized.
|
286 |
|
|
; Next pass initializes the initial value list.
|
287 |
|
|
|
288 |
|
|
; Object elements begin at offset 2 in the element vector.
|
289 |
|
|
; Make a class.
|
290 |
|
|
;
|
291 |
|
|
|
292 |
|
|
; exist yet, though they must exist when the class is first instantiated.
|
293 |
|
|
; ELMS is a either a list of either element names or name/value pairs.
|
294 |
|
|
; Elements without initial values are marked as "unbound".
|
295 |
|
|
|
296 |
|
|
; method-make!.
|
297 |
|
|
; Mark elements without initial values as unbound, and
|
298 |
|
|
; compute indices into the element vector (relative to the class's
|
299 |
|
|
|
300 |
|
|
; Elements are recorded as (symbol initial-value private? . vector-index)
|
301 |
|
|
; FIXME: For now all elements are marked as "public".
|
302 |
|
|
; done
|
303 |
|
|
|
304 |
|
|
; The caller can override afterwards if desired.
|
305 |
|
|
; Note that if there are any parent classes then we don't know the names
|
306 |
|
|
; of all of the elements yet, that is only known after the class has been
|
307 |
|
|
|
308 |
|
|
; This method won't be called until that happens though so we're safe.
|
309 |
|
|
; This is written without knowledge of the names, it just initializes
|
310 |
|
|
; all elements.
|
311 |
|
|
|
312 |
|
|
"make!""""wrong number of arguments to method `make!'"; Create an object of a class CLASS.
|
313 |
|
|
"new""Instantiating class "".\n"; Make a copy of OBJ.
|
314 |
|
|
|
315 |
|
|
"object-copy"; Make a copy of OBJ.
|
316 |
|
|
; This makes a copy of top level object, with any specialization discarded.
|
317 |
|
|
; WARNING: A shallow copy is done on the elements!
|
318 |
|
|
"object-copy-top"; Utility to define a standard `make!' method.
|
319 |
|
|
; A standard make! method is one in which all it does is initialize
|
320 |
|
|
; fields from args.
|
321 |
|
|
; The "standard" way to invoke `make!' is (send (new class) 'make! ...).
|
322 |
|
|
; This puts all that in a cover function.
|
323 |
|
|
|
324 |
|
|
; Return #t if OBJECT is an instance of CLASS.
|
325 |
|
|
; This does not signal an error if OBJECT is not an object as this is
|
326 |
|
|
|
327 |
|
|
"class-instance?"; Element operations.
|
328 |
|
|
|
329 |
|
|
; The result is (class-desc . (private? . elm-offset)) or #f if not found.
|
330 |
|
|
|
331 |
|
|
; is restricted to this section of the source.
|
332 |
|
|
; Given the result of -class-lookup-element, return the element's delta
|
333 |
|
|
; from base-offset.
|
334 |
|
|
; Return a boolean indicating if ELM is bound in OBJ.
|
335 |
|
|
"elm-bound?"; Subroutine of elm-get.
|
336 |
|
|
"elm-get""elm-get""element not present: "; Get an element from an object.
|
337 |
|
|
; If OBJ is `self' then the caller is required to be a method and we emit
|
338 |
|
|
; memoized code. Otherwise we do things the slow way.
|
339 |
|
|
; ??? There must be a better way.
|
340 |
|
|
; What this does is turn
|
341 |
|
|
; (elm-get self 'foo)
|
342 |
|
|
; into
|
343 |
|
|
; ((-elm-make-method-get self 'foo) self)
|
344 |
|
|
|
345 |
|
|
; foo and returns a memoizing macro that returns the code to perform the
|
346 |
|
|
; operation with O(1). Cute, but I'm hoping there's an easier/better way.
|
347 |
|
|
; Subroutine of elm-set!.
|
348 |
|
|
"elm-set!""elm-set!""element not present: "; Set an element in an object.
|
349 |
|
|
|
350 |
|
|
; See the comments for `elm-get'!
|
351 |
|
|
; Get an element from an object.
|
352 |
|
|
; This is for invoking from outside a method, and without having to
|
353 |
|
|
; use elm-make-getter. It should be used sparingly.
|
354 |
|
|
"elm-xget"; FIXME: check private?
|
355 |
|
|
|
356 |
|
|
; This is for invoking from outside a method, and without having to
|
357 |
|
|
; use elm-make-setter. It should be used sparingly.
|
358 |
|
|
|
359 |
|
|
"elm-xset!""element not present: "; Return a boolean indicating if object OBJ has element NAME.
|
360 |
|
|
"elm-present?"; Return lambda to get element NAME in CLASS.
|
361 |
|
|
; FIXME: validate name.
|
362 |
|
|
|
363 |
|
|
; initialized yet.
|
364 |
|
|
; ??? Should be able to use fast-index in mi case.
|
365 |
|
|
; ??? Need to involve CLASS in lookup.
|
366 |
|
|
|
367 |
|
|
; FIXME: validate name.
|
368 |
|
|
"elm-make-setter"; We use delay here as we can't assume parent classes have been
|
369 |
|
|
; initialized yet.
|
370 |
|
|
; ??? Should be able to use fast-index in mi case.
|
371 |
|
|
; ??? Need to involve CLASS in lookup.
|
372 |
|
|
; Return a list of all elements in OBJ.
|
373 |
|
|
; Method operations.
|
374 |
|
|
; Lookup the next method in a class.
|
375 |
|
|
; This means begin the search in the parents.
|
376 |
|
|
; ??? What should this do for virtual methods. At present we treat them as
|
377 |
|
|
; non-virtual.
|
378 |
|
|
; Lookup a method in a class.
|
379 |
|
|
; The result is (class-desc . method). If the method is found in a parent
|
380 |
|
|
; class, the associated parent class descriptor is returned. If the method is
|
381 |
|
|
; a virtual method, the appropriate subclass's class descriptor is returned.
|
382 |
|
|
; VIRTUAL? is #t if virtual methods are to be treated as such.
|
383 |
|
|
; Otherwise they're treated as normal methods.
|
384 |
|
|
|
385 |
|
|
; FIXME: We don't yet implement the method cache.
|
386 |
|
|
"Looking up method "" in "".\n"; virtual?
|
387 |
|
|
; Traverse back up the inheritance chain looking for overriding
|
388 |
|
|
; methods. The closest one to the top is the one to use.
|
389 |
|
|
"Looking up virtual method "" in "".\n"; Method found, update goal object and method.
|
390 |
|
|
; Method not found at this level.
|
391 |
|
|
; Went all the way up to the top.
|
392 |
|
|
; Non-virtual, done.
|
393 |
|
|
; Method not found, search parents.
|
394 |
|
|
; Return a boolean indicating if object OBJ has method NAME.
|
395 |
|
|
"method-present?"; Return method NAME of CLASS or #f if not present.
|
396 |
|
|
; ??? Assumes CLASS has been initialized.
|
397 |
|
|
|
398 |
|
|
; FIXME: ensure method-name is a symbol
|
399 |
|
|
|
400 |
|
|
; FIXME: ensure method-name is a symbol
|
401 |
|
|
"method-make-virtual!""method-make-virtual!""method must be a procedure"; Utility to create "forwarding" methods.
|
402 |
|
|
; METHODS are forwarded to class member ELM-NAME, assumed to be an object.
|
403 |
|
|
; The created methods take a variable number of arguments.
|
404 |
|
|
; Argument length checking will be done by the receiving method.
|
405 |
|
|
; FIXME: ensure elm-name is a symbol
|
406 |
|
|
|
407 |
|
|
; FIXME: ensure elm-name is a symbol
|
408 |
|
|
|
409 |
|
|
"Sending "" to"" object """""" class "".\n"; Invoke a method in an object.
|
410 |
|
|
; When the method is invoked, the (possible parent class) object in which the
|
411 |
|
|
; method is found is passed to the method.
|
412 |
|
|
; ??? The word `send' comes from "sending messages". Perhaps should pick
|
413 |
|
|
|
414 |
|
|
"send""send""not a method name""""send""method not supported: "; Invoke the next method named METHOD-NAME in the heirarchy of OBJ.
|
415 |
|
|
; i.e. the method that would have been invoked if the calling method
|
416 |
|
|
|
417 |
|
|
; This may only be called by a method.
|
418 |
|
|
; ??? Ideally we shouldn't need the METHOD-NAME argument. It could be
|
419 |
|
|
; removed with a bit of effort, but is it worth it?
|
420 |
|
|
|
421 |
|
|
; Subroutine of `parent' to lookup a (potentially nested) parent class.
|
422 |
|
|
; The result is the parent's class-descriptor or #f if not found.
|
423 |
|
|
; Subroutine of `parent' to lookup a parent via a path.
|
424 |
|
|
; PARENT-PATH, a list, is the exact path to the parent class.
|
425 |
|
|
; The result is the parent's class-descriptor or #f if not found.
|
426 |
|
|
; For completeness' sake, if PARENT-PATH is empty, CLASS-DESC is returned.
|
427 |
|
|
; Lookup a parent class of object OBJ.
|
428 |
|
|
; CLASS is either a class or a list of classes.
|
429 |
|
|
; If CLASS is a list, it is a (possibly empty) "path" to the parent.
|
430 |
|
|
; Otherwise it is any parent and is searched for breadth-first.
|
431 |
|
|
; ??? Methinks this should be depth-first.
|
432 |
|
|
; The result is OBJ, specialized to the found parent.
|
433 |
|
|
"object-parent""object-parent""object-parent""invalid parent path"; Hobbit generates C code that passes the function
|
434 |
|
|
; -class-parent-via-path or -class-parent, not the appropriate
|
435 |
|
|
; SCM object.
|
436 |
|
|
; (let ((result ((if (or (null? class) (pair? class))
|
437 |
|
|
; -class-parent-via-path
|
438 |
|
|
; -class-parent)
|
439 |
|
|
|
440 |
|
|
; So it's rewritten like this.
|
441 |
|
|
"object-parent""parent not present"; FIXME: should print path in error message.
|
442 |
|
|
; Make PARENT-NAME a parent of CLASS, cons'd unto the front of the search
|
443 |
|
|
; order. This is used to add a parent class to a class after it has already
|
444 |
|
|
|
445 |
|
|
; The parent is added to the front of the current parent list (affects
|
446 |
|
|
; method lookup).
|
447 |
|
|
|
448 |
|
|
; This is used to add a parent class to a class after it has already been
|
449 |
|
|
|
450 |
|
|
; The parent is added to the end of the current parent list (affects
|
451 |
|
|
; method lookup).
|
452 |
|
|
"class-append-parent!""class-append-parent!""not a class name"; Miscellaneous publically accessible utilities.
|
453 |
|
|
; Reset the object system (delete all classes).
|
454 |
|
|
; Call once to initialize the object system.
|
455 |
|
|
|
456 |
|
|
; instantiated. This usually happens during development only.
|
457 |
|
|
|
458 |
|
|
; Utility to map over a class and all its parent classes, recursively.
|
459 |
|
|
; Return class tree of a class or object.
|
460 |
|
|
"class-tree""not a class or object"; Return names of each alist.
|
461 |
|
|
; Return complete layout of class-or-object.
|
462 |
|
|
"class-layout""not a class or object"; Like assq but based on the `name' element.
|
463 |
|
|
; WARNING: Slow.
|
464 |
|
|
; Like memq but based on the `name' element.
|
465 |
|
|
; WARNING: Slow.
|
466 |
|
|
; Misc. internal utilities.
|
467 |
|
|
; We need a fast vector copy operation.
|
468 |
|
|
; If `vector-copy' doesn't exist (which is assumed to be the fast one),
|
469 |
|
|
; provide a simple version.
|
470 |
|
|
; FIXME: Need deep copier instead.
|
471 |
|
|
; Profiling support
|
472 |
|
|
|