Class: Opal::Rewriters::ForRewriter
- Defined in:
- opal/lib/opal/rewriters/for_rewriter.rb
Defined Under Namespace
Classes: LocalVariableAssigns
Constant Summary
Constants inherited from Base
Instance Attribute Summary
Attributes inherited from Base
Class Method Summary collapse
Instance Method Summary collapse
-
#on_for(node) ⇒ Object
Handles for i in 0..3; j = i + 1; end.
Methods inherited from Base
#append_to_body, #prepend_to_body, #process, #s, s
Class Method Details
.next_tmp ⇒ Object
11 12 13 14 15 |
# File 'opal/lib/opal/rewriters/for_rewriter.rb', line 11 def self.next_tmp @counter ||= 0 @counter += 1 :$for_tmp#{@counter}" end |
.reset_tmp_counter! ⇒ Object
7 8 9 |
# File 'opal/lib/opal/rewriters/for_rewriter.rb', line 7 def self.reset_tmp_counter! @counter = 0 end |
Instance Method Details
#on_for(node) ⇒ Object
Handles for i in 0..3; j = i + 1; end
The problem here is that in Ruby for loop makes its
loop variable + all local variables available outside.
I.e. after this loop variable i
is 3 and j
is 4
This class rewrites it to the following code: j = nil i = nil (0..3).each { |__jstmp| i = __jstmp; j = i + 1 }
Complex stuff with multiple loop variables: for i, j in [[1, 2], [3, 4]]; end Becomes multiple left-hand assignment: i = nil j = nil [[1, 2], [3, 4]].each { |__jstmp| i, j = __jstmp }
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'opal/lib/opal/rewriters/for_rewriter.rb', line 36 def on_for(node) loop_variable, , loop_body = *node = LocalVariableAssigns.find(loop_variable) # [:i] lvars_declared_in_body = LocalVariableAssigns.find(loop_body) # [:j] # i = nil; j = nil outer_assigns = ( + lvars_declared_in_body).map do |lvar_name| s(:lvdeclare, lvar_name) end # :__jstmp tmp_loop_variable = self.class.next_tmp get_tmp_loop_variable = s(:js_tmp, tmp_loop_variable) loop_variable_assignment = case loop_variable.type when :mlhs # multiple left-hand statement like in "for i,j in [[1, 2], [3, 4]]" # i, j = __jstmp s(:masgn, loop_variable, get_tmp_loop_variable) else # single argument like "for i in (0..3)" # i = __jstmp loop_variable << get_tmp_loop_variable end loop_body = prepend_to_body(loop_body, loop_variable_assignment) node = s(:send, , :each, # (0..3).each { s(:iter, s(:args, s(:arg, tmp_loop_variable)), # |__jstmp| loop_body) # i = __jstmp; j = i + 1 } ) s(:begin, *outer_assigns, node) end |