diff --git a/lib/coffee_script/lexer.rb b/lib/coffee_script/lexer.rb index ed959f84..2e6d95ec 100644 --- a/lib/coffee_script/lexer.rb +++ b/lib/coffee_script/lexer.rb @@ -19,7 +19,7 @@ module CoffeeScript # Token matching regexes. IDENTIFIER = /\A([a-zA-Z$_]\w*)/ - NUMBER = /\A\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?))\b/i + NUMBER = /\A((\b|-)((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?)))\b/i STRING = /\A(""|''|"(.*?)[^\\]"|'(.*?)[^\\]')/m JS = /\A(``|`(.*?)[^\\]`)/m OPERATOR = /\A([+\*&|\/\-%=<>:!]+)/ diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 04064641..46c2ad74 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -307,8 +307,6 @@ module CoffeeScript # A range literal. Ranges can be used to extract portions (slices) of arrays, # or to specify a range for array comprehensions. - # RangeNodes get expanded into the equivalent array, if not used to index - # a slice or define an array comprehension. class RangeNode attr_reader :from, :to @@ -320,15 +318,20 @@ module CoffeeScript @exclusive end - # TODO -- figure out if we can detect if a range runs negative. - def downward? - + def less_operator + @exclusive ? '<' : '<=' end - # TODO -- figure out if we can expand ranges into the corresponding array, - # as an expression, reliably. - def compile(o={}) - write() + def greater_operator + @exclusive ? '>' : '>=' + end + + def compile(o, fv, tv) + fvv, tvv = @from.compile(o), @to.compile(o) + vars = "#{fv}=#{fvv}, #{tv}=#{tvv}" + compare = "(#{fvv} <= #{tvv} ? #{fv} #{less_operator} #{tv} : #{fv} #{greater_operator} #{tv})" + incr = "(#{fvv} <= #{tvv} ? #{fv} += 1 : #{fv} -= 1)" + "#{vars}; #{compare}; #{incr}" end end @@ -548,11 +551,10 @@ module CoffeeScript index_name = @index ? @index : nil if range source_part = '' - operator = @source.exclusive? ? '<' : '<=' - index_var = scope.free_variable - for_part = "#{index_var}=0, #{ivar}=#{@source.from.compile(o)}, #{lvar}=#{@source.to.compile(o)}; #{ivar}#{operator}#{lvar}; #{ivar}++, #{index_var}++" var_part = '' index_part = '' + index_var = scope.free_variable + for_part = "#{index_var}=0, #{@source.compile(o, ivar, lvar)}, #{index_var}++" else index_var = nil source_part = "#{svar} = #{@source.compile(o)};\n#{o[:indent]}" diff --git a/test/fixtures/execution/test_range_comprehension.coffee b/test/fixtures/execution/test_range_comprehension.coffee index 66ddefb2..8ae0b3d8 100644 --- a/test/fixtures/execution/test_range_comprehension.coffee +++ b/test/fixtures/execution/test_range_comprehension.coffee @@ -1,5 +1,8 @@ nums: i * 3 for i in [1..3]. -result: nums.join(', ') +negs: x for x in [-20..-10]. +negs: negs[0..2] -print(result is '3, 6, 9') \ No newline at end of file +result: nums.concat(negs).join(', ') + +print(result is '3, 6, 9, -20, -19, -18') \ No newline at end of file