Class: Ibex::Tables::CompactActions

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

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 =

Signature:

  • Integer

Returns:

  • (Integer)
0
ERROR_CODE =

Signature:

  • Integer

Returns:

  • (Integer)
-1 #: Integer
SHIFT_BASE =

Signature:

  • Integer

Returns:

  • (Integer)
1
REDUCE_BASE =

Signature:

  • Integer

Returns:

  • (Integer)
-2 #: Integer
LEGACY_ERROR_CODE =

Signature:

  • Integer

Returns:

  • (Integer)
1
LEGACY_SHIFT_BASE =

Signature:

  • Integer

Returns:

  • (Integer)
2
LEGACY_REDUCE_BASE =

Signature:

  • Integer

Returns:

  • (Integer)
3

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, #self?.dense_layout, #self?.initialize, #self?.lookup, #self?.row

Constructor Details

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

Returns a new instance of CompactActions.

RBS:

  • (offsets: Array[Integer], codes: Array[Integer?], checks: Array[Integer?], row_count: Integer, ?encoding: Symbol, ?column_count: Integer?) -> void

Parameters:

  • offsets: (Array[Integer])
  • codes: (Array[Integer?])
  • checks: (Array[Integer?])
  • row_count: (Integer)
  • encoding: (Symbol) (defaults to: :legacy)
  • column_count: (Integer, nil) (defaults to: nil)


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

#codesArray[Integer?] (readonly)

Signature:

  • Array[Integer?]

Returns:

  • (Array[Integer?])


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

def codes
  @codes
end

#column_countInteger? (readonly)

Signature:

  • Integer?

Returns:

  • (Integer, nil)


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

def column_count
  @column_count
end

#dense_codesArray[Integer?]? (readonly)

Signature:

  • Array[Integer?]?

Returns:

  • (Array[Integer?], nil)


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

def dense_codes
  @dense_codes
end

Class Method Details

.build(rows) ⇒ CompactActions

RBS:

  • (Array[Hash[Integer, untyped]] rows) -> CompactActions

Parameters:

  • rows (Array[Hash[Integer, untyped]])

Returns:



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) ⇒ Integer?

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

RBS:

  • (Integer? code) -> Integer?

Parameters:

  • code (Integer, nil)

Returns:

  • (Integer, nil)


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) ⇒ Integer?

RBS:

  • (untyped action) -> Integer?

Parameters:

  • action (Object)

Returns:

  • (Integer, nil)


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) ⇒ CompactActions

RBS:

  • (String offsets, String codes, String checks, row_count: Integer, ?encoding: Symbol, ?column_count: Integer?) -> CompactActions

Parameters:

  • offsets (String)
  • codes (String)
  • checks (String)
  • row_count: (Integer)
  • encoding: (Symbol) (defaults to: :legacy)
  • column_count: (Integer, nil) (defaults to: nil)

Returns:



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

RBS:

  • (Integer? code) -> untyped

Parameters:

  • code (Integer, nil)

Returns:

  • (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

Instance Method Details

#dense_action_layout(offsets, codes, checks, row_count, column_count) ⇒ Array[Integer?]?

RBS:

  • (Array[Integer] offsets, Array[Integer?] codes, Array[Integer?] checks, Integer row_count, Integer? column_count) -> Array[Integer?]?

Parameters:

  • offsets (Array[Integer])
  • codes (Array[Integer?])
  • checks (Array[Integer?])
  • row_count (Integer)
  • column_count (Integer, nil)

Returns:

  • (Array[Integer?], nil)


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/ibex/tables/compact_actions.rb', line 114

def dense_action_layout(offsets, codes, checks, row_count, column_count)
  return nil unless column_count
  raise ArgumentError, "compact action column count must be positive" unless column_count.positive?

  return nil if (row_count * column_count) > Compact::DENSE_CELL_LIMIT

  dense = Array.new(row_count * column_count) #: Array[Integer?]
  checks.each_index do |index|
    row = checks[index]
    next unless row

    column = index - offsets.fetch(row)
    raise ArgumentError, "compact action column exceeds the dense row width" unless
      column.between?(0, column_count - 1)

    dense[(row * column_count) + column] = codes[index]
  end
  dense.freeze
end