Fixing inconsistencies for index variables

See the tests added to test_comprehensions.coffee. Previously, after
`for i in [1..3]`, i was 4. Also, index variables were never set to
any value in comprehensions containing both a closure and a break or
return.
This commit is contained in:
Trevor Burnham 2010-10-19 14:09:16 -04:00
parent 0e395569ee
commit 5005cb606f
13 changed files with 148 additions and 7 deletions

View File

@ -36,6 +36,8 @@
})();
script = _j;
}
return null;
};
if (window.addEventListener) {

View File

@ -51,6 +51,8 @@
arg = _ref[_i];
_result.push(invoke(arg));
}
return _result;
});
};
@ -64,6 +66,8 @@
desc = task.description ? ("# " + (task.description)) : '';
puts("cake " + name + spaces + " " + desc);
}
return switches.length ? puts(oparse.help()) : undefined;
};
missingTask = function(task) {

View File

@ -70,6 +70,8 @@
file = files[_k];
_result2.push(compile(path.join(source, file)));
}
return _result2;
});
} else if (topLevel || path.extname(source) === '.coffee') {
@ -86,6 +88,8 @@
})();
source = _j;
}
return _result;
};
compileScript = function(file, input, base) {
@ -97,6 +101,8 @@
req = _ref2[_i];
require(helpers.starts(req, '.') ? fs.realpathSync(req) : req);
}
}
try {
t = (task = {
@ -197,6 +203,8 @@
return "[" + tag + " " + value + "]";
})());
}
return _result;
})();
return puts(strings.join(' '));

View File

@ -604,15 +604,21 @@
tokens.push(token);
}
}
if (name === 'Root') {
alt[1] = ("return " + (alt[1]));
}
return alt;
})());
}
return _result;
})();
}
exports.parser = new Parser({
tokens: tokens.join(' '),
bnf: grammar,

View File

@ -10,6 +10,8 @@
return index;
}
}
return -1;
}));
exports.include = function(list, value) {
@ -32,6 +34,8 @@
_result.push(item);
}
}
return _result;
};
exports.count = function(string, letter) {
@ -51,6 +55,8 @@
val = properties[key];
object[key] = val;
}
return object;
});
exports.flatten = (flatten = function(array) {
@ -64,6 +70,8 @@
flattened.push(element);
}
}
return flattened;
});
exports.del = function(obj, key) {

View File

@ -6,4 +6,6 @@
val = _ref[key];
(exports[key] = val);
}
}).call(this);

View File

@ -226,6 +226,8 @@
}
tokens.push(['+', '+']);
}
tokens.pop();
if ((((_ref4 = tokens[0]) != null) ? _ref4[0] : undefined) !== 'STRING') {
this.tokens.push(['STRING', '""'], ['+', '+']);
@ -480,6 +482,8 @@
break;
}
}
}
if (!levels.length) {
break;
@ -550,6 +554,8 @@
this.token('STRING', this.makeString(value, '"', heredoc));
}
}
if (interpolated) {
this.token(')', ')');
}
@ -600,6 +606,8 @@
})) {
COFFEE_KEYWORDS.push(op);
}
RESERVED = ['case', 'default', 'do', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice'];
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
IDENTIFIER = /^([$A-Za-z_][$\w]*)([^\n\S]*:(?!:))?/;

View File

@ -58,6 +58,8 @@
node = pair[i];
(pair[i] = node.compile(o));
}
}
return pair;
};
@ -106,6 +108,8 @@
child = _ref2[_i];
_result.push(child.toString(idt + TAB));
}
return _result;
}).call(this).join('');
klass = override || this.constructor.name + (this.soakNode ? '?' : '');
@ -126,8 +130,12 @@
return;
}
}
}
}
return _result;
};
Base.prototype.collectChildren = function() {
@ -208,6 +216,8 @@
node = _ref2[_i];
_result.push(this.compileExpression(node, merge(o)));
}
return _result;
}).call(this).join('\n');
};
@ -411,6 +421,8 @@
prop = props[_i];
(code += prop.compile(o));
}
return code;
};
Value.prototype.unfoldSoak = function(o) {
@ -436,6 +448,8 @@
return ifn;
}
}
return null;
};
return Value;
@ -542,6 +556,8 @@
}
ifn = If.unfoldSoak(o, call, 'variable');
}
return ifn;
};
Call.prototype.compileNode = function(o) {
@ -556,12 +572,16 @@
return this.compileSplat(o);
}
}
args = (function() {
_result = [];
for (_j = 0, _len2 = (_ref4 = this.args).length; _j < _len2; _j++) {
arg = _ref4[_j];
_result.push((arg.parenthetical = true) && arg.compile(o));
}
return _result;
}).call(this).join(', ');
return this.isSuper ? this.compileSuper(args, o) : ("" + (this.prefix()) + (this.variable.compile(o)) + "(" + args + ")");
@ -792,6 +812,8 @@
_result.push(prop);
}
}
return _result;
}).call(this);
lastNoncom = last(nonComments);
@ -810,6 +832,8 @@
return indent + prop.compile(o) + join;
}).call(this));
}
return _result;
}).call(this);
props = props.join('');
@ -824,6 +848,8 @@
return true;
}
}
return false;
};
return ObjectLiteral;
@ -852,12 +878,16 @@
return this.compileSplatLiteral(o);
}
}
objects = [];
for (i = 0, _len2 = (_ref3 = this.objects).length; i < _len2; i++) {
obj = _ref3[i];
code = obj.compile(o);
objects.push(obj instanceof Comment ? ("\n" + code + "\n" + (o.indent)) : (i === this.objects.length - 1 ? code : code + ', '));
}
objects = objects.join('');
return 0 < objects.indexOf('\n') ? ("[\n" + (o.indent) + objects + "\n" + (this.tab) + "]") : ("[" + objects + "]");
};
@ -869,6 +899,8 @@
return true;
}
}
return false;
};
return ArrayLiteral;
@ -957,6 +989,8 @@
}
props.push(prop);
}
constructor.className = className.match(/[\w\d\$_]+$/);
if (me) {
constructor.body.unshift(new Literal("" + me + " = this"));
@ -1082,6 +1116,8 @@
}
assigns.push(new Assign(obj, val).compile(otop));
}
if (!top) {
assigns.push(valVar);
}
@ -1159,6 +1195,8 @@
}
}
}
o.scope.startLevel();
params = (function() {
_result = [];
@ -1166,6 +1204,8 @@
param = params[_i];
_result.push(param.compile(o));
}
return _result;
})();
if (!(empty || this.noReturn)) {
@ -1175,6 +1215,8 @@
param = params[_i];
(o.scope.parameter(param));
}
comm = this.comment ? this.comment.compile(o) + '\n' : '';
if (this.className) {
o.indent = this.idt(2);
@ -1262,6 +1304,8 @@
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) + end + ")";
};
@ -1291,6 +1335,8 @@
}
args[++end] = i === 0 ? code : (".concat(" + code + ")");
}
return args.join('');
};
return Splat;
@ -1492,6 +1538,8 @@
item = _ref2[i];
_result.push("" + (i ? this.obj2 : this.obj1) + " === " + (item.compile(o)));
}
return _result;
}).call(this);
return "(" + (tests.join(' || ')) + ")";
@ -1657,7 +1705,7 @@
return '';
};
For.prototype.compileNode = function(o) {
var body, codeInBody, forPart, guardPart, idt1, index, ivar, lastLine, lvar, name, namePart, nvar, range, ref, resultPart, returnResult, rvar, scope, source, sourcePart, stepPart, svar, topLevel, varPart, vars;
var body, codeInBody, forPart, guardPart, idt1, index, ivar, lastLine, lvar, name, namePart, nvar, range, ref, resultPart, returnResult, rvar, scope, source, sourcePart, stepPart, svar, topLevel, unstepPart, 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;
@ -1689,6 +1737,7 @@
}
varPart = '';
guardPart = '';
unstepPart = '';
body = Expressions.wrap([this.body]);
idt1 = this.idt(1);
if (range) {
@ -1724,10 +1773,12 @@
if (this.guard) {
body = Expressions.wrap([new If(this.guard, body)]);
}
if (codeInBody && !body.containsPureStatement()) {
if (codeInBody) {
if (range) {
body.unshift(new Literal("var " + name + " = " + ivar));
}
}
if (codeInBody && !body.containsPureStatement()) {
if (namePart) {
body.unshift(new Literal("var " + namePart));
}
@ -1754,6 +1805,9 @@
if (namePart) {
varPart = ("" + idt1 + namePart + ";\n");
}
if (forPart && name === ivar) {
unstepPart = this.step ? ("\n" + name + " -= " + (this.step.compile(o)) + ";") : ("\n" + name + "--;");
}
}
if (this.object) {
forPart = ("" + ivar + " in " + sourcePart);
@ -1766,7 +1820,7 @@
top: true
}));
vars = range ? name : ("" + name + ", " + ivar);
return "" + resultPart + (this.tab) + "for (" + forPart + ") {" + guardPart + "\n" + varPart + body + "\n" + (this.tab) + "}" + returnResult;
return "" + resultPart + (this.tab) + "for (" + forPart + ") {" + guardPart + "\n" + varPart + body + "\n" + (this.tab) + "}\n" + unstepPart + "\n" + returnResult;
};
return For;
})();
@ -1792,6 +1846,8 @@
pair = _ref2[_i];
pair[1].makeReturn();
}
if (this.otherwise) {
this.otherwise.makeReturn();
}
@ -1813,11 +1869,15 @@
}
code += ("\n" + (this.idt(1)) + "case " + (condition.compile(o)) + ":");
}
code += ("\n" + (block.compile(o)));
if (!(last(exprs) instanceof Return)) {
code += ("\n" + idt + "break;");
}
}
if (this.otherwise) {
code += ("\n" + (this.idt(1)) + "default:\n" + (this.otherwise.compile(o)));
}

View File

@ -28,6 +28,8 @@
break;
}
}
if (isOption && !matchedRule) {
throw new Error("unrecognized option: " + arg);
}
@ -36,6 +38,8 @@
break;
}
}
return options;
};
OptionParser.prototype.help = function() {
@ -51,6 +55,8 @@
letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' ';
lines.push(' ' + letPart + rule.longFlag + spaces + rule.description);
}
return "\n" + (lines.join('\n')) + "\n";
};
return OptionParser;
@ -71,6 +77,8 @@
return buildRule.apply(buildRule, tuple);
})());
}
return _result;
};
buildRule = function(shortFlag, longFlag, description, options) {
@ -98,10 +106,14 @@
l = _ref[_j];
result.push('-' + l);
}
} else {
result.push(arg);
}
}
return result;
};
}).call(this);

View File

@ -90,6 +90,8 @@
break;
}
}
return i ? this.tokens.splice(0, i) : undefined;
};
exports.Rewriter.prototype.removeMidExpressionNewlines = function() {
@ -296,6 +298,8 @@
throw Error("too many " + (token[1]) + " on line " + (token[2] + 1));
}
}
return 1;
});
unclosed = (function() {
@ -306,6 +310,8 @@
_result.push(key);
}
}
return _result;
})();
if (unclosed.length) {
@ -319,6 +325,8 @@
for (key in INVERSES) {
(debt[key] = 0);
}
return this.scanTokens(function(token, i, tokens) {
var inv, match, mtag, oppos, tag, val;
if (include(EXPRESSION_START, tag = token[0])) {
@ -366,6 +374,8 @@
EXPRESSION_START.push(INVERSES[rite] = left);
EXPRESSION_END.push(INVERSES[left] = rite);
}
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', '@', '->', '=>', '[', '(', '{', '--', '++'];

View File

@ -35,6 +35,8 @@
_result.push(vars[name] = 'reuse');
}
}
return _result;
};
Scope.prototype.find = function(name, options) {
@ -53,6 +55,8 @@
return true;
}
}
return false;
};
Scope.prototype.parameter = function(name) {
@ -108,6 +112,8 @@
_result.push(key);
}
}
return _result;
}).call(this).sort();
};
@ -121,6 +127,8 @@
_result.push("" + key + " = " + (val.value));
}
}
return _result;
};
Scope.prototype.compiledDeclarations = function() {

View File

@ -1428,6 +1428,7 @@ exports.For = class For extends Base
nvar = scope.freeVariable 'i' if name and not range and codeInBody
varPart = ''
guardPart = ''
unstepPart = ''
body = Expressions.wrap([@body])
idt1 = @idt 1
if range
@ -1452,8 +1453,9 @@ exports.For = class For extends Base
body = Push.wrap(rvar, body) unless topLevel
if @guard
body = Expressions.wrap([new If(@guard, body)])
if codeInBody and not body.containsPureStatement()
if codeInBody
body.unshift new Literal "var #{name} = #{ivar}" if range
if codeInBody and not body.containsPureStatement()
body.unshift new Literal "var #{namePart}" if namePart
body.unshift new Literal "var #{index} = #{ivar}" if index
lastLine = body.expressions.pop()
@ -1466,6 +1468,8 @@ exports.For = class For extends Base
body.push new Assign new Literal(name), new Literal nvar or ivar if name
else
varPart = "#{idt1}#{namePart};\n" if namePart
if forPart and name is ivar
unstepPart = if @step then "\n#{name} -= #{ @step.compile(o) };" else "\n#{name}--;"
if @object
forPart = "#{ivar} in #{sourcePart}"
guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" unless @raw
@ -1474,7 +1478,9 @@ exports.For = class For extends Base
"""
#{resultPart}#{@tab}for (#{forPart}) {#{guardPart}
#{varPart}#{body}
#{@tab}}#{returnResult}
#{@tab}}
#{unstepPart}
#{returnResult}
"""
#### Switch

View File

@ -23,6 +23,8 @@ negs = negs[0..2]
result = nums.concat(negs).join(', ')
ok result is '3, 6, 9, -20, -19, -18'
ok i is 3
ok x is -10
# With range comprehensions, you can loop in steps.
@ -70,17 +72,22 @@ ok obj.one() is "I'm one"
ok obj.two() is "I'm two"
ok obj.three() is "I'm three"
i = 0
for i in [1..3]
-> 'func'
break if false
ok i is 3
# Ensure that local variables are closed over for range comprehensions.
funcs = for i in [1..3]
-> -i
ok (func() for func in funcs).join(' ') is '-1 -2 -3'
ok i is 3
# Ensure that closing over local variables doesn't break scoping laws.
ok i is 3
for i in [0]
count = 0
i = 50