<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2653.12">
<TITLE>RE: [GOODIE] Delegation and Self like things for Squeak</TITLE>
</HEAD>
<BODY>
<P><FONT SIZE=2>(All, sorry about the HTML; I am unable to turn it off with my mail client...Outlook 2000 - grimace)</FONT>
</P>
<P><FONT SIZE=2>Stephen, I did manage to compile and test with a converted image. I got a walkback when first sending ProtoBehavior class>>#lobby. It blew up in the Mirror method that calls #primitiveGetProtoBehavior. I have included the c source, below, that my interpreter generated, in case it was different than yours or you happen to see something. Note that this base prototype object is unable to #printString, for the same reason I believe.</FONT></P>
<P><FONT SIZE=2>> Withers, Robert wrote:</FONT>
<BR><FONT SIZE=2>> >Hi Stephen, </FONT>
<BR><FONT SIZE=2>> >I will attempt the full VM build and image preparation this </FONT>
<BR><FONT SIZE=2>> evening and</FONT>
<BR><FONT SIZE=2>> let you know how my Linux machine likes it. As you know, I had</FONT>
<BR><FONT SIZE=2>> difficulty with the Forwarder changeset under Linux. I am </FONT>
<BR><FONT SIZE=2>> wondering if</FONT>
<BR><FONT SIZE=2>> it may have been due to my not running the image prep code you list</FONT>
<BR><FONT SIZE=2>> here.</FONT>
<BR><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> Possible. There are other problems with the Forwarder stuff. Squeak</FONT>
<BR><FONT SIZE=2>> seems to expect all objects to natively respond to at least the</FONT>
<BR><FONT SIZE=2>> ProtoObject protocol for some things that it does (like </FONT>
<BR><FONT SIZE=2>> scanning for all</FONT>
<BR><FONT SIZE=2>> references and such). As soon as I began to address those issues, I</FONT>
<BR><FONT SIZE=2>> realized that I could do everything I needed with a more generalized</FONT>
<BR><FONT SIZE=2>> delegation scheme...so, the delegation stuff supercedes the Forwarder</FONT>
<BR><FONT SIZE=2>> code (I'll make a note of it on the website).</FONT>
</P>
<P><FONT SIZE=2>I does start to seem like just an extended Proxy, with the ability to install methods. This is very nice, but it may not be the thing I think I need. Having instance methods, or rather reference-scoped methods, is half of the solution. The other bit is a truly stateless, first-class reference, that maintains identity, but allows for method override and lookup notification.</FONT></P>
<P><FONT SIZE=2>> >It strikes me that this may be an alternative to your proposal for</FONT>
<BR><FONT SIZE=2>> differentiating multiple versions of the same message. If we proxy an</FONT>
<BR><FONT SIZE=2>> object reference, with a delegate, then we can pick up any overriding</FONT>
<BR><FONT SIZE=2>> implementations of a method for it's class, within that </FONT>
<BR><FONT SIZE=2>> Module. Instead</FONT>
<BR><FONT SIZE=2>> on overriding a superclass' implementation, we are overriding a class</FONT>
<BR><FONT SIZE=2>> implementation in an inner, more generic module, with an </FONT>
<BR><FONT SIZE=2>> implementation</FONT>
<BR><FONT SIZE=2>> in a more specific module implementation. In this way, don't </FONT>
<BR><FONT SIZE=2>> extensions</FONT>
<BR><FONT SIZE=2>> of classes between modules look like Self-style inheritance?</FONT>
<BR><FONT SIZE=2>> </FONT>
<BR><FONT SIZE=2>> What about identity comparisons? Seems like that would cause trouble.</FONT>
<BR><FONT SIZE=2>> How would the compiler be able direct a message to it's </FONT>
<BR><FONT SIZE=2>> special wrapper</FONT>
<BR><FONT SIZE=2>> instance instead of the real object? Also, it would add a good bit of</FONT>
<BR><FONT SIZE=2>> storage overhead.</FONT>
</P>
<P><FONT SIZE=2>I believe it would depend on how we bring Forwarder/ManagedObjects support using this mechanism. The forwardee would be a parental slot, that would have it's protocol delegated too. How would we do pushSelf substitution in this scheme? I imagine that the receiverSelf for the forwardee would be the forwarder prototype.</FONT></P>
<P><FONT SIZE=2>I understand about the storage overhead (receiverMap) - that sucks. We need a first class reference object, that the VM knows how to manipulate. </FONT></P>
<P><FONT SIZE=2>For my desire to have managed objects (managing message sending), this provides a mechanism to override methods at the instance level in the proxy prototype. I would have to compile/install all methods I want to intercept, with the correct intercept code. So for my needs, I would rather have a way to either:</FONT></P>
<P> <FONT SIZE=2>1 - have a message lookup notification, with the ability to either cancel further lookup, or choose not to resend</FONT></P>
<P> <FONT SIZE=2>2 - have the ability to install custom lookup methods for an instance, and have the VM check and activate custom lookup when a send occurs.</FONT></P>
<P><FONT SIZE=2>Another alternative is a notification whenever lookup is changing it's scope to a superclass or parent, as the case may be.</FONT></P>
<P><FONT SIZE=2>- Rob</FONT>
</P>
<P><FONT SIZE=2>int primitiveGetProtoBehavior(void) {</FONT>
<BR><FONT SIZE=2> int object;</FONT>
<BR><FONT SIZE=2> int oop;</FONT>
<BR><FONT SIZE=2> int sp;</FONT>
<BR><FONT SIZE=2> int oop1;</FONT>
<BR><FONT SIZE=2> int ccIndex;</FONT>
</P>
<P> <FONT SIZE=2>/* begin stackObjectValue: */</FONT>
<BR> <FONT SIZE=2>oop1 = longAt(stackPointer - (0 * 4));</FONT>
<BR> <FONT SIZE=2>if ((oop1 & 1)) {</FONT>
<BR> <FONT SIZE=2>/* begin primitiveFail */</FONT>
<BR> <FONT SIZE=2>successFlag = 0;</FONT>
<BR> <FONT SIZE=2>object = null;</FONT>
<BR> <FONT SIZE=2>goto l1;</FONT>
<BR> <FONT SIZE=2>}</FONT>
<BR> <FONT SIZE=2>object = oop1;</FONT>
<BR><FONT SIZE=2>l1: /* end stackObjectValue: */;</FONT>
<BR> <FONT SIZE=2>if (successFlag) {</FONT>
<BR> <FONT SIZE=2>if (!((fetchClassOf(fetchClassOf(object))) == (longAt(((((char *) specialObjectsOop)) + 4) + (49 << 2))))) {</FONT></P>
<P> <FONT SIZE=2>successFlag = 0;</FONT>
<BR> <FONT SIZE=2>}</FONT>
<BR> <FONT SIZE=2>}</FONT>
<BR> <FONT SIZE=2>if (successFlag) {</FONT>
<BR> <FONT SIZE=2>/* begin pop:thenPush: */</FONT>
<BR> <FONT SIZE=2>/* begin fetchClassOf: */</FONT>
<BR> <FONT SIZE=2>if ((object & 1)) {</FONT>
<BR> <FONT SIZE=2>oop = longAt(((((char *) specialObjectsOop)) + 4) + (5 << 2));</FONT>
<BR> <FONT SIZE=2>goto l2;</FONT>
<BR> <FONT SIZE=2>}</FONT>
<BR> <FONT SIZE=2>ccIndex = (((unsigned) (longAt(object))) >> 12) & 31;</FONT>
<BR> <FONT SIZE=2>if (ccIndex == 0) {</FONT>
<BR> <FONT SIZE=2>oop = (longAt(object - 4)) & 4294967292U;</FONT>
<BR> <FONT SIZE=2>goto l2;</FONT>
<BR> <FONT SIZE=2>} else {</FONT>
<BR> <FONT SIZE=2>oop = longAt(((((char *) (longAt(((((char *) specialObjectsOop)) + 4) + (28 << 2))))) + 4) + ((ccIndex - 1) << 2));</FONT></P>
<P> <FONT SIZE=2>goto l2;</FONT>
<BR> <FONT SIZE=2>}</FONT>
<BR> <FONT SIZE=2>l2: /* end fetchClassOf: */;</FONT>
<BR> <FONT SIZE=2>longAtput(sp = stackPointer - ((2 - 1) * 4), oop);</FONT>
<BR> <FONT SIZE=2>stackPointer = sp;</FONT>
<BR> <FONT SIZE=2>}</FONT>
<BR><FONT SIZE=2>}</FONT>
</P>
</BODY>
</HTML>