Class: SystemNavigation::InstructionStream::Decoder

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

Overview

Since:

  • 0.1.0

Instance Method Summary collapse

Constructor Details

#initialize(scanner) ⇒ Decoder

Returns a new instance of Decoder.

Since:

  • 0.1.0



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

def initialize(scanner)
  @scanner = scanner
end

Instance Method Details

#cvar_read_scan(cvar) ⇒ Object

Since:

  • 0.1.0



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

def cvar_read_scan(cvar)
  self.select_instructions(literal: cvar) do |_prev_prev, prev, instruction|
    next instruction if instruction.reads_cvar?(cvar)
  end
end

#cvar_write_scan(cvar) ⇒ Object

Since:

  • 0.1.0



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

def cvar_write_scan(cvar)
  self.select_instructions(literal: cvar) do |prev_prev, prev, instruction|
    next instruction if instruction.writes_cvar?(cvar)
  end
end

#gvar_read_scan(gvar) ⇒ Object

Since:

  • 0.1.0



45
46
47
48
49
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 45

def gvar_read_scan(gvar)
  self.select_instructions(literal: gvar) do |_prev_prev, prev, instruction|
    next instruction if instruction.reads_gvar?(gvar)
  end
end

#gvar_write_scan(gvar) ⇒ Object

Since:

  • 0.1.0



51
52
53
54
55
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 51

def gvar_write_scan(gvar)
  self.select_instructions(literal: gvar) do |prev_prev, prev, instruction|
    next instruction if instruction.writes_gvar?(gvar)
  end
end

#ivar_read_scan(ivar) ⇒ Object

Since:

  • 0.1.0



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

Since:

  • 0.1.0



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

Since:

  • 0.1.0



69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 69

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

Since:

  • 0.1.0



82
83
84
85
86
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 82

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

Since:

  • 0.1.0



88
89
90
91
92
# File 'lib/system_navigation/instruction_stream/decoder.rb', line 88

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

Since:

  • 0.1.0



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