Class: Stupidedi::Builder::InstructionTable::NonEmpty

Inherits:
Stupidedi::Builder::InstructionTable show all
Defined in:
lib/stupidedi/builder/instruction_table.rb

Constant Summary

Constants inherited from Stupidedi::Builder::InstructionTable

Empty

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Stupidedi::Builder::InstructionTable

build, empty

Methods included from Inspect

#inspect

Constructor Details

#initialize(instructions, pop) ⇒ NonEmpty

Returns a new instance of NonEmpty.



12
13
14
15
16
17
# File 'lib/stupidedi/builder/instruction_table.rb', line 12

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

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

Instance Attribute Details

#instructionsArray<Instruction> (readonly)

Returns:



10
11
12
# File 'lib/stupidedi/builder/instruction_table.rb', line 10

def instructions
  @instructions
end

Instance Method Details

#at(segment_use) ⇒ Instruction

Returns:



32
33
34
# File 'lib/stupidedi/builder/instruction_table.rb', line 32

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

#copy(changes = {}) ⇒ InstructionTable

Returns:



20
21
22
23
24
# File 'lib/stupidedi/builder/instruction_table.rb', line 20

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

#drop(count) ⇒ InstructionTable

Returns:



82
83
84
85
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
# File 'lib/stupidedi/builder/instruction_table.rb', line 82

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

#lengthInteger

Returns:



27
28
29
# File 'lib/stupidedi/builder/instruction_table.rb', line 27

def length
  @instructions.length
end

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

Returns:



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/stupidedi/builder/instruction_table.rb', line 48

def matches(segment_tok, strict = false)
  @__matches ||= 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

  if @__matches.defined_at?(segment_tok.id)
    @__matches.at(segment_tok.id).matches(segment_tok, strict)
  else
    []
  end
end

#pop(count) ⇒ InstructionTable

Returns:



73
74
75
76
77
78
79
# File 'lib/stupidedi/builder/instruction_table.rb', line 73

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

#pretty_print(q) ⇒ void

This method returns an undefined value.



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/stupidedi/builder/instruction_table.rb', line 119

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:



37
38
39
40
41
42
43
44
45
# File 'lib/stupidedi/builder/instruction_table.rb', line 37

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