mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
merging master changes into symbology
This commit is contained in:
parent
a0b2b78962
commit
6b0418a74a
14 changed files with 339 additions and 355 deletions
|
@ -17,12 +17,11 @@
|
|||
action = _a[0];
|
||||
description = _a[1];
|
||||
}
|
||||
tasks[name] = {
|
||||
return (tasks[name] = {
|
||||
name: name,
|
||||
description: description,
|
||||
action: action
|
||||
};
|
||||
return tasks[name];
|
||||
});
|
||||
},
|
||||
option: function(letter, flag, description) {
|
||||
return switches.push([letter, flag, description]);
|
||||
|
|
|
@ -51,8 +51,7 @@
|
|||
},
|
||||
setInput: function(tokens) {
|
||||
this.tokens = tokens;
|
||||
this.pos = 0;
|
||||
return this.pos;
|
||||
return (this.pos = 0);
|
||||
},
|
||||
upcomingInput: function() {
|
||||
return "";
|
||||
|
|
|
@ -195,8 +195,7 @@
|
|||
options.compile = options.compile || !!o.output;
|
||||
options.run = !(o.compile || o.print || o.lint);
|
||||
options.print = !!(o.print || (o.eval || o.stdio && o.compile));
|
||||
sources = options.arguments;
|
||||
return sources;
|
||||
return (sources = options.arguments);
|
||||
};
|
||||
compileOptions = function(source) {
|
||||
var o;
|
||||
|
|
12
lib/lexer.js
12
lib/lexer.js
|
@ -219,8 +219,7 @@
|
|||
};
|
||||
Lexer.prototype.balancedToken = function() {
|
||||
var delimited;
|
||||
var _d = arguments.length, _e = _d >= 1;
|
||||
delimited = __slice.call(arguments, 0, _d - 0);
|
||||
delimited = __slice.call(arguments, 0);
|
||||
return this.balancedString(this.chunk, delimited);
|
||||
};
|
||||
Lexer.prototype.lineToken = function() {
|
||||
|
@ -387,8 +386,7 @@
|
|||
} else if (_d === ')') {
|
||||
tok[0] = 'PARAM_END';
|
||||
} else if (_d === '(' || _d === 'CALL_START') {
|
||||
tok[0] = 'PARAM_START';
|
||||
return tok[0];
|
||||
return (tok[0] = 'PARAM_START');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -543,8 +541,7 @@
|
|||
return null;
|
||||
}
|
||||
if (typeof newTag !== "undefined" && newTag !== null) {
|
||||
tok[0] = newTag;
|
||||
return tok[0];
|
||||
return (tok[0] = newTag);
|
||||
}
|
||||
return tok[0];
|
||||
};
|
||||
|
@ -554,8 +551,7 @@
|
|||
return null;
|
||||
}
|
||||
if (typeof val !== "undefined" && val !== null) {
|
||||
tok[1] = val;
|
||||
return tok[1];
|
||||
return (tok[1] = val);
|
||||
}
|
||||
return tok[1];
|
||||
};
|
||||
|
|
42
lib/nodes.js
42
lib/nodes.js
|
@ -203,11 +203,6 @@
|
|||
this.expressions[idx] = last.makeReturn();
|
||||
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) {
|
||||
o = o || {};
|
||||
return o.scope ? Expressions.__superClass__.compile.call(this, o) : this.compileRoot(o);
|
||||
|
@ -399,8 +394,7 @@
|
|||
part = prop.compile(o);
|
||||
baseline += part;
|
||||
complete += part;
|
||||
this.last = part;
|
||||
return this.last;
|
||||
return (this.last = part);
|
||||
}
|
||||
}).call(this);
|
||||
}
|
||||
|
@ -452,7 +446,7 @@
|
|||
CallNode.prototype.superReference = function(o) {
|
||||
var meth, methname;
|
||||
methname = o.scope.method.name;
|
||||
meth = (function() {
|
||||
return (meth = (function() {
|
||||
if (o.scope.method.proto) {
|
||||
return "" + (o.scope.method.proto) + ".__superClass__." + methname;
|
||||
} else if (methname) {
|
||||
|
@ -460,8 +454,7 @@
|
|||
} else {
|
||||
throw new Error("cannot call super on an anonymous function.");
|
||||
}
|
||||
})();
|
||||
return meth;
|
||||
})());
|
||||
};
|
||||
CallNode.prototype.compileNode = function(o) {
|
||||
var _b, _c, _d, _e, _f, _g, _h, arg, args, compilation;
|
||||
|
@ -841,7 +834,11 @@
|
|||
return this.variable instanceof ValueNode;
|
||||
};
|
||||
AssignNode.prototype.makeReturn = function() {
|
||||
if (this.isStatement()) {
|
||||
return new Expressions([this, new ReturnNode(this.variable)]);
|
||||
} else {
|
||||
return AssignNode.__superClass__.makeReturn.call(this);
|
||||
}
|
||||
};
|
||||
AssignNode.prototype.isStatement = function() {
|
||||
return this.isValue() && (this.variable.isArray() || this.variable.isObject());
|
||||
|
@ -952,7 +949,7 @@
|
|||
top = del(o, 'top');
|
||||
o.scope = sharedScope || new Scope(o.scope, this.body, this);
|
||||
o.top = true;
|
||||
o.indent = this.idt(this.bound ? 2 : 1);
|
||||
o.indent = this.idt(1);
|
||||
del(o, 'noWrap');
|
||||
del(o, 'globals');
|
||||
i = 0;
|
||||
|
@ -983,23 +980,17 @@
|
|||
return _e;
|
||||
})();
|
||||
this.body.makeReturn();
|
||||
if (this.bound) {
|
||||
this.body.rewriteThis();
|
||||
}
|
||||
_j = params;
|
||||
for (_i = 0, _k = _j.length; _i < _k; _i++) {
|
||||
param = _j[_i];
|
||||
(o.scope.parameter(param));
|
||||
}
|
||||
code = this.body.expressions.length ? ("\n" + (this.body.compileWithDeclarations(o)) + "\n") : '';
|
||||
func = ("function(" + (params.join(', ')) + ") {" + code + (code && this.idt(this.bound ? 1 : 0)) + "}");
|
||||
if (top && !this.bound) {
|
||||
func = ("(" + func + ")");
|
||||
func = ("function(" + (params.join(', ')) + ") {" + code + (code && this.tab) + "}");
|
||||
if (this.bound) {
|
||||
return ("" + (utility('bind')) + "(" + func + ", this)");
|
||||
}
|
||||
if (!(this.bound)) {
|
||||
return func;
|
||||
}
|
||||
return "(function(_this) {\n" + (this.idt(1)) + "return " + func + "\n" + this.tab + "})(this)";
|
||||
return top ? ("(" + func + ")") : func;
|
||||
};
|
||||
CodeNode.prototype.topSensitive = function() {
|
||||
return true;
|
||||
|
@ -1040,20 +1031,24 @@
|
|||
return (typeof (_b = this.index) !== "undefined" && _b !== null) ? this.compileParam(o) : this.name.compile(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);
|
||||
o.scope.find(name);
|
||||
end = '';
|
||||
if (this.trailings.length) {
|
||||
len = o.scope.freeVariable();
|
||||
o.scope.assign(len, "arguments.length");
|
||||
variadic = o.scope.freeVariable();
|
||||
o.scope.assign(variadic, ("" + len + " >= " + this.arglength));
|
||||
end = this.trailings.length ? (", " + len + " - " + (this.trailings.length)) : null;
|
||||
_b = this.trailings;
|
||||
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) {
|
||||
var trail;
|
||||
|
@ -1682,6 +1677,7 @@
|
|||
});
|
||||
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 }",
|
||||
bind: "function(func, context) {\n return function(){ return func.apply(context, arguments); };\n }",
|
||||
hasProp: 'Object.prototype.hasOwnProperty',
|
||||
slice: 'Array.prototype.slice'
|
||||
};
|
||||
|
|
124
lib/rewriter.js
124
lib/rewriter.js
|
@ -1,6 +1,8 @@
|
|||
(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 __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) {
|
||||
_a = require('./helpers');
|
||||
helpers = _a.helpers;
|
||||
|
@ -38,30 +40,28 @@
|
|||
return true;
|
||||
};
|
||||
Rewriter.prototype.adjustComments = function() {
|
||||
return this.scanTokens((function(_this) {
|
||||
return function(prev, token, post, i) {
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, _d, after, before;
|
||||
if (!(token[0] === 'HERECOMMENT')) {
|
||||
return 1;
|
||||
}
|
||||
_c = [_this.tokens[i - 2], _this.tokens[i + 2]];
|
||||
_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);
|
||||
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;
|
||||
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]]);
|
||||
this.tokens.splice(i, 0, ['TERMINATOR', "\n", prev[2]]);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
})(this));
|
||||
}, this));
|
||||
};
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var _c;
|
||||
|
@ -72,22 +72,19 @@
|
|||
return _c;
|
||||
};
|
||||
Rewriter.prototype.removeMidExpressionNewlines = function() {
|
||||
return this.scanTokens((function(_this) {
|
||||
return function(prev, token, post, i) {
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
if (!(post && include(EXPRESSION_CLOSE, post[0]) && token[0] === 'TERMINATOR')) {
|
||||
return 1;
|
||||
}
|
||||
_this.tokens.splice(i, 1);
|
||||
this.tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
})(this));
|
||||
}, this));
|
||||
};
|
||||
Rewriter.prototype.closeOpenCallsAndIndexes = function() {
|
||||
var brackets, parens;
|
||||
parens = [0];
|
||||
brackets = [0];
|
||||
return this.scanTokens((function(_this) {
|
||||
return function(prev, token, post, i) {
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c;
|
||||
if ((_c = token[0]) === 'CALL_START') {
|
||||
parens.push(0);
|
||||
|
@ -113,32 +110,28 @@
|
|||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
})(this));
|
||||
}, this));
|
||||
};
|
||||
Rewriter.prototype.addImplicitBraces = function() {
|
||||
var closeBrackets, stack;
|
||||
stack = [0];
|
||||
closeBrackets = (function(_this) {
|
||||
return function(i) {
|
||||
closeBrackets = __bind(function(i) {
|
||||
var _c, len, size, tmp;
|
||||
len = stack.length - 1;
|
||||
_c = stack[len];
|
||||
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((function(_this) {
|
||||
return function(prev, token, post, i) {
|
||||
}, 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];
|
||||
before = this.tokens[i - 2];
|
||||
after = this.tokens[i + 2];
|
||||
open = stack[len] > 0;
|
||||
if (include(EXPRESSION_START, tag)) {
|
||||
stack.push(tag === '{' ? 1 : 0);
|
||||
|
@ -155,34 +148,30 @@
|
|||
}
|
||||
} else if (tag === ':' && !open) {
|
||||
idx = before && before[0] === '@' ? i - 2 : i - 1;
|
||||
_this.tokens.splice(idx, 0, ['{', '{', token[2]]);
|
||||
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] === ':'))) {
|
||||
} 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));
|
||||
}, this));
|
||||
};
|
||||
Rewriter.prototype.addImplicitParentheses = function() {
|
||||
var closeCalls, stack;
|
||||
stack = [0];
|
||||
closeCalls = (function(_this) {
|
||||
return function(i) {
|
||||
closeCalls = __bind(function(i) {
|
||||
var _c, size, tmp;
|
||||
_c = stack[stack.length - 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);
|
||||
return this.scanTokens((function(_this) {
|
||||
return function(prev, token, post, i) {
|
||||
}, this);
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, _d, j, nx, open, size, tag;
|
||||
tag = token[0];
|
||||
if (tag === 'OUTDENT') {
|
||||
|
@ -190,7 +179,7 @@
|
|||
}
|
||||
open = stack[stack.length - 1] > 0;
|
||||
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]]);
|
||||
this.tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
stack[stack.length - 1] += 1;
|
||||
if (include(EXPRESSION_START, tag)) {
|
||||
stack.push(0);
|
||||
|
@ -208,12 +197,12 @@
|
|||
}
|
||||
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])) {
|
||||
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 ((typeof nx !== "undefined" && nx !== null) && nx[0] === ',' && this.tokens[i + j - 1][0] === 'OUTDENT') {
|
||||
if (tag === 'TERMINATOR') {
|
||||
_this.tokens.splice(i, 1);
|
||||
this.tokens.splice(i, 1);
|
||||
}
|
||||
} else {
|
||||
size = closeCalls(i);
|
||||
|
@ -228,39 +217,37 @@
|
|||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
})(this));
|
||||
}, this));
|
||||
};
|
||||
Rewriter.prototype.addImplicitIndentation = function() {
|
||||
return this.scanTokens((function(_this) {
|
||||
return function(prev, token, post, i) {
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, idx, indent, insertion, outdent, parens, pre, starter, tok;
|
||||
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;
|
||||
}
|
||||
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)));
|
||||
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);
|
||||
_c = this.indentation(token);
|
||||
indent = _c[0];
|
||||
outdent = _c[1];
|
||||
indent.generated = (outdent.generated = true);
|
||||
_this.tokens.splice(i + 1, 0, indent);
|
||||
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];
|
||||
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);
|
||||
this.tokens.splice(insertion, 0, outdent);
|
||||
break;
|
||||
}
|
||||
if (tok[0] === '(') {
|
||||
|
@ -273,17 +260,15 @@
|
|||
if (!(token[0] === 'THEN')) {
|
||||
return 1;
|
||||
}
|
||||
_this.tokens.splice(i, 1);
|
||||
this.tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
})(this));
|
||||
}, this));
|
||||
};
|
||||
Rewriter.prototype.ensureBalance = function(pairs) {
|
||||
var _c, _d, key, levels, line, open, openLine, unclosed, value;
|
||||
levels = {};
|
||||
openLine = {};
|
||||
this.scanTokens((function(_this) {
|
||||
return function(prev, token, post, i) {
|
||||
this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var _c, _d, _e, _f, close, open, pair;
|
||||
_d = pairs;
|
||||
for (_c = 0, _e = _d.length; _c < _e; _c++) {
|
||||
|
@ -306,8 +291,7 @@
|
|||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
})(this));
|
||||
}, this));
|
||||
unclosed = (function() {
|
||||
_c = []; _d = levels;
|
||||
for (key in _d) {
|
||||
|
@ -333,8 +317,7 @@
|
|||
val = _c[key];
|
||||
(debt[key] = 0);
|
||||
}
|
||||
return this.scanTokens((function(_this) {
|
||||
return function(prev, token, post, i) {
|
||||
return this.scanTokens(__bind(function(prev, token, post, i) {
|
||||
var inv, match, mtag, oppos, tag;
|
||||
tag = token[0];
|
||||
inv = INVERSES[token[0]];
|
||||
|
@ -344,7 +327,7 @@
|
|||
} else if (include(EXPRESSION_END, tag)) {
|
||||
if (debt[inv] > 0) {
|
||||
debt[inv] -= 1;
|
||||
_this.tokens.splice(i, 1);
|
||||
this.tokens.splice(i, 1);
|
||||
return 0;
|
||||
} else {
|
||||
match = stack.pop();
|
||||
|
@ -355,19 +338,18 @@
|
|||
}
|
||||
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);
|
||||
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);
|
||||
this.tokens.splice(i, 0, val);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
})(this));
|
||||
}, this));
|
||||
};
|
||||
Rewriter.prototype.indentation = function(token) {
|
||||
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
|
||||
|
|
|
@ -41,8 +41,7 @@
|
|||
return false;
|
||||
};
|
||||
Scope.prototype.parameter = function(name) {
|
||||
this.variables[name] = 'param';
|
||||
return this.variables[name];
|
||||
return (this.variables[name] = 'param');
|
||||
};
|
||||
Scope.prototype.check = function(name) {
|
||||
if (this.variables.hasOwnProperty(name)) {
|
||||
|
@ -60,11 +59,10 @@
|
|||
return this.tempVar;
|
||||
};
|
||||
Scope.prototype.assign = function(name, value) {
|
||||
this.variables[name] = {
|
||||
return (this.variables[name] = {
|
||||
value: value,
|
||||
assigned: true
|
||||
};
|
||||
return this.variables[name];
|
||||
});
|
||||
};
|
||||
Scope.prototype.hasDeclarations = function(body) {
|
||||
return body === this.expressions && this.any(function(k, val) {
|
||||
|
|
|
@ -185,12 +185,6 @@ exports.Expressions = class Expressions extends BaseNode
|
|||
@expressions[idx] = last.makeReturn()
|
||||
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.
|
||||
compile: (o) ->
|
||||
o or= {}
|
||||
|
@ -764,7 +758,10 @@ exports.AssignNode = class AssignNode extends BaseNode
|
|||
@variable instanceof ValueNode
|
||||
|
||||
makeReturn: ->
|
||||
if @isStatement()
|
||||
return new Expressions [this, new ReturnNode(@variable)]
|
||||
else
|
||||
super()
|
||||
|
||||
isStatement: ->
|
||||
@isValue() and (@variable.isArray() or @variable.isObject())
|
||||
|
@ -866,7 +863,7 @@ exports.CodeNode = class CodeNode extends BaseNode
|
|||
top = del o, 'top'
|
||||
o.scope = sharedScope or new Scope(o.scope, @body, this)
|
||||
o.top = true
|
||||
o.indent = @idt(if @bound then 2 else 1)
|
||||
o.indent = @idt(1)
|
||||
del o, 'noWrap'
|
||||
del o, 'globals'
|
||||
i = 0
|
||||
|
@ -886,13 +883,11 @@ exports.CodeNode = class CodeNode extends BaseNode
|
|||
i += 1
|
||||
params = (param.compile(o) for param in params)
|
||||
@body.makeReturn()
|
||||
@body.rewriteThis() if @bound
|
||||
(o.scope.parameter(param)) for param in params
|
||||
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 = "($func)" if top and not @bound
|
||||
return func unless @bound
|
||||
"(function(_this) {\n${@idt(1)}return $func\n$@tab})(this)"
|
||||
func = "function(${ params.join(', ') }) {$code${ code and @tab }}"
|
||||
return "${utility('bind')}($func, this)" if @bound
|
||||
if top then "($func)" else func
|
||||
|
||||
topSensitive: ->
|
||||
true
|
||||
|
@ -927,14 +922,17 @@ exports.SplatNode = class SplatNode extends BaseNode
|
|||
compileParam: (o) ->
|
||||
name = @name.compile(o)
|
||||
o.scope.find name
|
||||
end = ''
|
||||
if @trailings.length
|
||||
len = o.scope.freeVariable()
|
||||
o.scope.assign len, "arguments.length"
|
||||
variadic = o.scope.freeVariable()
|
||||
o.scope.assign variadic, "$len >= $@arglength"
|
||||
end = if @trailings.length then ", $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, $len - ${@trailings.length})"
|
||||
"$name = ${utility('slice')}.call(arguments, $@index$end)"
|
||||
|
||||
# A compiling a splat as a destructuring assignment means slicing arguments
|
||||
# from the right-hand-side's corresponding array.
|
||||
|
@ -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.
|
||||
hasProp: 'Object.prototype.hasOwnProperty'
|
||||
slice: 'Array.prototype.slice'
|
||||
|
|
|
@ -19,17 +19,27 @@ ok y.x() is 3
|
|||
|
||||
|
||||
obj = {
|
||||
name: "Fred"
|
||||
name: 'Fred'
|
||||
|
||||
bound: ->
|
||||
(=> ok(this.name is "Fred"))()
|
||||
(=> ok(this.name is 'Fred'))()
|
||||
|
||||
unbound: ->
|
||||
(-> ok(!this.name?))()
|
||||
|
||||
nested: ->
|
||||
(=>
|
||||
(=>
|
||||
(=>
|
||||
ok this.name is 'Fred'
|
||||
)()
|
||||
)()
|
||||
)()
|
||||
}
|
||||
|
||||
obj.unbound()
|
||||
obj.bound()
|
||||
obj.nested()
|
||||
|
||||
|
||||
# Python decorator style wrapper that memoizes any function
|
||||
|
|
Loading…
Add table
Reference in a new issue