DAVE'S LIFE ON HOLD

The Coffeescript Approach

The past few weekends, I have been playing around with modifying the coffeescript parser and compiler. Most of my explorations have been driven by trying to port Phos to Coffeescript. I have also been playing around with Phos on Nodejs, which would make a very interesting platform. Last night I downloaded Webian and tried Phos out on it and discovered quite a few glitches that made it unsuitable for anything. All of these explorations lead to a list of features which would make JavaScript easier for building interesting applications:


After thinking it though a little further, it struck me that basically all of these design requirements were really just "make it more like Self". Which is understandable, since JS is heavily inspired by Self, and lacks some of the interesting bits that made Self a pleasure to work with. Since Phos was an attempt to bring a Self style development environment to JS, this makes even more sense. So thinking about Coffeescript, and looking at the Self grammar, I began working on a literal Self parser in JS which would translate Self into an intermediate form, that could then be compiled into JavaScript.

One of the key bits to making this real will be implementing the algorithm for Self message sends. This is going to involve creating a "primative" extension to Object.prototype which will do the message send calls. The Self selectors can be safely stored in object properties, and all of the accessor methods can be modeled via variable argument functions with hidden state as Phos already does. Also static slot assignments can also be mapped to functions which return a value. Removing assignment from the language can simply be achieved by using Self syntax, and that translates easily. As a result most objects will simply consist of slots whose keys can not be called via dot notation, and all calls made via a special _send method on Object.prototype.

Since the value of each property will itself be a function, I can also attach annotations to each, by making the function have an .annotation property. I will probably add a method to Function.prototype to manage these as well. Finally, the isParent predicate can exploit the fact that object keys may end in * as in Self, and produce a simple lookup mechanism. The scoping rules will ultimately also require implementing Blocks as a Self object with the block traits, and the nested method. In reality, I can get away by adding some primitives to Function.prototype, and create an invoke method that passes in the function object itself as the Block context. It's properties can be used to capture block state.

In the end, the hardest bit is not implementing Self, but building out a rather massive library of useful objects. All of the JS produced by this compiler will be straight forward JS. But the techniques employed will probably break optimization. That said, since we can use it to compile JS and then post to a KV store like Riak or CouchDB, I can always come back to any code and recompile later to a more optimized form. Mixed in with an environment like Chromeless, this might be a viable way to move Self into the browser.