mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-04-11 03:00:13 -04:00
Merging type, children and statement functions
This commit is contained in:
228
lib/nodes.js
228
lib/nodes.js
@@ -1,12 +1,12 @@
|
||||
(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, index_of, literal, merge, statement, type, utility;
|
||||
var __slice = Array.prototype.slice, __extends = function(child, parent) {
|
||||
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, compact, del, flatten, helpers, index_of, literal, merge, register, utility;
|
||||
var __extends = function(child, parent) {
|
||||
var ctor = function(){ };
|
||||
ctor.prototype = parent.prototype;
|
||||
child.__superClass__ = parent.prototype;
|
||||
child.prototype = new ctor();
|
||||
child.prototype.constructor = child;
|
||||
}, __bind = function(func, obj, args) {
|
||||
}, __slice = Array.prototype.slice, __bind = function(func, obj, args) {
|
||||
return function() {
|
||||
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
|
||||
};
|
||||
@@ -32,31 +32,28 @@
|
||||
merge = _a.merge;
|
||||
del = _a.del;
|
||||
index_of = _a.index_of;
|
||||
type = function(klass, name) {
|
||||
klass.prototype.constructor_name = name;
|
||||
return klass.prototype.constructor_name;
|
||||
};
|
||||
// Helper function that marks a node as a JavaScript *statement*, or as a
|
||||
// *pure_statement*. Statements must be wrapped in a closure when used as an
|
||||
// expression, and nodes tagged as *pure_statement* cannot be closure-wrapped
|
||||
// without losing their meaning.
|
||||
statement = function(klass, only) {
|
||||
klass.prototype.is_statement = function() {
|
||||
return true;
|
||||
};
|
||||
if (only) {
|
||||
klass.prototype.is_pure_statement = function() {
|
||||
// Helper function that registers a node class. If `is_statement` is passed,
|
||||
// marks the node as a JavaScript *statement*, or as a *pure_statement*.
|
||||
// Statements must be wrapped in a closure when used as an expression, and
|
||||
// nodes tagged as *pure_statement* cannot be closure-wrapped without losing
|
||||
// their meaning.
|
||||
register = function(klass, o) {
|
||||
o = o || {};
|
||||
klass.prototype.constructor_name = o.name;
|
||||
if (o.is_statement) {
|
||||
(klass.prototype.is_statement = function() {
|
||||
return true;
|
||||
};
|
||||
return klass.prototype.is_pure_statement;
|
||||
});
|
||||
}
|
||||
if (o.is_pure_statement) {
|
||||
(klass.prototype.is_pure_statement = function() {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
if (o.children) {
|
||||
klass.prototype.children_attributes = o.children;
|
||||
return klass.prototype.children_attributes;
|
||||
}
|
||||
};
|
||||
children = function(klass) {
|
||||
var child_attrs;
|
||||
var _b = arguments.length, _c = _b >= 2;
|
||||
child_attrs = __slice.call(arguments, 1, _b - 0);
|
||||
klass.prototype.children_attributes = child_attrs;
|
||||
return klass.prototype.children_attributes;
|
||||
};
|
||||
//### BaseNode
|
||||
// The **BaseNode** is the abstract base class for all nodes in the syntax tree.
|
||||
@@ -210,8 +207,10 @@
|
||||
}
|
||||
});
|
||||
};
|
||||
// Default implementations of the common node identification methods. Nodes
|
||||
// Default implementations of the common node properties and methods. Nodes
|
||||
// will override these with custom logic, if needed.
|
||||
BaseNode.prototype.constructor_name = 'BaseNode';
|
||||
BaseNode.prototype.children_attributes = [];
|
||||
BaseNode.prototype.unwrap = function() {
|
||||
return this;
|
||||
};
|
||||
@@ -226,7 +225,9 @@
|
||||
};
|
||||
return BaseNode;
|
||||
})();
|
||||
type(BaseNode, 'BaseNode');
|
||||
register(BaseNode, {
|
||||
name: 'BaseNode'
|
||||
});
|
||||
//### Expressions
|
||||
// The expressions body is the list of expressions that forms the body of an
|
||||
// indented block of code -- the implementation of a function, a clause in an
|
||||
@@ -349,9 +350,11 @@
|
||||
}
|
||||
return new Expressions(nodes);
|
||||
};
|
||||
type(Expressions, 'Expressions');
|
||||
children(Expressions, 'expressions');
|
||||
statement(Expressions);
|
||||
register(Expressions, {
|
||||
name: 'Expressions',
|
||||
is_statement: true,
|
||||
children: ['expressions']
|
||||
});
|
||||
//### LiteralNode
|
||||
// Literals are static values that can be passed through directly into
|
||||
// JavaScript without translation, such as: strings, numbers,
|
||||
@@ -379,7 +382,9 @@
|
||||
};
|
||||
return LiteralNode;
|
||||
})();
|
||||
type(LiteralNode, 'LiteralNode');
|
||||
register(LiteralNode, {
|
||||
name: 'LiteralNode'
|
||||
});
|
||||
//### ReturnNode
|
||||
// A `return` is a *pure_statement* -- wrapping it in a closure wouldn't
|
||||
// make sense.
|
||||
@@ -406,9 +411,12 @@
|
||||
};
|
||||
return ReturnNode;
|
||||
})();
|
||||
type(ReturnNode, 'ReturnNode');
|
||||
statement(ReturnNode, true);
|
||||
children(ReturnNode, 'expression');
|
||||
register(ReturnNode, {
|
||||
name: 'ReturnNode',
|
||||
is_statement: true,
|
||||
is_pure_statement: true,
|
||||
children: ['expression']
|
||||
});
|
||||
//### ValueNode
|
||||
// A value, variable or literal or parenthesized, indexed or dotted into,
|
||||
// or vanilla.
|
||||
@@ -514,8 +522,10 @@
|
||||
};
|
||||
return ValueNode;
|
||||
})();
|
||||
type(ValueNode, 'ValueNode');
|
||||
children(ValueNode, 'base', 'properties');
|
||||
register(ValueNode, {
|
||||
name: 'ValueNode',
|
||||
children: ['base', 'properties']
|
||||
});
|
||||
//### CommentNode
|
||||
// CoffeeScript passes through comments as JavaScript comments at the
|
||||
// same position.
|
||||
@@ -541,8 +551,10 @@
|
||||
};
|
||||
return CommentNode;
|
||||
})();
|
||||
type(CommentNode, 'CommentNode');
|
||||
statement(CommentNode);
|
||||
register(CommentNode, {
|
||||
name: 'CommentNode',
|
||||
is_statement: true
|
||||
});
|
||||
//### CallNode
|
||||
// Node for a function invocation. Takes care of converting `super()` calls into
|
||||
// calls against the prototype's function of the same name.
|
||||
@@ -631,8 +643,10 @@
|
||||
};
|
||||
return CallNode;
|
||||
})();
|
||||
type(CallNode, 'CallNode');
|
||||
children(CallNode, 'variable', 'args');
|
||||
register(CallNode, {
|
||||
name: 'CallNode',
|
||||
children: ['variable', 'args']
|
||||
});
|
||||
//### CurryNode
|
||||
// Binds a context object and a list of arguments to a function,
|
||||
// returning the bound function. After ECMAScript 5, Prototype.js, and
|
||||
@@ -665,8 +679,10 @@
|
||||
};
|
||||
return CurryNode;
|
||||
}).apply(this, arguments);
|
||||
type(CurryNode, 'CurryNode');
|
||||
children(CurryNode, 'meth', 'context', 'args');
|
||||
register(CurryNode, {
|
||||
name: 'CurryNode',
|
||||
children: ['meth', 'context', 'args']
|
||||
});
|
||||
//### ExtendsNode
|
||||
// Node to extend an object's prototype with an ancestor object.
|
||||
// After `goog.inherits` from the
|
||||
@@ -686,8 +702,10 @@
|
||||
};
|
||||
return ExtendsNode;
|
||||
})();
|
||||
type(ExtendsNode, 'ExtendsNode');
|
||||
children(ExtendsNode, 'child', 'parent');
|
||||
register(ExtendsNode, {
|
||||
name: 'ExtendsNode',
|
||||
children: ['child', 'parent']
|
||||
});
|
||||
//### AccessorNode
|
||||
// A `.` accessor into a property of a value, or the `::` shorthand for
|
||||
// an accessor into the object's prototype.
|
||||
@@ -708,8 +726,10 @@
|
||||
};
|
||||
return AccessorNode;
|
||||
})();
|
||||
type(AccessorNode, 'AccessorNode');
|
||||
children(AccessorNode, 'name');
|
||||
register(AccessorNode, {
|
||||
name: 'AccessorNode',
|
||||
children: ['name']
|
||||
});
|
||||
//### IndexNode
|
||||
// A `[ ... ]` indexed accessor into an array or object.
|
||||
exports.IndexNode = (function() {
|
||||
@@ -727,8 +747,10 @@
|
||||
};
|
||||
return IndexNode;
|
||||
})();
|
||||
type(IndexNode, 'IndexNode');
|
||||
children(IndexNode, 'index');
|
||||
register(IndexNode, {
|
||||
name: 'IndexNode',
|
||||
children: ['index']
|
||||
});
|
||||
//### RangeNode
|
||||
// A range literal. Ranges can be used to extract portions (slices) of arrays,
|
||||
// to specify a range for comprehensions, or as a value, to be expanded into the
|
||||
@@ -786,8 +808,10 @@
|
||||
};
|
||||
return RangeNode;
|
||||
})();
|
||||
type(RangeNode, 'RangeNode');
|
||||
children(RangeNode, 'from', 'to');
|
||||
register(RangeNode, {
|
||||
name: 'RangeNode',
|
||||
children: ['from', 'to']
|
||||
});
|
||||
//### SliceNode
|
||||
// An array slice literal. Unlike JavaScript's `Array#slice`, the second parameter
|
||||
// specifies the index of the end of the slice, just as the first parameter
|
||||
@@ -808,8 +832,10 @@
|
||||
};
|
||||
return SliceNode;
|
||||
})();
|
||||
type(SliceNode, 'SliceNode');
|
||||
children(SliceNode, 'range');
|
||||
register(SliceNode, {
|
||||
name: 'SliceNode',
|
||||
children: ['range']
|
||||
});
|
||||
//### ObjectNode
|
||||
// An object literal, nothing fancy.
|
||||
exports.ObjectNode = (function() {
|
||||
@@ -860,8 +886,10 @@
|
||||
};
|
||||
return ObjectNode;
|
||||
})();
|
||||
type(ObjectNode, 'ObjectNode');
|
||||
children(ObjectNode, 'properties');
|
||||
register(ObjectNode, {
|
||||
name: 'ObjectNode',
|
||||
children: ['properties']
|
||||
});
|
||||
//### ArrayNode
|
||||
// An array literal.
|
||||
exports.ArrayNode = (function() {
|
||||
@@ -898,8 +926,10 @@
|
||||
};
|
||||
return ArrayNode;
|
||||
})();
|
||||
type(ArrayNode, 'ArrayNode');
|
||||
children(ArrayNode, 'objects');
|
||||
register(ArrayNode, {
|
||||
name: 'ArrayNode',
|
||||
children: ['objects']
|
||||
});
|
||||
//### ClassNode
|
||||
// The CoffeeScript class definition.
|
||||
exports.ClassNode = (function() {
|
||||
@@ -960,9 +990,11 @@
|
||||
};
|
||||
return ClassNode;
|
||||
})();
|
||||
type(ClassNode, 'ClassNode');
|
||||
statement(ClassNode);
|
||||
children(ClassNode, 'variable', 'parent', 'properties');
|
||||
register(ClassNode, {
|
||||
name: 'ClassNode',
|
||||
is_statement: true,
|
||||
children: ['variable', 'parent', 'properties']
|
||||
});
|
||||
//### AssignNode
|
||||
// The **AssignNode** is used to assign a local variable to value, or to set the
|
||||
// property of an object -- including within object literals.
|
||||
@@ -1096,8 +1128,10 @@
|
||||
};
|
||||
return AssignNode;
|
||||
})();
|
||||
type(AssignNode, 'AssignNode');
|
||||
children(AssignNode, 'variable', 'value');
|
||||
register(AssignNode, {
|
||||
name: 'AssignNode',
|
||||
children: ['variable', 'value']
|
||||
});
|
||||
//### CodeNode
|
||||
// A function definition. This is the only node that creates a new Scope.
|
||||
// When for the purposes of walking the contents of a function body, the CodeNode
|
||||
@@ -1180,7 +1214,7 @@
|
||||
}
|
||||
};
|
||||
CodeNode.prototype.toString = function(idt) {
|
||||
var _b, _c, _d, _e, child;
|
||||
var _b, _c, _d, _e, child, children;
|
||||
idt = idt || '';
|
||||
children = (function() {
|
||||
_b = []; _d = this.children();
|
||||
@@ -1194,8 +1228,10 @@
|
||||
};
|
||||
return CodeNode;
|
||||
})();
|
||||
type(CodeNode, 'CodeNode');
|
||||
children(CodeNode, 'params', 'body');
|
||||
register(CodeNode, {
|
||||
name: 'CodeNode',
|
||||
children: ['params', 'body']
|
||||
});
|
||||
//### SplatNode
|
||||
// A splat, either as a parameter to a function, an argument to a call,
|
||||
// or as part of a destructuring assignment.
|
||||
@@ -1270,8 +1306,10 @@
|
||||
};
|
||||
return SplatNode;
|
||||
}).call(this);
|
||||
type(SplatNode, 'SplatNode');
|
||||
children(SplatNode, 'name');
|
||||
register(SplatNode, {
|
||||
name: 'SplatNode',
|
||||
children: ['name']
|
||||
});
|
||||
//### WhileNode
|
||||
// A while loop, the only sort of low-level loop exposed by CoffeeScript. From
|
||||
// it, all other loops can be manufactured. Useful in cases where you need more
|
||||
@@ -1328,9 +1366,11 @@
|
||||
};
|
||||
return WhileNode;
|
||||
})();
|
||||
type(WhileNode, 'WhileNode');
|
||||
statement(WhileNode);
|
||||
children(WhileNode, 'condition', 'guard', 'body');
|
||||
register(WhileNode, {
|
||||
name: 'WhileNode',
|
||||
is_statement: true,
|
||||
children: ['condition', 'guard', 'body']
|
||||
});
|
||||
//### OpNode
|
||||
// Simple Arithmetic and logical operations. Performs some conversion from
|
||||
// CoffeeScript operations into their JavaScript equivalents.
|
||||
@@ -1434,8 +1474,10 @@
|
||||
};
|
||||
return OpNode;
|
||||
})();
|
||||
type(OpNode, 'OpNode');
|
||||
children(OpNode, 'first', 'second');
|
||||
register(OpNode, {
|
||||
name: 'OpNode',
|
||||
children: ['first', 'second']
|
||||
});
|
||||
//### TryNode
|
||||
// A classic *try/catch/finally* block.
|
||||
exports.TryNode = (function() {
|
||||
@@ -1471,9 +1513,11 @@
|
||||
};
|
||||
return TryNode;
|
||||
})();
|
||||
type(TryNode, 'TryNode');
|
||||
statement(TryNode);
|
||||
children(TryNode, 'attempt', 'recovery', 'ensure');
|
||||
register(TryNode, {
|
||||
name: 'TryNode',
|
||||
is_statement: true,
|
||||
children: ['attempt', 'recovery', 'ensure']
|
||||
});
|
||||
//### ThrowNode
|
||||
// Simple node to throw an exception.
|
||||
exports.ThrowNode = (function() {
|
||||
@@ -1491,9 +1535,11 @@
|
||||
};
|
||||
return ThrowNode;
|
||||
})();
|
||||
type(ThrowNode, 'ThrowNode');
|
||||
statement(ThrowNode);
|
||||
children(ThrowNode, 'expression');
|
||||
register(ThrowNode, {
|
||||
name: 'ThrowNode',
|
||||
is_statement: true,
|
||||
children: ['expression']
|
||||
});
|
||||
//### ExistenceNode
|
||||
// Checks a variable for existence -- not *null* and not *undefined*. This is
|
||||
// similar to `.nil?` in Ruby, and avoids having to consult a JavaScript truth
|
||||
@@ -1527,8 +1573,10 @@
|
||||
};
|
||||
return ExistenceNode;
|
||||
}).call(this);
|
||||
type(ExistenceNode, 'ExistenceNode');
|
||||
children(ExistenceNode, 'expression');
|
||||
register(ExistenceNode, {
|
||||
name: 'ExistenceNode',
|
||||
children: ['expression']
|
||||
});
|
||||
//### ParentheticalNode
|
||||
// An extra set of parentheses, specified explicitly in the source. At one time
|
||||
// we tried to clean up the results by detecting and removing redundant
|
||||
@@ -1564,8 +1612,10 @@
|
||||
};
|
||||
return ParentheticalNode;
|
||||
})();
|
||||
type(ParentheticalNode, 'ParentheticalNode');
|
||||
children(ParentheticalNode, 'expression');
|
||||
register(ParentheticalNode, {
|
||||
name: 'ParentheticalNode',
|
||||
children: ['expression']
|
||||
});
|
||||
//### ForNode
|
||||
// CoffeeScript's replacement for the *for* loop is our array and object
|
||||
// comprehensions, that compile into *for* loops here. They also act as an
|
||||
@@ -1684,9 +1734,11 @@
|
||||
};
|
||||
return ForNode;
|
||||
})();
|
||||
type(ForNode, 'ForNode');
|
||||
statement(ForNode);
|
||||
children(ForNode, 'body', 'source', 'guard');
|
||||
register(ForNode, {
|
||||
name: 'ForNode',
|
||||
is_statement: true,
|
||||
children: ['body', 'source', 'guard']
|
||||
});
|
||||
//### IfNode
|
||||
// *If/else* statements. Our *switch/when* will be compiled into this. Acts as an
|
||||
// expression by pushing down requested returns to the last line of each clause.
|
||||
@@ -1829,8 +1881,10 @@
|
||||
};
|
||||
return IfNode;
|
||||
})();
|
||||
type(IfNode, 'IfNode');
|
||||
children(IfNode, 'condition', 'body', 'else_body', 'assigner');
|
||||
register(IfNode, {
|
||||
name: 'IfNode',
|
||||
children: ['condition', 'body', 'else_body', 'assigner']
|
||||
});
|
||||
// Faux-Nodes
|
||||
// ----------
|
||||
//### PushNode
|
||||
|
||||
Reference in New Issue
Block a user