mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
another reshuffle ... removed utilities.coffee entirely.
This commit is contained in:
parent
4a8c2e8a13
commit
6d7a04228f
5 changed files with 92 additions and 114 deletions
42
lib/nodes.js
42
lib/nodes.js
|
@ -1,5 +1,5 @@
|
|||
(function(){
|
||||
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, CurryNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, ValueNode, WhileNode, compact, del, flatten, helpers, literal, merge, statement;
|
||||
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, CurryNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, compact, del, flatten, helpers, literal, merge, statement;
|
||||
var __extend = function(child, parent) {
|
||||
var ctor = function(){ };
|
||||
ctor.prototype = parent.prototype;
|
||||
|
@ -596,10 +596,14 @@
|
|||
};
|
||||
CurryNode.prototype.compile_node = function compile_node(o) {
|
||||
var ref;
|
||||
o.scope.utility('slice');
|
||||
ref = new ValueNode(literal(o.scope.utility('bind')));
|
||||
CurryNode.assign_bind();
|
||||
ref = new ValueNode(literal('__bind'));
|
||||
return (new CallNode(ref, [this.meth, this.context, literal(this.arguments(o))])).compile(o);
|
||||
};
|
||||
CurryNode.assign_bind = function assign_bind() {
|
||||
Scope.root.assign('__slice', UTILITIES['slice']);
|
||||
return Scope.root.assign('__bind', UTILITIES['bind']);
|
||||
};
|
||||
return CurryNode;
|
||||
}).call(this);
|
||||
//### ExtendsNode
|
||||
|
@ -616,7 +620,7 @@
|
|||
// Hooks one constructor into another's prototype chain.
|
||||
ExtendsNode.prototype.compile_node = function compile_node(o) {
|
||||
var ref;
|
||||
ref = new ValueNode(literal(o.scope.utility('extend')));
|
||||
ref = new ValueNode(literal(Scope.root.assign('__extend', UTILITIES['extend'])));
|
||||
return (new CallNode(ref, [this.child, this.parent])).compile(o);
|
||||
};
|
||||
return ExtendsNode;
|
||||
|
@ -741,7 +745,7 @@
|
|||
to = (typeof (_b = this.range.to) !== "undefined" && _b !== null) ? this.range.to : literal('null');
|
||||
exclusive = this.range.exclusive ? 'true' : 'false';
|
||||
v = o.scope.free_variable();
|
||||
rng = new CallNode(new ValueNode(literal(o.scope.utility('range'))), [literal(array), from, to, literal(exclusive)]);
|
||||
rng = new CallNode(new ValueNode(literal(Scope.root.assign('__range', UTILITIES['range']))), [literal(array), from, to, literal(exclusive)]);
|
||||
args = literal("[(" + v + " = " + (rng.compile(o)) + ")[0], " + v + "[1] - " + v + "[0]].concat(" + (replace.compile(o)) + ")");
|
||||
call = new CallNode(new ValueNode(literal(array), [literal('.splice.apply')]), [literal(array), args]);
|
||||
return call.compile(o);
|
||||
|
@ -752,7 +756,7 @@
|
|||
from = (typeof (_a = this.range.from) !== "undefined" && _a !== null) ? this.range.from : literal('null');
|
||||
to = (typeof (_b = this.range.to) !== "undefined" && _b !== null) ? this.range.to : literal('null');
|
||||
exclusive = this.range.exclusive ? 'true' : 'false';
|
||||
rng = new CallNode(new ValueNode(literal(o.scope.utility('range'))), [literal(array), from, to, literal(exclusive)]);
|
||||
rng = new CallNode(new ValueNode(literal(Scope.root.assign('__range', UTILITIES['range']))), [literal(array), from, to, literal(exclusive)]);
|
||||
call = new CallNode(new ValueNode(literal(array), [literal('.slice.apply')]), [literal(array), rng]);
|
||||
return call.compile(o);
|
||||
};
|
||||
|
@ -1084,8 +1088,8 @@
|
|||
if (!(this.bound)) {
|
||||
return func;
|
||||
}
|
||||
o.scope.utility('slice');
|
||||
ref = new ValueNode(literal(o.scope.utility('bind')));
|
||||
CurryNode.assign_bind();
|
||||
ref = new ValueNode(literal('__bind'));
|
||||
return (new CallNode(ref, [literal(func), literal('this')])).compile(o);
|
||||
};
|
||||
CodeNode.prototype.top_sensitive = function top_sensitive() {
|
||||
|
@ -1156,16 +1160,15 @@
|
|||
o.scope.assign(trailing.compile(o), "arguments[arguments.length - " + this.trailings.length + " + " + i + "]");
|
||||
i += 1;
|
||||
}
|
||||
return "" + name + " = " + (o.scope.utility('slice')) + ".call(arguments, " + this.index + ", arguments.length - " + (this.trailings.length) + ")";
|
||||
return "" + name + " = " + (Scope.root.assign('__slice', UTILITIES['slice'])) + ".call(arguments, " + this.index + ", arguments.length - " + (this.trailings.length) + ")";
|
||||
};
|
||||
// A compiling a splat as a destructuring assignment means slicing arguments
|
||||
// from the right-hand-side's corresponding array.
|
||||
SplatNode.prototype.compile_value = function compile_value(o, name, index, trailings) {
|
||||
if ((typeof trailings !== "undefined" && trailings !== null)) {
|
||||
return "" + (o.scope.utility('slice')) + ".call(" + name + ", " + index + ", " + (name) + ".length - " + trailings + ")";
|
||||
} else {
|
||||
return "" + (o.scope.utility('slice')) + ".call(" + name + ", " + index + ")";
|
||||
}
|
||||
var trail;
|
||||
Scope.root.assign('__slice', UTILITIES['slice']);
|
||||
trail = trailings ? ", " + (name) + ".length - " + trailings : '';
|
||||
return "__slice.call(" + name + ", " + index + trail + ")";
|
||||
};
|
||||
// Utility function that converts arbitrary number of elements, mixed with
|
||||
// splats, to a proper array
|
||||
|
@ -1576,7 +1579,7 @@
|
|||
body = PushNode.wrap(rvar, body);
|
||||
}
|
||||
this.filter ? (body = Expressions.wrap([new IfNode(this.filter, body)])) : null;
|
||||
this.object ? (for_part = "" + ivar + " in " + svar + ") { if (" + (o.scope.utility('hasProp')) + ".call(" + svar + ", " + ivar + ")") : null;
|
||||
this.object ? (for_part = "" + ivar + " in " + svar + ") { if (" + (Scope.root.assign('__hasProp', UTILITIES['hasProp'])) + ".call(" + svar + ", " + ivar + ")") : null;
|
||||
body = body.compile(merge(o, {
|
||||
indent: body_dent,
|
||||
top: true
|
||||
|
@ -1769,6 +1772,15 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
// Utility Functions
|
||||
// -----------------
|
||||
UTILITIES = {
|
||||
extend: "function(child, parent) {\n var ctor = function(){ };\n ctor.prototype = parent.prototype;\n child.__superClass__ = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n }",
|
||||
bind: "function(func, obj, args) {\n return function() {\n return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);\n };\n }",
|
||||
range: "function(array, from, to, exclusive) {\n return [\n (from < 0 ? from + array.length : from || 0),\n (to < 0 ? to + array.length : to || array.length) + (exclusive ? 0 : 1)\n ];\n }",
|
||||
hasProp: 'Object.prototype.hasOwnProperty',
|
||||
slice: 'Array.prototype.slice'
|
||||
};
|
||||
// Constants
|
||||
// ---------
|
||||
// Tabs are two spaces for pretty printing.
|
||||
|
|
39
lib/scope.js
39
lib/scope.js
|
@ -1,5 +1,5 @@
|
|||
(function(){
|
||||
var Scope, utilities;
|
||||
var Scope;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
// The **Scope** class regulates lexical scoping within CoffeeScript. As you
|
||||
// generate code, you create a tree of scopes in the same shape as the nested
|
||||
|
@ -11,7 +11,6 @@
|
|||
if (!((typeof process !== "undefined" && process !== null))) {
|
||||
this.exports = this;
|
||||
}
|
||||
utilities = (typeof process !== "undefined" && process !== null) ? require('./utilities').utilities : this.utilities;
|
||||
exports.Scope = (function() {
|
||||
Scope = function Scope(parent, expressions, method) {
|
||||
var _a;
|
||||
|
@ -81,38 +80,12 @@
|
|||
};
|
||||
// Ensure that an assignment is made at the top of this scope
|
||||
// (or at the top-level scope, if requested).
|
||||
Scope.prototype.assign = function assign(name, value, top_level) {
|
||||
if (top_level) {
|
||||
return Scope.root.assign(name, value);
|
||||
}
|
||||
Scope.prototype.assign = function assign(name, value) {
|
||||
this.variables[name] = {
|
||||
value: value,
|
||||
assigned: true
|
||||
};
|
||||
return this.variables[name];
|
||||
};
|
||||
// Ensure the CoffeeScript utility object is included in the top level
|
||||
// then return a CallNode curried constructor bound to the utility function
|
||||
Scope.prototype.utility = function utility(name) {
|
||||
var _a;
|
||||
if (this.parent) {
|
||||
return Scope.root.utility(name);
|
||||
}
|
||||
if ((typeof (_a = utilities[name]) !== "undefined" && _a !== null)) {
|
||||
this.utilities = this.utilities || {};
|
||||
this.utilities[name] = utilities[name];
|
||||
}
|
||||
return "__" + name;
|
||||
};
|
||||
// Formats an javascript object containing the utility methods required
|
||||
// in the scope
|
||||
Scope.prototype.included_utilities = function included_utilities() {
|
||||
var _a, _b, key;
|
||||
_a = []; _b = this.utilities;
|
||||
for (key in _b) { if (__hasProp.call(_b, key)) {
|
||||
_a.push("__" + key + " = " + (utilities[key]));
|
||||
}}
|
||||
return _a;
|
||||
return name;
|
||||
};
|
||||
// Does this scope reference any variables that need to be declared in the
|
||||
// given function body?
|
||||
|
@ -124,9 +97,9 @@
|
|||
// Does this scope reference any assignments that need to be declared at the
|
||||
// top of the given function body?
|
||||
Scope.prototype.has_assignments = function has_assignments(body) {
|
||||
return body === this.expressions && (this.utilities || this.any(function(k, val) {
|
||||
return body === this.expressions && this.any(function(k, val) {
|
||||
return val.assigned;
|
||||
}));
|
||||
});
|
||||
};
|
||||
// Return the list of variables first declared in this scope.
|
||||
Scope.prototype.declared_variables = function declared_variables() {
|
||||
|
@ -157,7 +130,7 @@
|
|||
};
|
||||
// Compile the JavaScript for all of the variable assignments in this scope.
|
||||
Scope.prototype.compiled_assignments = function compiled_assignments(tab) {
|
||||
return this.assigned_variables().concat(this.included_utilities()).join(', ');
|
||||
return this.assigned_variables().join(', ');
|
||||
};
|
||||
return Scope;
|
||||
}).call(this);
|
||||
|
|
|
@ -430,10 +430,15 @@ exports.CurryNode: class CurryNode extends CallNode
|
|||
(new ArrayNode(@args)).compile o
|
||||
|
||||
compile_node: (o) ->
|
||||
o.scope.utility('slice')
|
||||
ref: new ValueNode literal(o.scope.utility('bind'))
|
||||
CurryNode.assign_bind()
|
||||
ref: new ValueNode literal '__bind'
|
||||
(new CallNode(ref, [@meth, @context, literal(@arguments(o))])).compile o
|
||||
|
||||
@assign_bind: ->
|
||||
Scope.root.assign '__slice', UTILITIES['slice']
|
||||
Scope.root.assign '__bind', UTILITIES['bind']
|
||||
|
||||
|
||||
#### ExtendsNode
|
||||
|
||||
# Node to extend an object's prototype with an ancestor object.
|
||||
|
@ -447,7 +452,7 @@ exports.ExtendsNode: class ExtendsNode extends BaseNode
|
|||
|
||||
# Hooks one constructor into another's prototype chain.
|
||||
compile_node: (o) ->
|
||||
ref: new ValueNode literal(o.scope.utility('extend'))
|
||||
ref: new ValueNode literal(Scope.root.assign('__extend', UTILITIES['extend']))
|
||||
(new CallNode ref, [@child, @parent]).compile o
|
||||
|
||||
#### AccessorNode
|
||||
|
@ -548,7 +553,7 @@ exports.SliceNode: class SliceNode extends BaseNode
|
|||
to: if @range.to? then @range.to else literal('null')
|
||||
exclusive: if @range.exclusive then 'true' else 'false'
|
||||
v: o.scope.free_variable()
|
||||
rng: new CallNode new ValueNode(literal(o.scope.utility('range'))), [literal(array), from, to, literal(exclusive)]
|
||||
rng: new CallNode new ValueNode(literal(Scope.root.assign('__range', UTILITIES['range']))), [literal(array), from, to, literal(exclusive)]
|
||||
args: literal "[($v = ${rng.compile(o)})[0], $v[1] - $v[0]].concat(${replace.compile(o)})"
|
||||
call: new CallNode new ValueNode(literal(array), [literal('.splice.apply')]), [literal(array), args]
|
||||
call.compile(o)
|
||||
|
@ -558,7 +563,7 @@ exports.SliceNode: class SliceNode extends BaseNode
|
|||
from: if @range.from? then @range.from else literal('null')
|
||||
to: if @range.to? then @range.to else literal('null')
|
||||
exclusive: if @range.exclusive then 'true' else 'false'
|
||||
rng: new CallNode new ValueNode(literal(o.scope.utility('range'))), [literal(array), from, to, literal(exclusive)]
|
||||
rng: new CallNode new ValueNode(literal(Scope.root.assign('__range', UTILITIES['range']))), [literal(array), from, to, literal(exclusive)]
|
||||
call: new CallNode new ValueNode(literal(array), [literal('.slice.apply')]), [literal(array), rng]
|
||||
call.compile(o)
|
||||
|
||||
|
@ -802,8 +807,8 @@ exports.CodeNode: class CodeNode extends BaseNode
|
|||
func: "function${ if @bound then '' else name_part }(${ params.join(', ') }) {$code${@idt(if @bound then 1 else 0)}}"
|
||||
func: "($func)" if top and not @bound
|
||||
return func unless @bound
|
||||
o.scope.utility('slice')
|
||||
ref: new ValueNode literal(o.scope.utility('bind'))
|
||||
CurryNode.assign_bind()
|
||||
ref: new ValueNode literal('__bind')
|
||||
(new CallNode ref, [literal(func), literal('this')]).compile o
|
||||
|
||||
top_sensitive: ->
|
||||
|
@ -847,13 +852,14 @@ exports.SplatNode: class SplatNode extends BaseNode
|
|||
for trailing in @trailings
|
||||
o.scope.assign(trailing.compile(o), "arguments[arguments.length - $@trailings.length + $i]")
|
||||
i: + 1
|
||||
"$name = ${o.scope.utility('slice')}.call(arguments, $@index, arguments.length - ${@trailings.length})"
|
||||
"$name = ${Scope.root.assign('__slice', UTILITIES['slice'])}.call(arguments, $@index, arguments.length - ${@trailings.length})"
|
||||
|
||||
# A compiling a splat as a destructuring assignment means slicing arguments
|
||||
# from the right-hand-side's corresponding array.
|
||||
compile_value: (o, name, index, trailings) ->
|
||||
if trailings? then "${o.scope.utility('slice')}.call($name, $index, ${name}.length - $trailings)" \
|
||||
else "${o.scope.utility('slice')}.call($name, $index)"
|
||||
Scope.root.assign '__slice', UTILITIES['slice']
|
||||
trail: if trailings then ", ${name}.length - $trailings" else ''
|
||||
"__slice.call($name, $index$trail)"
|
||||
|
||||
# Utility function that converts arbitrary number of elements, mixed with
|
||||
# splats, to a proper array
|
||||
|
@ -1172,7 +1178,7 @@ exports.ForNode: class ForNode extends BaseNode
|
|||
if @filter
|
||||
body: Expressions.wrap([new IfNode(@filter, body)])
|
||||
if @object
|
||||
for_part: "$ivar in $svar) { if (${o.scope.utility('hasProp')}.call($svar, $ivar)"
|
||||
for_part: "$ivar in $svar) { if (${Scope.root.assign('__hasProp', UTILITIES['hasProp'])}.call($svar, $ivar)"
|
||||
body: body.compile(merge(o, {indent: body_dent, top: true}))
|
||||
vars: if range then name else "$name, $ivar"
|
||||
close: if @object then '}}\n' else '}\n'
|
||||
|
@ -1322,6 +1328,44 @@ ClosureNode: exports.ClosureNode: {
|
|||
|
||||
}
|
||||
|
||||
# Utility Functions
|
||||
# -----------------
|
||||
|
||||
UTILITIES: {
|
||||
|
||||
extend: """
|
||||
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) {
|
||||
return function() {
|
||||
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
|
||||
};
|
||||
}
|
||||
"""
|
||||
|
||||
range: """
|
||||
function(array, from, to, exclusive) {
|
||||
return [
|
||||
(from < 0 ? from + array.length : from || 0),
|
||||
(to < 0 ? to + array.length : to || array.length) + (exclusive ? 0 : 1)
|
||||
];
|
||||
}
|
||||
"""
|
||||
|
||||
hasProp: 'Object.prototype.hasOwnProperty'
|
||||
|
||||
slice: 'Array.prototype.slice'
|
||||
|
||||
}
|
||||
|
||||
# Constants
|
||||
# ---------
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
# Set up exported variables for both **Node.js** and the browser.
|
||||
this.exports: this unless process?
|
||||
utilities: if process? then require('./utilities').utilities else this.utilities
|
||||
|
||||
exports.Scope: class Scope
|
||||
|
||||
|
@ -61,23 +60,9 @@ exports.Scope: class Scope
|
|||
|
||||
# Ensure that an assignment is made at the top of this scope
|
||||
# (or at the top-level scope, if requested).
|
||||
assign: (name, value, top_level) ->
|
||||
return Scope.root.assign(name, value) if top_level
|
||||
assign: (name, value) ->
|
||||
@variables[name]: {value: value, assigned: true}
|
||||
|
||||
# Ensure the CoffeeScript utility object is included in the top level
|
||||
# then return a CallNode curried constructor bound to the utility function
|
||||
utility: (name) ->
|
||||
return Scope.root.utility(name) if @parent
|
||||
if utilities[name]?
|
||||
@utilities: or {}
|
||||
@utilities[name]: utilities[name]
|
||||
"__$name"
|
||||
|
||||
# Formats an javascript object containing the utility methods required
|
||||
# in the scope
|
||||
included_utilities: ->
|
||||
"__$key = ${utilities[key]}" for key of @utilities
|
||||
name
|
||||
|
||||
# Does this scope reference any variables that need to be declared in the
|
||||
# given function body?
|
||||
|
@ -87,7 +72,7 @@ exports.Scope: class Scope
|
|||
# Does this scope reference any assignments that need to be declared at the
|
||||
# top of the given function body?
|
||||
has_assignments: (body) ->
|
||||
body is @expressions and (@utilities or @any (k, val) -> val.assigned)
|
||||
body is @expressions and @any (k, val) -> val.assigned
|
||||
|
||||
# Return the list of variables first declared in this scope.
|
||||
declared_variables: ->
|
||||
|
@ -104,4 +89,4 @@ exports.Scope: class Scope
|
|||
|
||||
# Compile the JavaScript for all of the variable assignments in this scope.
|
||||
compiled_assignments: (tab) ->
|
||||
[@assigned_variables()..., @included_utilities()...].join ', '
|
||||
@assigned_variables().join ', '
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
this.exports: this unless process?
|
||||
|
||||
exports.utilities: {
|
||||
|
||||
extend: """
|
||||
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) {
|
||||
return function() {
|
||||
return func.apply(obj || {}, args ? args.concat(__slice.call(arguments, 0)) : arguments);
|
||||
};
|
||||
}
|
||||
"""
|
||||
|
||||
range: """
|
||||
function(array, from, to, exclusive) {
|
||||
return [
|
||||
(from < 0 ? from + array.length : from || 0),
|
||||
(to < 0 ? to + array.length : to || array.length) + (exclusive ? 0 : 1)
|
||||
];
|
||||
}
|
||||
"""
|
||||
|
||||
hasProp: 'Object.prototype.hasOwnProperty'
|
||||
|
||||
slice: 'Array.prototype.slice'
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue