In this post I will explain with an example how Smalltalk code can be compiled to Javascript using AjTalk.Compiler, named ajtalkc. As usual, the code is in my repo:
http://code.google.com/p/ajtalk/
I filed out a simple Pharo class: Point. Top fragment:
Object subclass: #Point instanceVariableNames: 'x y' classVariableNames: '' poolDictionaries: '' category: 'Graphics-Primitives'! !Point commentStamp: '<historical>' prior: 0! I represent an x-y pair of numbers usually designating a location on the screen.! !Point methodsFor: '*Polymorph-Geometry' stamp: 'gvc 10/31/2006 11:01'! directionToLineFrom: p1 to: p2 "Answer the direction of the line from the receiver position. < 0 => left (receiver to right) = => on line > 0 => right (receiver to left)." ^((p2 x - p1 x) * (self y - p1 y)) - ((self x - p1 x) * (p2 y - p1 y))! ! ....I compiled it using the ajtalkc.exe command line program (see AjTalk.Compiler console project in AjTalk solution; it has a CodeFiles folder with my fileouts):
ajtalkc CodeFiles\PharoCorePoint.st
A new file is created: Program.js. Let's explore how a class is represented in Javascript. These lines define the Point class as a Javascript function, and its class as another Javascript function:
function PointClass() { } function Point() { }Nothing special. The following two lines are:
Point.prototype.__class = PointClass.prototype; Point.classPrototype = PointClass.prototype;In this way, every instance of Point class has a variable __class that points to the singleton PointClass.prototype. And the function/”class” Point has a variable classPrototype to point to the same singleton, if it needed.
How to create a new instance of point? Using a PointClass method, in this case defining its basicNew method:
PointClass.prototype['_basicNew'] = function() { return new Point(); };I added an underscore to avoid name collision with any Javascript common method.
Now, how to assure all instances have two instance variables? Defining them at the propotype:
Point.prototype.x = null; Point.prototype.y = null;And the most interesting par: how to translate a method? Let be the min method in Smalltalk:
min "Answer a number that is the minimum of the x and y of the receiver." ^self x min: self y! !Its translation to a method in the Point prototype:
Point.prototype['_min'] = function() { var self = this; return send(send(self, '_x'), '_min_', [send(self, '_y')]); };Notice that I defined the variable self to be used in the rest of the method (specially in any Javascript closure, where this could not survive). And the use of an utility method send that takes: a target object, the name of the method to invoke, and an array with the arguments.
All this is work in progress. Now, I'm generating additional lines to use Program.js from Node.js, but if I removed them, I could use the code at client side, from the browser. I should write different compilers for server and client sides. I plan to write a translator to Ruby, too, just as a proof of concept of the power of having an abstract model of the program to execute.
Next topics: compiler options; compiling to browser, to node; how to run in Node.js; using the generated Javascript code; utility functions, inheritance, blocks and closures.
Keep tuned!
Angel “Java” Lopez
http://www.ajlopez.com
[...] Next Post [...]
Pingback by AjTalk and Javascript (Part 1) Abstract Model « Angel “Java” Lopez on Blog — December 13, 2011 @ 10:11 am
Finally I read, interesting experiment.
You wrote the translator to javascript from scratch? What ideas do you used in it?
I lik the feature of remove a few lines and have client code or add a few lines and add different server side code.
Nice job!
Comment by garduino (@garduino) — December 18, 2011 @ 8:58 pm
[...] working on the implementation of my open source Smalltalk VM AjTalk (Recently, I was posting about translation from Smalltalk to Javascript). My first contact with Smalltalk was in the eighties, and since then, I was interested in it. It [...]
Pingback by Smalltalk: Links, News and Resources (1) « Angel “Java” Lopez on Blog — December 23, 2011 @ 8:52 am