class CodeTools::AST::RescueCondition

Attributes

assignment[RW]
body[RW]
conditions[RW]
next[RW]
splat[RW]

Public Class Methods

new(line, conditions, body, nxt) click to toggle source
# File lib/rubinius/code/ast/exceptions.rb, line 372
def initialize(line, conditions, body, nxt)
  @line = line
  @next = nxt
  @splat = nil
  @assignment = nil
  @conditions = nil

  case conditions
  when ArrayLiteral
    @conditions = conditions
  when ConcatArgs
    @conditions = conditions.array
    @splat = RescueSplat.new line, conditions.rest
  when SplatValue
    @splat = RescueSplat.new line, conditions.value
  when nil
    condition = ConstantAccess.new line, :StandardError, true
    @conditions = ArrayLiteral.new line, [condition]
  end

  case body
  when Block
    @assignment = body.array.shift if assignment? body.array.first
    @body = body.array.size == 1 ? body.array.first : body
  when nil
    @body = NilLiteral.new line
  else
    if assignment? body
      @assignment = body
      @body = NilLiteral.new line
    else
      @body = body
    end
  end
end

Public Instance Methods

assignment?(node) click to toggle source
# File lib/rubinius/code/ast/exceptions.rb, line 408
def assignment?(node)
  case node
  when VariableAssignment
    value = node.value
  when AttributeAssignment
    value = node.arguments.array.last
  else
    return false
  end

  return true if value.kind_of? CurrentException
end
bytecode(g, reraise, done, outer_exc_state) click to toggle source
# File lib/rubinius/code/ast/exceptions.rb, line 421
def bytecode(g, reraise, done, outer_exc_state)
  pos(g)
  body = g.new_label

  # Exception has left the current exception on the top
  # of the stack, use it rather than using push_current_exception.

  if @conditions
    @conditions.body.each do |c|
      g.dup
      c.bytecode(g)
      g.swap
      g.send :===, 1
      g.goto_if_true body
    end
  end

  @splat.bytecode(g, body) if @splat

  if @next
    if_false = g.new_label
    g.goto if_false
  else
    g.goto reraise
  end

  body.set!

  # Remove the current exception from the top of the stack now
  # that we've hit a handler
  g.pop

  if @assignment
    @assignment.bytecode(g)
    g.pop
  end

  current_break = g.break
  g.break = g.new_label

  current_next = g.next
  g.next = g.new_label

  g.state.push_rescue(outer_exc_state)
  @body.bytecode(g)
  g.state.pop_rescue

  g.clear_exception
  g.goto done

  if g.break.used?
    g.break.set!
    g.clear_exception

    # Reset the outer exception
    g.push_stack_local outer_exc_state
    g.restore_exception_state

    if current_break
      g.goto current_break
    else
      g.raise_break
    end
  end

  g.break = current_break

  if g.next.used?
    g.next.set!

    g.clear_exception

    # Reset the outer exception
    g.push_stack_local outer_exc_state
    g.restore_exception_state

    if current_next
      g.goto current_next
    else
      g.ret
    end
  end

  g.next = current_next

  if @next
    if_false.set!
    @next.bytecode(g, reraise, done, outer_exc_state)
  end
end
to_sexp() click to toggle source
# File lib/rubinius/code/ast/exceptions.rb, line 512
def to_sexp
  sexp = [:resbody]

  if @conditions
    array = @conditions.to_sexp
    sexp << array
  else
    array = sexp
  end

  array << @splat.to_sexp if @splat
  array << @assignment.to_sexp if @assignment

  case @body
  when Block
    sexp << (@body ? @body.array.map { |x| x.to_sexp } : nil)
  when nil
    sexp << nil
  else
    sexp << @body.to_sexp
  end

  sexp << @next.to_sexp if @next

  sexp
end