merging in gfxmonk's cleanup to how children of nodes are determined. Removing some (so far) unused portions.

This commit is contained in:
Jeremy Ashkenas
2010-05-10 22:41:18 -04:00
parent 3324b03a5d
commit 393fbf1b66
2 changed files with 49 additions and 74 deletions

View File

@@ -1,15 +1,15 @@
(function(){ (function(){
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, CurryNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, children, compact, del, flatten, helpers, literal, merge, statement, utility; var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, CurryNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, children, compact, del, flatten, helpers, literal, merge, statement, utility;
var __slice = Array.prototype.slice, __bind = function(func, obj, args) { var __slice = Array.prototype.slice, __extends = function(child, parent) {
return function() {
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
};
}, __extends = function(child, parent) {
var ctor = function(){ }; var ctor = function(){ };
ctor.prototype = parent.prototype; ctor.prototype = parent.prototype;
child.__superClass__ = parent.prototype; child.__superClass__ = parent.prototype;
child.prototype = new ctor(); child.prototype = new ctor();
child.prototype.constructor = child; child.prototype.constructor = child;
}, __bind = function(func, obj, args) {
return function() {
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
};
}; };
// `nodes.coffee` contains all of the node classes for the syntax tree. Most // `nodes.coffee` contains all of the node classes for the syntax tree. Most
// nodes are created as the result of actions in the [grammar](grammar.html), // nodes are created as the result of actions in the [grammar](grammar.html),
@@ -50,8 +50,8 @@
var child_attrs; var child_attrs;
var _b = arguments.length, _c = _b >= 2; var _b = arguments.length, _c = _b >= 2;
child_attrs = __slice.call(arguments, 1, _b - 0); child_attrs = __slice.call(arguments, 1, _b - 0);
klass.prototype._children_attributes = child_attrs; klass.prototype.children_attributes = child_attrs;
return klass.prototype._children_attributes; return klass.prototype.children_attributes;
}; };
//### BaseNode //### BaseNode
// The **BaseNode** is the abstract base class for all nodes in the syntax tree. // The **BaseNode** is the abstract base class for all nodes in the syntax tree.
@@ -131,12 +131,12 @@
BaseNode.prototype.contains = function contains(block) { BaseNode.prototype.contains = function contains(block) {
var contains; var contains;
contains = false; contains = false;
this._traverse_children(false, __bind(function(node, attr, index) { this.traverse_children(false, function(node) {
if (block(node)) { if (block(node)) {
contains = true; contains = true;
return false; return false;
} }
}, this)); });
return contains; return contains;
}; };
// Is this node of a certain type, or does it contain the type? // Is this node of a certain type, or does it contain the type?
@@ -154,7 +154,7 @@
}; };
// Perform an in-order traversal of the AST. Crosses scope boundaries. // Perform an in-order traversal of the AST. Crosses scope boundaries.
BaseNode.prototype.traverse = function traverse(block) { BaseNode.prototype.traverse = function traverse(block) {
return this._traverse_children(true, block); return this.traverse_children(true, block);
}; };
// `toString` representation of the node, for inspecting the parse tree. // `toString` representation of the node, for inspecting the parse tree.
// This is what `coffee --nodes` prints out. // This is what `coffee --nodes` prints out.
@@ -171,46 +171,37 @@
}).call(this).join(''); }).call(this).join('');
}; };
BaseNode.prototype.children = function children() { BaseNode.prototype.children = function children() {
var _children; var nodes;
_children = []; nodes = [];
this._each_child(function(child) { this.each_child(function(node) {
return _children.push(child); return nodes.push(node);
}); });
return _children; return nodes;
}; };
BaseNode.prototype._each_child = function _each_child(func) { BaseNode.prototype.each_child = function each_child(func) {
var _b, _c, _d, _e, _f, _g, attr, child, child_collection, i, result; var _b, _c, _d, _e, _f, _g, attr, child;
_c = this._children_attributes; _c = this.children_attributes;
for (_b = 0, _d = _c.length; _b < _d; _b++) { for (_b = 0, _d = _c.length; _b < _d; _b++) {
attr = _c[_b]; attr = _c[_b];
child_collection = this[attr]; if (this[attr]) {
if (!((typeof child_collection !== "undefined" && child_collection !== null))) { _f = flatten([this[attr]]);
continue;
}
if (child_collection instanceof Array) {
i = 0;
_f = child_collection;
for (_e = 0, _g = _f.length; _e < _g; _e++) { for (_e = 0, _g = _f.length; _e < _g; _e++) {
child = _f[_e]; child = _f[_e];
result = func(child, attr, i); if (func(child) === false) {
if (result === false) {
return null; return null;
} }
i += 1;
} }
} else {
func(child_collection, attr);
} }
} }
}; };
BaseNode.prototype._traverse_children = function _traverse_children(cross_scope, func) { BaseNode.prototype.traverse_children = function traverse_children(cross_scope, func) {
if (!(this._children_attributes)) { if (!(this.children_attributes)) {
return null; return null;
} }
return this._each_child(function(child, attr, i) { return this.each_child(function(child) {
func.apply(this, arguments); func.apply(this, arguments);
if (child instanceof BaseNode) { if (child instanceof BaseNode) {
return child._traverse_children(cross_scope, func); return child.traverse_children(cross_scope, func);
} }
}); });
}; };
@@ -263,10 +254,6 @@
Expressions.prototype.empty = function empty() { Expressions.prototype.empty = function empty() {
return this.expressions.length === 0; return this.expressions.length === 0;
}; };
// Make a copy of this node.
Expressions.prototype.copy = function copy() {
return new Expressions(this.Expressions.slice());
};
// An Expressions node does not return its entire body, rather it // An Expressions node does not return its entire body, rather it
// ensures that the final expression is returned. // ensures that the final expression is returned.
Expressions.prototype.make_return = function make_return() { Expressions.prototype.make_return = function make_return() {
@@ -1157,11 +1144,11 @@
CodeNode.prototype.top_sensitive = function top_sensitive() { CodeNode.prototype.top_sensitive = function top_sensitive() {
return true; return true;
}; };
// Short-circuit _traverse_children method to prevent it from crossing scope boundaries // Short-circuit traverse_children method to prevent it from crossing scope boundaries
// unless cross_scope is true // unless cross_scope is true
CodeNode.prototype._traverse_children = function _traverse_children(cross_scope, func) { CodeNode.prototype.traverse_children = function traverse_children(cross_scope, func) {
if (cross_scope) { if (cross_scope) {
return CodeNode.__superClass__._traverse_children.call(this, cross_scope, func); return CodeNode.__superClass__.traverse_children.call(this, cross_scope, func);
} }
}; };
CodeNode.prototype.toString = function toString(idt) { CodeNode.prototype.toString = function toString(idt) {

View File

@@ -25,7 +25,7 @@ statement: (klass, only) ->
(klass::is_pure_statement: -> true) if only (klass::is_pure_statement: -> true) if only
children: (klass, child_attrs...) -> children: (klass, child_attrs...) ->
klass::_children_attributes: child_attrs klass::children_attributes: child_attrs
#### BaseNode #### BaseNode
@@ -96,11 +96,11 @@ exports.BaseNode: class BaseNode
# scope boundaries. # scope boundaries.
contains: (block) -> contains: (block) ->
contains: false contains: false
@_traverse_children false, (node, attr, index) => @traverse_children false, (node) ->
if block(node) if block(node)
contains: true contains: true
return false return false
return contains contains
# Is this node of a certain type, or does it contain the type? # Is this node of a certain type, or does it contain the type?
contains_type: (type) -> contains_type: (type) ->
@@ -112,7 +112,7 @@ exports.BaseNode: class BaseNode
@is_pure_statement() or @contains (n) -> n.is_pure_statement() @is_pure_statement() or @contains (n) -> n.is_pure_statement()
# Perform an in-order traversal of the AST. Crosses scope boundaries. # Perform an in-order traversal of the AST. Crosses scope boundaries.
traverse: (block) -> @_traverse_children true, block traverse: (block) -> @traverse_children true, block
# `toString` representation of the node, for inspecting the parse tree. # `toString` representation of the node, for inspecting the parse tree.
# This is what `coffee --nodes` prints out. # This is what `coffee --nodes` prints out.
@@ -121,28 +121,20 @@ exports.BaseNode: class BaseNode
'\n' + idt + @constructor.name + (child.toString(idt + TAB) for child in @children()).join('') '\n' + idt + @constructor.name + (child.toString(idt + TAB) for child in @children()).join('')
children: -> children: ->
_children: [] nodes: []
@_each_child (child) -> _children.push(child) @each_child (node) -> nodes.push node
_children nodes
_each_child: (func) -> each_child: (func) ->
for attr in @_children_attributes for attr in @children_attributes when this[attr]
child_collection: this[attr] for child in flatten [this[attr]]
continue unless child_collection? return if func(child) is false
if child_collection instanceof Array
i: 0
for child in child_collection
result: func(child, attr, i)
return if result is false
i += 1
else
func(child_collection, attr)
_traverse_children: (cross_scope, func) -> traverse_children: (cross_scope, func) ->
return unless @_children_attributes return unless @children_attributes
@_each_child (child, attr, i) -> @each_child (child) ->
func.apply(this, arguments) func.apply(this, arguments)
child._traverse_children(cross_scope, func) if child instanceof BaseNode child.traverse_children(cross_scope, func) if child instanceof BaseNode
# Default implementations of the common node identification methods. Nodes # Default implementations of the common node identification methods. Nodes
# will override these with custom logic, if needed. # will override these with custom logic, if needed.
@@ -180,10 +172,6 @@ exports.Expressions: class Expressions extends BaseNode
empty: -> empty: ->
@expressions.length is 0 @expressions.length is 0
# Make a copy of this node.
copy: ->
new Expressions @Expressions.slice()
# An Expressions node does not return its entire body, rather it # An Expressions node does not return its entire body, rather it
# ensures that the final expression is returned. # ensures that the final expression is returned.
make_return: -> make_return: ->
@@ -853,9 +841,9 @@ exports.CodeNode: class CodeNode extends BaseNode
top_sensitive: -> top_sensitive: ->
true true
# Short-circuit _traverse_children method to prevent it from crossing scope boundaries # Short-circuit traverse_children method to prevent it from crossing scope boundaries
# unless cross_scope is true # unless cross_scope is true
_traverse_children: (cross_scope, func) -> super(cross_scope, func) if cross_scope traverse_children: (cross_scope, func) -> super(cross_scope, func) if cross_scope
toString: (idt) -> toString: (idt) ->
idt: or '' idt: or ''