Read my book

I wrote books about Webpack and React. Check them out!

Monday, May 16, 2011

Using JSShaper to Provide Operator Overloading for JavaScript

In this post I'm going to show you how to use JSShaper to implement operator overloading for JavaScript. It's one of those features I've missed a lot.

I tried something similar previously by writing a primitive JavaScript precompiler using Python. JSShaper provides more reasonable way to achieve the same result by directly modifying JavaScript AST. Code-wise the solution is more than adequate as you shall see.

The current approach has still some limitations. I believe it should provide a good starting point for some further experiments, though.

The Idea


The whole point of operator overloading is to make it possible to write code using proper operators instead of having to rely on methods. It is particularly useful in case you want to implement your own custom types. This is common especially if you are dealing with math.

I use a special Point class a lot. It acts like a two-dimensional vector and provides a selection of functionality. The following listing contains its source:

In order to operate on Points, we might use code like this in vanilla JavaScript:

As you can see it's not very readable. Pure math notation works much better as evidenced by the comment. JSShaper allows us to reach this.

The Implementation


Essentially JSShaper takes some source code in and spits transformed version out. In order to implement operator overloading for JavaScript, we have to abstract out actual operations performed and then generate the code matching this abstraction. Here's one example of such abstraction (valid JavaScript).

Source:

Target:

As you can see the idea is that we transform each operation to some kind of a call. This call deals with actual polymorphism. Implementation of the operations could look something like this:

In this case we just check if type of the first operation input matches to any of our classes and then execute its method matching given type matched. Else we will just perform what JavaScript would perform usually.

We're still missing one vital bit. The plugin performing actual transformation! With some guidance from Olov I ended up with following kind of solution:

In case you want to play around with my implementation, you can find it at GitHub.

To run the transformation, you could try something along this at terminal (expects that you are with /src): node run-shaper.js -- examples/op-overloading/tests/simple.js examples/op-overloading/op-overloading.js --source . In addition to node JSShaper should work with various other engines. Check out JSShaper documentation for more accurate information.

Known Limitations


The current implementation is missing support for assignment by operation (ie. a += 2;). Apparently it should be possible to implement this using restricter.

In addition the whole hack needs to be bolted into your build chain somehow. How to do that probably depends a lot on the situation.

Conclusion


Operator overloading provides one powerful example of what you can achieve using JSShaper. I'm very new to the tool. It seems pretty dang cool, nonetheless.

I think it's really great to see tools like JSShaper around. People interested in this kind of stuff should probably check out Google's Traceur. It's awesome to have these kind of meta-programming tools available these days.

I want to thank Olov Lassus, the author of JSShaper, for providing inspiration and guidance. Cheers!