diff options
Diffstat (limited to 'lib/ast.js')
-rw-r--r-- | lib/ast.js | 137 |
1 files changed, 66 insertions, 71 deletions
@@ -44,21 +44,21 @@ "use strict"; function DEFNODE(type, props, methods, base) { - if (arguments.length < 4) base = AST_Node; - if (!props) props = []; - else props = props.split(/\s+/); + if (typeof base === "undefined") base = AST_Node; + props = props ? props.split(/\s+/) : []; var self_props = props; - if (base && base.PROPS) - props = props.concat(base.PROPS); - var code = "return function AST_" + type + "(props){ if (props) { "; - for (var i = props.length; --i >= 0;) { - code += "this." + props[i] + " = props." + props[i] + ";"; - } + if (base && base.PROPS) props = props.concat(base.PROPS); + var code = [ + "return function AST_", type, "(props){", + "if(props){", + ]; + props.forEach(function(prop) { + code.push("this.", prop, "=props.", prop, ";"); + }); var proto = base && new base; - if (proto && proto.initialize || (methods && methods.initialize)) - code += "this.initialize();"; - code += "}}"; - var ctor = new Function(code)(); + if (proto && proto.initialize || methods && methods.initialize) code.push("this.initialize();"); + code.push("}}"); + var ctor = new Function(code.join(""))(); if (proto) { ctor.prototype = proto; ctor.BASE = base; @@ -71,11 +71,11 @@ function DEFNODE(type, props, methods, base) { if (type) { ctor.prototype.TYPE = ctor.TYPE = type; } - if (methods) for (i in methods) if (HOP(methods, i)) { - if (/^\$/.test(i)) { - ctor[i.substr(1)] = methods[i]; + if (methods) for (var name in methods) if (HOP(methods, name)) { + if (/^\$/.test(name)) { + ctor[name.substr(1)] = methods[name]; } else { - ctor.prototype[i] = methods[i]; + ctor.prototype[name] = methods[name]; } } ctor.DEFMETHOD = function(name, method) { @@ -85,7 +85,7 @@ function DEFNODE(type, props, methods, base) { exports["AST_" + type] = ctor; } return ctor; -}; +} var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", { }, null); @@ -148,7 +148,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.body._walk(visitor); }); } @@ -158,11 +158,10 @@ function walk_body(node, visitor) { var body = node.body; if (body instanceof AST_Statement) { body._walk(visitor); - } - else for (var i = 0, len = body.length; i < len; i++) { - body[i]._walk(visitor); - } -}; + } else body.forEach(function(node) { + node._walk(visitor); + }); +} var AST_Block = DEFNODE("Block", "body", { $documentation: "A body of statements (usually braced)", @@ -170,7 +169,7 @@ var AST_Block = DEFNODE("Block", "body", { body: "[AST_Statement*] an array of statements" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { walk_body(this, visitor); }); } @@ -197,7 +196,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { label: "[AST_Label] a label definition" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.label._walk(visitor); this.body._walk(visitor); }); @@ -233,7 +232,7 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", { var AST_Do = DEFNODE("Do", null, { $documentation: "A `do` statement", _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.body._walk(visitor); this.condition._walk(visitor); }); @@ -243,7 +242,7 @@ var AST_Do = DEFNODE("Do", null, { var AST_While = DEFNODE("While", null, { $documentation: "A `while` statement", _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.condition._walk(visitor); this.body._walk(visitor); }); @@ -258,7 +257,7 @@ var AST_For = DEFNODE("For", "init condition step", { step: "[AST_Node?] the `for` update clause, or null if empty" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { if (this.init) this.init._walk(visitor); if (this.condition) this.condition._walk(visitor); if (this.step) this.step._walk(visitor); @@ -274,7 +273,7 @@ var AST_ForIn = DEFNODE("ForIn", "init object", { object: "[AST_Node] the object that we're looping through" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.init._walk(visitor); this.object._walk(visitor); this.body._walk(visitor); @@ -288,7 +287,7 @@ var AST_With = DEFNODE("With", "expression", { expression: "[AST_Node] the `with` expression" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.expression._walk(visitor); this.body._walk(visitor); }); @@ -329,7 +328,7 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", { var body = this.body; var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");"; wrapped_tl = parse(wrapped_tl); - wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) { if (node instanceof AST_Directive && node.value == "$ORIG") { return MAP.splice(body); } @@ -363,12 +362,11 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { if (this.name) this.name._walk(visitor); - var argnames = this.argnames; - for (var i = 0, len = argnames.length; i < len; i++) { - argnames[i]._walk(visitor); - } + this.argnames.forEach(function(argname) { + argname._walk(visitor); + }); walk_body(this, visitor); }); } @@ -398,7 +396,7 @@ var AST_Exit = DEFNODE("Exit", "value", { value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" }, _walk: function(visitor) { - return visitor._visit(this, this.value && function(){ + return visitor._visit(this, this.value && function() { this.value._walk(visitor); }); } @@ -418,7 +416,7 @@ var AST_LoopControl = DEFNODE("LoopControl", "label", { label: "[AST_LabelRef?] the label, or null if none", }, _walk: function(visitor) { - return visitor._visit(this, this.label && function(){ + return visitor._visit(this, this.label && function() { this.label._walk(visitor); }); } @@ -441,7 +439,7 @@ var AST_If = DEFNODE("If", "condition alternative", { alternative: "[AST_Statement?] the `else` part, or null if not present" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.condition._walk(visitor); this.body._walk(visitor); if (this.alternative) this.alternative._walk(visitor); @@ -457,7 +455,7 @@ var AST_Switch = DEFNODE("Switch", "expression", { expression: "[AST_Node] the `switch` “discriminant”" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.expression._walk(visitor); walk_body(this, visitor); }); @@ -478,7 +476,7 @@ var AST_Case = DEFNODE("Case", "expression", { expression: "[AST_Node] the `case` expression" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.expression._walk(visitor); walk_body(this, visitor); }); @@ -494,7 +492,7 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", { bfinally: "[AST_Finally?] the finally block, or null if not present" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { walk_body(this, visitor); if (this.bcatch) this.bcatch._walk(visitor); if (this.bfinally) this.bfinally._walk(visitor); @@ -508,7 +506,7 @@ var AST_Catch = DEFNODE("Catch", "argname", { argname: "[AST_SymbolCatch] symbol for the exception" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.argname._walk(visitor); walk_body(this, visitor); }); @@ -527,11 +525,10 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", { definitions: "[AST_VarDef*] array of variable definitions" }, _walk: function(visitor) { - return visitor._visit(this, function(){ - var definitions = this.definitions; - for (var i = 0, len = definitions.length; i < len; i++) { - definitions[i]._walk(visitor); - } + return visitor._visit(this, function() { + this.definitions.forEach(function(defn) { + defn._walk(visitor); + }); }); } }, AST_Statement); @@ -547,7 +544,7 @@ var AST_VarDef = DEFNODE("VarDef", "name value", { value: "[AST_Node?] initializer, or null of there's no initializer" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.name._walk(visitor); if (this.value) this.value._walk(visitor); }); @@ -582,7 +579,7 @@ var AST_Sequence = DEFNODE("Sequence", "expressions", { expressions: "[AST_Node*] array of expressions (at least two)" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.expressions.forEach(function(node) { node._walk(visitor); }); @@ -601,7 +598,7 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", { var AST_Dot = DEFNODE("Dot", null, { $documentation: "A dotted property access expression", _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.expression._walk(visitor); }); } @@ -610,7 +607,7 @@ var AST_Dot = DEFNODE("Dot", null, { var AST_Sub = DEFNODE("Sub", null, { $documentation: "Index-style property access, i.e. `a[\"foo\"]`", _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.expression._walk(visitor); this.property._walk(visitor); }); @@ -624,7 +621,7 @@ var AST_Unary = DEFNODE("Unary", "operator expression", { expression: "[AST_Node] expression that this unary operator applies to" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.expression._walk(visitor); }); } @@ -646,7 +643,7 @@ var AST_Binary = DEFNODE("Binary", "operator left right", { right: "[AST_Node] right-hand side expression" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.left._walk(visitor); this.right._walk(visitor); }); @@ -661,7 +658,7 @@ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", alternative: "[AST_Node]" }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.condition._walk(visitor); this.consequent._walk(visitor); this.alternative._walk(visitor); @@ -681,11 +678,10 @@ var AST_Array = DEFNODE("Array", "elements", { elements: "[AST_Node*] array of elements" }, _walk: function(visitor) { - return visitor._visit(this, function(){ - var elements = this.elements; - for (var i = 0, len = elements.length; i < len; i++) { - elements[i]._walk(visitor); - } + return visitor._visit(this, function() { + this.elements.forEach(function(element) { + element._walk(visitor); + }); }); } }); @@ -696,11 +692,10 @@ var AST_Object = DEFNODE("Object", "properties", { properties: "[AST_ObjectProperty*] array of properties" }, _walk: function(visitor) { - return visitor._visit(this, function(){ - var properties = this.properties; - for (var i = 0, len = properties.length; i < len; i++) { - properties[i]._walk(visitor); - } + return visitor._visit(this, function() { + this.properties.forEach(function(prop) { + prop._walk(visitor); + }); }); } }); @@ -712,7 +707,7 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { value: "[AST_Node] property value. For getters and setters this is an AST_Accessor." }, _walk: function(visitor) { - return visitor._visit(this, function(){ + return visitor._visit(this, function() { this.value._walk(visitor); }); } @@ -839,12 +834,12 @@ var AST_NaN = DEFNODE("NaN", null, { var AST_Undefined = DEFNODE("Undefined", null, { $documentation: "The `undefined` value", - value: (function(){}()) + value: function(){}() }, AST_Atom); var AST_Hole = DEFNODE("Hole", null, { $documentation: "A hole in an array", - value: (function(){}()) + value: function(){}() }, AST_Atom); var AST_Infinity = DEFNODE("Infinity", null, { @@ -872,11 +867,11 @@ function TreeWalker(callback) { this.visit = callback; this.stack = []; this.directives = Object.create(null); -}; +} TreeWalker.prototype = { _visit: function(node, descend) { this.push(node); - var ret = this.visit(node, descend ? function(){ + var ret = this.visit(node, descend ? function() { descend.call(node); } : noop); if (!ret && descend) { |