class Opal::Nodes::PostArgsNode


4. list of required args (for both mlhs/post-args, can be blank)
3. restarg (for both mlhs/post-args, can be nil)
2. list of optargs (only for post-args, can be blank)
1. list of required arguments (only for mlhs, can be blank)
3. post_args here always have the same structure:
These statements simplify everything, keep them in mind.
3. splat/rest argument (restarg)
2. optional argument (optarg)
1. required arg (norm arg, mlhs arg)
c) precedence order:
b) optional args always appear in the sequence (i.e. you can’t have def m(a=1,b,c=1))
a) optional arg always goes BEFORE the rest arg
2. Super important:
b. JS arguments length < args sexp length - then our splat is blank
and we know how many of them should come to splat
a. JS arguments length > args sexp length - then our splat has some items
In this case if:
1. There can be some arguments after the splat, this is why this node exist.
Node responsible for extracting post-splat args

def compile

def compile
  return if children.empty?
  old_working_arguments = scope.working_arguments
  if @sexp.meta[:js_source]
    js_source = @sexp.meta[:js_source]
    scope.working_arguments = "#{js_source}_args"
  else
    js_source = "arguments"
    scope.working_arguments = "$post_args"
  end
  add_temp "#{scope.working_arguments}"
  line "#{scope.working_arguments} = Opal.slice.call(#{js_source}, #{scope.inline_args.size}, #{js_source}.length);"
  extract_arguments
  push process(kwargs_sexp)
  required_left_args.each do |arg|
    compile_required_arg(arg)
  end
  optargs.each do |optarg|
    compile_optarg(optarg)
  end
  compile_restarg
  required_right_args.each do |arg|
    compile_required_arg(arg)
  end
  scope.working_arguments = old_working_arguments
end

def compile_optarg(optarg)

def compile_optarg(optarg)
  var_name, _ = *optarg
  add_temp var_name
  line "if (#{required_right_args.size} < #{scope.working_arguments}.length) {"
  indent do
    line "#{var_name} = #{scope.working_arguments}.splice(0,1)[0];"
  end
  line "}"
  push process(optarg)
end

def compile_required_arg(arg)

def compile_required_arg(arg)
  push process(arg)
end

def compile_restarg

def compile_restarg
  return unless restarg
  line "if (#{required_right_args.size} < #{scope.working_arguments}.length) {"
    indent do
      # there are some items coming to the splat, extracting them
      extract_restarg
    end
  line "} else {"
    indent do
      # splat is empty
      extract_blank_restarg
    end
  line "}"
end

def extract_arguments

def extract_arguments
  found_opt_or_rest = false
  children.each do |arg|
    arg.meta[:post] = true
    case arg.type
    when :kwarg, :kwoptarg, :kwrestarg
      @kwargs << arg
    when :restarg
      @restarg = arg
      found_opt_or_rest = true
    when :optarg
      @optargs << arg
      found_opt_or_rest = true
    when :arg, :mlhs
      if found_opt_or_rest
        @required_right_args << arg
      else
        @required_left_args << arg
      end
    end
  end
end

def extract_blank_restarg

def extract_blank_restarg
  var_name, _ = *restarg
  if var_name
    add_temp var_name
    line "#{var_name} = [];"
  end
end

def extract_restarg

def extract_restarg
  extract_code = "#{scope.working_arguments}.splice(0, #{scope.working_arguments}.length - #{required_right_args.size});"
  var_name, _ = *restarg
  if var_name
    add_temp var_name
    line "#{var_name} = #{extract_code}"
  else
    line extract_code
  end
end

def initialize(*)

def initialize(*)
  super
  @kwargs = []
  @required_left_args = []
  @optargs = []
  @restarg = nil
  @required_right_args = []
end

def kwargs_sexp

def kwargs_sexp
  s(:post_kwargs, *kwargs)
end