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

Internals Proposal



Here is my proposal for the interface to the non-portable common part of object
systems.  This basically solves the problem of how the object can specify how
it is to be printed, etc.  This works well with standard object systems, and
can be made to work with nonstandard object systems, although not as easily.
It's mostly words, because so much of the internal stuff is
implementation-dependent; what I'm advocating is more of an approach.

DEFINITIONS

@i(Object system): any programming system with objects that are manipulated via
message passing.  I claim the standard for Common Lisp is that a message
consists of an atomic message name or key, and some message arguments (not
unlike function arguments).  An object system primitive is used to send
messages to an object.

@i(instance): an object belonging to a message system.  This term has been
appropriated to refer to objects of the instance datatype, which implements
instances of all object systems that want access to the facility this paper
describes.

@i(Sending function): a function of the instance, message name, and arguments
(in that order) that sends a message to an instance belonging to a particular
object system.  Althouigh it is fully intended that standard object systems can
use their primitive send as their sending function, this is not necessarily so.
The sending function could perform some translation of the message, and it need
not send a message to the object at all.  [This is the case if you want to hack
up an object that acts like a list and a vector, for instance.]

LISP:SEND default-handler instance message-key . message-args [FUNCTION]

I decided to snarf the name in spite of its popularity; object systems that
want to call their sending primitive SEND will have to shadow it.  Basically
this determines the sending function of the object system of the instance, and
calls it with the instance, message name and arguments.  This is primarily
intended for the lisp system to communicate with instances from arbitrary
object systems, but other applications may have need for such a facility
(especially those that would be considered language extensions, such as error
systems).  If the message is unhandled (see the section after the next), a
non-nil default handler is called with all arguments; otherwise, an error is
signalled. 

THE INSTANCE DATATYPE

All objects are implemented with the same data type, which I call @i(instance).
The internal structure of this is up to the implementation; it may vary with
the particular object systems supported by the implementation, and with how
much effort the implementors want to put into it.  Besides determining the
operations available on the object, the structure must of course eventually
point to the object system's sending function.  Since everything here is
implementation-dependent, the best that can be done is to point out which
function in an object system is the sending function, so that it can be dealt
with appropriately by the implementation.

STANDARD MESSAGES AND LISP:UNHANDLED

The lisp system communicates with objects through a standard set of messages.
This set may be pretty large, though, and probably only a few will be relevant
to a given application.  Also, if LISP::SEND comes to be used for other
applications, they will need to be able to determine whether the given object
handles the appropriate messages.

Some object systems have some seperate operation that examines the object to
see if it will handle a given message; this is not possible where most of the
"object" is a piece of code that dispatches off the message key.  Also, some
applications (or at least Lisp) have some default behavior for a give object;
it's silly to expect all objects to know what this is, especially if that
information is duplicated over multiple object systems.  I propose that the
sending function (and hence handlers) be allowed to return LISP:UNHANDLED,
which tells LISP:SEND that the message went unhandled and allows the default
action to take place.  This certainly simplifies the task of writing sending
functions that allow objects to perform in arbitrary ways to lisp primitives,
and should also simplify the task of interfacing to a nonstandard object
system.

MUCKING WITH LISP TYPES

I think it would be neat to allow objects to masquerade as primitive types.
Basically instead of signalling a wrong-type-argument error, you do a send if
it's an object, with the default action being to go ahead and signal the error.
I think some experimentation or additional thought is called for, since this
could do horrible things to the notion of the type of an object, and probably
isn't appropriate to standard architectures.  If this does happen, LISP::SEND
would be the way to do it.

EXAMPLES

Although the system was designed with making flavors:send be Flavors's sending
function, this probably won't be the case.  Best would probably be to have
flavors signal a condition when a message was unhandled - the sending function
would be something that bound that condition and then did a send (the send
would probably be inline).

Some standard messages will be:
PRIN1 stream
TYPEP type
DESCRIBE
DUMPING-FORM
  Returns a form that should create a like-behaving instance.  Used by the
  compiler to dump an instance.