Class: Ibex::Tables::CompactActions

Inherits:
Compact
  • Object
show all
Defined in:
lib/ibex/tables/compact_actions.rb

Overview

Compact action table with an integer-coded hot representation and a compatible decoded lookup surface for the generic runtime.

Constant Summary collapse

ACCEPT_CODE =

: Integer

0
ERROR_CODE =

: Integer

-1 #: Integer
SHIFT_BASE =

: Integer

1
REDUCE_BASE =

: Integer

-2 #: Integer

Constants inherited from Compact

Ibex::Tables::Compact::DENSE_CELL_LIMIT

Instance Attribute Summary collapse

Attributes inherited from Compact

#checks, #dense_values, #dense_width, #offsets, #row_count, #values

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Compact

#lookup, #row

Constructor Details

#initialize(offsets:, codes:, checks:, row_count:, encoding: :legacy, column_count: nil) ⇒ CompactActions

Returns a new instance of CompactActions.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/ibex/tables/compact_actions.rb', line 94

def initialize(offsets:, codes:, checks:, row_count:, encoding: :legacy, column_count: nil)
  codes = codes.map { |code| self.class.legacy_to_signed(code) } if encoding == :legacy
  unless %i[legacy signed].include?(encoding)
    raise ArgumentError, "unknown compact action encoding #{encoding.inspect}"
  end

  @codes = codes.freeze
  @column_count = column_count
  @dense_codes = dense_action_layout(offsets, codes, checks, row_count, column_count)
  decoded_cache = {} #: Hash[Integer, untyped]
  decoded = codes.map do |code|
    code.nil? ? nil : decoded_cache[code] ||= self.class.unpack(code)
  end
  super(offsets: offsets, values: decoded, checks: checks, row_count: row_count)
end

Instance Attribute Details

#codesObject (readonly)

: Array



20
21
22
# File 'lib/ibex/tables/compact_actions.rb', line 20

def codes
  @codes
end

#column_countObject (readonly)

: Integer?



22
23
24
# File 'lib/ibex/tables/compact_actions.rb', line 22

def column_count
  @column_count
end

#dense_codesObject (readonly)

: Array?



21
22
23
# File 'lib/ibex/tables/compact_actions.rb', line 21

def dense_codes
  @dense_codes
end

Class Method Details

.build(rows) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/ibex/tables/compact_actions.rb', line 26

def build(rows)
  packed_rows = rows.map do |row|
    row.transform_values { |action| pack(action) }
  end
  layout = Compact.build(packed_rows, dense: false)
  column_count = rows.flat_map(&:keys).max.to_i + 1
  column_count = nil if (rows.length * column_count) > Compact::DENSE_CELL_LIMIT
  new(
    offsets: layout.offsets,
    codes: layout.values,
    checks: layout.checks,
    row_count: layout.row_count,
    encoding: :signed,
    column_count: column_count
  )
end

.legacy_to_signed(code) ⇒ Object

Convert codes emitted before signed compact actions without changing their generated table literals.



82
83
84
85
86
87
88
89
# File 'lib/ibex/tables/compact_actions.rb', line 82

def legacy_to_signed(code)
  return unless code
  return ACCEPT_CODE if code == ACCEPT_CODE
  return ERROR_CODE if code == LEGACY_ERROR_CODE
  return SHIFT_BASE + ((code - LEGACY_SHIFT_BASE) / 2) if code.even?

  REDUCE_BASE - ((code - LEGACY_REDUCE_BASE) / 2)
end

.pack(action) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/ibex/tables/compact_actions.rb', line 57

def pack(action)
  return unless action

  case action.fetch(0)
  when :accept then ACCEPT_CODE
  when :error then ERROR_CODE
  when :shift then SHIFT_BASE + action.fetch(1)
  when :reduce then REDUCE_BASE - action.fetch(1)
  else raise ArgumentError, "unknown compact parser action #{action.inspect}"
  end
end

.packed(offsets, codes, checks, row_count:, encoding: :legacy, column_count: nil) ⇒ Object



45
46
47
48
49
50
51
52
53
54
# File 'lib/ibex/tables/compact_actions.rb', line 45

def packed(offsets, codes, checks, row_count:, encoding: :legacy, column_count: nil)
  new(
    offsets: PackedIntegers.decode_required(offsets),
    codes: encoding == :signed ? PackedIntegers.decode_signed(codes) : PackedIntegers.decode(codes),
    checks: PackedIntegers.decode(checks),
    row_count: row_count,
    encoding: encoding,
    column_count: column_count
  )
end

.unpack(code) ⇒ Object



70
71
72
73
74
75
76
77
# File 'lib/ibex/tables/compact_actions.rb', line 70

def unpack(code)
  return unless code
  return [:accept].freeze if code == ACCEPT_CODE
  return [:error].freeze if code == ERROR_CODE
  return [:shift, code - SHIFT_BASE].freeze if code.positive?

  [:reduce, REDUCE_BASE - code].freeze
end