[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

subtypep on structures

    Date: Wed, 17 Jan 90 13:41 EST
    From: Mike Wellman <wellman@aagate.avlab.wpafb.af.mil>
    According to my reading of the common lisp manual (and corroborated by
    Allegro CL), defstruct types formed with :INCLUDEs should be subtypes of
    the :INCLUDEd structure.  So, after defining

      (defstruct foo)
      (defstruct (bar (:include foo)))

    the expression

      (subtypep 'bar 'foo)

    should return T T, not NIL NIL as it does.  Note that 

Well, unfortunately, this is perfectly legal under Common Lisp.
NIL NIL means that the system doesn't know, not that it
isn't a subtype.  The Common Lisp type system is brain-dead
in several important ways, and this is one of them.  There is
just too little specified about SUBTYPEP, and TYPE-OF.  The
balance between implementation flexibility and portability and
usable specificity is all wrong...

The fact that Allegro does what you expect doesn't make it a
required part of Common Lisp.  You're certainly being reasonable
to want the behaviour, but Common Lisp isn't reasonable in not
guarenteeing it.

However, the Symbolics code for SUBTYPEP tries to handle this,
it just has a bug.  To avoid sending Symbolics Code out over
mail, I'll just tell you to look at the code for CLI::TYPE-EXPAND.
The COND clause which looks for an SI:DEFSTRUCT-DESCRIPTION
property should occur *BEFORE* the COND clause which looks for
a DEFTYPE property.

Anyway, I'm a little bit surprised that DW:PRESENTATION-TYPEP
doesn't know about it.  I must have gotten lazy.

However, if you use (STRUCTURE BAR) and (STRUCTURE FOO) as your
types, it will work if you add the following code to the
DEFINE-PRESENTATION-TYPE for STRUCTURE.  Add this immediately after
the first call to MERGE-META-ARGS:

	 (let* ((desc (get structure-name 'si:defstruct-description))
		(include (car (si:defstruct-description-include desc))))
	   (when include
	     (stack-let ((new-type `(structure ,include)))
	       (merge-meta-args new-type pr-args function include predicate))))

It's a bug in DW::MAP-OVER-TYPE-HIERARCHY that you need to use
(STRUCTURE <name>) instead of just <name>. The bug is that in
the STRUCTURE case it directly goes from FOO to STRUCTURE to
SYS:EXPRESSION, and completely skips invoking STRUCTURE's
presentation-type descriptor's :MAP-OVER-SUPERTYPES handler.
It should be doing

(stack-let ((new-type `(structure ,type)))

and recursing on NEW-TYPE.

But even though I wrote it, I don't have access to the sources
for DW::MAP-OVER-TYPE-HIERARCHY, so I can't supply a general
fix.  (For performance reasons, I wouldn't recommend trying to
do it with ADVISE).

      (foo-p (make-bar))

    properly returns T.

    This bug really matters when trying to use structure types for
    presentation objects.  Any ideas or workarounds?

Make the above patches, and always use (STRUCTURE <name>) for types.
When you do PRESENT, explicitly supply the type as (STRUCTURE <name>)
instead of letting it default to the value of (TYPE-OF object).  Or
get Symbolics to apply my fix to DW:MAP-OVER-TYPE-HIERARCHY and supply
you with that code.

    --Mike Wellman.