Hi Colin--
Let's say I've got some GIS code, and I overload #at:put:. So 1-at:put: refers to the usual meaning for Arrays and Dictionaries, while 2-at:put: is my new meaning for plotting locations on maps.
I'll just add here that if you're actually coming up with a new conceptual meaning, from a sender's point of view, it's better (by virtue of intelligibility) to just use a differently-named selector. I'd anticipate overloaded selectors being useful for having multiple implementations of the same conceptual action (e.g., for performance reasons).
My GIS module uses both. Let's say that a class implementing 2-at:put: gets transferred...
"A" class? Don't you mean *the* class?
...and then later, a method that sends 2-at:put:. So we've got 2-at:put: going across the wire in 3 places: as a key in a method dictionary...
Note that, normally, during imprinting, when a class is defined remotely, no additions are made to the new method dictionary at that time. Methods are defined only later, as they are needed. An exception to this is when the class contains overrides; then method placeholders[1] are added.
If an involved Selector is overloaded (not interned in the default selector table), the providing system tells the requesting system this as part of installing the placeholder. The receiving system can then ensure that the Selector it uses for a method dictionary key is not interned in the default Selector table.
...in the literal frame of a compiled method, and during [passive] imprinting, a request for a missing method implementation.
Somehow, Spoon has to disambiguate between 1-at:put: and 2-at:put: as they move across the wire, so that selectors in literal frames correspond to the selectors in method dictionaries the same way they did in the development image. This is what I mean by "maintain Selector identity." How does Spoon accomplish it?
When a providing system transfers a method with an overloaded Selector in the literal frame, it uses a special literal marker to transfer the Selector when transferring the method's literals. See the class comment for the MethodLiteralTransmissionMarker class in Spoon for more about literal markers. Basically, they're used to transfer "special" method literals, like class pool associations.
When a system requests a method with an overloaded Selector, it communicates the sending method's signature as part of the request. The providing system can then find the appropriate Selector in its own memory (from the literal frame of its own copy of the sending method), and thus look up the correct method to define.
If the sending method's signature is itself overloaded, the requesting system provides a sending chain of method signatures, ending with a non-overloaded method signature. The providing system can then proceed as above. This scheme won't work if the only non-overloaded method signature in the sender graph is an unbound method, but that never happens in an imprinting situation. There is other metadata associated with methods (by modules) that I could use for resolution in the providing system, like author, but I don't think I need to.
Spoon's remote messaging protocol supports sending remote messages in the middle of sending other messages, nested arbitrarily deeply, amongst an arbitrary number of systems. For example, for system A to answer a message sent by system B, it might in turn need to send remote messages to B and C, which in turn might need to send still more messages to A. And each parameter of each message can be a proxy on a different arbitrary system.
So, if necessary, there can be a quite complex back-and-forth conversation between multiple systems in order to accomplish a particular message-send. This functionality is needed for remote debugging (it's why I wrote it), but I don't think it's needed for this overloaded-selector problem. But it's available in case we come across some pathological case I haven't thought of yet. :)
Also note that each Selector has its own version sequence (recall that I store a 15-bit version number in the trailer of each compiled method). I.e., if the 1-at:put: method has version number 1, with no 2-at:put: in existence, and I create a 2-at:put: method, the new 2-at:put: method will have version number 1, not 2.
Phew. :)
thanks,
-C
[1]
http://lists.squeakfoundation.org/pipermail/squeak-dev/2006-May/103418.html
spoon@lists.squeakfoundation.org