Hello, I've looked at some of the new code (I do regular 'git pull' on the project) and have some comments, which I discuss below. It occurred to me that it might be a good practice to do regular code reviews to catch bugs and understand the code base we are creating. What are your thoughts about this?
As for the comments, here they are... File source/ir/instructions.js :
/** @class String constant value @augments ConstInstr */ function StrConst(value) { /** Get a string representation of a string constant */ this.toString = function() { return '"' + String(this.value) + '"'; }
... }
1) There's a semicolon missing at the end of the assignment this.toString = ...
2) It would be more space efficient to do, after the function definition, StrConst.prototype.toString = ... (I didn't have that habit when I wrote the parser, but in new code I am now using that style as it can save a lot of space for objects that are frequent).
3) It might be very OOish to have separate classes for each type of constant (null, undefined, boolean, integer, float, string, object) as subclasses to the ConstInstr, but I don't see the point. The code becomes very verbose for no apparent benefit. In the AST there is just one node type for literals with the field "value", and JS introspection can be used on the value when it is important to know the type of value (i.e. typeof x.value == "number"). For example, to test for a constant that is a number equal to 0, it would be possible to do if (x.value === 0) ... instead of if (x instanceof IntConst && x.value == 0) ... Moreover, to test for a number n it would be possible to do if (x.value === n) ... instead of if ((x instanceof IntConst || x instanceof FPConst) && x.value == n) ... If a class hierarchy is used for constants, why stop at those specific types? Why not also have subclasses of "boolean" for "true" and "false", and a subclass of integer for nonnegative integers, and one for 32 bit integers (or fixnums)? Also, to be consistent, the integer and float subclasses should have a "number" superclass. For other types of instructions I agree that a class hierarchy can be beneficial for code clarity and modularity.
4) What is an "Object" constant? I fail to see when it would be useful. In JS the notations [ ... ] and { ... } construct *new* objects when they are evaluated, even when all their fields are constant, including when there are no fields or elements. For example:
function f() { return []; } print(f() == f()); // prints false print(f() === f()); // prints false
5) What is a "ConstInstr"? Is it a constant instruction? What does a constant *instruction* do? Perhaps "ConstExpr", for constant expression, or "ConstOperand" would be a better name?
6) The toString function for strings as written above does not generate the proper escapes for embedded special characters. I understand that this was probably coded expediently to hack something together quickly. I'm in the habit of leaving a "TODO" comment for such code so that I remember to come back to it later and actually implement the proper behaviour.
7) The toString function for strings (which generates escapes) is needed in several places, including the AST pretty-printer, so this is definitely a function that should be in a global module (such as a "miscellaneous" module misc.js).
I'm happy to see that the code base is growing quickly!
Marc