making range comprehensions compile safely, even when you assign to the same variable as your endposts.

This commit is contained in:
Jeremy Ashkenas 2010-01-01 10:55:43 -05:00
parent f622fc43bc
commit 305f883eab
2 changed files with 22 additions and 9 deletions

View File

@ -334,7 +334,7 @@ module CoffeeScript
# A range literal. Ranges can be used to extract portions (slices) of arrays,
# or to specify a range for array comprehensions.
class RangeNode
class RangeNode < Node
attr_reader :from, :to
def initialize(from, to, exclusive=false)
@ -353,12 +353,18 @@ module CoffeeScript
@exclusive ? '>' : '>='
end
def compile_variables(o)
idt = o[:indent]
@from_var, @to_var = o[:scope].free_variable, o[:scope].free_variable
from_val, to_val = @from.compile(o), @to.compile(o)
write("#{idt}#{@from_var} = #{from_val};\n#{idt}#{@to_var} = #{to_val};\n#{idt}")
end
def compile(o, fv)
fvv, tvv = @from.compile(o), @to.compile(o)
vars = "#{fv}=#{fvv}"
compare = "(#{fvv} <= #{tvv} ? #{fv} #{less_operator} #{tvv} : #{fv} #{greater_operator} #{tvv})"
incr = "(#{fvv} <= #{tvv} ? #{fv} += 1 : #{fv} -= 1)"
"#{vars}; #{compare}; #{incr}"
vars = "#{fv}=#{@from_var}"
compare = "(#{@from_var} <= #{@to_var} ? #{fv} #{less_operator} #{@to_var} : #{fv} #{greater_operator} #{@to_var})"
incr = "(#{@from_var} <= #{@to_var} ? #{fv} += 1 : #{fv} -= 1)"
write("#{vars}; #{compare}; #{incr}")
end
end
@ -624,9 +630,9 @@ module CoffeeScript
tvar = scope.free_variable
if range
body_dent = o[:indent] + TAB
source_part, var_part = '', '', ''
pre_cond, post_cond = '', ''
var_part, pre_cond, post_cond = '', '', ''
index_var = scope.free_variable
source_part = @source.compile_variables(o)
for_part = "#{index_var}=0, #{@source.compile(o, ivar)}, #{index_var}++"
else
index_var = nil

View File

@ -5,4 +5,11 @@ negs: negs[0..2]
result: nums.concat(negs).join(', ')
print(result is '3, 6, 9, -20, -19, -18')
print(result is '3, 6, 9, -20, -19, -18')
# Ensure that ranges are safe. This used to infinite loop:
j = 5
result: for j in [j..(j+3)]
j
print(result.join(' ') is '5 6 7 8')