I'm progressing fairly well in the IR translation. I now have code generation for closures, and exception handling. I also believe I'm supporting all primitive operators. I added code to Marc's ast pass 1 to transform expressions of the form x += y into x = x + y, to minimize the code generation effort. I'm in the process of implementing code generation for the with statement. After this, I'll be missing the for-in loop and the switch statement, which I hope to complete by Wednesday.
I wanted to run some ideas by you guys:
1) To implement the for-in loop, we will need some way to iterate over the property names of an object. This will require some sort of iterator object, and property iteration instructions at the IR level. I am considering using a simple index integer as an iterator, and having two IR instructions, one to find the next property index, and one to get the property name at the current index. The index would be initialized at 0, and could possibly go to -1 when there are no more properties to be found.
Another possibility is to make the iteration work with an abstract iterator object, with iterator manipulations to get an iterator on an object, get the next property, and check if the iterator is still valid.
2) Many of the IR instruction classes I wrote so far are very resemblant. I am considering writing a function to generate a "generic" instruction constructor using a closure (an instruction class maker function), in order to minimize the amount of code. This way, it would actually be easy to have an instruction class for each arithmetic operator, for example, and the "instanceof" check would still work on instruction classes created this way.
3) I've been brainstorming about inline IR, and how to code handlers to implement things like function calls and arithmetic operators. It seems to me like it's still not 100% clear how to factor these in terms of JavaScript code and inline IR, or even how to structure the lower levels of IR to make them most convenient to use.
I was discussing with Erick, and I was thinking that, for a first version of our compiler, we could write all handlers for function calls, arithmetic operators, etc., in x86 directly. Once we see what kind of code has to actually go in there, it will become clearer how we can refactor this into higher level IR to make it more optimizable/specializable/portable. For a first compiler version, we could write handlers to only support a few simple types, and a mimimal subset of the language in this way.
- Maxime