Class: Opal::Nodes::ZsuperNode

Inherits:
SuperNode show all
Defined in:
opal/lib/opal/nodes/super.rb

Overview

super with implicit args

Constant Summary

Constants inherited from CallNode

CallNode::OPERATORS, CallNode::SPECIALS

Instance Attribute Summary

Attributes inherited from CallNode

#arglist, #iter, #meth, #recvr

Attributes inherited from Base

#compiler, #sexp, #type

Instance Method Summary collapse

Methods inherited from BaseSuperNode

#compile_using_send

Methods inherited from CallNode

add_special

Methods inherited from Base

#add_gvar, #add_ivar, #add_local, #add_temp, children, #children, #class_variable_owner, #class_variable_owner_nesting_level, #comments, #compile_to_fragments, #error, #expr, #expr?, #expr_or_nil, #fragment, handle, handlers, #has_rescue_else?, #helper, #in_ensure, #in_ensure?, #in_resbody, #in_resbody?, #in_rescue, #in_while?, #process, #push, #recv, #recv?, #s, #scope, #source_location, #stmt, #stmt?, #top_scope, truthy_optimize?, #unshift, #while_loop, #with_temp, #wrap

Methods included from Helpers

#current_indent, #empty_line, #indent, #js_truthy, #js_truthy_optimize, #line, #mid_to_jsid, #property, #valid_name?

Constructor Details

#initializeZsuperNode

Returns a new instance of ZsuperNode.



148
149
150
151
152
153
154
155
156
157
158
# File 'opal/lib/opal/nodes/super.rb', line 148

def initialize(*)
  super

  # preserve a block if we have one already but otherwise, assume a block is coming from higher
  # up the chain
  unless iter.type == :iter
    # Need to support passing block up even if it's not referenced in this method at all
    scope.uses_block!
    @iter = s(:js_tmp, scope.block_name || '$yield')
  end
end

Instance Method Details

#block_nameObject



212
213
214
215
216
217
218
219
220
221
# File 'opal/lib/opal/nodes/super.rb', line 212

def block_name
  case def_scope
  when Opal::Nodes::IterNode
    def_scope.block_name
  when Opal::Nodes::DefNode
    def_scope.block_name
  else
    raise "Don't know what to do with super in the scope #{def_scope}"
  end
end

#compileObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'opal/lib/opal/nodes/super.rb', line 160

def compile
  if def_scope
    implicit_args = implicit_arglist
    # If the method we're in has a block and we're using a default super call with no args, we need to grab the block
    # If an iter (block via braces) is provided, that takes precedence
    if block_name && !iter
      block_pass = s(:block_pass, s(:lvar, block_name))
      implicit_args << block_pass
    end

    @arglist = s(:arglist, *implicit_args)
  end

  compile_using_send
end

#implicit_arglistObject



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'opal/lib/opal/nodes/super.rb', line 176

def implicit_arglist
  args = []
  kwargs = []
  same_arg_counter = Hash.new(0)

  def_scope.original_args.children.each do |sexp|
    lvar_name = sexp.children[0]

    case sexp.type
    when :arg, :optarg
      arg_node = s(:lvar, lvar_name)
      #   def m(_, _)
      # is compiled to
      #   function $$m(_, __$2)
      # See Opal::Node::ArgsNode
      if lvar_name[0] == '_'
        same_arg_counter[lvar_name] += 1
        arg_node = s(:js_tmp, "#{lvar_name}_$#{same_arg_counter[lvar_name]}") if same_arg_counter[lvar_name] > 1
      end
      args << arg_node
    when :restarg
      arg_node = lvar_name ? s(:lvar, lvar_name) : s(:js_tmp, '$rest_arg')
      args << s(:splat, arg_node)
    when :kwarg, :kwoptarg
      key_name = sexp.meta[:arg_name]
      kwargs << s(:pair, s(:sym, key_name), s(:lvar, lvar_name))
    when :kwrestarg
      arg_node = lvar_name ? s(:lvar, lvar_name) : s(:js_tmp, '$kw_rest_arg')
      kwargs << s(:kwsplat, arg_node)
    end
  end

  args << s(:hash, *kwargs) unless kwargs.empty?
  args
end

#implicit_arguments_paramObject



144
145
146
# File 'opal/lib/opal/nodes/super.rb', line 144

def implicit_arguments_param
  'true'
end