1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

let's try to merge these indexOf patches.

This commit is contained in:
Jeremy Ashkenas 2010-10-19 23:27:15 -04:00
parent c1d24944dc
commit 113d7ce98f
9 changed files with 113 additions and 114 deletions

View file

@ -12,9 +12,6 @@
} }
return -1; return -1;
})); }));
exports.include = function(list, value) {
return indexOf(list, value) >= 0;
};
exports.starts = function(string, literal, start) { exports.starts = function(string, literal, start) {
return literal === string.substr(start, literal.length); return literal === string.substr(start, literal.length);
}; };

View file

@ -1,7 +1,11 @@
(function() { (function() {
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_SPACES, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NEXT_ELLIPSIS, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, _ref, compact, count, include, last, op, starts; var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LEADING_SPACES, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NEXT_ELLIPSIS, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, _ref, compact, count, last, op, starts;
var __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) if (this[i] === item) return i;
return -1;
};
Rewriter = require('./rewriter').Rewriter; Rewriter = require('./rewriter').Rewriter;
_ref = require('./helpers'), include = _ref.include, count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last; _ref = require('./helpers'), count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
exports.Lexer = (function() { exports.Lexer = (function() {
Lexer = (function() { Lexer = (function() {
function Lexer() { function Lexer() {
@ -32,7 +36,7 @@
return (new Rewriter).rewrite(this.tokens); return (new Rewriter).rewrite(this.tokens);
}; };
Lexer.prototype.identifierToken = function() { Lexer.prototype.identifierToken = function() {
var colon, forcedIdentifier, id, input, match, tag; var _ref2, colon, forcedIdentifier, id, input, match, tag;
if (!(match = IDENTIFIER.exec(this.chunk))) { if (!(match = IDENTIFIER.exec(this.chunk))) {
return false; return false;
} }
@ -44,15 +48,15 @@
} }
forcedIdentifier = colon || this.tagAccessor(); forcedIdentifier = colon || this.tagAccessor();
tag = 'IDENTIFIER'; tag = 'IDENTIFIER';
if (include(JS_KEYWORDS, id) || !forcedIdentifier && include(COFFEE_KEYWORDS, id)) { if ((__indexOf.call(JS_KEYWORDS, id) >= 0) || !forcedIdentifier && (__indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
tag = id.toUpperCase(); tag = id.toUpperCase();
if (tag === 'WHEN' && include(LINE_BREAK, this.tag())) { if (tag === 'WHEN' && (_ref2 = this.tag(), __indexOf.call(LINE_BREAK, _ref2) >= 0)) {
tag = 'LEADING_WHEN'; tag = 'LEADING_WHEN';
} else if (tag === 'FOR') { } else if (tag === 'FOR') {
this.seenFor = true; this.seenFor = true;
} else if (include(UNARY, tag)) { } else if (__indexOf.call(UNARY, tag) >= 0) {
tag = 'UNARY'; tag = 'UNARY';
} else if (include(RELATION, tag)) { } else if (__indexOf.call(RELATION, tag) >= 0) {
if (tag !== 'INSTANCEOF' && this.seenFor) { if (tag !== 'INSTANCEOF' && this.seenFor) {
this.seenFor = false; this.seenFor = false;
tag = 'FOR' + tag; tag = 'FOR' + tag;
@ -65,12 +69,12 @@
} }
} }
} }
if (include(JS_FORBIDDEN, id)) { if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {
if (forcedIdentifier) { if (forcedIdentifier) {
tag = 'IDENTIFIER'; tag = 'IDENTIFIER';
id = new String(id); id = new String(id);
id.reserved = true; id.reserved = true;
} else if (include(RESERVED, id)) { } else if (__indexOf.call(RESERVED, id) >= 0) {
this.identifierError(id); this.identifierError(id);
} }
} }
@ -80,9 +84,9 @@
} }
if (id === '!') { if (id === '!') {
tag = 'UNARY'; tag = 'UNARY';
} else if (include(LOGIC, id)) { } else if (__indexOf.call(LOGIC, id) >= 0) {
tag = 'LOGIC'; tag = 'LOGIC';
} else if (include(BOOL, tag)) { } else if (__indexOf.call(BOOL, tag) >= 0) {
id = tag.toLowerCase(); id = tag.toLowerCase();
tag = 'BOOL'; tag = 'BOOL';
} }
@ -181,14 +185,14 @@
return true; return true;
}; };
Lexer.prototype.regexToken = function() { Lexer.prototype.regexToken = function() {
var match, regex; var _ref2, match, regex;
if (this.chunk.charAt(0) !== '/') { if (this.chunk.charAt(0) !== '/') {
return false; return false;
} }
if (match = HEREGEX.exec(this.chunk)) { if (match = HEREGEX.exec(this.chunk)) {
return this.heregexToken(match); return this.heregexToken(match);
} }
if (include(NOT_REGEX, this.tag())) { if (_ref2 = this.tag(), __indexOf.call(NOT_REGEX, _ref2) >= 0) {
return false; return false;
} }
if (!(match = REGEX.exec(this.chunk))) { if (!(match = REGEX.exec(this.chunk))) {
@ -322,7 +326,7 @@
return true; return true;
}; };
Lexer.prototype.literalToken = function() { Lexer.prototype.literalToken = function() {
var _ref2, match, prev, tag, value; var _ref2, _ref3, _ref4, _ref5, match, prev, tag, value;
if (match = OPERATOR.exec(this.chunk)) { if (match = OPERATOR.exec(this.chunk)) {
value = match[0]; value = match[0];
if (CODE.test(value)) { if (CODE.test(value)) {
@ -335,10 +339,10 @@
tag = value; tag = value;
prev = last(this.tokens); prev = last(this.tokens);
if (value === '=' && prev) { if (value === '=' && prev) {
if (!prev[1].reserved && include(JS_FORBIDDEN, prev[1])) { if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
this.assignmentError(); this.assignmentError();
} }
if (((_ref2 = prev[1]) === '||' || _ref2 === '&&')) { if (((_ref3 = prev[1]) === '||' || _ref3 === '&&')) {
prev[0] = 'COMPOUND_ASSIGN'; prev[0] = 'COMPOUND_ASSIGN';
prev[1] += '='; prev[1] += '=';
return true; return true;
@ -346,27 +350,27 @@
} }
if (';' === value) { if (';' === value) {
tag = 'TERMINATOR'; tag = 'TERMINATOR';
} else if (include(LOGIC, value)) { } else if (__indexOf.call(LOGIC, value) >= 0) {
tag = 'LOGIC'; tag = 'LOGIC';
} else if (include(MATH, value)) { } else if (__indexOf.call(MATH, value) >= 0) {
tag = 'MATH'; tag = 'MATH';
} else if (include(COMPARE, value)) { } else if (__indexOf.call(COMPARE, value) >= 0) {
tag = 'COMPARE'; tag = 'COMPARE';
} else if (include(COMPOUND_ASSIGN, value)) { } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) {
tag = 'COMPOUND_ASSIGN'; tag = 'COMPOUND_ASSIGN';
} else if (include(UNARY, value)) { } else if (__indexOf.call(UNARY, value) >= 0) {
tag = 'UNARY'; tag = 'UNARY';
} else if (include(SHIFT, value)) { } else if (__indexOf.call(SHIFT, value) >= 0) {
tag = 'SHIFT'; tag = 'SHIFT';
} else if (value === '?' && ((prev != null) ? prev.spaced : undefined)) { } else if (value === '?' && ((prev != null) ? prev.spaced : undefined)) {
tag = 'LOGIC'; tag = 'LOGIC';
} else if (prev && !prev.spaced) { } else if (prev && !prev.spaced) {
if (value === '(' && include(CALLABLE, prev[0])) { if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
if (prev[0] === '?') { if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST'; prev[0] = 'FUNC_EXIST';
} }
tag = 'CALL_START'; tag = 'CALL_START';
} else if (value === '[' && include(INDEXABLE, prev[0])) { } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
tag = 'INDEX_START'; tag = 'INDEX_START';
switch (prev[0]) { switch (prev[0]) {
case '?': case '?':

View file

@ -1,14 +1,17 @@
(function() { (function() {
var Accessor, ArrayLiteral, Assign, Base, Call, Class, Closure, Code, Comment, Existence, Expressions, Extends, For, IDENTIFIER, IS_STRING, If, In, Index, Literal, NO, NUMBER, ObjectLiteral, Op, Param, Parens, Push, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, TRAILING_WHITESPACE, Throw, Try, UTILITIES, Value, While, YES, _ref, compact, del, ends, flatten, include, last, merge, starts, utility; var Accessor, ArrayLiteral, Assign, Base, Call, Class, Closure, Code, Comment, Existence, Expressions, Extends, For, IDENTIFIER, IS_STRING, If, In, Index, Literal, NO, NUMBER, ObjectLiteral, Op, Param, Parens, Push, Range, Return, SIMPLENUM, Scope, Slice, Splat, Switch, TAB, THIS, TRAILING_WHITESPACE, Throw, Try, UTILITIES, Value, While, YES, _ref, compact, del, ends, flatten, last, merge, starts, utility;
var __extends = function(child, parent) { var __extends = function(child, parent) {
function ctor() { this.constructor = child; } function ctor() { this.constructor = child; }
ctor.prototype = parent.prototype; ctor.prototype = parent.prototype;
child.prototype = new ctor; child.prototype = new ctor;
if (typeof parent.extended === "function") parent.extended(child); if (typeof parent.extended === "function") parent.extended(child);
child.__super__ = parent.prototype; child.__super__ = parent.prototype;
}, __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) if (this[i] === item) return i;
return -1;
}; };
Scope = require('./scope').Scope; Scope = require('./scope').Scope;
_ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, merge = _ref.merge, del = _ref.del, include = _ref.include, starts = _ref.starts, ends = _ref.ends, last = _ref.last; _ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, merge = _ref.merge, del = _ref.del, starts = _ref.starts, ends = _ref.ends, last = _ref.last;
YES = function() { YES = function() {
return true; return true;
}; };
@ -983,7 +986,7 @@
Assign.prototype.children = ['variable', 'value']; Assign.prototype.children = ['variable', 'value'];
Assign.prototype.topSensitive = YES; Assign.prototype.topSensitive = YES;
Assign.prototype.compileNode = function(o) { Assign.prototype.compileNode = function(o) {
var ifn, isValue, match, name, stmt, top, val; var _ref2, ifn, isValue, match, name, stmt, top, val;
if (isValue = this.variable instanceof Value) { if (isValue = this.variable instanceof Value) {
if (this.variable.isArray() || this.variable.isObject()) { if (this.variable.isArray() || this.variable.isObject()) {
return this.compilePatternMatch(o); return this.compilePatternMatch(o);
@ -995,7 +998,7 @@
delete o.top; delete o.top;
return ifn.compile(o); return ifn.compile(o);
} }
if (include(this.CONDITIONAL, this.context)) { if (_ref2 = this.context, __indexOf.call(this.CONDITIONAL, _ref2) >= 0) {
return this.compileConditional(o); return this.compileConditional(o);
} }
} }
@ -1391,7 +1394,8 @@
return this.operator !== '!' || this.first.isComplex(); return this.operator !== '!' || this.first.isComplex();
}; };
Op.prototype.isChainable = function() { Op.prototype.isChainable = function() {
return include(this.CHAINABLE, this.operator); var _ref2;
return (_ref2 = this.operator, __indexOf.call(this.CHAINABLE, _ref2) >= 0);
}; };
Op.prototype.invert = function() { Op.prototype.invert = function() {
var _ref2; var _ref2;
@ -1404,12 +1408,12 @@
return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator); return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator);
}; };
Op.prototype.compileNode = function(o) { Op.prototype.compileNode = function(o) {
var ifn; var _ref2, ifn;
if (this.isChainable() && this.first.unwrap().isChainable()) { if (this.isChainable() && this.first.unwrap().isChainable()) {
return this.compileChain(o); return this.compileChain(o);
} }
if (this.isUnary()) { if (this.isUnary()) {
if (include(this.MUTATORS, this.operator) && (ifn = If.unfoldSoak(o, this, 'first'))) { if ((_ref2 = this.operator, __indexOf.call(this.MUTATORS, _ref2) >= 0) && (ifn = If.unfoldSoak(o, this, 'first'))) {
return ifn.compile(o); return ifn.compile(o);
} }
return this.compileUnary(o); return this.compileUnary(o);
@ -1439,8 +1443,8 @@
return new Existence(fst).compile(o) + (" ? " + ref + " : " + (this.second.compile(o))); return new Existence(fst).compile(o) + (" ? " + ref + " : " + (this.second.compile(o)));
}; };
Op.prototype.compileUnary = function(o) { Op.prototype.compileUnary = function(o) {
var parts, space; var _ref2, parts, space;
space = include(this.PREFIX_OPERATORS, this.operator) ? ' ' : ''; space = (_ref2 = this.operator, __indexOf.call(this.PREFIX_OPERATORS, _ref2) >= 0) ? ' ' : '';
parts = [this.operator, space, this.first.compile(o)]; parts = [this.operator, space, this.first.compile(o)];
return (this.flip ? parts.reverse() : parts).join(''); return (this.flip ? parts.reverse() : parts).join('');
}; };
@ -1480,14 +1484,15 @@
return "(" + (tests.join(' || ')) + ")"; return "(" + (tests.join(' || ')) + ")";
}; };
In.prototype.compileLoopTest = function(o) { In.prototype.compileLoopTest = function(o) {
var _ref2, obj1, obj2, prefix; var _ref2, code, obj1, obj2, prefix;
_ref2 = this.object.compileReference(merge(o, { _ref2 = this.object.compileReference(merge(o, {
top: true top: true
}), { }), {
precompile: true precompile: true
}), obj1 = _ref2[0], obj2 = _ref2[1]; }), obj1 = _ref2[0], obj2 = _ref2[1];
prefix = obj1 !== obj2 ? ("" + obj1 + ", ") : ''; prefix = obj1 !== obj2 ? ("" + obj1 + ", ") : '';
return "(" + prefix + (utility('indexOf')) + ".call(" + (this.array.compile(o)) + ", " + obj2 + ") >= 0)"; code = ("" + prefix + (utility('indexOf')) + ".call(" + (this.array.compile(o)) + ", " + obj2 + ") >= 0");
return this.parenthetical ? code : ("(" + code + ")");
}; };
return In; return In;
})(); })();

View file

@ -1,6 +1,9 @@
(function() { (function() {
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, _i, _len, _ref, include, left, rite; var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, _i, _len, _ref, left, rite;
include = require('./helpers').include; var __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) if (this[i] === item) return i;
return -1;
};
exports.Rewriter = (function() { exports.Rewriter = (function() {
function Rewriter() { function Rewriter() {
return this; return this;
@ -32,7 +35,7 @@
return true; return true;
}; };
exports.Rewriter.prototype.detectEnd = function(i, condition, action) { exports.Rewriter.prototype.detectEnd = function(i, condition, action) {
var levels, token, tokens; var _ref, _ref2, levels, token, tokens;
tokens = this.tokens; tokens = this.tokens;
levels = 0; levels = 0;
while (token = tokens[i]) { while (token = tokens[i]) {
@ -42,9 +45,9 @@
if (!token || levels < 0) { if (!token || levels < 0) {
return action.call(this, token, i - 1); return action.call(this, token, i - 1);
} }
if (include(EXPRESSION_START, token[0])) { if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
levels += 1; levels += 1;
} else if (include(EXPRESSION_END, token[0])) { } else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
levels -= 1; levels -= 1;
} }
i += 1; i += 1;
@ -94,7 +97,8 @@
}; };
exports.Rewriter.prototype.removeMidExpressionNewlines = function() { exports.Rewriter.prototype.removeMidExpressionNewlines = function() {
return this.scanTokens(function(token, i, tokens) { return this.scanTokens(function(token, i, tokens) {
if (!(token[0] === 'TERMINATOR' && include(EXPRESSION_CLOSE, this.tag(i + 1)))) { var _ref;
if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) {
return 1; return 1;
} }
tokens.splice(i, 1); tokens.splice(i, 1);
@ -149,12 +153,12 @@
return this.tokens.splice(i, 0, ['}', '}', token[2]]); return this.tokens.splice(i, 0, ['}', '}', token[2]]);
}; };
return this.scanTokens(function(token, i, tokens) { return this.scanTokens(function(token, i, tokens) {
var idx, tag, tok; var _ref, idx, tag, tok;
if (include(EXPRESSION_START, tag = token[0])) { if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
stack.push(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag); stack.push(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag);
return 1; return 1;
} }
if (include(EXPRESSION_END, tag)) { if (__indexOf.call(EXPRESSION_END, tag) >= 0) {
stack.pop(); stack.pop();
return 1; return 1;
} }
@ -182,27 +186,27 @@
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]); return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
}; };
return this.scanTokens(function(token, i, tokens) { return this.scanTokens(function(token, i, tokens) {
var callObject, next, prev, seenSingle, tag; var _ref, _ref2, callObject, next, prev, seenSingle, tag;
tag = token[0]; tag = token[0];
if (tag === 'CLASS') { if (tag === 'CLASS') {
classLine = true; classLine = true;
} }
prev = tokens[i - 1]; prev = tokens[i - 1];
next = tokens[i + 1]; next = tokens[i + 1];
callObject = !classLine && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && include(IMPLICIT_FUNC, prev[0]); callObject = !classLine && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref) >= 0);
seenSingle = false; seenSingle = false;
if (include(LINEBREAKS, tag)) { if (__indexOf.call(LINEBREAKS, tag) >= 0) {
classLine = false; classLine = false;
} }
if (prev && !prev.spaced && tag === '?') { if (prev && !prev.spaced && tag === '?') {
token.call = true; token.call = true;
} }
if (!(callObject || ((prev != null) ? prev.spaced : undefined) && (prev.call || include(IMPLICIT_FUNC, prev[0])) && (include(IMPLICIT_CALL, tag) || include(IMPLICIT_UNSPACED_CALL, tag) && !token.spaced))) { if (!(callObject || ((prev != null) ? prev.spaced : undefined) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && ((__indexOf.call(IMPLICIT_CALL, tag) >= 0) || (__indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0) && !token.spaced))) {
return 1; return 1;
} }
tokens.splice(i, 0, ['CALL_START', '(', token[2]]); tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
this.detectEnd(i + (callObject ? 2 : 1), function(token, i) { this.detectEnd(i + (callObject ? 2 : 1), function(token, i) {
var post; var _ref3, post;
if (!seenSingle && token.fromThen) { if (!seenSingle && token.fromThen) {
return true; return true;
} }
@ -213,7 +217,7 @@
if (tag === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT') { if (tag === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT') {
return true; return true;
} }
return !token.generated && this.tag(i - 1) !== ',' && include(IMPLICIT_END, tag) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && !include(IMPLICIT_BLOCK, this.tag(i - 1)) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{'))); return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && !(_ref3 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref3) >= 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
}, action); }, action);
if (prev[0] === '?') { if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST'; prev[0] = 'FUNC_EXIST';
@ -233,7 +237,7 @@
tokens.splice.apply(tokens, [i + 2, 0].concat(this.indentation(token))); tokens.splice.apply(tokens, [i + 2, 0].concat(this.indentation(token)));
return 4; return 4;
} }
if (include(SINGLE_LINERS, tag) && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) { if ((__indexOf.call(SINGLE_LINERS, tag) >= 0) && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
starter = tag; starter = tag;
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1]; _ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
if (starter === 'THEN') { if (starter === 'THEN') {
@ -242,7 +246,8 @@
indent.generated = (outdent.generated = true); indent.generated = (outdent.generated = true);
tokens.splice(i + 1, 0, indent); tokens.splice(i + 1, 0, indent);
condition = function(token, i) { condition = function(token, i) {
return token[1] !== ';' && include(SINGLE_CLOSERS, token[0]) && !(token[0] === 'ELSE' && !(starter === 'IF' || starter === 'THEN')); var _ref3;
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && !(starter === 'IF' || starter === 'THEN'));
}; };
action = function(token, i) { action = function(token, i) {
return this.tokens.splice(this.tag(i - 1) === ',' ? i - 1 : i, 0, outdent); return this.tokens.splice(this.tag(i - 1) === ',' ? i - 1 : i, 0, outdent);
@ -320,12 +325,12 @@
(debt[key] = 0); (debt[key] = 0);
} }
return this.scanTokens(function(token, i, tokens) { return this.scanTokens(function(token, i, tokens) {
var inv, match, mtag, oppos, tag, val; var _ref, inv, match, mtag, oppos, tag, val;
if (include(EXPRESSION_START, tag = token[0])) { if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
stack.push(token); stack.push(token);
return 1; return 1;
} }
if (!include(EXPRESSION_END, tag)) { if (!(__indexOf.call(EXPRESSION_END, tag) >= 0)) {
return 1; return 1;
} }
if (debt[(inv = INVERSES[tag])] > 0) { if (debt[(inv = INVERSES[tag])] > 0) {

View file

@ -14,10 +14,6 @@ indexOf = exports.indexOf = Array.indexOf or
return index return index
-1 -1
# Does a list include a value?
exports.include = (list, value) ->
indexOf(list, value) >= 0
# Peek at the beginning of a given string to see if it matches a sequence. # Peek at the beginning of a given string to see if it matches a sequence.
exports.starts = (string, literal, start) -> exports.starts = (string, literal, start) ->
literal is string.substr start, literal.length literal is string.substr start, literal.length

View file

@ -10,7 +10,7 @@
{Rewriter} = require './rewriter' {Rewriter} = require './rewriter'
# Import the helpers we need. # Import the helpers we need.
{include, count, starts, compact, last} = require './helpers' {count, starts, compact, last} = require './helpers'
# The Lexer Class # The Lexer Class
# --------------- # ---------------
@ -80,16 +80,16 @@ exports.Lexer = class Lexer
return true return true
forcedIdentifier = colon or @tagAccessor() forcedIdentifier = colon or @tagAccessor()
tag = 'IDENTIFIER' tag = 'IDENTIFIER'
if include(JS_KEYWORDS, id) or if id in JS_KEYWORDS or
not forcedIdentifier and include(COFFEE_KEYWORDS, id) not forcedIdentifier and id in COFFEE_KEYWORDS
tag = id.toUpperCase() tag = id.toUpperCase()
if tag is 'WHEN' and include LINE_BREAK, @tag() if tag is 'WHEN' and @tag() in LINE_BREAK
tag = 'LEADING_WHEN' tag = 'LEADING_WHEN'
else if tag is 'FOR' else if tag is 'FOR'
@seenFor = yes @seenFor = yes
else if include UNARY, tag else if tag in UNARY
tag = 'UNARY' tag = 'UNARY'
else if include RELATION, tag else if tag in RELATION
if tag isnt 'INSTANCEOF' and @seenFor if tag isnt 'INSTANCEOF' and @seenFor
@seenFor = no @seenFor = no
tag = 'FOR' + tag tag = 'FOR' + tag
@ -98,20 +98,20 @@ exports.Lexer = class Lexer
if @value() is '!' if @value() is '!'
@tokens.pop() @tokens.pop()
id = '!' + id id = '!' + id
if include JS_FORBIDDEN, id if id in JS_FORBIDDEN
if forcedIdentifier if forcedIdentifier
tag = 'IDENTIFIER' tag = 'IDENTIFIER'
id = new String id id = new String id
id.reserved = yes id.reserved = yes
else if include RESERVED, id else if id in RESERVED
@identifierError id @identifierError id
unless forcedIdentifier unless forcedIdentifier
tag = id = COFFEE_ALIASES[id] if COFFEE_ALIASES.hasOwnProperty id tag = id = COFFEE_ALIASES[id] if COFFEE_ALIASES.hasOwnProperty id
if id is '!' if id is '!'
tag = 'UNARY' tag = 'UNARY'
else if include LOGIC, id else if id in LOGIC
tag = 'LOGIC' tag = 'LOGIC'
else if include BOOL, tag else if tag in BOOL
id = tag.toLowerCase() id = tag.toLowerCase()
tag = 'BOOL' tag = 'BOOL'
@token tag, id @token tag, id
@ -187,7 +187,7 @@ exports.Lexer = class Lexer
regexToken: -> regexToken: ->
return false if @chunk.charAt(0) isnt '/' return false if @chunk.charAt(0) isnt '/'
return @heregexToken match if match = HEREGEX.exec @chunk return @heregexToken match if match = HEREGEX.exec @chunk
return false if include NOT_REGEX, @tag() return false if @tag() in NOT_REGEX
return false unless match = REGEX.exec @chunk return false unless match = REGEX.exec @chunk
[regex] = match [regex] = match
@token 'REGEX', if regex is '//' then '/(?:)/' else regex @token 'REGEX', if regex is '//' then '/(?:)/' else regex
@ -313,24 +313,24 @@ exports.Lexer = class Lexer
tag = value tag = value
prev = last @tokens prev = last @tokens
if value is '=' and prev if value is '=' and prev
@assignmentError() if not prev[1].reserved and include JS_FORBIDDEN, prev[1] @assignmentError() if not prev[1].reserved and prev[1] in JS_FORBIDDEN
if prev[1] in ['||', '&&'] if prev[1] in ['||', '&&']
prev[0] = 'COMPOUND_ASSIGN' prev[0] = 'COMPOUND_ASSIGN'
prev[1] += '=' prev[1] += '='
return true return true
if ';' is value then tag = 'TERMINATOR' if ';' is value then tag = 'TERMINATOR'
else if include LOGIC , value then tag = 'LOGIC' else if value in LOGIC then tag = 'LOGIC'
else if include MATH , value then tag = 'MATH' else if value in MATH then tag = 'MATH'
else if include COMPARE , value then tag = 'COMPARE' else if value in COMPARE then tag = 'COMPARE'
else if include COMPOUND_ASSIGN, value then tag = 'COMPOUND_ASSIGN' else if value in COMPOUND_ASSIGN then tag = 'COMPOUND_ASSIGN'
else if include UNARY , value then tag = 'UNARY' else if value in UNARY then tag = 'UNARY'
else if include SHIFT , value then tag = 'SHIFT' else if value in SHIFT then tag = 'SHIFT'
else if value is '?' and prev?.spaced then tag = 'LOGIC' else if value is '?' and prev?.spaced then tag = 'LOGIC'
else if prev and not prev.spaced else if prev and not prev.spaced
if value is '(' and include CALLABLE, prev[0] if value is '(' and prev[0] in CALLABLE
prev[0] = 'FUNC_EXIST' if prev[0] is '?' prev[0] = 'FUNC_EXIST' if prev[0] is '?'
tag = 'CALL_START' tag = 'CALL_START'
else if value is '[' and include INDEXABLE, prev[0] else if value is '[' and prev[0] in INDEXABLE
tag = 'INDEX_START' tag = 'INDEX_START'
switch prev[0] switch prev[0]
when '?' then prev[0] = 'INDEX_SOAK' when '?' then prev[0] = 'INDEX_SOAK'

View file

@ -6,7 +6,7 @@
{Scope} = require './scope' {Scope} = require './scope'
# Import the helpers we plan to use. # Import the helpers we plan to use.
{compact, flatten, merge, del, include, starts, ends, last} = require './helpers' {compact, flatten, merge, del, starts, ends, last} = require './helpers'
# Constant functions for nodes that don't need customization. # Constant functions for nodes that don't need customization.
YES = -> yes YES = -> yes
@ -857,7 +857,7 @@ exports.Assign = class Assign extends Base
if ifn = If.unfoldSoak o, this, 'variable' if ifn = If.unfoldSoak o, this, 'variable'
delete o.top delete o.top
return ifn.compile o return ifn.compile o
return @compileConditional o if include @CONDITIONAL, @context return @compileConditional o if @context in @CONDITIONAL
top = del o, 'top' top = del o, 'top'
stmt = del o, 'asStatement' stmt = del o, 'asStatement'
name = @variable.compile o name = @variable.compile o
@ -1192,7 +1192,7 @@ exports.Op = class Op extends Base
isComplex: -> @operator isnt '!' or @first.isComplex() isComplex: -> @operator isnt '!' or @first.isComplex()
isChainable: -> isChainable: ->
include(@CHAINABLE, @operator) @operator in @CHAINABLE
invert: -> invert: ->
if @operator in ['===', '!=='] if @operator in ['===', '!==']
@ -1209,7 +1209,7 @@ exports.Op = class Op extends Base
compileNode: (o) -> compileNode: (o) ->
return @compileChain o if @isChainable() and @first.unwrap().isChainable() return @compileChain o if @isChainable() and @first.unwrap().isChainable()
if @isUnary() if @isUnary()
return ifn.compile o if include(@MUTATORS, @operator) and ifn = If.unfoldSoak o, this, 'first' return ifn.compile o if @operator in @MUTATORS and ifn = If.unfoldSoak o, this, 'first'
return @compileUnary o return @compileUnary o
return @compileExistence o if @operator is '?' return @compileExistence o if @operator is '?'
@first.tags.front = @tags.front @first.tags.front = @tags.front
@ -1237,7 +1237,7 @@ exports.Op = class Op extends Base
# Compile a unary **Op**. # Compile a unary **Op**.
compileUnary: (o) -> compileUnary: (o) ->
space = if include @PREFIX_OPERATORS, @operator then ' ' else '' space = if @operator in @PREFIX_OPERATORS then ' ' else ''
parts = [@operator, space, @first.compile(o)] parts = [@operator, space, @first.compile(o)]
(if @flip then parts.reverse() else parts).join '' (if @flip then parts.reverse() else parts).join ''
@ -1264,7 +1264,8 @@ exports.In = class In extends Base
compileLoopTest: (o) -> compileLoopTest: (o) ->
[obj1, obj2] = @object.compileReference merge(o, top: yes), precompile: yes [obj1, obj2] = @object.compileReference merge(o, top: yes), precompile: yes
prefix = if obj1 isnt obj2 then "#{obj1}, " else '' prefix = if obj1 isnt obj2 then "#{obj1}, " else ''
"(#{prefix}#{utility 'indexOf'}.call(#{@array.compile o}, #{obj2}) >= 0)" code = "#{prefix}#{utility 'indexOf'}.call(#{@array.compile o}, #{obj2}) >= 0"
if @parenthetical then code else "(#{code})"
#### Try #### Try

View file

@ -5,9 +5,6 @@
# shorthand into the unambiguous long form, add implicit indentation and # shorthand into the unambiguous long form, add implicit indentation and
# parentheses, balance incorrect nestings, and generally clean things up. # parentheses, balance incorrect nestings, and generally clean things up.
# Import the helpers we need.
{include} = require './helpers'
# The **Rewriter** class is used by the [Lexer](lexer.html), directly against # The **Rewriter** class is used by the [Lexer](lexer.html), directly against
# its internal array of tokens. # its internal array of tokens.
class exports.Rewriter class exports.Rewriter
@ -51,9 +48,9 @@ class exports.Rewriter
while token = tokens[i] while token = tokens[i]
return action.call this, token, i if levels is 0 and condition.call this, token, i return action.call this, token, i if levels is 0 and condition.call this, token, i
return action.call this, token, i - 1 if not token or levels < 0 return action.call this, token, i - 1 if not token or levels < 0
if include EXPRESSION_START, token[0] if token[0] in EXPRESSION_START
levels += 1 levels += 1
else if include EXPRESSION_END, token[0] else if token[0] in EXPRESSION_END
levels -= 1 levels -= 1
i += 1 i += 1
i - 1 i - 1
@ -93,7 +90,7 @@ class exports.Rewriter
# this, remove their trailing newlines. # this, remove their trailing newlines.
removeMidExpressionNewlines: -> removeMidExpressionNewlines: ->
@scanTokens (token, i, tokens) -> @scanTokens (token, i, tokens) ->
return 1 unless token[0] is 'TERMINATOR' and include EXPRESSION_CLOSE, @tag(i + 1) return 1 unless token[0] is 'TERMINATOR' and @tag(i + 1) in EXPRESSION_CLOSE
tokens.splice i, 1 tokens.splice i, 1
0 0
@ -131,10 +128,10 @@ class exports.Rewriter
tag is ',' and one?[0] not in ['IDENTIFIER', 'NUMBER', 'STRING', '@', 'TERMINATOR', 'OUTDENT'] tag is ',' and one?[0] not in ['IDENTIFIER', 'NUMBER', 'STRING', '@', 'TERMINATOR', 'OUTDENT']
action = (token, i) -> @tokens.splice i, 0, ['}', '}', token[2]] action = (token, i) -> @tokens.splice i, 0, ['}', '}', token[2]]
@scanTokens (token, i, tokens) -> @scanTokens (token, i, tokens) ->
if include EXPRESSION_START, tag = token[0] if (tag = token[0]) in EXPRESSION_START
stack.push if tag is 'INDENT' and @tag(i - 1) is '{' then '{' else tag stack.push if tag is 'INDENT' and @tag(i - 1) is '{' then '{' else tag
return 1 return 1
if include EXPRESSION_END, tag if tag in EXPRESSION_END
stack.pop() stack.pop()
return 1 return 1
return 1 unless tag is ':' and stack[stack.length - 1] isnt '{' return 1 unless tag is ':' and stack[stack.length - 1] isnt '{'
@ -162,22 +159,22 @@ class exports.Rewriter
next = tokens[i + 1] next = tokens[i + 1]
callObject = not classLine and tag is 'INDENT' and callObject = not classLine and tag is 'INDENT' and
next and next.generated and next[0] is '{' and next and next.generated and next[0] is '{' and
prev and include(IMPLICIT_FUNC, prev[0]) prev and prev[0] in IMPLICIT_FUNC
seenSingle = no seenSingle = no
classLine = no if include LINEBREAKS, tag classLine = no if tag in LINEBREAKS
token.call = yes if prev and not prev.spaced and tag is '?' token.call = yes if prev and not prev.spaced and tag is '?'
return 1 unless callObject or return 1 unless callObject or
prev?.spaced and (prev.call or include(IMPLICIT_FUNC, prev[0])) and prev?.spaced and (prev.call or prev[0] in IMPLICIT_FUNC) and
(include(IMPLICIT_CALL, tag) or include(IMPLICIT_UNSPACED_CALL, tag) and not token.spaced) (tag in IMPLICIT_CALL or tag in IMPLICIT_UNSPACED_CALL and not token.spaced)
tokens.splice i, 0, ['CALL_START', '(', token[2]] tokens.splice i, 0, ['CALL_START', '(', token[2]]
@detectEnd i + (if callObject then 2 else 1), (token, i) -> @detectEnd i + (if callObject then 2 else 1), (token, i) ->
return yes if not seenSingle and token.fromThen return yes if not seenSingle and token.fromThen
[tag] = token [tag] = token
seenSingle = yes if tag in ['IF', 'ELSE', 'UNLESS', '->', '=>'] seenSingle = yes if tag in ['IF', 'ELSE', 'UNLESS', '->', '=>']
return yes if tag is 'PROPERTY_ACCESS' and @tag(i - 1) is 'OUTDENT' return yes if tag is 'PROPERTY_ACCESS' and @tag(i - 1) is 'OUTDENT'
not token.generated and @tag(i - 1) isnt ',' and include(IMPLICIT_END, tag) and not token.generated and @tag(i - 1) isnt ',' and tag in IMPLICIT_END and
(tag isnt 'INDENT' or (tag isnt 'INDENT' or
(@tag(i - 2) isnt 'CLASS' and not include(IMPLICIT_BLOCK, @tag(i - 1)) and (@tag(i - 2) isnt 'CLASS' and not (@tag(i - 1) in IMPLICIT_BLOCK) and
not ((post = @tokens[i + 1]) and post.generated and post[0] is '{'))) not ((post = @tokens[i + 1]) and post.generated and post[0] is '{')))
, action , action
prev[0] = 'FUNC_EXIST' if prev[0] is '?' prev[0] = 'FUNC_EXIST' if prev[0] is '?'
@ -196,7 +193,7 @@ class exports.Rewriter
if tag is 'CATCH' and @tag(i + 2) in ['TERMINATOR', 'FINALLY'] if tag is 'CATCH' and @tag(i + 2) in ['TERMINATOR', 'FINALLY']
tokens.splice i + 2, 0, @indentation(token)... tokens.splice i + 2, 0, @indentation(token)...
return 4 return 4
if include(SINGLE_LINERS, tag) and @tag(i + 1) isnt 'INDENT' and if tag in SINGLE_LINERS and @tag(i + 1) isnt 'INDENT' and
not (tag is 'ELSE' and @tag(i + 1) is 'IF') not (tag is 'ELSE' and @tag(i + 1) is 'IF')
starter = tag starter = tag
[indent, outdent] = @indentation token [indent, outdent] = @indentation token
@ -204,7 +201,7 @@ class exports.Rewriter
indent.generated = outdent.generated = true indent.generated = outdent.generated = true
tokens.splice i + 1, 0, indent tokens.splice i + 1, 0, indent
condition = (token, i) -> condition = (token, i) ->
token[1] isnt ';' and include(SINGLE_CLOSERS, token[0]) and token[1] isnt ';' and token[0] in SINGLE_CLOSERS and
not (token[0] is 'ELSE' and starter not in ['IF', 'THEN']) not (token[0] is 'ELSE' and starter not in ['IF', 'THEN'])
action = (token, i) -> action = (token, i) ->
@tokens.splice (if @tag(i - 1) is ',' then i - 1 else i), 0, outdent @tokens.splice (if @tag(i - 1) is ',' then i - 1 else i), 0, outdent
@ -265,10 +262,10 @@ class exports.Rewriter
debt = {} debt = {}
(debt[key] = 0) for all key of INVERSES (debt[key] = 0) for all key of INVERSES
@scanTokens (token, i, tokens) -> @scanTokens (token, i, tokens) ->
if include EXPRESSION_START, tag = token[0] if (tag = token[0]) in EXPRESSION_START
stack.push token stack.push token
return 1 return 1
return 1 unless include EXPRESSION_END, tag return 1 unless tag in EXPRESSION_END
if debt[inv = INVERSES[tag]] > 0 if debt[inv = INVERSES[tag]] > 0
debt[inv] -= 1 debt[inv] -= 1
tokens.splice i, 1 tokens.splice i, 1

View file

@ -1,4 +1,4 @@
{indexOf, include, starts, ends, compact, count, merge, extend, flatten, del, last} = CoffeeScript.helpers {indexOf, starts, ends, compact, count, merge, extend, flatten, del, last} = CoffeeScript.helpers
array = [0..4] array = [0..4]
string = array.join '' string = array.join ''
@ -10,12 +10,6 @@ eq 2, indexOf array, 2
eq 4, indexOf array, 4 eq 4, indexOf array, 4
eq(-1, indexOf array, 6) eq(-1, indexOf array, 6)
# Test `include`
ok include array, 0
ok include array, 2
ok include array, 4
ok not include array, 6
# Test `starts` # Test `starts`
ok starts string, '012' ok starts string, '012'
ok starts string, '34', 3 ok starts string, '34', 3