Recently, I was playing with the CLIM-LISTENER (thanks to Paolo's
suggestion that it would provide good exercise for the graph-rendering
code), and found that it often crashed under Allegro CL, with MOP
errors.
I'm no MOP authority, so I dropped a line to Franz to ask them why
this was happening. Steve Haflich kindly filled me in on why, and
offered some comments on the use of the MOP to interrogate the class
hierarchy in the CLIM listener. With his permission, here's some of
what he said:
From: rpgoldman(a)sift.info
I have been trying to use a portable class browser for class
hierarchies with ACL 6.2, and have been getting frequent errors like
this:
CL-USER(8): (aclmop:class-slots (find-class 'clim::application-frame))
Error: Class #<STANDARD-CLASS CLIM:APPLICATION-FRAME> is not yet finalized.
[condition type: PROGRAM-ERROR]
Restart actions (select using :continue):
0: Return to Top Level (an "abort" restart).
1: Abort entirely from this process.
[1] CL-USER(9):
[note: this is with the open McCLIM clim implementation, not ACL
CLIM.]
I'm confused by this error, since it seems to contradict the
documentation I have, which states:
"Class finalization is the process of computing the information a
class inherits from its superclasses and preparing to actually
allocate instances of the class. ...
To support forward-referenced superclasses, and to account for the
fact that not all classes are actually instantiated, class
finalization is not done as part of the initialization of the class
metaobject. Instead, finalization is done as a separate protocol,
invoked by calling the generic function finalize-inheritance. The
exact point at which finalize-inheritance is called depends on the
class of the class metaobject; for standard-class it is called
sometime after all the classes superclasses are defined, but no later
than when the first instance of the class is allocated (by
allocate-instance)."
But I have an instance of this class that the MOP seems to be telling
me is not finalized:
GRAPH-MDP(77): (class-of *frame*)
#<STANDARD-CLASS TAEMS-MDP-APP>
GRAPH-MDP(78): (aclmop:class-direct-superclasses (class-of *frame*))
(#<STANDARD-CLASS STANDARD-APPLICATION-FRAME>)
(aclmop:class-direct-superclasses (first (aclmop:class-direct-superclasses (class-of *frame*))))
(#<STANDARD-CLASS APPLICATION-FRAME> #<STANDARD-CLASS CLIM-INTERNALS::PRESENTATION-HISTORY-MIXIN>)
Based on the above, shouldn't APPLICATION-FRAME have been finalized?
Or is it not finalized because it doesn't have any DIRECT instances?
SMH> Your suggested analysis is correct: A class is only required to be
SMH> finalized when it is directly instantiated. (See the term "direct
SMH> instance" in the ANS Glossary.) There is no need to finialize
SMH> superclasses. In fact, there is good reason not to do so, even beyond
SMH> the fact that it is a waste of time and storage:
SMH> If one has a collection of mixin classes, sometimes the oeration of
SMH> one mixin might depend on functionality, perhaps a method, provided by
SMH> a different mixin. If one instantiates a class that doesn't have a
SMH> complete set of these interrelated mixins, an error can be signalled
SMH> at execution time. It is sometime done that a mixin will implement
SMH> checking for other necessary classes and/or method. It can do this in
SMH> various ways, such as by defining :after methods on
SMH> finalize-inheritance. The idea is that it is much better to signal
SMH> error for some inconsistency earlier rather than later.
Steve went on to directly comment on the class browsing in
CLIM-LISTENER:
SMH> .... We agreed in the last round that a class does not _have_ a
SMH> class-slots property until it is finalized, and not all classes are
SMH> always finalized. Further, it's even worse, because some classes
SMH> cannot even be finalized. As I suggested before, a mixin class might
SMH> have code to guarantee it is not finalized (or instantiated) unless
SMH> certain conditions are met. And of course finalization is impossible
SMH> if a class' superclasses include a forward-reference-class.
SMH> So ideas like trying to force all classes to be finalized or to
SMH> trigger class finalization when inspected probably aren't good ones.
SMH> I don't know if it is possible for you to suggest McCLIM be fixed
SMH> (which would be best) or whether you have to try to patch this locally
SMH> in your copy. But you might investigate what the McCLIM inspector
SMH> itself does in the situation that a class still has forward
SMH> references.
SMH> class-slots is defined to return a list of
SMH> effective-slot-definition-objects, which cannot exist until
SMH> finalization. Depending on the needs of the browser, it is
SMH> straightforward to write a class walker that computes a partial list
SMH> of known slots by walking the portions of the superclass tree that are
SMH> defined (i.e. stopping on forward-reference-classes). But that would
SMH> compute a set of direct-slot-definition-objects (possibly multiple
SMH> dsd's per slot) instead of esd's, so the browser would need to be
SMH> modified to accept this.
As I said, I'm no expert on the MOP, or the internals of the
CLIM-LISTENER, so I'm not sure how feasible/desirable such a rewrite
would be. For that matter, I'm not sure why the CLIM-LISTENER works
on CMUCL and SBCL...
I'd be willing to rally round to help fix this if anyone wants to take
charge, especially to conduct tests on ACL 6.2 and 7.0. But I'm not
qualified to be more than a foot-soldier in that effort....
Cheers,
R