From 95bc4c5eeb7df69f79dc976635d197abce9ff02b Mon Sep 17 00:00:00 2001 From: satyr Date: Thu, 7 Oct 2010 12:24:32 +0900 Subject: [PATCH] reenabled stricter caching on `For` compilation as well as reduced a line from it --- lib/browser.js | 3 +- lib/cake.js | 10 ++-- lib/command.js | 9 ++-- lib/grammar.js | 3 +- lib/index.js | 3 +- lib/lexer.js | 5 +- lib/nodes.js | 116 +++++++++++++++++++++-------------------------- lib/optparse.js | 9 ++-- lib/rewriter.js | 13 +++--- lib/scope.js | 15 +++--- src/nodes.coffee | 33 ++++++++------ 11 files changed, 100 insertions(+), 119 deletions(-) diff --git a/lib/browser.js b/lib/browser.js index d8bc9ddb..e69199b5 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -24,8 +24,7 @@ }; processScripts = function() { var _i, _len, _ref; - _ref = document.getElementsByTagName('script'); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref = document.getElementsByTagName('script')).length; _i < _len; _i++) { (function() { var script = _ref[_i]; return script.type === 'text/coffeescript' ? (script.src ? CoffeeScript.load(script.src) : setTimeout(function() { diff --git a/lib/cake.js b/lib/cake.js index d5247fd8..c378d48a 100755 --- a/lib/cake.js +++ b/lib/cake.js @@ -46,8 +46,8 @@ return printTasks(); } options = oparse.parse(args); - _result = []; _ref = options.arguments; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { + _result = []; + for (_i = 0, _len = (_ref = options.arguments).length; _i < _len; _i++) { arg = _ref[_i]; _result.push(invoke(arg)); } @@ -55,10 +55,10 @@ }); }; printTasks = function() { - var desc, name, spaces, task; + var _ref, desc, name, spaces, task; puts(''); - for (name in tasks) { - task = tasks[name]; + for (name in _ref = tasks) { + task = _ref[name]; spaces = 20 - name.length; spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; desc = task.description ? ("# " + (task.description)) : ''; diff --git a/lib/command.js b/lib/command.js index e896391e..212d1a68 100644 --- a/lib/command.js +++ b/lib/command.js @@ -49,12 +49,12 @@ return compileScripts(); }; compileScripts = function() { - var _i, _len, _result; + var _i, _len, _ref2, _result; _result = []; - for (_i = 0, _len = sources.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref2 = sources).length; _i < _len; _i++) { (function() { var base, compile; - var source = sources[_i]; + var source = _ref2[_i]; return _result.push((function() { base = source; compile = function(source, topLevel) { @@ -93,8 +93,7 @@ o = opts; options = compileOptions(file); if (o.require) { - _ref2 = o.require; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref2 = o.require).length; _i < _len; _i++) { req = _ref2[_i]; require(helpers.starts(req, '.') ? fs.realpathSync(req) : req); } diff --git a/lib/grammar.js b/lib/grammar.js index 3433ec39..432e1e6f 100644 --- a/lib/grammar.js +++ b/lib/grammar.js @@ -612,8 +612,7 @@ for (_i = 0, _len = alternatives.length; _i < _len; _i++) { alt = alternatives[_i]; _result.push((function() { - _ref = alt[0].split(' '); - for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) { + for (_j = 0, _len2 = (_ref = alt[0].split(' ')).length; _j < _len2; _j++) { token = _ref[_j]; if (!(grammar[token])) { tokens.push(token); diff --git a/lib/index.js b/lib/index.js index 6b65054d..dc5ab13c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,8 +1,7 @@ (function() { var _ref, key, val; var __hasProp = Object.prototype.hasOwnProperty; - _ref = require('./coffee-script'); - for (key in _ref) { + for (key in _ref = require('./coffee-script')) { if (!__hasProp.call(_ref, key)) continue; val = _ref[key]; (exports[key] = val); diff --git a/lib/lexer.js b/lib/lexer.js index d171417a..cd0eec6b 100644 --- a/lib/lexer.js +++ b/lib/lexer.js @@ -201,10 +201,9 @@ this.token('IDENTIFIER', 'RegExp'); this.tokens.push(['CALL_START', '(']); tokens = []; - _ref3 = this.interpolateString(body, { + for (_i = 0, _len = (_ref3 = this.interpolateString(body, { regex: true - }); - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + })).length; _i < _len; _i++) { _ref4 = _ref3[_i], tag = _ref4[0], value = _ref4[1]; if (tag === 'TOKENS') { tokens.push.apply(tokens, value); diff --git a/lib/nodes.js b/lib/nodes.js index 92e03c07..29e4cf5e 100644 --- a/lib/nodes.js +++ b/lib/nodes.js @@ -99,8 +99,8 @@ var _i, _len, _ref2, _result, child, children, klass; idt || (idt = ''); children = (function() { - _result = []; _ref2 = this.collectChildren(); - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _result = []; + for (_i = 0, _len = (_ref2 = this.collectChildren()).length; _i < _len; _i++) { child = _ref2[_i]; _result.push(child.toString(idt + TAB)); } @@ -114,12 +114,11 @@ if (!(this.children)) { return; } - _result = []; _ref2 = this.children; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _result = []; + for (_i = 0, _len = (_ref2 = this.children).length; _i < _len; _i++) { attr = _ref2[_i]; if (this[attr]) { - _ref3 = flatten([this[attr]]); - for (_j = 0, _len2 = _ref3.length; _j < _len2; _j++) { + for (_j = 0, _len2 = (_ref3 = flatten([this[attr]])).length; _j < _len2; _j++) { child = _ref3[_j]; if (func(child) === false) { return; @@ -196,8 +195,8 @@ Expressions.prototype.compileNode = function(o) { var _i, _len, _ref2, _result, node; return (function() { - _result = []; _ref2 = this.expressions; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _result = []; + for (_i = 0, _len = (_ref2 = this.expressions).length; _i < _len; _i++) { node = _ref2[_i]; _result.push(this.compileExpression(node, merge(o))); } @@ -401,8 +400,7 @@ Array.prototype.push.apply(this.base.body.properties, this.properties); return this.base; } - _ref2 = this.properties; - for (i = 0, _len = _ref2.length; i < _len; i++) { + for (i = 0, _len = (_ref2 = this.properties).length; i < _len; i++) { prop = _ref2[i]; if (prop.soakNode) { prop.soakNode = false; @@ -510,8 +508,7 @@ break; } } - _ref2 = list.reverse(); - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref2 = list.reverse()).length; _i < _len; _i++) { call = _ref2[_i]; if (node) { if (call.variable instanceof Call) { @@ -545,16 +542,15 @@ rite = rite.compile(o); return ("(" + left + " ? undefined : " + rite + ")"); } - _ref3 = this.args; - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref3 = this.args).length; _i < _len; _i++) { arg = _ref3[_i]; if (arg instanceof Splat) { return this.compileSplat(o); } } args = (function() { - _result = []; _ref4 = this.args; - for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) { + _result = []; + for (_j = 0, _len2 = (_ref4 = this.args).length; _j < _len2; _j++) { arg = _ref4[_j]; _result.push((arg.parenthetical = true) && arg.compile(o)); } @@ -590,8 +586,7 @@ argvar = function(node) { return node instanceof Literal && node.value === 'arguments'; }; - _ref2 = this.args; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref2 = this.args).length; _i < _len; _i++) { arg = _ref2[_i]; if (arg.contains(argvar)) { call = 'apply(this, arguments)'; @@ -694,13 +689,11 @@ if (this.from !== this.fromVar) { parts.push(this.from); } - if (this.to !== this.toVar) { - parts.push(this.to); - } - return parts.length ? ("" + (parts.join('; ')) + "; ") : ''; + return this.to !== this.toVar ? parts.push(this.to) : undefined; }; Range.prototype.compileNode = function(o) { var compare, idx, incr, intro, step, stepPart, vars; + this.compileVariables(o); if (!(o.index)) { return this.compileArray(o); } @@ -709,7 +702,7 @@ } idx = del(o, 'index'); step = del(o, 'step'); - vars = ("" + idx + " = " + (this.fromVar)); + vars = ("" + idx + " = " + (this.from)) + (this.to !== this.toVar ? (", " + (this.to)) : ''); intro = ("(" + (this.fromVar) + " <= " + (this.toVar) + " ? " + idx); compare = ("" + intro + " <" + (this.equals) + " " + (this.toVar) + " : " + idx + " >" + (this.equals) + " " + (this.toVar) + ")"); stepPart = step ? step.compile(o) : '1'; @@ -726,14 +719,10 @@ }; Range.prototype.compileArray = function(o) { var _i, _ref2, _ref3, _result, body, clause, i, idt, post, pre, range, result, vars; - idt = this.idt(1); - vars = this.compileVariables(merge(o, { - indent: idt - })); if (this.fromNum && this.toNum && (Math.abs(this.fromNum - this.toNum) <= 20)) { range = (function() { - _result = []; _ref2 = +this.fromNum; _ref3 = +this.toNum; - for (var _i = _ref2; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i += 1 : _i -= 1){ _result.push(_i); } + _result = []; + for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i += 1 : _i -= 1){ _result.push(_i); } return _result; }).call(this); if (this.exclusive) { @@ -741,15 +730,17 @@ } return ("[" + (range.join(', ')) + "]"); } + idt = this.idt(1); i = o.scope.freeVariable('i'); result = o.scope.freeVariable('result'); - pre = ("\n" + idt + result + " = []; " + vars); + pre = ("\n" + idt + result + " = [];"); if (this.fromNum && this.toNum) { o.index = i; body = this.compileSimple(o); } else { + vars = ("" + i + " = " + (this.from)) + (this.to !== this.toVar ? (", " + (this.to)) : ''); clause = ("" + (this.fromVar) + " <= " + (this.toVar) + " ?"); - body = ("var " + i + " = " + (this.fromVar) + "; " + clause + " " + i + " <" + (this.equals) + " " + (this.toVar) + " : " + i + " >" + (this.equals) + " " + (this.toVar) + "; " + clause + " " + i + " += 1 : " + i + " -= 1"); + body = ("var " + vars + "; " + 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)); return "(function() {" + pre + "\n" + idt + "for (" + body + ")" + post + "}).call(this)"; @@ -794,8 +785,8 @@ top = del(o, 'top'); o.indent = this.idt(1); nonComments = (function() { - _result = []; _ref2 = this.properties; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _result = []; + for (_i = 0, _len = (_ref2 = this.properties).length; _i < _len; _i++) { prop = _ref2[_i]; if (!(prop instanceof Comment)) { _result.push(prop); @@ -805,8 +796,8 @@ }).call(this); lastNoncom = last(nonComments); props = (function() { - _result = []; _ref2 = this.properties; - for (i = 0, _len = _ref2.length; i < _len; i++) { + _result = []; + for (i = 0, _len = (_ref2 = this.properties).length; i < _len; i++) { prop = _ref2[i]; _result.push((function() { join = ",\n"; @@ -851,8 +842,7 @@ var _len, _ref2, code, i, obj, objects; o.indent = this.idt(1); objects = []; - _ref2 = this.objects; - for (i = 0, _len = _ref2.length; i < _len; i++) { + for (i = 0, _len = (_ref2 = this.objects).length; i < _len; i++) { obj = _ref2[i]; code = obj.compile(o); if (obj instanceof Splat) { @@ -907,8 +897,7 @@ } else { constructor = new Code; } - _ref2 = this.properties; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref2 = this.properties).length; _i < _len; _i++) { prop = _ref2[_i]; _ref3 = [prop.variable, prop.value], pvar = _ref3[0], func = _ref3[1]; if (pvar && pvar.base.value === 'constructor') { @@ -1118,8 +1107,7 @@ del(o, 'globals'); splat = undefined; params = []; - _ref2 = this.params; - for (i = 0, _len = _ref2.length; i < _len; i++) { + for (i = 0, _len = (_ref2 = this.params).length; i < _len; i++) { param = _ref2[i]; if (splat) { if (param.attach) { @@ -1235,8 +1223,7 @@ variadic = o.scope.freeVariable('result'); o.scope.assign(variadic, len + ' >= ' + this.arglength); end = this.trailings.length ? (", " + len + " - " + (this.trailings.length)) : undefined; - _ref2 = this.trailings; - for (idx = 0, _len = _ref2.length; idx < _len; idx++) { + for (idx = 0, _len = (_ref2 = this.trailings).length; idx < _len; idx++) { trailing = _ref2[idx]; if (trailing.attach) { assign = trailing.assign; @@ -1478,8 +1465,8 @@ In.prototype.compileOrTest = function(o) { var _len, _ref2, _result, i, item, tests; tests = (function() { - _result = []; _ref2 = this.array.base.objects; - for (i = 0, _len = _ref2.length; i < _len; i++) { + _result = []; + for (i = 0, _len = (_ref2 = this.array.base.objects).length; i < _len; i++) { item = _ref2[i]; _result.push("" + (item.compile(o)) + " === " + (i ? this.obj2 : this.obj1)); } @@ -1646,7 +1633,7 @@ return ''; }; For.prototype.compileNode = function(o) { - var _ref2, body, codeInBody, forPart, guardPart, idt1, index, ivar, lvar, name, namePart, range, returnResult, rvar, scope, source, sourcePart, stepPart, svar, topLevel, varPart, vars; + var body, codeInBody, forPart, guardPart, idt1, index, ivar, lvar, name, namePart, range, ref, resultPart, returnResult, rvar, scope, source, sourcePart, stepPart, svar, topLevel, varPart, vars; topLevel = del(o, 'top') && !this.returns; range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length; source = range ? this.source.base : this.source; @@ -1678,29 +1665,33 @@ body = Expressions.wrap([this.body]); idt1 = this.idt(1); if (range) { - sourcePart = source.compileVariables(o); forPart = source.compile(merge(o, { index: ivar, step: this.step })); } else { - _ref2 = this.source.compileReference(merge(o, { - top: true - }), { - precompile: true - }), sourcePart = _ref2[0], svar = _ref2[1]; - sourcePart = sourcePart === svar ? '' : ("" + sourcePart + ";"); + svar = this.source.compile(o); + if (IDENTIFIER.test(svar) && scope.check(svar, { + immediate: true + })) { + sourcePart = svar; + } else { + sourcePart = ("" + (ref = scope.freeVariable('ref')) + " = " + svar); + if (!(this.object)) { + sourcePart = ("(" + sourcePart + ")"); + } + svar = ref; + } namePart = this.pattern ? new Assign(this.name, literal("" + svar + "[" + ivar + "]")).compile(merge(o, { top: true })) : (name ? ("" + name + " = " + svar + "[" + ivar + "]") : undefined); if (!(this.object)) { lvar = scope.freeVariable('len'); stepPart = this.step ? ("" + ivar + " += " + (this.step.compile(o))) : ("" + ivar + "++"); - forPart = ("" + ivar + " = 0, " + lvar + " = " + svar + ".length; " + ivar + " < " + lvar + "; " + stepPart); + forPart = ("" + ivar + " = 0, " + lvar + " = " + sourcePart + ".length; " + ivar + " < " + lvar + "; " + stepPart); } } - sourcePart = (rvar ? ("" + rvar + " = []; ") : '') + sourcePart; - sourcePart = sourcePart ? ("" + (this.tab) + sourcePart + "\n" + (this.tab)) : this.tab; + resultPart = rvar ? ("" + (this.tab) + rvar + " = [];\n") : ''; returnResult = this.compileReturnValue(rvar, o); if (!(topLevel)) { body = Push.wrap(rvar, body); @@ -1725,7 +1716,7 @@ } } if (this.object) { - forPart = ("" + ivar + " in " + svar); + forPart = ("" + ivar + " in " + sourcePart); if (!(this.raw)) { guardPart = ("\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")) continue;"); } @@ -1735,7 +1726,7 @@ top: true })); vars = range ? name : ("" + name + ", " + ivar); - return "" + sourcePart + "for (" + forPart + ") {" + guardPart + "\n" + varPart + body + "\n" + (this.tab) + "}" + returnResult; + return "" + resultPart + (this.tab) + "for (" + forPart + ") {" + guardPart + "\n" + varPart + body + "\n" + (this.tab) + "}" + returnResult; }; return For; })(); @@ -1756,8 +1747,7 @@ Switch.prototype.isStatement = YES; Switch.prototype.makeReturn = function() { var _i, _len, _ref2, pair; - _ref2 = this.cases; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref2 = this.cases).length; _i < _len; _i++) { pair = _ref2[_i]; pair[1].makeReturn(); } @@ -1771,13 +1761,11 @@ idt = (o.indent = this.idt(2)); o.top = true; code = ("" + (this.tab) + "switch (" + (this.subject.compile(o)) + ") {"); - _ref2 = this.cases; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref2 = this.cases).length; _i < _len; _i++) { pair = _ref2[_i]; _ref3 = pair, conditions = _ref3[0], block = _ref3[1]; exprs = block.expressions; - _ref4 = flatten([conditions]); - for (_j = 0, _len2 = _ref4.length; _j < _len2; _j++) { + for (_j = 0, _len2 = (_ref4 = flatten([conditions])).length; _j < _len2; _j++) { condition = _ref4[_j]; if (this.tags.subjectless) { condition = new Op('!!', new Parenthetical(condition)); diff --git a/lib/optparse.js b/lib/optparse.js index a541aa13..80eda2eb 100755 --- a/lib/optparse.js +++ b/lib/optparse.js @@ -18,8 +18,7 @@ arg = args[i]; isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG)); matchedRule = false; - _ref = this.rules; - for (_i = 0, _len2 = _ref.length; _i < _len2; _i++) { + for (_i = 0, _len2 = (_ref = this.rules).length; _i < _len2; _i++) { rule = _ref[_i]; if (rule.shortFlag === arg || rule.longFlag === arg) { value = rule.hasArgument ? args[i += 1] : true; @@ -44,8 +43,7 @@ if (this.banner) { lines.unshift("" + (this.banner) + "\n"); } - _ref = this.rules; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { + for (_i = 0, _len = (_ref = this.rules).length; _i < _len; _i++) { rule = _ref[_i]; spaces = 15 - rule.longFlag.length; spaces = spaces > 0 ? Array(spaces + 1).join(' ') : ''; @@ -95,8 +93,7 @@ for (_i = 0, _len = args.length; _i < _len; _i++) { arg = args[_i]; if (match = arg.match(MULTI_FLAG)) { - _ref = match[1].split(''); - for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) { + for (_j = 0, _len2 = (_ref = match[1].split('')).length; _j < _len2; _j++) { l = _ref[_j]; result.push('-' + l); } diff --git a/lib/rewriter.js b/lib/rewriter.js index cfe9b318..db77bb82 100644 --- a/lib/rewriter.js +++ b/lib/rewriter.js @@ -81,8 +81,7 @@ }; exports.Rewriter.prototype.removeLeadingNewlines = function() { var _len, _ref, i, tag; - _ref = this.tokens; - for (i = 0, _len = _ref.length; i < _len; i++) { + for (i = 0, _len = (_ref = this.tokens).length; i < _len; i++) { tag = _ref[i][0]; if (tag !== 'TERMINATOR') { break; @@ -281,10 +280,10 @@ levels = {}; openLine = {}; this.scanTokens(function(token, i) { - var _i, _len, _ref, close, open, tag; + var _i, _len, _ref, _ref2, close, open, tag; tag = token[0]; - for (_i = 0, _len = pairs.length; _i < _len; _i++) { - _ref = pairs[_i], open = _ref[0], close = _ref[1]; + for (_i = 0, _len = (_ref = pairs).length; _i < _len; _i++) { + _ref2 = _ref[_i], open = _ref2[0], close = _ref2[1]; levels[open] |= 0; if (tag === open) { if (levels[open] === 0) { @@ -315,10 +314,10 @@ } }; exports.Rewriter.prototype.rewriteClosingParens = function() { - var debt, key, stack; + var _ref, debt, key, stack; stack = []; debt = {}; - for (key in INVERSES) { + for (key in _ref = INVERSES) { (debt[key] = 0); } return this.scanTokens(function(token, i, tokens) { diff --git a/lib/scope.js b/lib/scope.js index 75a2d1a0..5e73eec6 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -27,8 +27,8 @@ Scope.prototype.endLevel = function() { var _i, _len, _ref2, _result, name, vars; vars = this.variables; - _result = []; _ref2 = this.garbage.pop(); - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { + _result = []; + for (_i = 0, _len = (_ref2 = this.garbage.pop()).length; _i < _len; _i++) { name = _ref2[_i]; if (vars[name] === 'var') { _result.push(vars[name] = 'reuse'); @@ -45,8 +45,7 @@ }; Scope.prototype.any = function(fn) { var _ref2, k, v; - _ref2 = this.variables; - for (v in _ref2) { + for (v in _ref2 = this.variables) { if (!__hasProp.call(_ref2, v)) continue; k = _ref2[v]; if (fn(v, k)) { @@ -100,8 +99,8 @@ Scope.prototype.declaredVariables = function() { var _ref2, _result, key, val; return (function() { - _result = []; _ref2 = this.variables; - for (key in _ref2) { + _result = []; + for (key in _ref2 = this.variables) { if (!__hasProp.call(_ref2, key)) continue; val = _ref2[key]; if (('var' === val || 'reuse' === val)) { @@ -113,8 +112,8 @@ }; Scope.prototype.assignedVariables = function() { var _ref2, _result, key, val; - _result = []; _ref2 = this.variables; - for (key in _ref2) { + _result = []; + for (key in _ref2 = this.variables) { if (!__hasProp.call(_ref2, key)) continue; val = _ref2[key]; if (val.assigned) { diff --git a/src/nodes.coffee b/src/nodes.coffee index cc30d327..828489e1 100644 --- a/src/nodes.coffee +++ b/src/nodes.coffee @@ -622,16 +622,16 @@ exports.Range = class Range extends Base parts = [] parts.push @from if @from isnt @fromVar parts.push @to if @to isnt @toVar - if parts.length then "#{parts.join('; ')}; " else '' # When compiled normally, the range returns the contents of the *for loop* # needed to iterate over the values in the range. Used by comprehensions. compileNode: (o) -> + @compileVariables o return @compileArray(o) unless o.index return @compileSimple(o) if @fromNum and @toNum idx = del o, 'index' step = del o, 'step' - vars = "#{idx} = #{@fromVar}" + vars = "#{idx} = #{@from}" + if @to isnt @toVar then ", #{@to}" else '' intro = "(#{@fromVar} <= #{@toVar} ? #{idx}" compare = "#{intro} <#{@equals} #{@toVar} : #{idx} >#{@equals} #{@toVar})" stepPart = if step then step.compile(o) else '1' @@ -651,21 +651,21 @@ exports.Range = class Range extends Base # When used as a value, expand the range into the equivalent array. compileArray: (o) -> - idt = @idt 1 - vars = @compileVariables merge o, indent: idt if @fromNum and @toNum and Math.abs(@fromNum - @toNum) <= 20 range = [+@fromNum..+@toNum] range.pop() if @exclusive return "[#{ range.join(', ') }]" - i = o.scope.freeVariable 'i' + idt = @idt 1 + i = o.scope.freeVariable 'i' result = o.scope.freeVariable 'result' - pre = "\n#{idt}#{result} = []; #{vars}" + pre = "\n#{idt}#{result} = [];" if @fromNum and @toNum o.index = i body = @compileSimple o else + vars = "#{i} = #{@from}" + if @to isnt @toVar then ", #{@to}" else '' clause = "#{@fromVar} <= #{@toVar} ?" - body = "var #{i} = #{@fromVar}; #{clause} #{i} <#{@equals} #{@toVar} : #{i} >#{@equals} #{@toVar}; #{clause} #{i} += 1 : #{i} -= 1" + body = "var #{vars}; #{clause} #{i} <#{@equals} #{@toVar} : #{i} >#{@equals} #{@toVar}; #{clause} #{i} += 1 : #{i} -= 1" post = "{ #{result}.push(#{i}); }\n#{idt}return #{result};\n#{o.indent}" "(function() {#{pre}\n#{idt}for (#{body})#{post}}).call(this)" @@ -1431,11 +1431,15 @@ exports.For = class For extends Base body = Expressions.wrap([@body]) idt1 = @idt 1 if range - sourcePart = source.compileVariables(o) forPart = source.compile merge o, index: ivar, step: @step else - [sourcePart, svar] = @source.compileReference merge(o, top: yes), precompile: yes - sourcePart = if sourcePart is svar then '' else "#{sourcePart};" + svar = @source.compile o + if IDENTIFIER.test(svar) and scope.check(svar, immediate: on) + sourcePart = svar + else + sourcePart = "#{ref = scope.freeVariable 'ref'} = #{svar}" + sourcePart = "(#{sourcePart})" unless @object + svar = ref namePart = if @pattern new Assign(@name, literal "#{svar}[#{ivar}]").compile merge o, top: on else if name @@ -1443,9 +1447,8 @@ exports.For = class For extends Base unless @object lvar = scope.freeVariable 'len' stepPart = if @step then "#{ivar} += #{ @step.compile(o) }" else "#{ivar}++" - forPart = "#{ivar} = 0, #{lvar} = #{svar}.length; #{ivar} < #{lvar}; #{stepPart}" - sourcePart = (if rvar then "#{rvar} = []; " else '') + sourcePart - sourcePart = if sourcePart then "#{@tab}#{sourcePart}\n#{@tab}" else @tab + forPart = "#{ivar} = 0, #{lvar} = #{sourcePart}.length; #{ivar} < #{lvar}; #{stepPart}" + resultPart = if rvar then "#{@tab}#{rvar} = [];\n" else '' returnResult = @compileReturnValue(rvar, o) body = Push.wrap(rvar, body) unless topLevel if @guard @@ -1458,12 +1461,12 @@ exports.For = class For extends Base else varPart = "#{idt1}#{namePart};\n" if namePart if @object - forPart = "#{ivar} in #{svar}" + forPart = "#{ivar} in #{sourcePart}" guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" unless @raw body = body.compile merge o, indent: idt1, top: true vars = if range then name else "#{name}, #{ivar}" """ - #{sourcePart}for (#{forPart}) {#{guardPart} + #{resultPart}#{@tab}for (#{forPart}) {#{guardPart} #{varPart}#{body} #{@tab}}#{returnResult} """