How Moby works

Posted: February 18, 2013 in DCI, Thoughts on development
Tags: , ,

As I wrote in my previous post I would write on how Moby maroon works internally. This is definitely not a post explaining DCI. As a matter of fact it might confuse you and potentially impair your understanding of DCI so tread carefully if you are new to DCI. The target audience is Rubyists that want to know how Moby maroon is capable of getting performance on par with regular method invocation and/or those that might want to contribute to Moby maroon and thereby indirectly to Marvin and DCI as well,

The context defined in the previous post is rewritten to an ordinary ruby class the source code of this class is returned as one of two objects from the define method. The first object being returned is the newly created class it self. The second object is the actual source of this class. In the case of the hello world example the source looks like this

class Greeter
   def greet
       p("#{greeting} #{self_who_say}!")
   end

   @who
   @greeting

   private
   def who;@who end
   def greeting;@greeting end
   def self_who_say 
     who
   end
end

As you can see there’s really nothing magically going on. So what did actually happen? Well firstly each role is rewritten to a definition of an instance variable and a getter. So for the who role there’s an instance variable ‘@who’ and a method ‘who’ and similar for the ‘greeting’ role. But there’s no role methods any more, where did the role method go? The last method in the source
def self_who_say
who
end

is where the role method went. The name might hint at this. Role methods are rewritten into instance methods of the context. And this is where you might be confused if you are new to DCI, so it’s worth stressing that this rewrite violates the mental model of DCI. Paradoxically DCI is very much about expressing the mental models and not violating them. A role method should be seen as a part of the role player and never be considered a part of the context.

it would have been safe to rewrite this to

def self_who_say
@who
end

So why isn’t it done? The reason to this is that there’s two rewriting phases in Moby maroon. The first rewrites the use of self to the corresponding role getter and the second rewriting phase depends on the role getter. When a role getter is encoutered the rewriter  will check to see it’s the instance expression of a role method invocation. If it is it will rewrite that invocation. E.g if we changed the who role to

role :who do
    say do
      self
    end
    talk do
      self.say
    end
  end

Then the first phase would rewrite talk to

talk do
who.say
end

And the second phase would the see this as a role method invocation and rewrite it to

def self_who_talk 
  self_who_say  
end

Recollecting from the previous post that if you call a method directly on the instance variable (in this case ‘@who’) it will always be an instance method and never a role method it should be obvious why the first phase rewrites to the role player getter and not the instance variable. Rewriting self to the instance variable would result in the second phase being unable to identify role method invocations.

Having seen how role method invocations are translated into invocations of instance method on the context obejct it should also be clear that there can be no performance difference between calling a role method or calling a regular instance method after all seen from the view of the interpreter role methods are instance methods.

In the next post we will look at how to bind block variables to roles followed by another post on how the rewriting handles this.

Advertisement
Comments
  1. Kendall says:

    Is there hope for sharing roles between contexts?

    • runefs says:

      Sharing roles between context is by definition not an option in DCI (it’s related to what a role is). It makes for a good subject for a post. So I’ll take that up in a later post

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s