Class: SystemNavigation::InstructionStream::Instruction

Inherits:
Object
  • Object
show all
Defined in:
lib/system_navigation/instruction_stream/instruction.rb,
lib/system_navigation/instruction_stream/instruction/attr_instruction.rb

Direct Known Subclasses

AttrInstruction

Defined Under Namespace

Classes: AttrInstruction, AttrReaderInstruction, AttrWriterInstruction

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(str) ⇒ Instruction

Returns a new instance of Instruction.



8
9
10
11
12
13
14
15
16
17
18
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 8

def initialize(str)
  @raw = StringScanner.new(str)
  @pos = nil
  @opcode = ''
  @operand = nil
  @evaling_str = nil
  @lineno = nil
  @op_id = nil
  @ivar = nil
  @service_instruction = false
end

Class Method Details

.parse(str) ⇒ Object



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

def self.parse(str)
  self.new(str).parse
end

Instance Method Details

#accessing_ivar?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 94

def accessing_ivar?
  @opcode == 'getinstancevariable' || @opcode == 'setinstancevariable'
end

#duparrays?(str) ⇒ Boolean

Returns:

  • (Boolean)


151
152
153
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 151

def duparrays?(str)
  !!(@opcode == 'duparray' && @operand.match(/:#{str}[,\]]/))
end

#dynamically_reads_ivar?Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 110

def dynamically_reads_ivar?
  @op_id == 'instance_variable_get'
end

#dynamically_writes_ivar?Boolean

Returns:

  • (Boolean)


114
115
116
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 114

def dynamically_writes_ivar?
  @op_id == 'instance_variable_set'
end

#evaling_strObject



163
164
165
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 163

def evaling_str
  @evaling_str ||= @operand.sub!(/\A"(.+)"/, '\1')
end

#evals?Boolean

Returns:

  • (Boolean)


118
119
120
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 118

def evals?
  @op_id == 'eval'
end

#find_messageObject



167
168
169
170
171
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 167

def find_message
  return unless sending?

  @op_id
end

#operandObject



159
160
161
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 159

def operand
  @operand
end

#parseObject



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 20

def parse
  return if parse_service_instruction

  parse_position
  parse_opcode
  parse_operand
  parse_lineno
  parse_op_id
  parse_ivar

  self
end

#parse_ivarObject



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

def parse_ivar
  return unless accessing_ivar?

  ivar = StringScanner.new(@operand)
  @ivar = ivar.scan(/:[^,]+/)[1..-1].to_sym
  ivar.terminate
end

#parse_linenoObject



71
72
73
74
75
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 71

def parse_lineno
  n = @raw.scan(/[0-9]+/)
  @lineno = n.to_i if n
  @raw.skip(/\)/)
end

#parse_op_idObject



77
78
79
80
81
82
83
84
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 77

def parse_op_id
  return unless sending?

  callinfo = StringScanner.new(@operand)
  callinfo.skip(/<callinfo!mid:/)
  @op_id = callinfo.scan(/\S+(?=,)/)
  callinfo.terminate
end

#parse_opcodeObject



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

def parse_opcode
  @opcode = @raw.scan(/[a-zA-Z0-9_]+/)
  @raw.skip(/\s*/)
end

#parse_operandObject



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 50

def parse_operand
  if @raw.check(/</)
    @operand = @raw.scan(/<.+>/)
  elsif @raw.check(/\[/)
    @operand = @raw.scan(/\[.*\]/)
  elsif @raw.check(/"/)
    @operand = @raw.scan(/".*"/)
  elsif @raw.check(%r{/})
    @operand = @raw.scan(%r{/.*/})
  else
    @operand = @raw.scan(/-?[0-9a-zA-Z:@_=.]+/)

    if @raw.peek(1) == ','
      @operand << @raw.scan(/[^\(]*/).rstrip
    end
  end

  @raw.skip(/\s*\(?/)
  @raw.skip(/\s*/)
end

#parse_positionObject



39
40
41
42
43
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 39

def parse_position
  n = @raw.scan(/[0-9]{4,6}/)
  @pos = n.to_i if n
  @raw.skip(/\s*/)
end

#parse_service_instructionObject



33
34
35
36
37
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 33

def parse_service_instruction
  if @raw.peek(2) == '==' || @raw.peek(6) !~ /[0-9]{4,6} /
    @service_instruction = true
  end
end

#putnils?(str) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
149
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 146

def putnils?(str)
  return false unless @opcode == 'putnil'
  @operand == str.inspect
end

#putobjects?(str) ⇒ Boolean

Returns:

  • (Boolean)


137
138
139
140
141
142
143
144
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 137

def putobjects?(str)
  return false unless @opcode == 'putobject'

  return true if @operand.match(/(?::#{str}\z|\[.*:#{str},.*\])/)
  return true if @operand == str.inspect

  false
end

#putstrings?(str) ⇒ Boolean

Returns:

  • (Boolean)


122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 122

def putstrings?(str)
  return false unless @opcode == 'putstring'

  s = str.inspect

  return true if @operand == s || @operand == %|"#{s}"|
  if @operand.match(/(eval\()?.*:?#{str}[^[\w;]].*\)?/)
    return true
  else

  end

  false
end

#reads_ivar?(ivar) ⇒ Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 102

def reads_ivar?(ivar)
  @opcode == 'getinstancevariable' && @ivar == ivar
end

#sends_msg?(message) ⇒ Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 155

def sends_msg?(message)
  !!(sending? && @op_id == message.to_s)
end

#vm_operative?Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 98

def vm_operative?
  @service_instruction == false
end

#writes_ivar?(ivar) ⇒ Boolean

Returns:

  • (Boolean)


106
107
108
# File 'lib/system_navigation/instruction_stream/instruction.rb', line 106

def writes_ivar?(ivar)
  @opcode == 'setinstancevariable' && @ivar == ivar
end