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

findSlot utility



When you get a run-time error telling you that some message send is
ambiguous, you usually want to know which slots are being referenced
so you can decide which one you want.  The following utility can be
used for this purpose.  It uses mirrors to find the slot(s) being
referenced when you send some object some message from some method
holder.  The method holder only matters when there are private slots.
See the comments in the file below for details.

I hope others find this as useful as I do.

- Danny Epstein
  dje@scs.carleton.ca

-------------------------------------------------------------------------------

"findSlot.self"
"version 1.0"
"for Self 1.0 or 1.1"
"Danny Epstein <dje@scs.carleton.ca>"

"Add several methods to the lobby to find slots.  The first method
finds the slot being referenced when you send a particular message to
a particular object from a particular place.  The next method assumes
the method is being sent from the object, meaning that it can see all
private slots.  The last method uses the receiver rather than an
argument.  This will only work when the object inherits from the
lobby.  The results of all three of these methods is the object that
contains the named slot, if the message send would be legal.  If the
message send would be ambiguous, a list of the objects is returned.
If the message wouldn't be understood, an empty list is returned.
Examples:

Find a single slot:
  > lobby findSlot: 'name:'
  printing
Find no slot: message not understood:
  > lobby findSlot: 'foobar'
  list{}
Find two slots: ambiguous:
  > lobby findSlot: 'system'
  list{oddballs, prototypes}
Doesn't inherit from the lobby:
  > findSlot: 'traits' In: globals
  globals
Can see private slot locally:
  > findSlot: 'collectionName' In: traits list
  traits list
Can't see private slot from somewhere else:
  > findSlot: 'collectionName' In: traits list From: 5
  list{}"

_AddSlots: ( |
  ^ findSlot: slotName In: anObject From: holder = ( | mirror. slots. |
      "Find the slot with the given name in the given object.  The
      holder is wehere the reference is being made from.  It is used
      to determine whether private slots are visible."
      mirror: reflect: anObject.
      slots: list copy.
      (mirror lookupKey: slotName Holder: (reflect: holder)) do: [ | :aSlot. |
        slots addLast: aSlot mirror reflectee.
      ].
      slots size = 1 ifTrue: [slots: slots first].
      slots.
    ).
  ^ findSlot: slotName In: anObject = ( | mirror. slots. |
      "Find the slot with the given name in the given object.  Allow
      private slots."
      findSlot: slotName In: anObject From: anObject.
    ).
  ^ findSlot: slotName = (
      "A shortcut for when the object inherits from the lobby."
      findSlot: slotName In: self.
    ).
| )