mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
first draft of safe range comprehensions, upwards and downwards.
This commit is contained in:
parent
09b243e689
commit
76685e6e51
3 changed files with 55 additions and 18 deletions
36
lib/nodes.js
36
lib/nodes.js
|
|
@ -1507,9 +1507,6 @@
|
|||
}
|
||||
extend(this, head);
|
||||
this.body = Expressions.wrap([body]);
|
||||
if (!this.object) {
|
||||
this.step || (this.step = new Literal(1));
|
||||
}
|
||||
this.pattern = this.name instanceof Value;
|
||||
this.returns = false;
|
||||
return this;
|
||||
|
|
@ -1534,7 +1531,7 @@
|
|||
return '';
|
||||
};
|
||||
For.prototype.compileNode = function(o) {
|
||||
var body, code, cond, defPart, forPart, guardPart, hasCode, idt, index, ivar, lvar, name, namePart, pvar, retPart, rvar, scope, sourcePart, step, svar, tail, tvar, varPart, vars, _ref, _ref2, _ref3, _ref4, _ref5;
|
||||
var body, code, cond, defPart, forPart, fvar, guardPart, hasCode, head, idt, incr, index, intro, ivar, lvar, name, namePart, pvar, retPart, rvar, scope, sourcePart, step, svar, tail, tvar, varPart, vars, _ref, _ref2, _ref3, _ref4, _ref5, _ref6;
|
||||
scope = o.scope;
|
||||
body = this.body;
|
||||
hasCode = this.body.contains(function(node) {
|
||||
|
|
@ -1557,15 +1554,31 @@
|
|||
_ref3 = this.step.compileLoopReference(o, 'step'), step = _ref3[0], pvar = _ref3[1];
|
||||
}
|
||||
if (this.from) {
|
||||
_ref4 = this.to.compileLoopReference(o, 'to'), tail = _ref4[0], tvar = _ref4[1];
|
||||
vars = ivar + ' = ' + this.from.compile(o);
|
||||
_ref4 = this.from.compileLoopReference(o, 'from'), head = _ref4[0], fvar = _ref4[1];
|
||||
_ref5 = this.to.compileLoopReference(o, 'to'), tail = _ref5[0], tvar = _ref5[1];
|
||||
vars = ivar + ' = ' + head;
|
||||
if (tail !== tvar) {
|
||||
vars += ', ' + tail;
|
||||
}
|
||||
cond = +pvar ? "" + ivar + " " + (pvar < 0 ? '>' : '<') + "= " + tvar : "" + pvar + " < 0 ? " + ivar + " >= " + tvar + " : " + ivar + " <= " + tvar;
|
||||
if (SIMPLENUM.test(head) && SIMPLENUM.test(tail)) {
|
||||
if (+head <= +tail) {
|
||||
cond = "" + ivar + " <= " + tail;
|
||||
} else {
|
||||
pvar || (pvar = -1);
|
||||
cond = "" + ivar + " >= " + tail;
|
||||
}
|
||||
} else {
|
||||
if (+pvar) {
|
||||
cond = "" + ivar + " " + (pvar < 0 ? '>' : '<') + "= " + tvar;
|
||||
} else {
|
||||
intro = "" + fvar + " <= " + tvar + " ? " + ivar;
|
||||
cond = "" + intro + " <= " + tvar + " : " + ivar + " >= " + tvar;
|
||||
incr = pvar ? "" + ivar + " += " + pvar : "" + intro + "++ : " + ivar + "--";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (name || this.object && !this.raw) {
|
||||
_ref5 = this.source.compileLoopReference(o, 'ref'), sourcePart = _ref5[0], svar = _ref5[1];
|
||||
_ref6 = this.source.compileLoopReference(o, 'ref'), sourcePart = _ref6[0], svar = _ref6[1];
|
||||
} else {
|
||||
sourcePart = svar = this.source.compile(o, LEVEL_PAREN);
|
||||
}
|
||||
|
|
@ -1585,13 +1598,14 @@
|
|||
forPart = ivar + ' in ' + sourcePart;
|
||||
guardPart = this.raw ? '' : idt + ("if (!" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")) continue;\n");
|
||||
} else {
|
||||
if (step !== pvar) {
|
||||
pvar || (pvar = 1);
|
||||
if (step && (step !== pvar)) {
|
||||
vars += ', ' + step;
|
||||
}
|
||||
if (svar !== sourcePart) {
|
||||
defPart = this.tab + sourcePart + ';\n';
|
||||
}
|
||||
forPart = vars + ("; " + cond + "; ") + ivar + (function() {
|
||||
forPart = vars + ("; " + cond + "; ") + (incr || (ivar + (function() {
|
||||
switch (+pvar) {
|
||||
case 1:
|
||||
return '++';
|
||||
|
|
@ -1600,7 +1614,7 @@
|
|||
default:
|
||||
return pvar < 0 ? ' -= ' + pvar.slice(1) : ' += ' + pvar;
|
||||
}
|
||||
})();
|
||||
})()));
|
||||
}
|
||||
if (hasCode) {
|
||||
body = Closure.wrap(body, true);
|
||||
|
|
|
|||
|
|
@ -1268,7 +1268,6 @@ exports.For = class For extends Base
|
|||
throw SyntaxError 'index cannot be a pattern matching expression'
|
||||
extend this, head
|
||||
@body = Expressions.wrap [body]
|
||||
@step or= new Literal 1 unless @object
|
||||
@pattern = @name instanceof Value
|
||||
@returns = false
|
||||
|
||||
|
|
@ -1301,13 +1300,23 @@ exports.For = class For extends Base
|
|||
scope.find(index, yes) if index
|
||||
[step, pvar] = @step.compileLoopReference o, 'step' if @step
|
||||
if @from
|
||||
[head, fvar] = @from.compileLoopReference o, 'from'
|
||||
[tail, tvar] = @to.compileLoopReference o, 'to'
|
||||
vars = ivar + ' = ' + @from.compile o
|
||||
vars = ivar + ' = ' + head
|
||||
vars += ', ' + tail if tail isnt tvar
|
||||
cond = if +pvar
|
||||
"#{ivar} #{ if pvar < 0 then '>' else '<' }= #{tvar}"
|
||||
if SIMPLENUM.test(head) and SIMPLENUM.test(tail)
|
||||
if +head <= +tail
|
||||
cond = "#{ivar} <= #{tail}"
|
||||
else
|
||||
pvar or= -1
|
||||
cond = "#{ivar} >= #{tail}"
|
||||
else
|
||||
"#{pvar} < 0 ? #{ivar} >= #{tvar} : #{ivar} <= #{tvar}"
|
||||
if +pvar
|
||||
cond = "#{ivar} #{ if pvar < 0 then '>' else '<' }= #{tvar}"
|
||||
else
|
||||
intro = "#{fvar} <= #{tvar} ? #{ivar}"
|
||||
cond = "#{intro} <= #{tvar} : #{ivar} >= #{tvar}"
|
||||
incr = if pvar then "#{ivar} += #{pvar}" else "#{intro}++ : #{ivar}--"
|
||||
else
|
||||
if name or @object and not @raw
|
||||
[sourcePart, svar] = @source.compileLoopReference o, 'ref'
|
||||
|
|
@ -1330,12 +1339,14 @@ exports.For = class For extends Base
|
|||
guardPart = if @raw then '' else
|
||||
idt + "if (!#{ utility 'hasProp' }.call(#{svar}, #{ivar})) continue;\n"
|
||||
else
|
||||
vars += ', ' + step if step isnt pvar
|
||||
pvar or= 1
|
||||
vars += ', ' + step if step and (step isnt pvar)
|
||||
defPart = @tab + sourcePart + ';\n' if svar isnt sourcePart
|
||||
forPart = vars + "; #{cond}; " + ivar + switch +pvar
|
||||
forPart = vars + "; #{cond}; " + (incr or (ivar + switch +pvar
|
||||
when 1 then '++'
|
||||
when -1 then '--'
|
||||
else (if pvar < 0 then ' -= ' + pvar.slice 1 else ' += ' + pvar)
|
||||
))
|
||||
body = Closure.wrap(body, yes) if hasCode
|
||||
varPart = idt + namePart + ';\n' if namePart
|
||||
defPart += @pluckDirectCall o, body, name, index unless @pattern
|
||||
|
|
|
|||
|
|
@ -26,6 +26,18 @@ eq "#{ x for x from 9 to 0 by -3 }", '9,6,3,0'
|
|||
eq "#{ x for x from 3*3 to 0*0 by 0-3 }", '9,6,3,0'
|
||||
|
||||
|
||||
# Range comprehension gymnastics.
|
||||
eq "#{i for i from 5 to 1}", '5,4,3,2,1'
|
||||
eq "#{i for i from 5 to -5 by -5}", '5,0,-5'
|
||||
|
||||
a = 6
|
||||
b = 0
|
||||
c = -2
|
||||
|
||||
eq "#{i for i from a to b}", '6,5,4,3,2,1,0'
|
||||
eq "#{i for i from a to b by c}", '6,4,2,0'
|
||||
|
||||
|
||||
# Multiline array comprehension with filter.
|
||||
evens = for num in [1, 2, 3, 4, 5, 6] when not (num & 1)
|
||||
num *= -1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue