class SyntaxTree::YARV::Disassembler

Attributes

current_iseq[RW]
current_prefix[R]
output[R]
queue[R]

Public Class Methods

new(current_iseq = nil) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 46
def initialize(current_iseq = nil)
  @output = StringIO.new
  @queue = []

  @current_prefix = ""
  @current_iseq = current_iseq
end

Public Instance Methods

calldata(value) click to toggle source

Helpers for various instructions

# File lib/syntax_tree/yarv/disassembler.rb, line 58
def calldata(value)
  value.inspect
end
enqueue(iseq) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 62
def enqueue(iseq)
  queue << iseq
end
event(name) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 66
def event(name)
  case name
  when :RUBY_EVENT_B_CALL
    "Bc"
  when :RUBY_EVENT_B_RETURN
    "Br"
  when :RUBY_EVENT_CALL
    "Ca"
  when :RUBY_EVENT_CLASS
    "Cl"
  when :RUBY_EVENT_END
    "En"
  when :RUBY_EVENT_LINE
    "Li"
  when :RUBY_EVENT_RETURN
    "Re"
  else
    raise "Unknown event: #{name}"
  end
end
format!() click to toggle source

Entrypoints

# File lib/syntax_tree/yarv/disassembler.rb, line 116
def format!
  while (@current_iseq = queue.shift)
    output << "\n" if output.pos > 0
    format_iseq(@current_iseq)
  end
end
format_insns!(insns, length = 0) { |insn, length| ... } click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 123
def format_insns!(insns, length = 0)
  events = []
  lines = []

  insns.each do |insn|
    case insn
    when Integer
      lines << insn
    when Symbol
      events << event(insn)
    when InstructionSequence::Label
      # skip
    else
      output << "#{current_prefix}%04d " % length

      disasm = insn.disasm(self)
      output << disasm

      if lines.any?
        output << " " * (65 - disasm.length) if disasm.length < 65
      elsif events.any?
        output << " " * (39 - disasm.length) if disasm.length < 39
      end

      if lines.any?
        output << "(%4d)" % lines.last
        lines.clear
      end

      if events.any?
        output << "[#{events.join}]"
        events.clear
      end

      # A hook here to allow for custom formatting of instructions after
      # the main body has been processed.
      yield insn, length if block_given?

      output << "\n"
      length += insn.length
    end
  end
end
inline_storage(cache) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 87
def inline_storage(cache)
  "<is:#{cache}>"
end
instruction(name, operands = []) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 91
def instruction(name, operands = [])
  operands.empty? ? name : "%-38s %s" % [name, operands.join(", ")]
end
label(value) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 95
def label(value)
  value.name["label_".length..]
end
local(index, explicit: nil, implicit: nil) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 99
def local(index, explicit: nil, implicit: nil)
  current = current_iseq
  (explicit || implicit).times { current = current.parent_iseq }

  value = "#{current.local_table.name_at(index)}@#{index}"
  value << ", #{explicit}" if explicit
  value
end
object(value) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 108
def object(value)
  value.inspect
end
print(string) click to toggle source
puts(string) click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 171
def puts(string)
  output.puts(string)
end
string() click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 175
def string
  output.string
end
with_prefix(value) { |value| ... } click to toggle source
# File lib/syntax_tree/yarv/disassembler.rb, line 179
def with_prefix(value)
  previous = @current_prefix

  begin
    @current_prefix = value
    yield value
  ensure
    @current_prefix = previous
  end
end