Class: Stupidedi::Parser::InstructionTable::NonEmpty

Inherits:
Stupidedi::Parser::InstructionTable show all
Defined in:
lib/stupidedi/parser/instruction_table.rb

Constant Summary

Constants inherited from Stupidedi::Parser::InstructionTable

Empty

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Stupidedi::Parser::InstructionTable

build, empty

Methods included from Inspect

#inspect

Constructor Details

#initialize(instructions, pop) ⇒ NonEmpty

Returns a new instance of NonEmpty.



15
16
17
18
19
20
# File 'lib/stupidedi/parser/instruction_table.rb', line 15

def initialize(instructions, pop)
  @instructions, @pop = instructions.freeze, pop

  @__push = Hash.new
  @__drop = Hash.new
end

Instance Attribute Details

#instructionsArray<Instruction> (readonly)

Returns:



11
12
13
# File 'lib/stupidedi/parser/instruction_table.rb', line 11

def instructions
  @instructions
end

Instance Method Details

#at(segment_use) ⇒ Instruction

Returns:



34
35
36
# File 'lib/stupidedi/parser/instruction_table.rb', line 34

def at(segment_use)
  @instructions.find{|op| op.segment_use.eql?(segment_use) }
end

#constraints



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/stupidedi/parser/instruction_table.rb', line 58

def constraints
  @__constraints ||= begin
    constraints = Hash.new

    # Group instructions by segment identifier
    grouped = Hash.new{|h,k| h[k] = [] }
    @instructions.each{|op| grouped[op.segment_id] << op }

    # For each group of instructions that have the same segment
    # id, build a constraint table that can distinguish them
    grouped.each do |segment_id, instructions|
      constraints[segment_id] = ConstraintTable.build(instructions)
    end

    constraints
  end
end

#copy(changes = {}) ⇒ InstructionTable

Returns:



27
28
29
30
31
# File 'lib/stupidedi/parser/instruction_table.rb', line 27

def copy(changes = {})
  NonEmpty.new \
    changes.fetch(:instructions, @instructions),
    changes.fetch(:pop, @pop)
end

#drop(count) ⇒ InstructionTable

Returns:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/stupidedi/parser/instruction_table.rb', line 86

def drop(count)
  if count.zero?
    self
  else
    @__drop[count] ||= begin
      # Calculate the fewest number of instructions we can drop. We
      # drop this many to construct the next InstructionTable, from
      # which we drop the remaining number of instructions.
      smallest = @instructions.length
      top = @instructions.take(@instructions.length - @pop.length)
      top.each do |i|
        unless i.drop_count.zero? or smallest < i.drop_count
          smallest = i.drop_count
        end
      end

      if smallest == count
        # There are no intermediate steps to take, because we can't drop
        # any fewer than the given number of instructions.
        remaining = @instructions.drop(count)

        # Adjust the drop_count for each remaining instruction except
        # those that belong to the parent InstructionTable @pop
        top, pop = remaining.split_at(remaining.length - @pop.length)

        top.map!{|op| op.copy(:drop_count => op.drop_count - count) }
        top.concat(pop)

        NonEmpty.new(top, @pop)
      else
        drop(smallest).drop(count - smallest)
      end
    end
  end
end

#hash



22
23
24
# File 'lib/stupidedi/parser/instruction_table.rb', line 22

def hash
  [NonEmpty, state].hash
end

#matches(segment_tok, strict = false, mode = :insert) ⇒ Array<Instruction>

Returns:



50
51
52
53
54
55
56
# File 'lib/stupidedi/parser/instruction_table.rb', line 50

def matches(segment_tok, strict = false, mode = :insert)
  if constraints.defined_at?(segment_tok.id)
    constraints.at(segment_tok.id).matches(segment_tok, strict, mode)
  else
    []
  end
end

#pop(count) ⇒ InstructionTable

Returns:



77
78
79
80
81
82
83
# File 'lib/stupidedi/parser/instruction_table.rb', line 77

def pop(count)
  if count.zero?
    self
  else
    @pop.pop(count - 1)
  end
end

#pretty_print(q)

This method returns an undefined value.

:nocov:



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/stupidedi/parser/instruction_table.rb', line 124

def pretty_print(q)
  q.text("InstructionTable")
  q.group(2, "(", ")") do
    q.breakable ""

    index = 0
    @instructions.each do |e|
      index += 1
      unless q.current_group.first?
        q.text ","
        q.breakable
      end

      q.text "#{"% 2s" % index}: "
      q.pp e
    end
  end
end

#push(instructions) ⇒ InstructionTable

Returns:



39
40
41
42
43
44
45
46
47
# File 'lib/stupidedi/parser/instruction_table.rb', line 39

def push(instructions)
  @__push[instructions] ||= begin
    bottom = @instructions.map do |op|
      op.copy(:pop_count => op.pop_count + 1)
    end

    NonEmpty.new(instructions + bottom, self)
  end
end