In 2007, while sitting in the lobby of Google Zurich, I wrote an implementation of prototypes and traits / mixins in Objective-C. Since then, Quentin has largely rewritten the traits support (see the last blog entry). I rewrote the prototypes support once to better support the new runtime - using runtime functions rather than manipulating the runtime data structures directly.
When I added support for associative references to the new runtime, I borrowed a lot of the code from the old prototypes implementation. The
- The ability to clone an object, so that slot lookups (including methods) are satisfied by the prototype if they can't be satisfied by the object.
These are now both supported in the GNUstep runtime, and will be part of the 1.6 release. We now have an
object_addMethod_np() function, which is the counterpart of
class_addMethod(). The arguments are almost identical, but it takes a single object instead of the class and just modifies that object.
We also have
object_getPrototype_np(). These clone an object and return its prototype. The prototypes support in EtoileFoundation is now just a thin wrapper around these.
Because this stuff works in Objective-C, we can also use it in languages that LanguageKit supports. For example, you can run this little Smalltalk program:
NSObject subclass: SmalltalkTool [ run [ |a b | a := NSObject new. b := a clone. a setValue: [ :this | ETTranscript show: 'self: '; show: this; show: ' prototype: '; show: this prototype; show: ' foo: '; show: (this slotValueForKey: 'Foo'); cr ] forKey: 'print'. a print. b print. b setValue: 'A fish!' forKey: 'Foo'. b print. ] ]
The output is:
self: <NSObject: 0x2b3b081c> prototype: (null) foo: (null) self: <NSObject: 0x2b2d9efc> prototype: <NSObject: 0x2b3b081c> foo: (null) self: <NSObject: 0x2b2d9efc> prototype: <NSObject: 0x2b3b081c> foo: A fish!
As always, this is lowered to the same sort of code that you'll get from Objective-C. Prototypes are generally slower than classes in the current implementation, but they are more flexible, and the advantage of LanguageKit is that you can combine the two easily. A language like EScript would be great for prototyping, while a language like Smalltalk is better for the real implementation. In the future, we'll be able to move between them completely fluidly.
Oh, and while I'm talking about EScript, the current code in svn is the result of a big refactoring effort. I've cleaned it up in a lot of places, and it now uses ARC or GC, not its own ad-hoc retain / release code. This should make it a bit more reliable, and means that it can benefit from the same ARC optimiser that clang uses. Expect a new release soon...