From 113d7ce98f4fc9facc084a2a7e90e5ae82e621e5 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Tue, 19 Oct 2010 23:27:15 -0400 Subject: [PATCH] let's try to merge these indexOf patches. --- lib/helpers.js | 3 --- lib/lexer.js | 52 +++++++++++++++++++++------------------- lib/nodes.js | 27 ++++++++++++--------- lib/rewriter.js | 45 ++++++++++++++++++---------------- src/helpers.coffee | 4 ---- src/lexer.coffee | 42 ++++++++++++++++---------------- src/nodes.coffee | 13 +++++----- src/rewriter.coffee | 33 ++++++++++++------------- test/test_helpers.coffee | 8 +------ 9 files changed, 113 insertions(+), 114 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index fab996d3..2e6ac240 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -12,9 +12,6 @@ } return -1; })); - exports.include = function(list, value) { - return indexOf(list, value) >= 0; - }; exports.starts = function(string, literal, start) { return literal === string.substr(start, literal.length); }; diff --git a/lib/lexer.js b/lib/lexer.js index 56a4d111..3e2c9db3 100644 --- a/lib/lexer.js +++ b/lib/lexer.js @@ -1,7 +1,11 @@ (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; - _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() { Lexer = (function() { function Lexer() { @@ -32,7 +36,7 @@ return (new Rewriter).rewrite(this.tokens); }; 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))) { return false; } @@ -44,15 +48,15 @@ } forcedIdentifier = colon || this.tagAccessor(); 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(); - if (tag === 'WHEN' && include(LINE_BREAK, this.tag())) { + if (tag === 'WHEN' && (_ref2 = this.tag(), __indexOf.call(LINE_BREAK, _ref2) >= 0)) { tag = 'LEADING_WHEN'; } else if (tag === 'FOR') { this.seenFor = true; - } else if (include(UNARY, tag)) { + } else if (__indexOf.call(UNARY, tag) >= 0) { tag = 'UNARY'; - } else if (include(RELATION, tag)) { + } else if (__indexOf.call(RELATION, tag) >= 0) { if (tag !== 'INSTANCEOF' && this.seenFor) { this.seenFor = false; tag = 'FOR' + tag; @@ -65,12 +69,12 @@ } } } - if (include(JS_FORBIDDEN, id)) { + if (__indexOf.call(JS_FORBIDDEN, id) >= 0) { if (forcedIdentifier) { tag = 'IDENTIFIER'; id = new String(id); id.reserved = true; - } else if (include(RESERVED, id)) { + } else if (__indexOf.call(RESERVED, id) >= 0) { this.identifierError(id); } } @@ -80,9 +84,9 @@ } if (id === '!') { tag = 'UNARY'; - } else if (include(LOGIC, id)) { + } else if (__indexOf.call(LOGIC, id) >= 0) { tag = 'LOGIC'; - } else if (include(BOOL, tag)) { + } else if (__indexOf.call(BOOL, tag) >= 0) { id = tag.toLowerCase(); tag = 'BOOL'; } @@ -181,14 +185,14 @@ return true; }; Lexer.prototype.regexToken = function() { - var match, regex; + var _ref2, match, regex; if (this.chunk.charAt(0) !== '/') { return false; } if (match = HEREGEX.exec(this.chunk)) { return this.heregexToken(match); } - if (include(NOT_REGEX, this.tag())) { + if (_ref2 = this.tag(), __indexOf.call(NOT_REGEX, _ref2) >= 0) { return false; } if (!(match = REGEX.exec(this.chunk))) { @@ -322,7 +326,7 @@ return true; }; 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)) { value = match[0]; if (CODE.test(value)) { @@ -335,10 +339,10 @@ tag = value; prev = last(this.tokens); 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(); } - if (((_ref2 = prev[1]) === '||' || _ref2 === '&&')) { + if (((_ref3 = prev[1]) === '||' || _ref3 === '&&')) { prev[0] = 'COMPOUND_ASSIGN'; prev[1] += '='; return true; @@ -346,27 +350,27 @@ } if (';' === value) { tag = 'TERMINATOR'; - } else if (include(LOGIC, value)) { + } else if (__indexOf.call(LOGIC, value) >= 0) { tag = 'LOGIC'; - } else if (include(MATH, value)) { + } else if (__indexOf.call(MATH, value) >= 0) { tag = 'MATH'; - } else if (include(COMPARE, value)) { + } else if (__indexOf.call(COMPARE, value) >= 0) { tag = 'COMPARE'; - } else if (include(COMPOUND_ASSIGN, value)) { + } else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) { tag = 'COMPOUND_ASSIGN'; - } else if (include(UNARY, value)) { + } else if (__indexOf.call(UNARY, value) >= 0) { tag = 'UNARY'; - } else if (include(SHIFT, value)) { + } else if (__indexOf.call(SHIFT, value) >= 0) { tag = 'SHIFT'; } else if (value === '?' && ((prev != null) ? prev.spaced : undefined)) { tag = 'LOGIC'; } else if (prev && !prev.spaced) { - if (value === '(' && include(CALLABLE, prev[0])) { + if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) { if (prev[0] === '?') { prev[0] = 'FUNC_EXIST'; } tag = 'CALL_START'; - } else if (value === '[' && include(INDEXABLE, prev[0])) { + } else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) { tag = 'INDEX_START'; switch (prev[0]) { case '?': diff --git a/lib/nodes.js b/lib/nodes.js index 2fb2d273..ccc07558 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -1,14 +1,17 @@ (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) { function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; if (typeof parent.extended === "function") parent.extended(child); 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; - _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() { return true; }; @@ -983,7 +986,7 @@ Assign.prototype.children = ['variable', 'value']; Assign.prototype.topSensitive = YES; 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 (this.variable.isArray() || this.variable.isObject()) { return this.compilePatternMatch(o); @@ -995,7 +998,7 @@ delete o.top; return ifn.compile(o); } - if (include(this.CONDITIONAL, this.context)) { + if (_ref2 = this.context, __indexOf.call(this.CONDITIONAL, _ref2) >= 0) { return this.compileConditional(o); } } @@ -1391,7 +1394,8 @@ return this.operator !== '!' || this.first.isComplex(); }; 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() { var _ref2; @@ -1404,12 +1408,12 @@ return Op.__super__.toString.call(this, idt, this.constructor.name + ' ' + this.operator); }; Op.prototype.compileNode = function(o) { - var ifn; + var _ref2, ifn; if (this.isChainable() && this.first.unwrap().isChainable()) { return this.compileChain(o); } 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 this.compileUnary(o); @@ -1439,8 +1443,8 @@ return new Existence(fst).compile(o) + (" ? " + ref + " : " + (this.second.compile(o))); }; Op.prototype.compileUnary = function(o) { - var parts, space; - space = include(this.PREFIX_OPERATORS, this.operator) ? ' ' : ''; + var _ref2, parts, space; + space = (_ref2 = this.operator, __indexOf.call(this.PREFIX_OPERATORS, _ref2) >= 0) ? ' ' : ''; parts = [this.operator, space, this.first.compile(o)]; return (this.flip ? parts.reverse() : parts).join(''); }; @@ -1480,14 +1484,15 @@ return "(" + (tests.join(' || ')) + ")"; }; In.prototype.compileLoopTest = function(o) { - var _ref2, obj1, obj2, prefix; + var _ref2, code, obj1, obj2, prefix; _ref2 = this.object.compileReference(merge(o, { top: true }), { precompile: true }), obj1 = _ref2[0], obj2 = _ref2[1]; 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; })(); diff --git a/lib/rewriter.js b/lib/rewriter.js index f67b8d3d..9458ced8 100644 --- a/lib/rewriter.js +++ b/lib/rewriter.js @@ -1,6 +1,9 @@ (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; - include = require('./helpers').include; + 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; + 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() { function Rewriter() { return this; @@ -32,7 +35,7 @@ return true; }; exports.Rewriter.prototype.detectEnd = function(i, condition, action) { - var levels, token, tokens; + var _ref, _ref2, levels, token, tokens; tokens = this.tokens; levels = 0; while (token = tokens[i]) { @@ -42,9 +45,9 @@ if (!token || levels < 0) { 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; - } else if (include(EXPRESSION_END, token[0])) { + } else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) { levels -= 1; } i += 1; @@ -94,7 +97,8 @@ }; exports.Rewriter.prototype.removeMidExpressionNewlines = function() { 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; } tokens.splice(i, 1); @@ -149,12 +153,12 @@ return this.tokens.splice(i, 0, ['}', '}', token[2]]); }; return this.scanTokens(function(token, i, tokens) { - var idx, tag, tok; - if (include(EXPRESSION_START, tag = token[0])) { + var _ref, idx, tag, tok; + if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) { stack.push(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag); return 1; } - if (include(EXPRESSION_END, tag)) { + if (__indexOf.call(EXPRESSION_END, tag) >= 0) { stack.pop(); return 1; } @@ -182,27 +186,27 @@ return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]); }; return this.scanTokens(function(token, i, tokens) { - var callObject, next, prev, seenSingle, tag; + var _ref, _ref2, callObject, next, prev, seenSingle, tag; tag = token[0]; if (tag === 'CLASS') { classLine = true; } prev = 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; - if (include(LINEBREAKS, tag)) { + if (__indexOf.call(LINEBREAKS, tag) >= 0) { classLine = false; } if (prev && !prev.spaced && tag === '?') { 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; } tokens.splice(i, 0, ['CALL_START', '(', token[2]]); this.detectEnd(i + (callObject ? 2 : 1), function(token, i) { - var post; + var _ref3, post; if (!seenSingle && token.fromThen) { return true; } @@ -213,7 +217,7 @@ if (tag === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT') { 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); if (prev[0] === '?') { prev[0] = 'FUNC_EXIST'; @@ -233,7 +237,7 @@ tokens.splice.apply(tokens, [i + 2, 0].concat(this.indentation(token))); 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; _ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1]; if (starter === 'THEN') { @@ -242,7 +246,8 @@ indent.generated = (outdent.generated = true); tokens.splice(i + 1, 0, indent); 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) { return this.tokens.splice(this.tag(i - 1) === ',' ? i - 1 : i, 0, outdent); @@ -320,12 +325,12 @@ (debt[key] = 0); } return this.scanTokens(function(token, i, tokens) { - var inv, match, mtag, oppos, tag, val; - if (include(EXPRESSION_START, tag = token[0])) { + var _ref, inv, match, mtag, oppos, tag, val; + if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) { stack.push(token); return 1; } - if (!include(EXPRESSION_END, tag)) { + if (!(__indexOf.call(EXPRESSION_END, tag) >= 0)) { return 1; } if (debt[(inv = INVERSES[tag])] > 0) { diff --git a/src/helpers.coffee b/src/helpers.coffee index 4d201deb..d62a2292 100644 --- a/src/helpers.coffee +++ b/src/helpers.coffee @@ -14,10 +14,6 @@ indexOf = exports.indexOf = Array.indexOf or return index -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. exports.starts = (string, literal, start) -> literal is string.substr start, literal.length diff --git a/src/lexer.coffee b/src/lexer.coffee index 0362eeb1..f29addf3 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -10,7 +10,7 @@ {Rewriter} = require './rewriter' # Import the helpers we need. -{include, count, starts, compact, last} = require './helpers' +{count, starts, compact, last} = require './helpers' # The Lexer Class # --------------- @@ -80,16 +80,16 @@ exports.Lexer = class Lexer return true forcedIdentifier = colon or @tagAccessor() tag = 'IDENTIFIER' - if include(JS_KEYWORDS, id) or - not forcedIdentifier and include(COFFEE_KEYWORDS, id) + if id in JS_KEYWORDS or + not forcedIdentifier and id in COFFEE_KEYWORDS tag = id.toUpperCase() - if tag is 'WHEN' and include LINE_BREAK, @tag() + if tag is 'WHEN' and @tag() in LINE_BREAK tag = 'LEADING_WHEN' else if tag is 'FOR' @seenFor = yes - else if include UNARY, tag + else if tag in UNARY tag = 'UNARY' - else if include RELATION, tag + else if tag in RELATION if tag isnt 'INSTANCEOF' and @seenFor @seenFor = no tag = 'FOR' + tag @@ -98,20 +98,20 @@ exports.Lexer = class Lexer if @value() is '!' @tokens.pop() id = '!' + id - if include JS_FORBIDDEN, id + if id in JS_FORBIDDEN if forcedIdentifier tag = 'IDENTIFIER' id = new String id id.reserved = yes - else if include RESERVED, id + else if id in RESERVED @identifierError id unless forcedIdentifier tag = id = COFFEE_ALIASES[id] if COFFEE_ALIASES.hasOwnProperty id if id is '!' tag = 'UNARY' - else if include LOGIC, id + else if id in LOGIC tag = 'LOGIC' - else if include BOOL, tag + else if tag in BOOL id = tag.toLowerCase() tag = 'BOOL' @token tag, id @@ -187,7 +187,7 @@ exports.Lexer = class Lexer regexToken: -> return false if @chunk.charAt(0) isnt '/' 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 [regex] = match @token 'REGEX', if regex is '//' then '/(?:)/' else regex @@ -313,24 +313,24 @@ exports.Lexer = class Lexer tag = value prev = last @tokens 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 ['||', '&&'] prev[0] = 'COMPOUND_ASSIGN' prev[1] += '=' return true - if ';' is value then tag = 'TERMINATOR' - else if include LOGIC , value then tag = 'LOGIC' - else if include MATH , value then tag = 'MATH' - else if include COMPARE , value then tag = 'COMPARE' - else if include COMPOUND_ASSIGN, value then tag = 'COMPOUND_ASSIGN' - else if include UNARY , value then tag = 'UNARY' - else if include SHIFT , value then tag = 'SHIFT' + if ';' is value then tag = 'TERMINATOR' + else if value in LOGIC then tag = 'LOGIC' + else if value in MATH then tag = 'MATH' + else if value in COMPARE then tag = 'COMPARE' + else if value in COMPOUND_ASSIGN then tag = 'COMPOUND_ASSIGN' + else if value in UNARY then tag = 'UNARY' + else if value in SHIFT then tag = 'SHIFT' else if value is '?' and prev?.spaced then tag = 'LOGIC' 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 '?' tag = 'CALL_START' - else if value is '[' and include INDEXABLE, prev[0] + else if value is '[' and prev[0] in INDEXABLE tag = 'INDEX_START' switch prev[0] when '?' then prev[0] = 'INDEX_SOAK' diff --git a/src/nodes.coffee b/src/nodes.coffee index 0730717c..b3a2a890 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -6,7 +6,7 @@ {Scope} = require './scope' # 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. YES = -> yes @@ -857,7 +857,7 @@ exports.Assign = class Assign extends Base if ifn = If.unfoldSoak o, this, 'variable' delete o.top return ifn.compile o - return @compileConditional o if include @CONDITIONAL, @context + return @compileConditional o if @context in @CONDITIONAL top = del o, 'top' stmt = del o, 'asStatement' name = @variable.compile o @@ -1192,7 +1192,7 @@ exports.Op = class Op extends Base isComplex: -> @operator isnt '!' or @first.isComplex() isChainable: -> - include(@CHAINABLE, @operator) + @operator in @CHAINABLE invert: -> if @operator in ['===', '!=='] @@ -1209,7 +1209,7 @@ exports.Op = class Op extends Base compileNode: (o) -> return @compileChain o if @isChainable() and @first.unwrap().isChainable() 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 @compileExistence o if @operator is '?' @first.tags.front = @tags.front @@ -1237,7 +1237,7 @@ exports.Op = class Op extends Base # Compile a unary **Op**. compileUnary: (o) -> - space = if include @PREFIX_OPERATORS, @operator then ' ' else '' + space = if @operator in @PREFIX_OPERATORS then ' ' else '' parts = [@operator, space, @first.compile(o)] (if @flip then parts.reverse() else parts).join '' @@ -1264,7 +1264,8 @@ exports.In = class In extends Base compileLoopTest: (o) -> [obj1, obj2] = @object.compileReference merge(o, top: yes), precompile: yes 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 diff --git a/src/rewriter.coffee b/src/rewriter.coffee index 0e19a1d2..96fcda38 100644 --- a/src/rewriter.coffee +++ b/src/rewriter.coffee @@ -5,9 +5,6 @@ # shorthand into the unambiguous long form, add implicit indentation and # 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 # its internal array of tokens. class exports.Rewriter @@ -51,9 +48,9 @@ class exports.Rewriter 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 - 1 if not token or levels < 0 - if include EXPRESSION_START, token[0] + if token[0] in EXPRESSION_START levels += 1 - else if include EXPRESSION_END, token[0] + else if token[0] in EXPRESSION_END levels -= 1 i += 1 i - 1 @@ -93,7 +90,7 @@ class exports.Rewriter # this, remove their trailing newlines. removeMidExpressionNewlines: -> @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 0 @@ -131,10 +128,10 @@ class exports.Rewriter tag is ',' and one?[0] not in ['IDENTIFIER', 'NUMBER', 'STRING', '@', 'TERMINATOR', 'OUTDENT'] action = (token, i) -> @tokens.splice i, 0, ['}', '}', token[2]] @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 return 1 - if include EXPRESSION_END, tag + if tag in EXPRESSION_END stack.pop() return 1 return 1 unless tag is ':' and stack[stack.length - 1] isnt '{' @@ -162,22 +159,22 @@ class exports.Rewriter next = tokens[i + 1] callObject = not classLine and tag is 'INDENT' 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 - classLine = no if include LINEBREAKS, tag + classLine = no if tag in LINEBREAKS token.call = yes if prev and not prev.spaced and tag is '?' return 1 unless callObject or - prev?.spaced and (prev.call or include(IMPLICIT_FUNC, prev[0])) and - (include(IMPLICIT_CALL, tag) or include(IMPLICIT_UNSPACED_CALL, tag) and not token.spaced) + prev?.spaced and (prev.call or prev[0] in IMPLICIT_FUNC) and + (tag in IMPLICIT_CALL or tag in IMPLICIT_UNSPACED_CALL and not token.spaced) tokens.splice i, 0, ['CALL_START', '(', token[2]] @detectEnd i + (if callObject then 2 else 1), (token, i) -> return yes if not seenSingle and token.fromThen [tag] = token seenSingle = yes if tag in ['IF', 'ELSE', 'UNLESS', '->', '=>'] 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(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 '{'))) , action 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'] tokens.splice i + 2, 0, @indentation(token)... 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') starter = tag [indent, outdent] = @indentation token @@ -204,7 +201,7 @@ class exports.Rewriter indent.generated = outdent.generated = true tokens.splice i + 1, 0, indent 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']) action = (token, i) -> @tokens.splice (if @tag(i - 1) is ',' then i - 1 else i), 0, outdent @@ -265,10 +262,10 @@ class exports.Rewriter debt = {} (debt[key] = 0) for all key of INVERSES @scanTokens (token, i, tokens) -> - if include EXPRESSION_START, tag = token[0] + if (tag = token[0]) in EXPRESSION_START stack.push token return 1 - return 1 unless include EXPRESSION_END, tag + return 1 unless tag in EXPRESSION_END if debt[inv = INVERSES[tag]] > 0 debt[inv] -= 1 tokens.splice i, 1 diff --git a/test/test_helpers.coffee b/test/test_helpers.coffee index 56a80173..d9f14fdb 100644 --- a/test/test_helpers.coffee +++ b/test/test_helpers.coffee @@ -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] string = array.join '' @@ -10,12 +10,6 @@ eq 2, indexOf array, 2 eq 4, indexOf array, 4 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` ok starts string, '012' ok starts string, '34', 3