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

Re: Compilation implications



    Date: Thu, 5 Jan 89  16:41:16 CST
    From: David N Gray <Gray@DSG.csc.ti.com>

    > You can make your REMAKE-OBJECT technique do this without modifying the loader
    > (you have to put in a special variable that allows you to detect recursive
    > calls).

    The problem with the approach of reading one form and then evaluating it
    is that the slot values have already been read and constructed before
    allocating the object they go in.  I suppose it would be possible to add
    special handling for recursive references that would maintain a list of
    these so that the loader can go back and fill them in later, but the
    approach of allocating the object before reading its contents is much
    simpler.  That's what we already do for lists and arrays.

Apparently my message wasn't clear.  What I meant to say was that you can
make the form returned by your MAKE-LOAD-FORM method do just that, allocate
the object and then fill in its contents.  Then you can detect nested
objects and move all the allocation forms to the front.

Oh, I'm sorry.  This all depends on the assumption that when the form is
(PROGN form1 form2), the loader evaluates form1 before reading form2.  I
had not realized that that might not be true of all loaders.  Should we
make special-case treatment of PROGN a requirement?

Probably it would be a better idea for MAKE-LOAD-FORM to return two
values, where the first value is a form that will create the object and
the second value is a form that will further initialize the object?
This way the order of evaluation requirement is more explicit.  It's
upward compatible since the second value can be NIL if you don't need
it.  Also this gives the opportunity to communicate between the forms
without using a special variable; suppose we plug the object returned by
the first form into the second form and do (schematically):

   ;; This part happens at compile time
   (MULTIPLE-VALUE-BIND (form1.1 form1.2)
       (MAKE-LOAD-FORM object1)
     (MULTIPLE-VALUE-BIND (form2.1 form2.2)
         (MAKE-LOAD-FORM object2)
       
       ;; This part happens at load time
       (LET ((x1 (EVAL form1.1))
             (x2 (EVAL form2.1)))
         (WHEN form1.2
           (EVAL (APPEND form1.2 (LIST (LIST 'QUOTE x1)))))
         (WHEN form2.2
           (EVAL (APPEND form2.2 (LIST (LIST 'QUOTE x2))))))))

Should I evolve the proposal I sent out the other day along these lines?

It's still the case that only the programmer of the class knows whether
this is an appropriate protocol, so it has to be under the control of the
programmer, not built-in.  Consider, for example, any class whose objects
are interned.  Calling ALLOCATE-INSTANCE unconditionally is not going to
work.  That's why I prefer to see an interface in terms of forms rather
than in terms of functions, since forms are the simplest way to do
something that is completely general.