Permalink
Browse files

first draft of safe range comprehensions, upwards and downwards.

  • Loading branch information...
1 parent 09b243e commit 76685e6e51803a686c82407a8cac64bf5c9e8933 @jashkenas committed Nov 5, 2010
Showing with 55 additions and 18 deletions.
  1. +25 −11 lib/nodes.js
  2. +18 −7 src/nodes.coffee
  3. +12 −0 test/test_comprehensions.coffee
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -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

0 comments on commit 76685e6

Please sign in to comment.