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.



516
517
518
519
520
521
522
523
524
525
526
# File 'lib/rubinius/code/ast/sends.rb', line 516

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.



514
515
516
# File 'lib/rubinius/code/ast/sends.rb', line 514

def arguments
  @arguments
end

#bodyObject

Returns the value of attribute body.



514
515
516
# File 'lib/rubinius/code/ast/sends.rb', line 514

def body
  @body
end

#parentObject

Returns the value of attribute parent.



514
515
516
# File 'lib/rubinius/code/ast/sends.rb', line 514

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.



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

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)


528
529
530
# File 'lib/rubinius/code/ast/sends.rb', line 528

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

#block_parameter?(name) ⇒ Boolean

Returns:

  • (Boolean)


532
533
534
# File 'lib/rubinius/code/ast/sends.rb', line 532

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

#bytecode(g) ⇒ Object



589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
# File 'lib/rubinius/code/ast/sends.rb', line 589

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)


536
537
538
# File 'lib/rubinius/code/ast/sends.rb', line 536

def module?
  false
end

#nest_scope(scope) ⇒ Object



540
541
542
# File 'lib/rubinius/code/ast/sends.rb', line 540

def nest_scope(scope)
  scope.parent = self
end

#new_local(name) ⇒ Object



561
562
563
# File 'lib/rubinius/code/ast/sends.rb', line 561

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

#new_nested_local(name) ⇒ Object



565
566
567
# File 'lib/rubinius/code/ast/sends.rb', line 565

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



550
551
552
553
554
555
556
557
558
559
# File 'lib/rubinius/code/ast/sends.rb', line 550

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



632
633
634
# File 'lib/rubinius/code/ast/sends.rb', line 632

def sexp_name
  :iter
end

#to_sexpObject



636
637
638
639
640
641
642
# File 'lib/rubinius/code/ast/sends.rb', line 636

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