Class: CodeTools::AST::Iter

Inherits:
Node
  • Object
show all
Includes:
Compiler::LocalVariables
Defined in:
lib/rubinius/code/ast/sends.rb

Direct Known Subclasses

For

Instance Attribute Summary collapse

Attributes inherited from Node

#line

Instance Method Summary collapse

Methods inherited from Node

#ascii_graph, #attributes, #children, #defined, match_arguments?, match_send?, #new_block_generator, #new_generator, #node_name, #or_bytecode, #pos, #set_child, #transform, transform, transform_comment, transform_kind, transform_kind=, transform_name, #value_defined, #visit, #walk

Constructor Details

#initialize(line, arguments, body) ⇒ Iter

Returns a new instance of Iter.



573
574
575
576
577
578
579
580
581
582
583
# File 'lib/rubinius/code/ast/sends.rb', line 573

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

Instance Attribute Details

#argumentsObject

Returns the value of attribute arguments.



571
572
573
# File 'lib/rubinius/code/ast/sends.rb', line 571

def arguments
  @arguments
end

#bodyObject

Returns the value of attribute body.



571
572
573
# File 'lib/rubinius/code/ast/sends.rb', line 571

def body
  @body
end

#parentObject

Returns the value of attribute parent.



571
572
573
# File 'lib/rubinius/code/ast/sends.rb', line 571

def parent
  @parent
end

Instance Method Details

#assign_local_reference(var) ⇒ Object

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.



631
632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'lib/rubinius/code/ast/sends.rb', line 631

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) ⇒ Boolean

Returns:

  • (Boolean)


585
586
587
# File 'lib/rubinius/code/ast/sends.rb', line 585

def block_local?(name)
  @locals.include?(name) if @locals
end

#block_parameter?(name) ⇒ Boolean

Returns:

  • (Boolean)


589
590
591
# File 'lib/rubinius/code/ast/sends.rb', line 589

def block_parameter?(name)
  @arguments.block_arg.name == name if @arguments.block_arg
end

#bytecode(g) ⇒ Object



646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
# File 'lib/rubinius/code/ast/sends.rb', line 646

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?Boolean

Returns:

  • (Boolean)


593
594
595
# File 'lib/rubinius/code/ast/sends.rb', line 593

def module?
  false
end

#nest_scope(scope) ⇒ Object



597
598
599
# File 'lib/rubinius/code/ast/sends.rb', line 597

def nest_scope(scope)
  scope.parent = self
end

#new_local(name) ⇒ Object



618
619
620
# File 'lib/rubinius/code/ast/sends.rb', line 618

def new_local(name)
  variables[name] ||= Compiler::LocalVariable.new allocate_slot
end

#new_nested_local(name) ⇒ Object



622
623
624
# File 'lib/rubinius/code/ast/sends.rb', line 622

def new_nested_local(name)
  new_local(name).nested_reference
end

#search_local(name) ⇒ Object

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).



607
608
609
610
611
612
613
614
615
616
# File 'lib/rubinius/code/ast/sends.rb', line 607

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_nameObject



689
690
691
# File 'lib/rubinius/code/ast/sends.rb', line 689

def sexp_name
  :iter
end

#to_sexpObject



693
694
695
696
697
698
699
# File 'lib/rubinius/code/ast/sends.rb', line 693

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