class CodeTools::AST::Iter

Attributes

arguments[RW]
body[RW]
parent[RW]

Public Class Methods

new(line, arguments, body) click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 572
def initialize(line, arguments, body)
  @line = line
  @arguments = arguments || Parameters.new(line)
  @body = body || NilLiteral.new(line)

  if @body.kind_of?(Block) and @body.locals
    @locals = @body.locals.body.map { |x| x.value }
  else
    @locals = nil
  end
end

Public Instance Methods

assign_local_reference(var) click to toggle source

If the local variable exists in this scope, set the local variable node attribute to a reference to the local variable. If the variable exists in an enclosing scope, set the local variable node attribute to a nested reference to the local variable. Otherwise, create a local variable in this scope and set the local variable node attribute.

# File lib/rubinius/code/ast/sends.rb, line 630
def assign_local_reference(var)
  if variable = variables[var.name]
    var.variable = variable.reference
  elsif block_local?(var.name) || var.placeholder? || block_parameter?(var.name)
    variable = new_local var.name
    var.variable = variable.reference
  elsif reference = @parent.search_local(var.name)
    reference.depth += 1
    var.variable = reference
  else
    variable = new_local var.name
    var.variable = variable.reference
  end
end
block_local?(name) click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 584
def block_local?(name)
  @locals.include?(name) if @locals
end
block_parameter?(name) click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 588
def block_parameter?(name)
  @arguments.block_arg.name == name if @arguments.block_arg
end
bytecode(g) click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 645
def bytecode(g)
  pos(g)

  state = g.state
  state.scope.nest_scope self

  blk = new_block_generator g, @arguments

  blk.push_state self
  blk.definition_line @line
  blk.state.push_super state.super
  blk.state.push_eval state.eval

  blk.state.push_name blk.name

  # Push line info down.
  pos(blk)

  @arguments.bytecode(blk)

  blk.state.push_block
  blk.push_modifiers
  blk.break = nil
  blk.next = nil
  blk.redo = blk.new_label
  blk.redo.set!

  @body.bytecode(blk)

  blk.pop_modifiers
  blk.state.pop_block
  blk.ret
  blk.close
  blk.pop_state

  blk.splat_index = @arguments.splat_index
  blk.kwrest_index = @arguments.kwrest_index
  blk.local_count = local_count
  blk.local_names = local_names

  g.create_block blk
end
module?() click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 592
def module?
  false
end
nest_scope(scope) click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 596
def nest_scope(scope)
  scope.parent = self
end
new_local(name) click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 617
def new_local(name)
  variables[name] ||= Compiler::LocalVariable.new allocate_slot
end
new_nested_local(name) click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 621
def new_nested_local(name)
  new_local(name).nested_reference
end
search_local(name) click to toggle source

A nested scope is looking up a local variable. If the variable exists in our local variables hash, return a nested reference to it. If it exists in an enclosing scope, increment the depth of the reference when it passes through this nested scope (i.e. the depth of a reference is a function of the nested scopes it passes through from the scope it is defined in to the scope it is used in).

# File lib/rubinius/code/ast/sends.rb, line 606
def search_local(name)
  if variable = variables[name]
    variable.nested_reference
  elsif block_local?(name)
    new_nested_local name
  elsif reference = @parent.search_local(name)
    reference.depth += 1
    reference
  end
end
sexp_name() click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 688
def sexp_name
  :iter
end
to_sexp() click to toggle source
# File lib/rubinius/code/ast/sends.rb, line 692
def to_sexp
  body_sexp = @body.to_sexp
  if @locals
    body_sexp[1] = @locals.map { |x| [:lvar, x] }
  end
  [sexp_name, @arguments.to_sexp, body_sexp]
end