mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-04-11 03:00:13 -04:00
merging in gfxmonk's cleanup to how children of nodes are determined. Removing some (so far) unused portions.
This commit is contained in:
77
lib/nodes.js
77
lib/nodes.js
@@ -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) {
|
||||||
|
|||||||
@@ -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 ''
|
||||||
|
|||||||
Reference in New Issue
Block a user