merging master changes into symbology

This commit is contained in:
Jeremy Ashkenas
2010-07-25 00:15:12 -07:00
parent a0b2b78962
commit 6b0418a74a
14 changed files with 339 additions and 355 deletions

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var CoffeeScript, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks; var CoffeeScript, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
fs = require('fs'); fs = require('fs');
path = require('path'); path = require('path');
@@ -17,12 +17,11 @@
action = _a[0]; action = _a[0];
description = _a[1]; description = _a[1];
} }
tasks[name] = { return (tasks[name] = {
name: name, name: name,
description: description, description: description,
action: action action: action
}; });
return tasks[name];
}, },
option: function(letter, flag, description) { option: function(letter, flag, description) {
return switches.push([letter, flag, description]); return switches.push([letter, flag, description]);

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var Lexer, compile, helpers, lexer, parser, path, processScripts; var Lexer, compile, helpers, lexer, parser, path, processScripts;
if (typeof process !== "undefined" && process !== null) { if (typeof process !== "undefined" && process !== null) {
path = require('path'); path = require('path');
@@ -51,8 +51,7 @@
}, },
setInput: function(tokens) { setInput: function(tokens) {
this.tokens = tokens; this.tokens = tokens;
this.pos = 0; return (this.pos = 0);
return this.pos;
}, },
upcomingInput: function() { upcomingInput: function() {
return ""; return "";

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var BANNER, CoffeeScript, SWITCHES, _a, compileOptions, compileScript, compileScripts, compileStdio, exec, fs, lint, optionParser, options, optparse, parseOptions, path, printTokens, sources, spawn, usage, version, watch, writeJs; var BANNER, CoffeeScript, SWITCHES, _a, compileOptions, compileScript, compileScripts, compileStdio, exec, fs, lint, optionParser, options, optparse, parseOptions, path, printTokens, sources, spawn, usage, version, watch, writeJs;
fs = require('fs'); fs = require('fs');
path = require('path'); path = require('path');
@@ -195,8 +195,7 @@
options.compile = options.compile || !!o.output; options.compile = options.compile || !!o.output;
options.run = !(o.compile || o.print || o.lint); options.run = !(o.compile || o.print || o.lint);
options.print = !!(o.print || (o.eval || o.stdio && o.compile)); options.print = !!(o.print || (o.eval || o.stdio && o.compile));
sources = options.arguments; return (sources = options.arguments);
return sources;
}; };
compileOptions = function(source) { compileOptions = function(source) {
var o; var o;

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var Parser, _a, _b, _c, _d, _e, _f, _g, _h, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap; var Parser, _a, _b, _c, _d, _e, _f, _g, _h, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
var __hasProp = Object.prototype.hasOwnProperty; var __hasProp = Object.prototype.hasOwnProperty;
Parser = require('jison').Parser; Parser = require('jison').Parser;

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var compact, count, del, ends, extend, flatten, helpers, include, indexOf, merge, starts; var compact, count, del, ends, extend, flatten, helpers, include, indexOf, merge, starts;
if (!(typeof process !== "undefined" && process !== null)) { if (!(typeof process !== "undefined" && process !== null)) {
this.exports = this; this.exports = this;

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var _a, key, val; var _a, key, val;
var __hasProp = Object.prototype.hasOwnProperty; var __hasProp = Object.prototype.hasOwnProperty;
_a = require('./coffee-script'); _a = require('./coffee-script');

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, INTERPOLATION, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, Lexer, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, STRING_NEWLINES, WHITESPACE, _a, _b, _c, compact, count, helpers, include, starts; var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, INTERPOLATION, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, Lexer, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, STRING_NEWLINES, WHITESPACE, _a, _b, _c, compact, count, helpers, include, starts;
var __slice = Array.prototype.slice; var __slice = Array.prototype.slice;
if (typeof process !== "undefined" && process !== null) { if (typeof process !== "undefined" && process !== null) {
@@ -219,8 +219,7 @@
}; };
Lexer.prototype.balancedToken = function() { Lexer.prototype.balancedToken = function() {
var delimited; var delimited;
var _d = arguments.length, _e = _d >= 1; delimited = __slice.call(arguments, 0);
delimited = __slice.call(arguments, 0, _d - 0);
return this.balancedString(this.chunk, delimited); return this.balancedString(this.chunk, delimited);
}; };
Lexer.prototype.lineToken = function() { Lexer.prototype.lineToken = function() {
@@ -387,8 +386,7 @@
} else if (_d === ')') { } else if (_d === ')') {
tok[0] = 'PARAM_END'; tok[0] = 'PARAM_END';
} else if (_d === '(' || _d === 'CALL_START') { } else if (_d === '(' || _d === 'CALL_START') {
tok[0] = 'PARAM_START'; return (tok[0] = 'PARAM_START');
return tok[0];
} }
} }
return true; return true;
@@ -543,8 +541,7 @@
return null; return null;
} }
if (typeof newTag !== "undefined" && newTag !== null) { if (typeof newTag !== "undefined" && newTag !== null) {
tok[0] = newTag; return (tok[0] = newTag);
return tok[0];
} }
return tok[0]; return tok[0];
}; };
@@ -554,8 +551,7 @@
return null; return null;
} }
if (typeof val !== "undefined" && val !== null) { if (typeof val !== "undefined" && val !== null) {
tok[1] = val; return (tok[1] = val);
return tok[1];
} }
return tok[1]; return tok[1];
}; };

View File

@@ -1,7 +1,7 @@
(function(){ (function() {
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, DOUBLE_PARENS, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, InNode, IndexNode, LiteralNode, NUMBER, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SIMPLENUM, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, ends, flatten, helpers, include, indexOf, literal, merge, starts, utility; var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, DOUBLE_PARENS, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IS_STRING, IfNode, InNode, IndexNode, LiteralNode, NUMBER, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SIMPLENUM, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, _a, compact, del, ends, flatten, helpers, include, indexOf, literal, merge, starts, utility;
var __extends = function(child, parent) { var __extends = function(child, parent) {
var ctor = function(){ }; var ctor = function(){};
ctor.prototype = parent.prototype; ctor.prototype = parent.prototype;
child.prototype = new ctor(); child.prototype = new ctor();
child.prototype.constructor = child; child.prototype.constructor = child;
@@ -203,11 +203,6 @@
this.expressions[idx] = last.makeReturn(); this.expressions[idx] = last.makeReturn();
return this; return this;
}; };
Expressions.prototype.rewriteThis = function() {
return this.traverseChildren(false, function(child) {
return child instanceof ValueNode && child.base.value === 'this' ? (child.base = literal('_this')) : null;
});
};
Expressions.prototype.compile = function(o) { Expressions.prototype.compile = function(o) {
o = o || {}; o = o || {};
return o.scope ? Expressions.__superClass__.compile.call(this, o) : this.compileRoot(o); return o.scope ? Expressions.__superClass__.compile.call(this, o) : this.compileRoot(o);
@@ -230,7 +225,7 @@
code = this.compileWithDeclarations(o); code = this.compileWithDeclarations(o);
code = code.replace(TRAILING_WHITESPACE, ''); code = code.replace(TRAILING_WHITESPACE, '');
code = code.replace(DOUBLE_PARENS, '($1)'); code = code.replace(DOUBLE_PARENS, '($1)');
return o.noWrap ? code : ("(function(){\n" + code + "\n})();\n"); return o.noWrap ? code : ("(function() {\n" + code + "\n})();\n");
}; };
Expressions.prototype.compileWithDeclarations = function(o) { Expressions.prototype.compileWithDeclarations = function(o) {
var code; var code;
@@ -399,8 +394,7 @@
part = prop.compile(o); part = prop.compile(o);
baseline += part; baseline += part;
complete += part; complete += part;
this.last = part; return (this.last = part);
return this.last;
} }
}).call(this); }).call(this);
} }
@@ -452,7 +446,7 @@
CallNode.prototype.superReference = function(o) { CallNode.prototype.superReference = function(o) {
var meth, methname; var meth, methname;
methname = o.scope.method.name; methname = o.scope.method.name;
meth = (function() { return (meth = (function() {
if (o.scope.method.proto) { if (o.scope.method.proto) {
return "" + (o.scope.method.proto) + ".__superClass__." + methname; return "" + (o.scope.method.proto) + ".__superClass__." + methname;
} else if (methname) { } else if (methname) {
@@ -460,8 +454,7 @@
} else { } else {
throw new Error("cannot call super on an anonymous function."); throw new Error("cannot call super on an anonymous function.");
} }
})(); })());
return meth;
}; };
CallNode.prototype.compileNode = function(o) { CallNode.prototype.compileNode = function(o) {
var _b, _c, _d, _e, _f, _g, _h, arg, args, compilation; var _b, _c, _d, _e, _f, _g, _h, arg, args, compilation;
@@ -500,7 +493,7 @@
} }
if (this.isNew) { if (this.isNew) {
utility('extends'); utility('extends');
return "(function() {\n" + (this.idt(1)) + "var ctor = function(){ };\n" + (this.idt(1)) + "__extends(ctor, " + meth + ");\n" + (this.idt(1)) + "return " + (meth) + ".apply(new ctor, " + (this.compileSplatArguments(o)) + ");\n" + this.tab + "}).call(this)"; return "(function() {\n" + (this.idt(1)) + "var ctor = function(){};\n" + (this.idt(1)) + "__extends(ctor, " + meth + ");\n" + (this.idt(1)) + "return " + (meth) + ".apply(new ctor, " + (this.compileSplatArguments(o)) + ");\n" + this.tab + "}).call(this)";
} else { } else {
return "" + (this.prefix()) + (meth) + ".apply(" + obj + ", " + (this.compileSplatArguments(o)) + ")"; return "" + (this.prefix()) + (meth) + ".apply(" + obj + ", " + (this.compileSplatArguments(o)) + ")";
} }
@@ -641,7 +634,7 @@
body = ("var " + i + " = " + this.fromVar + "; " + clause + " " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + clause + " " + i + " += 1 : " + i + " -= 1"); body = ("var " + i + " = " + this.fromVar + "; " + clause + " " + i + " <" + this.equals + " " + this.toVar + " : " + i + " >" + this.equals + " " + this.toVar + "; " + clause + " " + i + " += 1 : " + i + " -= 1");
} }
post = ("{ " + (result) + ".push(" + i + ") };\n" + (idt) + "return " + result + ";\n" + o.indent); post = ("{ " + (result) + ".push(" + i + ") };\n" + (idt) + "return " + result + ";\n" + o.indent);
return "(function(){" + (pre) + "\n" + (idt) + "for (" + body + ")" + post + "}).call(this)"; return "(function() {" + (pre) + "\n" + (idt) + "for (" + body + ")" + post + "}).call(this)";
}; };
return RangeNode; return RangeNode;
})(); })();
@@ -841,7 +834,11 @@
return this.variable instanceof ValueNode; return this.variable instanceof ValueNode;
}; };
AssignNode.prototype.makeReturn = function() { AssignNode.prototype.makeReturn = function() {
return new Expressions([this, new ReturnNode(this.variable)]); if (this.isStatement()) {
return new Expressions([this, new ReturnNode(this.variable)]);
} else {
return AssignNode.__superClass__.makeReturn.call(this);
}
}; };
AssignNode.prototype.isStatement = function() { AssignNode.prototype.isStatement = function() {
return this.isValue() && (this.variable.isArray() || this.variable.isObject()); return this.isValue() && (this.variable.isArray() || this.variable.isObject());
@@ -952,7 +949,7 @@
top = del(o, 'top'); top = del(o, 'top');
o.scope = sharedScope || new Scope(o.scope, this.body, this); o.scope = sharedScope || new Scope(o.scope, this.body, this);
o.top = true; o.top = true;
o.indent = this.idt(this.bound ? 2 : 1); o.indent = this.idt(1);
del(o, 'noWrap'); del(o, 'noWrap');
del(o, 'globals'); del(o, 'globals');
i = 0; i = 0;
@@ -983,23 +980,17 @@
return _e; return _e;
})(); })();
this.body.makeReturn(); this.body.makeReturn();
if (this.bound) {
this.body.rewriteThis();
}
_j = params; _j = params;
for (_i = 0, _k = _j.length; _i < _k; _i++) { for (_i = 0, _k = _j.length; _i < _k; _i++) {
param = _j[_i]; param = _j[_i];
(o.scope.parameter(param)); (o.scope.parameter(param));
} }
code = this.body.expressions.length ? ("\n" + (this.body.compileWithDeclarations(o)) + "\n") : ''; code = this.body.expressions.length ? ("\n" + (this.body.compileWithDeclarations(o)) + "\n") : '';
func = ("function(" + (params.join(', ')) + ") {" + code + (code && this.idt(this.bound ? 1 : 0)) + "}"); func = ("function(" + (params.join(', ')) + ") {" + code + (code && this.tab) + "}");
if (top && !this.bound) { if (this.bound) {
func = ("(" + func + ")"); return ("" + (utility('bind')) + "(" + func + ", this)");
} }
if (!(this.bound)) { return top ? ("(" + func + ")") : func;
return func;
}
return "(function(_this) {\n" + (this.idt(1)) + "return " + func + "\n" + this.tab + "})(this)";
}; };
CodeNode.prototype.topSensitive = function() { CodeNode.prototype.topSensitive = function() {
return true; return true;
@@ -1040,20 +1031,24 @@
return (typeof (_b = this.index) !== "undefined" && _b !== null) ? this.compileParam(o) : this.name.compile(o); return (typeof (_b = this.index) !== "undefined" && _b !== null) ? this.compileParam(o) : this.name.compile(o);
}; };
SplatNode.prototype.compileParam = function(o) { SplatNode.prototype.compileParam = function(o) {
var _b, _c, idx, len, name, pos, trailing, variadic; var _b, _c, end, idx, len, name, pos, trailing, variadic;
name = this.name.compile(o); name = this.name.compile(o);
o.scope.find(name); o.scope.find(name);
len = o.scope.freeVariable(); end = '';
o.scope.assign(len, "arguments.length"); if (this.trailings.length) {
variadic = o.scope.freeVariable(); len = o.scope.freeVariable();
o.scope.assign(variadic, ("" + len + " >= " + this.arglength)); o.scope.assign(len, "arguments.length");
_b = this.trailings; variadic = o.scope.freeVariable();
for (idx = 0, _c = _b.length; idx < _c; idx++) { o.scope.assign(variadic, ("" + len + " >= " + this.arglength));
trailing = _b[idx]; end = this.trailings.length ? (", " + len + " - " + (this.trailings.length)) : null;
pos = this.trailings.length - idx; _b = this.trailings;
o.scope.assign(trailing.compile(o), ("arguments[" + variadic + " ? " + len + " - " + pos + " : " + (this.index + idx) + "]")); for (idx = 0, _c = _b.length; idx < _c; idx++) {
trailing = _b[idx];
pos = this.trailings.length - idx;
o.scope.assign(trailing.compile(o), ("arguments[" + variadic + " ? " + len + " - " + pos + " : " + (this.index + idx) + "]"));
}
} }
return "" + name + " = " + (utility('slice')) + ".call(arguments, " + this.index + ", " + len + " - " + (this.trailings.length) + ")"; return "" + name + " = " + (utility('slice')) + ".call(arguments, " + this.index + end + ")";
}; };
SplatNode.prototype.compileValue = function(o, name, index, trailings) { SplatNode.prototype.compileValue = function(o, name, index, trailings) {
var trail; var trail;
@@ -1681,7 +1676,8 @@
} }
}); });
UTILITIES = { UTILITIES = {
'extends': "function(child, parent) {\n var ctor = function(){ };\n ctor.prototype = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n if (typeof parent.extended === \"function\") parent.extended(child);\n child.__superClass__ = parent.prototype;\n }", 'extends': "function(child, parent) {\n var ctor = function(){};\n ctor.prototype = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n if (typeof parent.extended === \"function\") parent.extended(child);\n child.__superClass__ = parent.prototype;\n }",
bind: "function(func, context) {\n return function(){ return func.apply(context, arguments); };\n }",
hasProp: 'Object.prototype.hasOwnProperty', hasProp: 'Object.prototype.hasOwnProperty',
slice: 'Array.prototype.slice' slice: 'Array.prototype.slice'
}; };

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments; var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
exports.OptionParser = (function() { exports.OptionParser = (function() {
OptionParser = function(rules, banner) { OptionParser = function(rules, banner) {

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var CoffeeScript, helpers, readline, repl, run, stdio; var CoffeeScript, helpers, readline, repl, run, stdio;
CoffeeScript = require('./coffee-script'); CoffeeScript = require('./coffee-script');
helpers = require('./helpers').helpers; helpers = require('./helpers').helpers;

View File

@@ -1,6 +1,8 @@
(function(){ (function() {
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, helpers, include, pair; var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, helpers, include, pair;
var __hasProp = Object.prototype.hasOwnProperty; var __bind = function(func, context) {
return function(){ return func.apply(context, arguments); };
}, __hasProp = Object.prototype.hasOwnProperty;
if (typeof process !== "undefined" && process !== null) { if (typeof process !== "undefined" && process !== null) {
_a = require('./helpers'); _a = require('./helpers');
helpers = _a.helpers; helpers = _a.helpers;
@@ -38,30 +40,28 @@
return true; return true;
}; };
Rewriter.prototype.adjustComments = function() { Rewriter.prototype.adjustComments = function() {
return this.scanTokens((function(_this) { return this.scanTokens(__bind(function(prev, token, post, i) {
return function(prev, token, post, i) { var _c, _d, after, before;
var _c, _d, after, before; if (!(token[0] === 'HERECOMMENT')) {
if (!(token[0] === 'HERECOMMENT')) {
return 1;
}
_c = [_this.tokens[i - 2], _this.tokens[i + 2]];
before = _c[0];
after = _c[1];
if (after && after[0] === 'INDENT') {
_this.tokens.splice(i + 2, 1);
before && before[0] === 'OUTDENT' && post && (prev[0] === post[0]) && (post[0] === 'TERMINATOR') ? _this.tokens.splice(i - 2, 1) : _this.tokens.splice(i, 0, after);
} else if (prev && !('TERMINATOR' === (_d = prev[0]) || 'INDENT' === _d || 'OUTDENT' === _d)) {
if (post && post[0] === 'TERMINATOR' && after && after[0] === 'OUTDENT') {
_this.tokens.splice.apply(_this.tokens, [i + 2, 0].concat(_this.tokens.splice(i, 2)));
_this.tokens[i + 2][0] !== 'TERMINATOR' ? _this.tokens.splice(i + 2, 0, ['TERMINATOR', "\n", prev[2]]) : null;
} else {
_this.tokens.splice(i, 0, ['TERMINATOR', "\n", prev[2]]);
}
return 2;
}
return 1; return 1;
} }
})(this)); _c = [this.tokens[i - 2], this.tokens[i + 2]];
before = _c[0];
after = _c[1];
if (after && after[0] === 'INDENT') {
this.tokens.splice(i + 2, 1);
before && before[0] === 'OUTDENT' && post && (prev[0] === post[0]) && (post[0] === 'TERMINATOR') ? this.tokens.splice(i - 2, 1) : this.tokens.splice(i, 0, after);
} else if (prev && !('TERMINATOR' === (_d = prev[0]) || 'INDENT' === _d || 'OUTDENT' === _d)) {
if (post && post[0] === 'TERMINATOR' && after && after[0] === 'OUTDENT') {
this.tokens.splice.apply(this.tokens, [i + 2, 0].concat(this.tokens.splice(i, 2)));
this.tokens[i + 2][0] !== 'TERMINATOR' ? this.tokens.splice(i + 2, 0, ['TERMINATOR', "\n", prev[2]]) : null;
} else {
this.tokens.splice(i, 0, ['TERMINATOR', "\n", prev[2]]);
}
return 2;
}
return 1;
}, this));
}; };
Rewriter.prototype.removeLeadingNewlines = function() { Rewriter.prototype.removeLeadingNewlines = function() {
var _c; var _c;
@@ -72,242 +72,226 @@
return _c; return _c;
}; };
Rewriter.prototype.removeMidExpressionNewlines = function() { Rewriter.prototype.removeMidExpressionNewlines = function() {
return this.scanTokens((function(_this) { return this.scanTokens(__bind(function(prev, token, post, i) {
return function(prev, token, post, i) { if (!(post && include(EXPRESSION_CLOSE, post[0]) && token[0] === 'TERMINATOR')) {
if (!(post && include(EXPRESSION_CLOSE, post[0]) && token[0] === 'TERMINATOR')) { return 1;
return 1;
}
_this.tokens.splice(i, 1);
return 0;
} }
})(this)); this.tokens.splice(i, 1);
return 0;
}, this));
}; };
Rewriter.prototype.closeOpenCallsAndIndexes = function() { Rewriter.prototype.closeOpenCallsAndIndexes = function() {
var brackets, parens; var brackets, parens;
parens = [0]; parens = [0];
brackets = [0]; brackets = [0];
return this.scanTokens((function(_this) { return this.scanTokens(__bind(function(prev, token, post, i) {
return function(prev, token, post, i) { var _c;
var _c; if ((_c = token[0]) === 'CALL_START') {
if ((_c = token[0]) === 'CALL_START') { parens.push(0);
parens.push(0); } else if (_c === 'INDEX_START') {
} else if (_c === 'INDEX_START') { brackets.push(0);
brackets.push(0); } else if (_c === '(') {
} else if (_c === '(') { parens[parens.length - 1] += 1;
parens[parens.length - 1] += 1; } else if (_c === '[') {
} else if (_c === '[') { brackets[brackets.length - 1] += 1;
brackets[brackets.length - 1] += 1; } else if (_c === ')') {
} else if (_c === ')') { if (parens[parens.length - 1] === 0) {
if (parens[parens.length - 1] === 0) { parens.pop();
parens.pop(); token[0] = 'CALL_END';
token[0] = 'CALL_END'; } else {
} else { parens[parens.length - 1] -= 1;
parens[parens.length - 1] -= 1; }
} } else if (_c === ']') {
} else if (_c === ']') { if (brackets[brackets.length - 1] === 0) {
if (brackets[brackets.length - 1] === 0) { brackets.pop();
brackets.pop(); token[0] = 'INDEX_END';
token[0] = 'INDEX_END'; } else {
} else { brackets[brackets.length - 1] -= 1;
brackets[brackets.length - 1] -= 1;
}
} }
return 1;
} }
})(this)); return 1;
}, this));
}; };
Rewriter.prototype.addImplicitBraces = function() { Rewriter.prototype.addImplicitBraces = function() {
var closeBrackets, stack; var closeBrackets, stack;
stack = [0]; stack = [0];
closeBrackets = (function(_this) { closeBrackets = __bind(function(i) {
return function(i) { var _c, len, size, tmp;
var _c, len, size, tmp; len = stack.length - 1;
len = stack.length - 1; _c = stack[len];
_c = stack[len]; for (tmp = 0; (0 <= _c ? tmp < _c : tmp > _c); (0 <= _c ? tmp += 1 : tmp -= 1)) {
for (tmp = 0; (0 <= _c ? tmp < _c : tmp > _c); (0 <= _c ? tmp += 1 : tmp -= 1)) { this.tokens.splice(i, 0, ['}', '}', this.tokens[i][2]]);
_this.tokens.splice(i, 0, ['}', '}', _this.tokens[i][2]]); }
size = stack[len] + 1;
stack[len] = 0;
return size;
}, this);
return this.scanTokens(__bind(function(prev, token, post, i) {
var after, before, idx, len, open, size, tag;
tag = token[0];
len = stack.length - 1;
before = this.tokens[i - 2];
after = this.tokens[i + 2];
open = stack[len] > 0;
if (include(EXPRESSION_START, tag)) {
stack.push(tag === '{' ? 1 : 0);
if (tag === '{' && post && post[0] === 'INDENT') {
return 2;
} }
size = stack[len] + 1; } else if (include(EXPRESSION_END, tag)) {
stack[len] = 0; if (tag === 'OUTDENT' && post && post[0] === '}') {
return 1;
}
stack[len - 1] += stack.pop();
if (tag === '}') {
stack[len - 1] -= 1;
}
} else if (tag === ':' && !open) {
idx = before && before[0] === '@' ? i - 2 : i - 1;
this.tokens.splice(idx, 0, ['{', '{', token[2]]);
stack[stack.length - 1] += 1;
return 2;
} else if (tag === 'TERMINATOR' && !((after && after[0] === ':') || (post && post[0] === '@' && this.tokens[i + 3] && this.tokens[i + 3][0] === ':'))) {
size = closeBrackets(i);
return size; return size;
} }
})(this); return 1;
return this.scanTokens((function(_this) { }, this));
return function(prev, token, post, i) {
var after, before, idx, len, open, size, tag;
tag = token[0];
len = stack.length - 1;
before = _this.tokens[i - 2];
after = _this.tokens[i + 2];
open = stack[len] > 0;
if (include(EXPRESSION_START, tag)) {
stack.push(tag === '{' ? 1 : 0);
if (tag === '{' && post && post[0] === 'INDENT') {
return 2;
}
} else if (include(EXPRESSION_END, tag)) {
if (tag === 'OUTDENT' && post && post[0] === '}') {
return 1;
}
stack[len - 1] += stack.pop();
if (tag === '}') {
stack[len - 1] -= 1;
}
} else if (tag === ':' && !open) {
idx = before && before[0] === '@' ? i - 2 : i - 1;
_this.tokens.splice(idx, 0, ['{', '{', token[2]]);
stack[stack.length - 1] += 1;
return 2;
} else if (tag === 'TERMINATOR' && !((after && after[0] === ':') || (post && post[0] === '@' && _this.tokens[i + 3] && _this.tokens[i + 3][0] === ':'))) {
size = closeBrackets(i);
return size;
}
return 1;
}
})(this));
}; };
Rewriter.prototype.addImplicitParentheses = function() { Rewriter.prototype.addImplicitParentheses = function() {
var closeCalls, stack; var closeCalls, stack;
stack = [0]; stack = [0];
closeCalls = (function(_this) { closeCalls = __bind(function(i) {
return function(i) { var _c, size, tmp;
var _c, size, tmp; _c = stack[stack.length - 1];
_c = stack[stack.length - 1]; for (tmp = 0; (0 <= _c ? tmp < _c : tmp > _c); (0 <= _c ? tmp += 1 : tmp -= 1)) {
for (tmp = 0; (0 <= _c ? tmp < _c : tmp > _c); (0 <= _c ? tmp += 1 : tmp -= 1)) { this.tokens.splice(i, 0, ['CALL_END', ')', this.tokens[i][2]]);
_this.tokens.splice(i, 0, ['CALL_END', ')', _this.tokens[i][2]]);
}
size = stack[stack.length - 1] + 1;
stack[stack.length - 1] = 0;
return size;
} }
})(this); size = stack[stack.length - 1] + 1;
return this.scanTokens((function(_this) { stack[stack.length - 1] = 0;
return function(prev, token, post, i) { return size;
var _c, _d, j, nx, open, size, tag; }, this);
tag = token[0]; return this.scanTokens(__bind(function(prev, token, post, i) {
if (tag === 'OUTDENT') { var _c, _d, j, nx, open, size, tag;
stack[stack.length - 2] += stack.pop(); tag = token[0];
} if (tag === 'OUTDENT') {
open = stack[stack.length - 1] > 0; stack[stack.length - 2] += stack.pop();
if (prev && prev.spaced && include(IMPLICIT_FUNC, prev[0]) && include(IMPLICIT_CALL, tag) && !(tag === '!' && (('IN' === (_c = post[0]) || 'OF' === _c)))) { }
_this.tokens.splice(i, 0, ['CALL_START', '(', token[2]]); open = stack[stack.length - 1] > 0;
stack[stack.length - 1] += 1; if (prev && prev.spaced && include(IMPLICIT_FUNC, prev[0]) && include(IMPLICIT_CALL, tag) && !(tag === '!' && (('IN' === (_c = post[0]) || 'OF' === _c)))) {
if (include(EXPRESSION_START, tag)) { this.tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
stack.push(0); stack[stack.length - 1] += 1;
}
return 2;
}
if (include(EXPRESSION_START, tag)) { if (include(EXPRESSION_START, tag)) {
if (tag === 'INDENT' && !token.generated && open && !(prev && include(IMPLICIT_BLOCK, prev[0]))) {
size = closeCalls(i);
stack.push(0);
return size;
}
stack.push(0); stack.push(0);
return 1;
} }
if (open && !token.generated && prev[0] !== ',' && (!post || include(IMPLICIT_END, tag))) { return 2;
j = 1; }
while ((typeof (_d = (nx = _this.tokens[i + j])) !== "undefined" && _d !== null) && include(IMPLICIT_END, nx[0])) { if (include(EXPRESSION_START, tag)) {
j++; if (tag === 'INDENT' && !token.generated && open && !(prev && include(IMPLICIT_BLOCK, prev[0]))) {
} size = closeCalls(i);
if ((typeof nx !== "undefined" && nx !== null) && nx[0] === ',' && _this.tokens[i + j - 1][0] === 'OUTDENT') { stack.push(0);
if (tag === 'TERMINATOR') { return size;
_this.tokens.splice(i, 1);
}
} else {
size = closeCalls(i);
if (tag !== 'OUTDENT' && include(EXPRESSION_END, tag)) {
stack.pop();
}
return size;
}
}
if (tag !== 'OUTDENT' && include(EXPRESSION_END, tag)) {
stack[stack.length - 2] += stack.pop();
return 1;
} }
stack.push(0);
return 1; return 1;
} }
})(this)); if (open && !token.generated && prev[0] !== ',' && (!post || include(IMPLICIT_END, tag))) {
j = 1;
while ((typeof (_d = (nx = this.tokens[i + j])) !== "undefined" && _d !== null) && include(IMPLICIT_END, nx[0])) {
j++;
}
if ((typeof nx !== "undefined" && nx !== null) && nx[0] === ',' && this.tokens[i + j - 1][0] === 'OUTDENT') {
if (tag === 'TERMINATOR') {
this.tokens.splice(i, 1);
}
} else {
size = closeCalls(i);
if (tag !== 'OUTDENT' && include(EXPRESSION_END, tag)) {
stack.pop();
}
return size;
}
}
if (tag !== 'OUTDENT' && include(EXPRESSION_END, tag)) {
stack[stack.length - 2] += stack.pop();
return 1;
}
return 1;
}, this));
}; };
Rewriter.prototype.addImplicitIndentation = function() { Rewriter.prototype.addImplicitIndentation = function() {
return this.scanTokens((function(_this) { return this.scanTokens(__bind(function(prev, token, post, i) {
return function(prev, token, post, i) { var _c, idx, indent, insertion, outdent, parens, pre, starter, tok;
var _c, idx, indent, insertion, outdent, parens, pre, starter, tok; if (token[0] === 'ELSE' && prev[0] !== 'OUTDENT') {
if (token[0] === 'ELSE' && prev[0] !== 'OUTDENT') { this.tokens.splice.apply(this.tokens, [i, 0].concat(this.indentation(token)));
_this.tokens.splice.apply(_this.tokens, [i, 0].concat(_this.indentation(token))); return 2;
return 2;
}
if (token[0] === 'CATCH' && (_this.tokens[i + 2][0] === 'TERMINATOR' || _this.tokens[i + 2][0] === 'FINALLY')) {
_this.tokens.splice.apply(_this.tokens, [i + 2, 0].concat(_this.indentation(token)));
return 4;
}
if (!(include(SINGLE_LINERS, token[0]) && post[0] !== 'INDENT' && !(token[0] === 'ELSE' && post[0] === 'IF'))) {
return 1;
}
starter = token[0];
_c = _this.indentation(token);
indent = _c[0];
outdent = _c[1];
indent.generated = (outdent.generated = true);
_this.tokens.splice(i + 1, 0, indent);
idx = i + 1;
parens = 0;
while (true) {
idx += 1;
tok = _this.tokens[idx];
pre = _this.tokens[idx - 1];
if ((!tok || (include(SINGLE_CLOSERS, tok[0]) && tok[1] !== ';' && parens === 0) || (tok[0] === ')' && parens === 0)) && !(tok[0] === 'ELSE' && !('IF' === starter || 'THEN' === starter))) {
insertion = pre[0] === "," ? idx - 1 : idx;
_this.tokens.splice(insertion, 0, outdent);
break;
}
if (tok[0] === '(') {
parens += 1;
}
if (tok[0] === ')') {
parens -= 1;
}
}
if (!(token[0] === 'THEN')) {
return 1;
}
_this.tokens.splice(i, 1);
return 0;
} }
})(this)); if (token[0] === 'CATCH' && (this.tokens[i + 2][0] === 'TERMINATOR' || this.tokens[i + 2][0] === 'FINALLY')) {
this.tokens.splice.apply(this.tokens, [i + 2, 0].concat(this.indentation(token)));
return 4;
}
if (!(include(SINGLE_LINERS, token[0]) && post[0] !== 'INDENT' && !(token[0] === 'ELSE' && post[0] === 'IF'))) {
return 1;
}
starter = token[0];
_c = this.indentation(token);
indent = _c[0];
outdent = _c[1];
indent.generated = (outdent.generated = true);
this.tokens.splice(i + 1, 0, indent);
idx = i + 1;
parens = 0;
while (true) {
idx += 1;
tok = this.tokens[idx];
pre = this.tokens[idx - 1];
if ((!tok || (include(SINGLE_CLOSERS, tok[0]) && tok[1] !== ';' && parens === 0) || (tok[0] === ')' && parens === 0)) && !(tok[0] === 'ELSE' && !('IF' === starter || 'THEN' === starter))) {
insertion = pre[0] === "," ? idx - 1 : idx;
this.tokens.splice(insertion, 0, outdent);
break;
}
if (tok[0] === '(') {
parens += 1;
}
if (tok[0] === ')') {
parens -= 1;
}
}
if (!(token[0] === 'THEN')) {
return 1;
}
this.tokens.splice(i, 1);
return 0;
}, this));
}; };
Rewriter.prototype.ensureBalance = function(pairs) { Rewriter.prototype.ensureBalance = function(pairs) {
var _c, _d, key, levels, line, open, openLine, unclosed, value; var _c, _d, key, levels, line, open, openLine, unclosed, value;
levels = {}; levels = {};
openLine = {}; openLine = {};
this.scanTokens((function(_this) { this.scanTokens(__bind(function(prev, token, post, i) {
return function(prev, token, post, i) { var _c, _d, _e, _f, close, open, pair;
var _c, _d, _e, _f, close, open, pair; _d = pairs;
_d = pairs; for (_c = 0, _e = _d.length; _c < _e; _c++) {
for (_c = 0, _e = _d.length; _c < _e; _c++) { pair = _d[_c];
pair = _d[_c]; _f = pair;
_f = pair; open = _f[0];
open = _f[0]; close = _f[1];
close = _f[1]; levels[open] = levels[open] || 0;
levels[open] = levels[open] || 0; if (token[0] === open) {
if (token[0] === open) { if (levels[open] === 0) {
if (levels[open] === 0) { openLine[open] = token[2];
openLine[open] = token[2];
}
levels[open] += 1;
}
if (token[0] === close) {
levels[open] -= 1;
}
if (levels[open] < 0) {
throw new Error(("too many " + (token[1]) + " on line " + (token[2] + 1)));
} }
levels[open] += 1;
}
if (token[0] === close) {
levels[open] -= 1;
}
if (levels[open] < 0) {
throw new Error(("too many " + (token[1]) + " on line " + (token[2] + 1)));
} }
return 1;
} }
})(this)); return 1;
}, this));
unclosed = (function() { unclosed = (function() {
_c = []; _d = levels; _c = []; _d = levels;
for (key in _d) { for (key in _d) {
@@ -333,41 +317,39 @@
val = _c[key]; val = _c[key];
(debt[key] = 0); (debt[key] = 0);
} }
return this.scanTokens((function(_this) { return this.scanTokens(__bind(function(prev, token, post, i) {
return function(prev, token, post, i) { var inv, match, mtag, oppos, tag;
var inv, match, mtag, oppos, tag; tag = token[0];
tag = token[0]; inv = INVERSES[token[0]];
inv = INVERSES[token[0]]; if (include(EXPRESSION_START, tag)) {
if (include(EXPRESSION_START, tag)) { stack.push(token);
stack.push(token); return 1;
return 1; } else if (include(EXPRESSION_END, tag)) {
} else if (include(EXPRESSION_END, tag)) { if (debt[inv] > 0) {
if (debt[inv] > 0) { debt[inv] -= 1;
debt[inv] -= 1; this.tokens.splice(i, 1);
_this.tokens.splice(i, 1); return 0;
return 0; } else {
} else { match = stack.pop();
match = stack.pop(); mtag = match[0];
mtag = match[0]; oppos = INVERSES[mtag];
oppos = INVERSES[mtag]; if (tag === oppos) {
if (tag === oppos) {
return 1;
}
debt[mtag] += 1;
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
if ((_this.tokens[i + 2] == undefined ? undefined : _this.tokens[i + 2][0]) === mtag) {
_this.tokens.splice(i + 3, 0, val);
stack.push(match);
} else {
_this.tokens.splice(i, 0, val);
}
return 1; return 1;
} }
} else { debt[mtag] += 1;
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
if ((this.tokens[i + 2] == undefined ? undefined : this.tokens[i + 2][0]) === mtag) {
this.tokens.splice(i + 3, 0, val);
stack.push(match);
} else {
this.tokens.splice(i, 0, val);
}
return 1; return 1;
} }
} else {
return 1;
} }
})(this)); }, this));
}; };
Rewriter.prototype.indentation = function(token) { Rewriter.prototype.indentation = function(token) {
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]]; return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];

View File

@@ -1,4 +1,4 @@
(function(){ (function() {
var Scope; var Scope;
var __hasProp = Object.prototype.hasOwnProperty; var __hasProp = Object.prototype.hasOwnProperty;
if (!(typeof process !== "undefined" && process !== null)) { if (!(typeof process !== "undefined" && process !== null)) {
@@ -41,8 +41,7 @@
return false; return false;
}; };
Scope.prototype.parameter = function(name) { Scope.prototype.parameter = function(name) {
this.variables[name] = 'param'; return (this.variables[name] = 'param');
return this.variables[name];
}; };
Scope.prototype.check = function(name) { Scope.prototype.check = function(name) {
if (this.variables.hasOwnProperty(name)) { if (this.variables.hasOwnProperty(name)) {
@@ -60,11 +59,10 @@
return this.tempVar; return this.tempVar;
}; };
Scope.prototype.assign = function(name, value) { Scope.prototype.assign = function(name, value) {
this.variables[name] = { return (this.variables[name] = {
value: value, value: value,
assigned: true assigned: true
}; });
return this.variables[name];
}; };
Scope.prototype.hasDeclarations = function(body) { Scope.prototype.hasDeclarations = function(body) {
return body === this.expressions && this.any(function(k, val) { return body === this.expressions && this.any(function(k, val) {

View File

@@ -185,12 +185,6 @@ exports.Expressions = class Expressions extends BaseNode
@expressions[idx] = last.makeReturn() @expressions[idx] = last.makeReturn()
this this
# A bound function uses a local `_this` variable instead of the real `this`.
rewriteThis: ->
@traverseChildren false, (child) ->
if child instanceof ValueNode and child.base.value is 'this'
child.base = literal '_this'
# An **Expressions** is the only node that can serve as the root. # An **Expressions** is the only node that can serve as the root.
compile: (o) -> compile: (o) ->
o or= {} o or= {}
@@ -204,12 +198,12 @@ exports.Expressions = class Expressions extends BaseNode
# It would be better not to generate them in the first place, but for now, # It would be better not to generate them in the first place, but for now,
# clean up obvious double-parentheses. # clean up obvious double-parentheses.
compileRoot: (o) -> compileRoot: (o) ->
o.indent = @tab = if o.noWrap then '' else TAB o.indent = @tab = if o.noWrap then '' else TAB
o.scope = new Scope(null, this, null) o.scope = new Scope(null, this, null)
code = @compileWithDeclarations(o) code = @compileWithDeclarations(o)
code = code.replace(TRAILING_WHITESPACE, '') code = code.replace(TRAILING_WHITESPACE, '')
code = code.replace(DOUBLE_PARENS, '($1)') code = code.replace(DOUBLE_PARENS, '($1)')
if o.noWrap then code else "(function(){\n$code\n})();\n" if o.noWrap then code else "(function() {\n$code\n})();\n"
# Compile the expressions body for the contents of a function, with # Compile the expressions body for the contents of a function, with
# declarations of all inner variables pushed up to the top. # declarations of all inner variables pushed up to the top.
@@ -459,7 +453,7 @@ exports.CallNode = class CallNode extends BaseNode
utility 'extends' utility 'extends'
""" """
(function() { (function() {
${@idt(1)}var ctor = function(){ }; ${@idt(1)}var ctor = function(){};
${@idt(1)}__extends(ctor, $meth); ${@idt(1)}__extends(ctor, $meth);
${@idt(1)}return ${meth}.apply(new ctor, ${ @compileSplatArguments(o) }); ${@idt(1)}return ${meth}.apply(new ctor, ${ @compileSplatArguments(o) });
$@tab}).call(this) $@tab}).call(this)
@@ -589,8 +583,8 @@ exports.RangeNode = class RangeNode extends BaseNode
else else
clause = "$@fromVar <= $@toVar ?" clause = "$@fromVar <= $@toVar ?"
body = "var $i = $@fromVar; $clause $i <$@equals $@toVar : $i >$@equals $@toVar; $clause $i += 1 : $i -= 1" body = "var $i = $@fromVar; $clause $i <$@equals $@toVar : $i >$@equals $@toVar; $clause $i += 1 : $i -= 1"
post = "{ ${result}.push($i) };\n${idt}return $result;\n$o.indent" post = "{ ${result}.push($i) };\n${idt}return $result;\n$o.indent"
"(function(){${pre}\n${idt}for ($body)$post}).call(this)" "(function() {${pre}\n${idt}for ($body)$post}).call(this)"
#### SliceNode #### SliceNode
@@ -764,7 +758,10 @@ exports.AssignNode = class AssignNode extends BaseNode
@variable instanceof ValueNode @variable instanceof ValueNode
makeReturn: -> makeReturn: ->
return new Expressions [this, new ReturnNode(@variable)] if @isStatement()
return new Expressions [this, new ReturnNode(@variable)]
else
super()
isStatement: -> isStatement: ->
@isValue() and (@variable.isArray() or @variable.isObject()) @isValue() and (@variable.isArray() or @variable.isObject())
@@ -866,7 +863,7 @@ exports.CodeNode = class CodeNode extends BaseNode
top = del o, 'top' top = del o, 'top'
o.scope = sharedScope or new Scope(o.scope, @body, this) o.scope = sharedScope or new Scope(o.scope, @body, this)
o.top = true o.top = true
o.indent = @idt(if @bound then 2 else 1) o.indent = @idt(1)
del o, 'noWrap' del o, 'noWrap'
del o, 'globals' del o, 'globals'
i = 0 i = 0
@@ -886,13 +883,11 @@ exports.CodeNode = class CodeNode extends BaseNode
i += 1 i += 1
params = (param.compile(o) for param in params) params = (param.compile(o) for param in params)
@body.makeReturn() @body.makeReturn()
@body.rewriteThis() if @bound
(o.scope.parameter(param)) for param in params (o.scope.parameter(param)) for param in params
code = if @body.expressions.length then "\n${ @body.compileWithDeclarations(o) }\n" else '' code = if @body.expressions.length then "\n${ @body.compileWithDeclarations(o) }\n" else ''
func = "function(${ params.join(', ') }) {$code${ code and @idt(if @bound then 1 else 0) }}" func = "function(${ params.join(', ') }) {$code${ code and @tab }}"
func = "($func)" if top and not @bound return "${utility('bind')}($func, this)" if @bound
return func unless @bound if top then "($func)" else func
"(function(_this) {\n${@idt(1)}return $func\n$@tab})(this)"
topSensitive: -> topSensitive: ->
true true
@@ -927,14 +922,17 @@ exports.SplatNode = class SplatNode extends BaseNode
compileParam: (o) -> compileParam: (o) ->
name = @name.compile(o) name = @name.compile(o)
o.scope.find name o.scope.find name
len = o.scope.freeVariable() end = ''
o.scope.assign len, "arguments.length" if @trailings.length
variadic = o.scope.freeVariable() len = o.scope.freeVariable()
o.scope.assign variadic, "$len >= $@arglength" o.scope.assign len, "arguments.length"
for trailing, idx in @trailings variadic = o.scope.freeVariable()
pos = @trailings.length - idx o.scope.assign variadic, "$len >= $@arglength"
o.scope.assign(trailing.compile(o), "arguments[$variadic ? $len - $pos : ${@index + idx}]") end = if @trailings.length then ", $len - ${@trailings.length}"
"$name = ${utility('slice')}.call(arguments, $@index, $len - ${@trailings.length})" for trailing, idx in @trailings
pos = @trailings.length - idx
o.scope.assign(trailing.compile(o), "arguments[$variadic ? $len - $pos : ${@index + idx}]")
"$name = ${utility('slice')}.call(arguments, $@index$end)"
# A compiling a splat as a destructuring assignment means slicing arguments # A compiling a splat as a destructuring assignment means slicing arguments
# from the right-hand-side's corresponding array. # from the right-hand-side's corresponding array.
@@ -1487,7 +1485,7 @@ UTILITIES = {
# [goog.inherits](http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.source.html#line1206). # [goog.inherits](http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.source.html#line1206).
extends: """ extends: """
function(child, parent) { function(child, parent) {
var ctor = function(){ }; var ctor = function(){};
ctor.prototype = parent.prototype; ctor.prototype = parent.prototype;
child.prototype = new ctor(); child.prototype = new ctor();
child.prototype.constructor = child; child.prototype.constructor = child;
@@ -1496,6 +1494,13 @@ UTILITIES = {
} }
""" """
# Create a function bound to the current value of "this".
bind: """
function(func, context) {
return function(){ return func.apply(context, arguments); };
}
"""
# Shortcuts to speed up the lookup time for native functions. # Shortcuts to speed up the lookup time for native functions.
hasProp: 'Object.prototype.hasOwnProperty' hasProp: 'Object.prototype.hasOwnProperty'
slice: 'Array.prototype.slice' slice: 'Array.prototype.slice'

View File

@@ -19,17 +19,27 @@ ok y.x() is 3
obj = { obj = {
name: "Fred" name: 'Fred'
bound: -> bound: ->
(=> ok(this.name is "Fred"))() (=> ok(this.name is 'Fred'))()
unbound: -> unbound: ->
(-> ok(!this.name?))() (-> ok(!this.name?))()
nested: ->
(=>
(=>
(=>
ok this.name is 'Fred'
)()
)()
)()
} }
obj.unbound() obj.unbound()
obj.bound() obj.bound()
obj.nested()
# Python decorator style wrapper that memoizes any function # Python decorator style wrapper that memoizes any function