diff options
author | Mihai Bazon <mihai@bazon.net> | 2012-09-05 11:31:02 +0300 |
---|---|---|
committer | Mihai Bazon <mihai@bazon.net> | 2012-09-05 11:39:43 +0300 |
commit | 8633b0073f016fddd655ae5e1f1726287a24828d (patch) | |
tree | 83f03aac1f74a30555e44edfa2a75eb5ca372e6f /lib/ast.js | |
parent | 1b5183dd5ee7d2b147f5862c9abf8f45f50fc82f (diff) | |
download | tracifyjs-8633b0073f016fddd655ae5e1f1726287a24828d.tar.gz tracifyjs-8633b0073f016fddd655ae5e1f1726287a24828d.zip |
cleaned up usage of AST_BlockStatement
The following nodes were instances of AST_BlockStatement: AST_Scope,
AST_SwitchBlock, AST_SwitchBranch. Also, AST_Try, AST_Catch, AST_Finally
were having a body instanceof AST_BlockStatement.
Overloading the meaning of AST_BlockStatement this way turned out to be a
mess; we now have an AST_Block class that is the base class for things
having a block of statements (might or might not be bracketed). The
`this.body` of AST_Scope, AST_Try, AST_Catch, AST_Finally is now an array of
statements (as they inherit from AST_Block).
Avoiding calling superclass's _walk function in walkers (turns out we walked
a node multiple times).
Diffstat (limited to 'lib/ast.js')
-rw-r--r-- | lib/ast.js | 63 |
1 files changed, 31 insertions, 32 deletions
@@ -127,7 +127,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", null, { $documentation: "A statement consisting of an expression, i.e. a = 1 + 2." }, AST_Statement); -var AST_BlockStatement = DEFNODE("BlockStatement", "required", { +var AST_BlockStatement = DEFNODE("BlockStatement", null, { $documentation: "A block statement.", _walk: function(visitor) { return visitor._visit(this, function(){ @@ -138,6 +138,21 @@ var AST_BlockStatement = DEFNODE("BlockStatement", "required", { } }, AST_Statement); +function walk_body(node, visitor) { + if (node.body instanceof Array) node.body.forEach(function(stat){ + stat._walk(visitor); + }); else node.body._walk(visitor); +}; + +var AST_Block = DEFNODE("Block", null, { + $documentation: "A block of statements (usually always bracketed)", + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + }); + } +}, AST_Statement); + var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { $documentation: "The empty statement (empty block or simply a semicolon).", _walk: function(visitor) { @@ -213,8 +228,8 @@ var AST_With = DEFNODE("With", "expression", { /* -----[ scope and functions ]----- */ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", { - $documentation: "Base class for all statements introducing a lexical scope" -}, AST_BlockStatement); + $documentation: "Base class for all statements introducing a lexical scope", +}, AST_Block); var AST_Toplevel = DEFNODE("Toplevel", null, { initialize: function() { @@ -231,7 +246,7 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { this.argnames.forEach(function(arg){ arg._walk(visitor); }); - this.body._walk(visitor); + walk_body(this, visitor); }); } }, AST_Scope); @@ -311,25 +326,14 @@ var AST_Switch = DEFNODE("Switch", "expression", { var AST_SwitchBlock = DEFNODE("SwitchBlock", null, { $documentation: "The switch block is somewhat special, hence a special node for it", - initialize: function() { - this.required = true; - }, -}, AST_BlockStatement); +}, AST_Block); var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { $documentation: "Base class for `switch` branches", - initialize: function() { - this.required = true; - }, -}, AST_BlockStatement); +}, AST_Block); var AST_Default = DEFNODE("Default", null, { $documentation: "A `default` switch branch", - _walk: function(visitor) { - return visitor._visit(this, function(){ - AST_BlockStatement.prototype._walk.call(this, visitor); - }); - } }, AST_SwitchBranch); var AST_Case = DEFNODE("Case", "expression", { @@ -337,23 +341,23 @@ var AST_Case = DEFNODE("Case", "expression", { _walk: function(visitor) { return visitor._visit(this, function(){ this.expression._walk(visitor); - AST_BlockStatement.prototype._walk.call(this, visitor); + walk_body(this, visitor); }); } }, AST_SwitchBranch); /* -----[ EXCEPTIONS ]----- */ -var AST_Try = DEFNODE("Try", "btry bcatch bfinally", { +var AST_Try = DEFNODE("Try", "bcatch bfinally", { $documentation: "A `try` statement", _walk: function(visitor) { return visitor._visit(this, function(){ - this.btry._walk(visitor); + walk_body(this, visitor); if (this.bcatch) this.bcatch._walk(visitor); if (this.bfinally) this.bfinally._walk(visitor); }); } -}, AST_Statement); +}, AST_Block); // XXX: this is wrong according to ECMA-262 (12.4). the catch block // should introduce another scope, as the argname should be visible @@ -361,24 +365,19 @@ var AST_Try = DEFNODE("Try", "btry bcatch bfinally", { // IE which simply introduces the name in the surrounding scope. If // we ever want to fix this then AST_Catch should inherit from // AST_Scope. -var AST_Catch = DEFNODE("Catch", "argname body", { +var AST_Catch = DEFNODE("Catch", "argname", { $documentation: "A `catch` node; only makes sense as part of a `try` statement", _walk: function(visitor) { return visitor._visit(this, function(){ this.argname._walk(visitor); - this.body._walk(visitor); + walk_body(this, visitor); }); } -}); +}, AST_Block); -var AST_Finally = DEFNODE("Finally", "body", { - $documentation: "A `finally` node; only makes sense as part of a `try` statement", - _walk: function(visitor) { - return visitor._visit(this, function(){ - this.body._walk(visitor); - }); - } -}); +var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" +}, AST_Block); /* -----[ VAR/CONST ]----- */ |