On 04/03/2011 04:58 PM, Stéphane Ducasse wrote:
Thanks I should digest it.
Now what I did not like in our stateful model was that
        - in introduced too many operators
        - I'm not sure I like trait state to be private because it changes a 
lot the smalltalk model
I'm not sure if it changes smalltalk too much! I'd rather say that it stays very much the same. When you weave in a stateful trait it's like weaving in a stateless trait, only behavior is added (from the point of view of the class). As for the extra operators, I'm not sure how weighty the aliasing of state from traits will be... I hope we can limit it.
        - the initialization is not modular so you end up write a lot of 
pattern initializeTrait and calling it.

How you model deal with initialization beside using initform a la clos (because 
you have first class slots ... that I want in pharo -- see the subliminal 
message).
Stef
The idea is that slots define how they should be initialized. This could be just a value like in CLOS, but is preferably something a lot more elaborate.

Another very cool thing that we can do now (which would require 3 lines of change in my system though), is that the slot can also be responsible for instance migration. There are four cases:
1- the instance variable didn't exist and now it does
2- the instance variable existed but disappeared
3- the metaobject changed (new semantics)
4- the metaobject stayed the same

Basically the only case that is "handled" by standard Pharo is case 1; and what you do there is putting nil in the field. In our model the slot could do something more interesting when it's migrating the instances. And we could tackle the other cases too. I think it's starting to get ideal to implement an active context on top ;-)

cheers,
Toon

On Apr 3, 2011, at 12:23 PM, Toon Verwaest wrote:

How are you dealing with the fact that the application of trait with state may 
change the layout of the class user and that you should recompile
all the class method to deal with that. And if you have two traits having state 
you should do the same but for the traits themselves.
So this means that the method in the traits cannot be reused (ok now we do not 
reuse them anymore sniff it was a nice model - reuse without cost of 
duplication).

How your layout object helps you for that?
This is why I want first class slot :)

Stef
I don't think I fully understand what you are saying...

The model is like this at the moment:

Every class has a layout attached to it. Layouts that have slots have 
LayoutScopes. For example, if you have

Class A super: Object slots: #(a b c)
Class B super: A slots: #(d e)

Then you get

Class A<->  PointerLayout ->  LayoutClassScope #(a b c) ->  LayoutClassScope #() 
->  LayoutEmptyScope
Class B<->  PointerLayout ->  LayoutClassScope #(d e) ->  LayoutClassScope #(a b c) 
->  LayoutClassScope #() ->  LayoutEmptyScope

where LayoutClassScope #(a b c) is shared between the scope of B and the layout 
of A. The empty LayoutClassScope comes from Object and is shared as well.

Now if you get a stateful trait, a stateful trait C with slots #(f) looks like 
this:

StatefulTrait C<->  PointerLayout ->  LayoutTraitScope #(f) ->  LayoutEmptyScope

If you were to install the trait C on B, it would become:

Class B<->  PointerLayout ->  LayoutClassScope #(d e) ->  LayoutForkScope ->  
LayoutClassScope #(a b c) ->  LayoutClassScope #() ->  LayoutEmptyScope

where the LayoutForkScope would have sidescopes:
LayoutForkScope sideScopes: { LayoutTraitScope #(f) ->  LayoutEmptyScope }

Then the classbuilder will build classes by always following the public path. 
Sidescopes aren't public. When you compile methods on the trait, its scopes are 
public; but when they are installed, they aren't public since they are 
sidescopes.

However, every method is compiled on the trait or class that provided the 
selector, so when you install the trait-related method, it will see the state 
related to the trait. And when the trait is installed, the sidescopes are 
actually copies of the original traitscope, so the actual fieldindices are 
updated in the LayoutTraitScope when it's installed.

Then how methods get updated based on state changes is at the moment completely 
unrelated to the trait implementation, since methods are already updated in my 
class builder based on a MethodModificationModel that knows how the fields have 
changed. This will use the decompiler/bytecode modification/recompiler to 
update the methods in place.

The only thing that I forgot to do until now is to actually modify all the 
classes that use a trait, every time the state of a trait changes... But that's 
straightforward. We just have to ask for the users of the stateful trait and 
reapply their class modification. That's all nicely modeled already.

As for overlapping state from multiple stateful traits.... there is no 
overlapping state since all state is private to the trait! You can use 2 traits 
with same slot names. This is no problem at all since the state is only seen by 
that trait. And their methods are only compiled on that trait, so the methods 
will always know exactly which of the slots you are referring to.

I hope this helps somehow :) Otherwise ... wait for the paper ;)

cheers,
Toon




Reply via email to