lib/opal/rewriters/mlhs_args.rb
# frozen_string_literal: true require 'opal/rewriters/base' module Opal module Rewriters # Rewrites # # def m( (a, b), (c, d) ) # body # end # # To # # def m($mlhs_tmp1, $mlhs_tmp2) # (a, b) = $mlhs_tmp1 # (c, d) = $mlhs_tmp2 # body # end # class MlhsArgs < Base def on_def(node) node = super(node) mid, args, body = *node arguments = Arguments.new(args) args = args.updated(nil, arguments.rewritten) if arguments.initialization body ||= s(:nil) # prevent returning mlhs assignment body = prepend_to_body(body, arguments.initialization) end node.updated(nil, [mid, args, body]) end def on_defs(node) node = super(node) recv, mid, args, body = *node arguments = Arguments.new(args) args = args.updated(nil, arguments.rewritten) if arguments.initialization body ||= s(:nil) # prevent returning mlhs assignment body = prepend_to_body(body, arguments.initialization) end node.updated(nil, [recv, mid, args, body]) end def on_iter(node) node = super(node) args, body = *node arguments = Arguments.new(args) args = args.updated(nil, arguments.rewritten) if arguments.initialization body ||= s(:nil) # prevent returning mlhs assignment body = prepend_to_body(body, arguments.initialization) end node.updated(nil, [args, body]) end class Arguments < Base attr_reader :rewritten, :initialization def initialize(args) @args = args @rewritten = [] @initialization = [] @rewriter = MlhsRewriter.new split! end def reset_tmp_counter! @counter = 0 end def new_mlhs_tmp @counter ||= 0 @counter += 1 :"$mlhs_tmp#{@counter}" end def split! @args.children.each do |arg| if arg.type == :mlhs var_name = new_mlhs_tmp rhs = s(:lvar, var_name) mlhs = @rewriter.process(arg) @initialization << s(:masgn, mlhs, rhs) @rewritten << s(:arg, var_name).updated(nil, nil, meta: { arg_name: var_name }) else @rewritten << arg end end if @initialization.length == 1 @initialization = @initialization[0] elsif @initialization.empty? @initialization = nil else @initialization = s(:begin, *@initialization) end end end class MlhsRewriter < Base def on_arg(node) node.updated(:lvasgn) end def on_restarg(node) name = node.children[0] if name s(:splat, node.updated(:lvasgn)) else s(:splat) end end end end end end