Folks -
My experiments with a simpler traits implementation are starting to bear results. Attached a version of NanoTraits which is the smallest implementation of traits that I could come up with. Making it loadable inside a current trunk image has been a bit of a challenge since it needs to operate side-by-side with the existing traits during load (apologies for the various isKindOf:'s), but it seems to work fairly well now (fingers crossed). There are few differences to the Berne trait implementation including: - TraitDescription is a subclass of ClassDescription. This is the main simplification since it avoids creating a dual trait/class hierarchy. It comes at the "cost" of having potentially support for instance variables in traits (i.e., stateful traits) but since this isn't exposed there is very little actual overhead. - NanoClassTrait is the class of NanoTrait (i.e., the same meta structure that classes have). Since this models exactly the structure that classes have, it makes browser integration significantly simpler (NanoTraits would work fine in 3.8 for example without changing browsers etc) and allows us to remove the (now unecessary) additional tool support. - Methods used from other traits retain a "method home" reference so that for any method in a class you can tell whether it was defined locally or in some other trait. This makes several things *a lot* easier and will allow us to get rid of all the localSelectors stuff in ClassDescription in the next pass (Igor - this gives you the information where a method is from without poking in other places; just ask i.e., (ClassDescription>>#addSelectorSilently:withMethod:) methodHome ==> TAccessingMethodDictDescription) - Some previously invalid trait composition are now valid, in particular T - {#x} - {#y} (meaning T- {#x. #y}) as well as T @ {#x->#y} @ (#a -> #b} (meaning T @ { #x -> #y. #a -> #b}. - You can't mix Berne and Nano traits. If you try it, things will blow up (incompatible internals). - You can't mix Berne and Nano traits tests. I don't know why but if you run them at the same time things go wrong. To install NanoTraits: * Load NanoTraits-Kernel.st * Load NanoTraits-Tests.st * Load NanoTraits-Extensions.cs * Run the NanoTraits-Tests * (assuming all tests are green) execute: NanoTraits install. This will make NanoTraits the default traits implementation and convert any existing traits. I've successfully played with Nile (the only other traits stuff I was aware about besides the class kernel which is a bit difficult to experiment with) but from what I can tell everything should work just fine. The one extra thing I'm seriously considering after our recent discussions is to change NanoTraits to actually use mixins to implement traits composition. What this would mean is that instead of adding trait methods to a class directly, they would be added to a (hidden) superclass. Composition rules would be unaffected by this change but it would solve the issue of trait methods messing up the methods *actually* defined in a class, showing a seven times when looking for implementors and more. Consider this my holiday gift to the community :-) Cheers, - Andreas NanoTraits-Kernel.st.gz (10K) Download Attachment NanoTraits-Tests.st.gz (11K) Download Attachment NanoTraits-Extensions.cs.gz (10K) Download Attachment |
2009/12/22 Andreas Raab <[hidden email]>:
> Folks - > > My experiments with a simpler traits implementation are starting to bear > results. Attached a version of NanoTraits which is the smallest > implementation of traits that I could come up with. Making it loadable > inside a current trunk image has been a bit of a challenge since it needs to > operate side-by-side with the existing traits during load (apologies for the > various isKindOf:'s), but it seems to work fairly well now (fingers > crossed). There are few differences to the Berne trait implementation > including: > > - TraitDescription is a subclass of ClassDescription. This is the main > simplification since it avoids creating a dual trait/class hierarchy. It > comes at the "cost" of having potentially support for instance variables in > traits (i.e., stateful traits) but since this isn't exposed there is very > little actual overhead. > > - NanoClassTrait is the class of NanoTrait (i.e., the same meta structure > that classes have). Since this models exactly the structure that classes > have, it makes browser integration significantly simpler (NanoTraits would > work fine in 3.8 for example without changing browsers etc) and allows us to > remove the (now unecessary) additional tool support. > > - Methods used from other traits retain a "method home" reference so that > for any method in a class you can tell whether it was defined locally or in > some other trait. This makes several things *a lot* easier and will allow us > to get rid of all the localSelectors stuff in ClassDescription in the next > pass (Igor - this gives you the information where a method is from without > poking in other places; just ask i.e., > (ClassDescription>>#addSelectorSilently:withMethod:) methodHome ==> > TAccessingMethodDictDescription) > And how to determine that SomeClass>>methodA is actually SomeTrait>>methodB which in own turn SomeOtherTrait>>methodC ? So, i could take a source code from SomeOtherTrait>>methodC and put a header "SomeOtherTrait>>methodC" and replace selector to: methodA :) > - Some previously invalid trait composition are now valid, in particular T - > {#x} - {#y} (meaning T- {#x. #y}) as well as T @ {#x->#y} @ (#a -> #b} > (meaning T @ { #x -> #y. #a -> #b}. > T1 - T2? > - You can't mix Berne and Nano traits. If you try it, things will blow up > (incompatible internals). > > - You can't mix Berne and Nano traits tests. I don't know why but if you run > them at the same time things go wrong. > > To install NanoTraits: > * Load NanoTraits-Kernel.st > * Load NanoTraits-Tests.st > * Load NanoTraits-Extensions.cs > * Run the NanoTraits-Tests > * (assuming all tests are green) execute: NanoTraits install. > > This will make NanoTraits the default traits implementation and convert any > existing traits. I've successfully played with Nile (the only other traits > stuff I was aware about besides the class kernel which is a bit difficult to > experiment with) but from what I can tell everything should work just fine. > > The one extra thing I'm seriously considering after our recent discussions > is to change NanoTraits to actually use mixins to implement traits > composition. What this would mean is that instead of adding trait methods to > a class directly, they would be added to a (hidden) superclass. Composition > rules would be unaffected by this change but it would solve the issue of > trait methods messing up the methods *actually* defined in a class, showing > a seven times when looking for implementors and more. > My primary concern with traits, is lack of system change notification support. We need them in deltastreams. > Consider this my holiday gift to the community :-) > > Cheers, > - Andreas -- Best regards, Igor Stasenko AKA sig. |
Igor Stasenko wrote:
> 2009/12/22 Andreas Raab <[hidden email]>: > > And how to determine that > SomeClass>>methodA > is actually > SomeTrait>>methodB > which in own turn > SomeOtherTrait>>methodC > ? Easy. In v0.6 (attached) we now retain a reference to the original compiled method instead of just the original home. Using the original trait method you can find out things like: method := SomeClass>>#methodA. method originalTraitMethod => CompiledMethod(SomeTrait>>methodB). method originalTraitMethod originalTraitMethod => CompiledMethod(SomeOtherTrait>>methodC). method originalTraitMethod originalTraitMethod originalTraitMethod => nil etc. Obviously, the methodHome the same for all of them. >> - Some previously invalid trait composition are now valid, in particular T - >> {#x} - {#y} (meaning T- {#x. #y}) as well as T @ {#x->#y} @ (#a -> #b} >> (meaning T @ { #x -> #y. #a -> #b}. >> > T1 - T2? Left as an exercise for the reader :-) Seriously, it's straightforward: First, implement #includesSelector: and #selectorsAndMethodsDo: in TraitExclusion so that it works with traits in addition to symbols in the list of exclusions. Next, implement #addTraitUser: and #removeTraitUser: in TraitExclusion so that it looks for additional traits inside the exclusions. Done. That's all. Four methods. > My primary concern with traits, is lack of system change notification support. > We need them in deltastreams. What kind of support is missing? In NanoTraits, almost all of this stuff is absolutely trivial because the entire implementation is deliberately simple and trying to fit in the existing class kernel. Some more things new in v0.6: - We no longer use a method property for the method home since this shows in decompiles. Instead we use NanoTraitMethodState (subclass of AddlMethodState) which keeps a reference to the original compiled method. - Support for Monticello. v0.6 is compatible with Berne traits when using Monticello. - Various fixes and a few more isKindOf:'s to avoid interactions with no longer used methods BTW, v0.6 should be considered a release candidate. Unless there are bugs that I haven't found yet, I think this version is good to go. Cheers, - Andreas NanoTraits-v0.6.zip (35K) Download Attachment |
In reply to this post by Andreas.Raab
On Mon, Dec 21, 2009 at 5:19 PM, Andreas Raab <[hidden email]> wrote:
This will make NanoTraits the default traits implementation and convert any existing traits. I've successfully played with Nile (the only other traits stuff I was aware about besides the class kernel which is a bit difficult to experiment with) but from what I can tell everything should work just fine. There is also this: http://map.squeak.org/package/566fac9f-7474-4823-8fc6-30a4a4b65f0f (but, I would have to dig the code off an old server in my closet)
It wasn't anything as fancy as what you've done with the meta-model integration however. I was using it for implementing a kind of transactional system back then. - Stephen
|
Free forum by Nabble | Edit this page |