# frozen_string_literal: truerequire'opal/rewriters/base'moduleOpalmoduleRewritersclassForRewriter<Basedefself.reset_tmp_counter!@counter=0enddefself.next_tmp@counter||=0@counter+=1:"$for_tmp#{@counter}"end# 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 }#defon_for(node)loop_variable,loop_range,loop_body=*node# Declare local variables used in the loop and the loop body at the outer scopeouter_assignments=generate_outer_assignments(loop_variable,loop_body)# Generate temporary loop variabletmp_loop_variable=self.class.next_tmpget_tmp_loop_variable=s(:js_tmp,tmp_loop_variable)# Assign the loop variables in the loop bodyloop_body=prepend_to_body(loop_body,assign_loop_variable(loop_variable,get_tmp_loop_variable))# Transform the for-loop into each-loop with updated loop bodynode=transform_for_to_each_loop(node,loop_range,tmp_loop_variable,loop_body)node.updated(:begin,[*outer_assignments,node])endprivatedefgenerate_outer_assignments(loop_variable,loop_body)loop_local_vars=LocalVariableAssigns.find(loop_variable)body_local_vars=LocalVariableAssigns.find(loop_body)(loop_local_vars+body_local_vars).map{|lvar_name|s(:lvdeclare,lvar_name)}enddefassign_loop_variable(loop_variable,tmp_loop_variable)caseloop_variable.typewhen:mlhs# multiple left-hand statement like in "for i,j in [[1, 2], [3, 4]]"loop_variable.updated(:masgn,[loop_variable,tmp_loop_variable])else# single argument like "for i in (0..3)"loop_variable<<tmp_loop_variableendend# rubocop:disable Layout/MultilineMethodCallBraceLayout,Layout/MultilineArrayBraceLayoutdeftransform_for_to_each_loop(node,loop_range,tmp_loop_variable,loop_body)node.updated(:send,[loop_range,:each,# (0..3).each {node.updated(:iter,[s(:args,s(:arg,tmp_loop_variable)),# |__jstmp|process(loop_body)# i = __jstmp; j = i + 1 }])])end# rubocop:enable Layout/MultilineMethodCallBraceLayout,Layout/MultilineArrayBraceLayoutclassLocalVariableAssigns<Baseattr_reader:resultdefself.find(node)processor=newprocessor.process(node)processor.result.to_aenddefinitialize@result=Set.newenddefon_lvasgn(node)name,_=*noderesult<<namesuperendendendendend