class Opal::Nodes::CallNode
def self.add_special(name, options = {}, &handler)
def self.add_special(name, options = {}, &handler) SPECIALS[name] = options define_method("handle_#{name}", &handler) end
def attr_assignment?
def attr_assignment? @assignment ||= meth.to_s =~ /#{REGEXP_START}[\da-z]+\=#{REGEXP_END}/i end
def compile
def compile # handle some methods specially handle_special # some special methods need to skip compilation return unless compile_default? compiler.method_calls << meth.to_sym if record_method? # if trying to access an lvar in irb mode return compile_irb_var if using_irb? default_compile end
def compile_assignment
def compile_assignment with_temp do |args_tmp| with_temp do |recv_tmp| args = expr(arglist) mid = mid_to_jsid meth.to_s push "((#{args_tmp} = [", args, "]), "+ "#{recv_tmp} = ", recv(recv_sexp), ", ", recv_tmp, mid, ".apply(#{recv_tmp}, #{args_tmp}), "+ "#{args_tmp}[#{args_tmp}.length-1])" end end end
def compile_default!
def compile_default! @compile_default = true end
def compile_default?
def compile_default? @compile_default end
def compile_irb_var
def compile_irb_var with_temp do |tmp| lvar = variable(meth) call = s(:call, s(:self), meth.intern, s(:arglist)) push "((#{tmp} = Opal.irb_vars.#{lvar}) == null ? ", expr(call), " : #{tmp})" end end
def default_compile
def default_compile mid = mid_to_jsid meth.to_s splat = arglist[1..-1].any? { |a| a.first == :splat } if Sexp === arglist.last and arglist.last.type == :block_pass block = arglist.pop elsif iter block = iter end blktmp = scope.new_temp if block tmprecv = scope.new_temp if splat || blktmp # must do this after assigning temp variables block = expr(block) if block recv_code = recv(recv_sexp) call_recv = s(:js_tmp, tmprecv || recv_code) if blktmp and !splat arglist.insert 1, call_recv end args = expr(arglist) if tmprecv push "(#{tmprecv} = ", recv_code, ")#{mid}" else push recv_code, mid end if blktmp unshift "(#{blktmp} = " push ", #{blktmp}.$$p = ", block, ", #{blktmp})" end if splat push ".apply(", (tmprecv || recv_code), ", ", args, ")" elsif blktmp push ".call(", args, ")" else push "(", args, ")" end scope.queue_temp blktmp if blktmp end
def handle_special
this method. If this method returns nil, then the method will continue
Handle "special" method calls, e.g. require(). Subclasses can override
def handle_special @compile_default = true if SPECIALS.include? meth @compile_default = false __send__("handle_#{meth}") elsif RuntimeHelpers.compatible?(recvr, meth, arglist) @compile_default = false push(RuntimeHelpers.new(@sexp, @level, @compiler).compile) end end
def record_method?
def record_method? true end
def recv_sexp
def recv_sexp recvr || s(:self) end
def using_irb?
a variable reference in irb mode in top scope might be a var ref,
def using_irb? @compiler.irb? and scope.top? and arglist == s(:arglist) and recvr.nil? and iter.nil? end