Class: SystemNavigation::InstructionStream::Decoder

Inherits:
Object
  • Object
show all
Defined in:
lib/system_navigation/instruction_stream/decoder.rb

Instance Method Summary collapse

Constructor Details

#initialize(scanner) ⇒ Decoder

Returns a new instance of Decoder.



4
5
6
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 4

def initialize(scanner)
  @scanner = scanner
end

Instance Method Details

#ivar_read_scan(ivar) ⇒ Object



25
26
27
28
29
30
31
32
33
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 25

def ivar_read_scan(ivar)
  self.select_instructions(literal: ivar) do |_prev_prev, prev, instruction|
    next instruction if instruction.reads_ivar?(ivar)

    if instruction.dynamically_reads_ivar? && prev.putobjects?(ivar)
      next instruction
    end
  end
end

#ivar_write_scan(ivar) ⇒ Object



35
36
37
38
39
40
41
42
43
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 35

def ivar_write_scan(ivar)
  self.select_instructions(literal: ivar) do |prev_prev, prev, instruction|
    next instruction if instruction.writes_ivar?(ivar)

    if instruction.dynamically_writes_ivar? && prev_prev.putobjects?(ivar)
      next instruction
    end
  end
end

#literal_scan(literal) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 45

def literal_scan(literal)
  name = @scanner.method.original_name

  self.select_instructions(method_name: name, literal: literal) do |_prev_prev, prev, instruction|
    if instruction.putobjects?(literal) ||
       instruction.putnils?(literal) ||
       instruction.duparrays?(literal) ||
       instruction.putstrings?(literal)
      next instruction
    end
  end
end

#msg_send_scan(message) ⇒ Object



58
59
60
61
62
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 58

def msg_send_scan(message)
  self.select_instructions(literal: message) do |_prev_prev, prev, instruction|
    next instruction if instruction.sends_msg?(message)
  end
end

#scan_for_sent_messagesObject



64
65
66
67
68
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 64

def scan_for_sent_messages
  @scanner.iseqs(nil).map do |instruction|
    instruction.find_message
  end.compact
end

#select_instructions(literal:, method_name: nil, &block) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 8

def select_instructions(literal:, method_name: nil, &block)
  instructions = @scanner.iseqs(method_name || literal)

  instructions.select.with_index do |instruction, i|
    prev = instructions[i - 1]
    prev_prev = instructions[i - 2]

    returned = block.call(prev_prev, prev, instruction)
    next instruction if returned

    next if !(instruction.evals? && prev.putstrings?(literal))

    self.class.new(iseq_from_eval(prev, @scanner.method)).
      __send__(block.binding.eval('__method__'), literal).any?
  end
end