The end of DCI without Rolemethod injection?

54 views
Skip to first unread message

Trygve Reenskaug

unread,
Nov 11, 2011, 9:32:25 AM11/11/11
to DCI-object-evolution
Hi all,
This is a long mail. The short version is that my first attempt at DCI without RoleMethod injection failed. It worked gloriously for 5 out of 6 examples. But it failed catastrophically for the last of the six. The conclusion is: Back to the drawing board.

The long version follows. It explains what went wrong.

I have been preparing my six DCI examples for publication by recompiling all RoleMethods without RoleMethod injection. It looked fine for a while, but the recompilation revealed some problems.

BB7, the Dijkstra example went beautifully. It illustrates that two Roles with a common RolePlayer object can have methods with the same name without name collision. And the
recursion caused no trouble.

BB6: Pay many bills, posed no problems.

BB5: The well known Bank Transfer example posed no problems.

At this stage, I was very happy.

BB4, Activity Network Planning,  exposed a problem with
self as it is used in an Activity RoleMethod:
    Activity::resetView 
        self addActivityViews.
        self addLines.

We always say that self refers to the RolePlayer object, but here it means the Role itself. There is no RoleMethod injection, so the RolePlayer object does not understand addActivityViews and addLines..
    
The solution was to realize that
self will always be the Role itself, here the Activity Role. The compiler can, therefore, replace self with the current Role. A small compiler fix, and it worked.

BB3, the game of Greed, posed no problems. (But it's not a beautiful program.)

BB2, the Stars and Circles (Planets) animation example, posed a new and deeply serious problem.
The RoleMethod for the first shape,
Shape1, is:

   
rolePlay1
      self displayLarge: '1'.
      CurrentContext sendMessage: #rolePlay2 from: self to: Shape2
.

The compiler transforms the last statement into a more common form of procedure invocation: 
       
CurrentContext sendMessageFrom:to: (#rolePlay2, self, Shape2)
(In Squeak, colon is a legal character in message selectors. The number of colons corresponds to the number of arguments.)


The receiving  RoleMethod in the CurrentContext is: (still using the more common form):

   
sendMessage:from:to: (selector, obj1, obj2)
      self window createNewArrow growFrom:to: (obj1, obj2).
      obj2 perform (selector).

The first statement is OK. The two arguments obj1 and obj2 refer to the actual RolePlayer objects and all is well.

The second statement gives an error. A
Star (or Circle) does not understand rolePlay2 since there is no injection. The argument obj2 should not have been dereferenced; it should be the actual Role, Shape2. The Role and its RolePlayer are distinct entities since they have different method dictionaries. At a first glance, this looks like object identity schizophrenia showing its ugly head. This is something we know all about and it threatens to be a fatal show stopper.

Fortunately, it may not be quite as bad as it sounds because
there is only one object at runtime, namely the RolePlayer object. The Role is only pure behavior with no state. (Actually, a Trait). My present compiler creates code for binding the Role identifier to its object with a runtime lookup in the CurrentContext. The BB2 example indicates that I am doing this too early in the compilation process.

It's back to the drawing board and more work (not for the first time in the life of DCI).


DCI with no injection remains a goal. I'm not a compiler guy so there will be some 'guess and learn' involved. I feel confident that a solution should exist since the DCI semantics with no injection seems to be clear and unambiguous.

Cheers,
--Trygve









rune funch

unread,
Nov 11, 2011, 10:28:11 AM11/11/11
to dci-ev...@googlegroups.com
Den 11/11/2011 kl. 15.32 skrev Trygve Reenskaug <try...@ifi.uio.no>:

> DCI with no injection remains a goal. I'm not a compiler guy so there will be some 'guess and learn' involved. I feel confident that a solution should exist since the DCI semantics with no injection seems to be clear and unambiguous

I can add that the language I posted about a little week ago has no
injection and can handle your 6th example. I'll write up how

Trygve Reenskaug

unread,
Nov 11, 2011, 10:58:46 AM11/11/11
to dci-ev...@googlegroups.com
FANTASTIC!!!

Rune Funch Søltoft

unread,
Nov 14, 2011, 2:17:56 AM11/14/11
to dci-ev...@googlegroups.com
Hi,
I wanted to write this up last week but I found I indeed had a bug that the sixth example found.


Here's how it works at current
When the parser finds a role declaration it rewrites it to a field declaration (a member variable for those that do not speak .NET) and attach some meta data describing the role

when the parser sees a method invocation on a field known to be a role it checks to see if there's role method that fits the method signature. If so uses that, if not calls an instance method.

When the object expression of a method invocation is not known to be a role then fun starts. The meta data is not available at compile time so the parser can't do the above rewrite, instead I have a small hack at the moment when it can't be determined if it's a role or not (Ie. basically all places where it's not possible to identify that it is a role) I will have a runtime check to see if it's a role and act accordingly.
I don't particularly like this and I'm going to see if I can find a way to have the runtime help me with this. I have a few ideas I'll want to try out. At the moment however I haven't even implemented the above runtime check. I'm stuck at a parser error after trying to implement the comments I got on my first post in regards to the language

Best regards
Rune

2011/11/11 Trygve Reenskaug <try...@ifi.uio.no>
Reply all
Reply to author
Forward
0 new messages