class CodeTools::AST::KeywordParameters

Attributes

arguments[RW]
defaults[RW]
kwrest[RW]
names[RW]
value[RW]

Public Class Methods

new(line, block, kwrest) click to toggle source
# File lib/rubinius/code/ast/definitions.rb, line 632
def initialize(line, block, kwrest)
  @line = line
  @kwrest = kwrest
  @required = []
  @defaults = []

  if block
    array = block.array
    @names = array.map { |a| a.name }

    array.each do |arg|
      if arg.value.kind_of?(SymbolLiteral) and arg.value.value == :*
        @required << arg
      else
        @defaults << arg
      end
    end

    @arguments = array
  else
    @arguments = []
    @names = []
  end

  if kwrest
    if kwrest.to_s.start_with?("_:")
      kwrest_name = :**
    else
      kwrest_name = :"**#{kwrest}"
    end

    @kwrest = LocalVariableAssignment.new line, kwrest
  end

  @names << kwrest_name if kwrest_name
end

Public Instance Methods

bytecode(g) click to toggle source
# File lib/rubinius/code/ast/definitions.rb, line 686
def bytecode(g)
  done = g.new_label
  assignments = g.new_label
  missing_value = g.new_label

  @value.bytecode(g)

  g.dup
  g.goto_if_not_nil assignments

  g.pop
  g.push_cpath_top
  g.find_const :Hash
  g.send :allocate, 0, true

  assignments.set!

  @required.each do |arg|
    g.dup
    g.push_literal arg.name
    g.send :find_item, 1, true

    g.dup
    g.goto_if_false missing_value

    g.send :value, 0, true

    arg.variable.set_bytecode(g)
    g.pop
  end

  defaults = g.new_label
  g.goto defaults

  missing_value.set!
  g.pop
  g.push_rubinius
  g.find_const :Runtime
  g.swap
  g.send :keywords_missing, 1, true
  g.goto done

  defaults.set!

  extra_keys = g.new_label

  if @defaults.empty?
    g.dup
    g.send :size, 0, true
    g.push_int @arguments.size
    g.goto_if_not_equal extra_keys

    if @kwrest
      g.push_cpath_top
      g.find_const :Hash
      g.send :allocate, 0, true
      @kwrest.variable.set_bytecode(g)
      g.pop
    end

    g.goto done
  else
    @defaults.each do |arg|
      next_value = g.new_label
      default_value = g.new_label

      g.dup
      g.push_literal arg.name
      g.send :find_item, 1, true

      g.dup
      g.goto_if_false default_value

      g.send :value, 0, true
      arg.variable.set_bytecode(g)
      g.goto next_value

      default_value.set!
      g.pop
      arg.bytecode(g)

      next_value.set!
      g.pop
    end
  end

  extra_keys.set!

  g.dup
  g.push_rubinius
  g.find_const :Runtime
  g.swap

  if @kwrest
    g.push_true
  else
    g.push_false
  end

  g.send :keywords_extra, 2, true
  @kwrest.variable.set_bytecode(g) if @kwrest
  g.pop

  done.set!
end
entries() click to toggle source
# File lib/rubinius/code/ast/definitions.rb, line 673
def entries
  entries = []
  @required.each { |arg| entries << arg.name << true }
  @defaults.each { |arg| entries << arg.name << false }
  entries
end
map_arguments(scope) click to toggle source
# File lib/rubinius/code/ast/definitions.rb, line 680
def map_arguments(scope)
  @arguments.each { |var| scope.assign_local_reference var }

  scope.assign_local_reference @kwrest if @kwrest
end
required?() click to toggle source
# File lib/rubinius/code/ast/definitions.rb, line 669
def required?
  not @required.empty?
end
to_sexp() click to toggle source
# File lib/rubinius/code/ast/definitions.rb, line 792
def to_sexp
  sexp = [:kwargs]
  sexp << @names unless @names.empty?
  sexp << @defaults.map { |x| x.to_sexp } unless @defaults.empty?
  sexp
end