diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 3928d31f..7d6280da 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -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 diff --git a/test/fixtures/execution/test_range_comprehension.coffee b/test/fixtures/execution/test_range_comprehension.coffee index 5702ff07..e4856201 100644 --- a/test/fixtures/execution/test_range_comprehension.coffee +++ b/test/fixtures/execution/test_range_comprehension.coffee @@ -5,4 +5,11 @@ negs: negs[0..2] result: nums.concat(negs).join(', ') -print(result is '3, 6, 9, -20, -19, -18') \ No newline at end of file +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') \ No newline at end of file