Merging type, children and statement functions

This commit is contained in:
Stan Angeloff
2010-05-19 22:50:29 +03:00
parent 97c2a70593
commit 57231ae75d
2 changed files with 183 additions and 163 deletions

View File

@@ -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