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, #begin_with_stmts, #dynamic!, #error, #on_top, #prepend_to_body, #process, s, #s, #stmts_of
Class Method Details
.next_tmp ⇒ Object
12 13 14 15 16 |
# File 'opal/lib/opal/rewriters/for_rewriter.rb', line 12 def self.next_tmp @counter ||= 0 @counter += 1 :"$for_tmp#{@counter}" end |
.reset_tmp_counter! ⇒ Object
8 9 10 |
# File 'opal/lib/opal/rewriters/for_rewriter.rb', line 8 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 }
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 69 70 |
# File 'opal/lib/opal/rewriters/for_rewriter.rb', line 37 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 loop_variable.updated(: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 = node.updated(:send, [, :each, # (0..3).each { node.updated(:iter, [s(:args, s(:arg, tmp_loop_variable)), # |__jstmp| process(loop_body)] # i = __jstmp; j = i + 1 } )] ) node.updated(:begin, [*outer_assigns, node]) end |