@@ -316,6 +316,21 @@ generateSoak = do ->
316316 [tests ,e ]= fn node
317317new CS.Conditional (foldl1 tests, (memo ,t )-> new CS.LogicalAndOp memo, t), e
318318
319+ extractNumber = (what )->
320+ return what .data if what .instanceof CS .Int
321+ return false unless what .instanceof CS .UnaryNegateOp
322+ return false unless what .expression .instanceof CS .Int
323+ return 0 - what .expression .data
324+
325+ extractStaticRange = (range )->
326+ return undefined unless range .instanceof CS .Range
327+ left = extractNumber range .left
328+ right = extractNumber range .right
329+
330+ return undefined if left== false
331+ return undefined if right== false
332+
333+ return [left, right]
319334
320335helperNames = {}
321336helpers =
@@ -392,7 +407,6 @@ for own h, fn of inlineHelpers
392407 helpers[h]= fn
393408
394409
395-
396410class exports.Compiler
397411
398412@ compile= => (new this ).compile arguments ...
@@ -449,17 +463,17 @@ class exports.Compiler
449463block = forceBlock body
450464block .body .push stmt helpers .undef ()unless block .body .length
451465
466+ numericRange = extractStaticRange (@target )
452467increment =
453468if @step ? and not ((@step .instanceof CS .Int )and @step .data is 1 )
454469 (x )-> new JS.AssignmentExpression ' +=' , x, step
470+ else if numericRange? and numericRange[1 ]< numericRange[0 ]
471+ (x )-> new JS.UpdateExpression ' --' ,yes , x
455472else
456473 (x )-> new JS.UpdateExpression ' ++' ,yes , x
457474
458475# optimise loops over static, integral ranges
459- if (@target .instanceof CS .Range )and
460- # TODO: extract this test to some "static, integral range" helper
461- ((@target .left .instanceof CS .Int )or ((@target .left .instanceof CS .UnaryNegateOp )and @target .left .expression .instanceof CS .Int ))and
462- ((@target .right .instanceof CS .Int )or ((@target .right .instanceof CS .UnaryNegateOp )and @target .right .expression .instanceof CS .Int ))
476+ if numericRange?
463477varDeclaration = new JS.VariableDeclaration ' var' , [new JS.VariableDeclarator i,compile @target .left ]
464478update = increment i
465479if @filter ?
@@ -471,7 +485,10 @@ class exports.Compiler
471485block .body .unshift stmt new JS.AssignmentExpression ' =' , keyAssignee, k
472486if valAssignee?
473487block .body .unshift stmt new JS.AssignmentExpression ' =' , valAssignee, i
474- op = if @target .isInclusive then ' <=' else ' <'
488+ if numericRange[1 ]> numericRange[0 ]
489+ op = if @target .isInclusive then ' <=' else ' <'
490+ else
491+ op = if @target .isInclusive then ' >=' else ' >'
475492return new JS.ForStatement varDeclaration, (new JS.BinaryExpression op, i,compile @target .right ), update, block
476493
477494e = if needsCaching @target then genSym ' cache' else target