class CodeTools::AST::OpAssignAttribute

Attributes

assign[RW]
name[RW]
op[RW]
receiver[RW]
value[RW]

Public Class Methods

new(line, receiver, name, op, value) click to toggle source
# File lib/rubinius/code/ast/operators.rb, line 283
def initialize(line, receiver, name, op, value)
  @line = line
  @receiver = receiver
  @name = name
  @op = op
  @value = value
  @assign = name.to_s[-1] == ?= ? name : :"#{name}="
end

Public Instance Methods

bytecode(g, anddot=false) click to toggle source
# File lib/rubinius/code/ast/operators.rb, line 292
def bytecode(g, anddot=false)
  pos(g)

  # X: h.a += 3, given h.a == 2
  @receiver.bytecode(g) unless anddot
  # X: TOS = h
  g.dup
  g.send @name, 0
  # X: TOS = 2

  if @op == :or or @op == :and
    fnd = g.new_label
    fin = g.new_label
    assign = g.new_label

    g.dup
    if @op == :or
      g.goto_if_true fnd
    else
      g.goto_if_false fnd
    end

    # Remove the copy of 2 and push @value on the stack
    g.pop

    old_break = g.break
    new_break = g.new_label
    g.break = new_break

    @value.bytecode(g)

    g.goto assign

    new_break.set!
    if old_break
      g.pop_many 2
      g.push_tagged_nil 0
      g.goto old_break
    end

    g.break = old_break

    assign.set!

    # Retain the this value to use as the expression value
    g.dup
    g.move_down 2

    # Call the assignement method, passing @value as the argument
    g.send @assign, 1
    g.pop

    g.goto fin

    fnd.set!

    # Clean up the stack
    g.swap
    g.pop

    fin.set!
  else
    assign = g.new_label

    old_break = g.break
    new_break = g.new_label
    g.break = new_break

    @value.bytecode(g)

    g.goto assign

    new_break.set!
    if old_break
      g.pop_many 3
      g.push_tagged_nil 0
      g.goto old_break
    end

    g.break = old_break

    assign.set!

    # X: TOS = 3
    # X: 2 + 3
    g.send @op, 1

    # Retain the this value to use as the expression value
    g.dup
    g.move_down 2
    # X: TOS = 5
    g.send @assign, 1
    # X: TOS = 5 (or whatever a=() returns)

    # Discard the methods return value
    g.pop
  end
end
sexp_name() click to toggle source
# File lib/rubinius/code/ast/operators.rb, line 391
def sexp_name
  :op_asgn2
end
to_sexp() click to toggle source
# File lib/rubinius/code/ast/operators.rb, line 395
def to_sexp
  case @op
  when :or
    op = :"||"
  when :and
    op = :"&&"
  else
    op = @op
  end
  [sexp_name, @receiver.to_sexp, :"#{@name}=", op, @value.to_sexp]
end