Class: Ibex::Tables::CompactProductions

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

Overview

Production metadata with parallel primitive arrays for the direct parser and a compatible Array-of-Hash surface for generic runtime consumers.

Constant Summary collapse

VALUES_ACTION =

[Hash[Symbol, Object?]]

Returns:

  • (Integer)
1
BORROWED_VALUES_ACTION =

Signature:

  • Integer

Returns:

  • (Integer)
2
LOCATION_ACTION =

Signature:

  • Integer

Returns:

  • (Integer)
4
COMPOSITION_ACTION =

Signature:

  • Integer

Returns:

  • (Integer)
8
POSITIONAL_ACTION =

Signature:

  • Integer

Returns:

  • (Integer)
16
VALID_FLAGS =

Signature:

  • Integer

Returns:

  • (Integer)
VALUES_ACTION | BORROWED_VALUES_ACTION | LOCATION_ACTION |
COMPOSITION_ACTION | POSITIONAL_ACTION
CORE_FIELDS =

Signature:

  • Integer

Returns:

  • (Array[Symbol])
%i[
  lhs length action values_action borrowed_values_action location_action composition_action
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(lhs_ids:, lengths:, actions:, flags:, metadata: {}) ⇒ CompactProductions

Returns a new instance of CompactProductions.

RBS:

  • (lhs_ids: Array[Integer], lengths: Array[Integer], actions: Array[Symbol?], flags: Array[Integer], ?metadata: Hash[Integer, Hash[Symbol, Object?]]) -> void

Parameters:

  • lhs_ids: (Array[Integer])
  • lengths: (Array[Integer])
  • actions: (Array[Symbol?])
  • flags: (Array[Integer])
  • metadata: (Hash[Integer, Hash[Symbol, Object?]]) (defaults to: {})


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/ibex/tables/compact_productions.rb', line 81

def initialize(lhs_ids:, lengths:, actions:, flags:, metadata: {})
  size = lhs_ids.length
  unless lengths.length == size && actions.length == size && flags.length == size
    raise ArgumentError, "compact production arrays must have the same length"
  end

  @lhs_ids = lhs_ids.map { |value| nonnegative_integer!(value, "lhs") }.freeze
  @lengths = lengths.map { |value| nonnegative_integer!(value, "length") }.freeze
  @actions = actions.map { |value| action!(value) }.freeze
  @flags = flags.map { |value| flags!(value) }.freeze
  validate_markers!
  validate_metadata!(, size)
  super(Array.new(size) { |index| decode(index, [index]) })
  freeze
end

Instance Attribute Details

#actionsArray[Symbol?] (readonly)

Signature:

  • Array[Symbol?]

Returns:

  • (Array[Symbol?])


23
24
25
# File 'lib/ibex/tables/compact_productions.rb', line 23

def actions
  @actions
end

#flagsArray[Integer] (readonly)

Signature:

  • Array[Integer]

Returns:

  • (Array[Integer])


24
25
26
# File 'lib/ibex/tables/compact_productions.rb', line 24

def flags
  @flags
end

#lengthsArray[Integer] (readonly)

Signature:

  • Array[Integer]

Returns:

  • (Array[Integer])


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

def lengths
  @lengths
end

#lhs_idsArray[Integer] (readonly)

Signature:

  • Array[Integer]

Returns:

  • (Array[Integer])


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

def lhs_ids
  @lhs_ids
end

Class Method Details

.build(productions) ⇒ CompactProductions

RBS:

  • (Array[Hash[Symbol, Object?]] productions) -> CompactProductions

Parameters:

  • productions (Array[Hash[Symbol, Object?]])

Returns:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/ibex/tables/compact_productions.rb', line 28

def build(productions)
  lhs_ids = [] #: Array[Integer]
  lengths = [] #: Array[Integer]
  actions = [] #: Array[Symbol?]
  flags = [] #: Array[Integer]
   = {} #: Hash[Integer, Hash[Symbol, Object?]]
  productions.each_with_index do |production, index|
    lhs = production.fetch(:lhs) #: Integer
    length = production.fetch(:length) #: Integer
    action = production[:action] #: Symbol?
    lhs_ids << lhs
    lengths << length
    actions << action
    flags << flags_for(production)
    extra = production.except(
      :lhs, :length, :action, :values_action, :borrowed_values_action, :location_action, :composition_action
    )
    [index] = extra unless extra.empty?
  end
  new(lhs_ids: lhs_ids, lengths: lengths, actions: actions, flags: flags, metadata: )
end

.packed(lhs_ids, lengths, flags, metadata: {}) ⇒ CompactProductions

RBS:

  • (String lhs_ids, String lengths, String flags, ?metadata: Hash[Integer, Hash[Symbol, Object?]]) -> CompactProductions

Parameters:

  • lhs_ids (String)
  • lengths (String)
  • flags (String)
  • metadata: (Hash[Integer, Hash[Symbol, Object?]]) (defaults to: {})

Returns:



52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/ibex/tables/compact_productions.rb', line 52

def packed(lhs_ids, lengths, flags, metadata: {})
  decoded_flags = PackedIntegers.decode_required(flags)
  actions = decoded_flags.each_index.map do |index|
    :"_ibex_action_#{index}" unless decoded_flags[index].zero?
  end
  new(
    lhs_ids: PackedIntegers.decode_required(lhs_ids),
    lengths: PackedIntegers.decode_required(lengths),
    actions: actions,
    flags: decoded_flags,
    metadata: 
  )
end

Instance Method Details

#action!(value) ⇒ Symbol?

RBS:

  • (Object? value) -> Symbol?

Parameters:

  • value (Object, nil)

Returns:

  • (Symbol, nil)


112
113
114
115
116
# File 'lib/ibex/tables/compact_productions.rb', line 112

def action!(value)
  return value if value.nil? || value.is_a?(Symbol)

  raise ArgumentError, "compact production action must be a Symbol or nil"
end

#decode(index, metadata) ⇒ Hash[Symbol, Object?]

RBS:

  • (Integer index, Hash[Symbol, Object?]? metadata) -> Hash[Symbol, Object?]

Parameters:

  • index (Integer)
  • metadata (Hash[Symbol, Object?], nil)

Returns:

  • (Hash[Symbol, Object?])


154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/ibex/tables/compact_productions.rb', line 154

def decode(index, )
  entry = {} #: Hash[Symbol, Object?]
  entry[:lhs] = @lhs_ids[index]
  entry[:length] = @lengths[index]
  entry[:action] = @actions[index]
  value = @flags[index]
  entry[:values_action] = true if value.anybits?(VALUES_ACTION)
  entry[:borrowed_values_action] = true if value.anybits?(BORROWED_VALUES_ACTION)
  entry[:location_action] = true if value.anybits?(LOCATION_ACTION)
  entry[:composition_action] = true if value.anybits?(COMPOSITION_ACTION)
  entry[:positional_action] = true if value.anybits?(POSITIONAL_ACTION)
  entry.merge!() if 
  entry.freeze
end

#direct_values?Boolean

RBS:

  • () -> bool

Returns:

  • (Boolean)


98
99
100
# File 'lib/ibex/tables/compact_productions.rb', line 98

def direct_values?
  @direct_values
end

#flags!(value) ⇒ Integer

RBS:

  • (Object? value) -> Integer

Parameters:

  • value (Object, nil)

Returns:

  • (Integer)


119
120
121
122
123
# File 'lib/ibex/tables/compact_productions.rb', line 119

def flags!(value)
  return value if value.is_a?(Integer) && !value.negative? && value.nobits?(~VALID_FLAGS)

  raise ArgumentError, "compact production flags are invalid"
end

#nonnegative_integer!(value, name) ⇒ Integer

RBS:

  • (Object? value, String name) -> Integer

Parameters:

  • value (Object, nil)
  • name (String)

Returns:

  • (Integer)


105
106
107
108
109
# File 'lib/ibex/tables/compact_productions.rb', line 105

def nonnegative_integer!(value, name)
  return value if value.is_a?(Integer) && !value.negative?

  raise ArgumentError, "compact production #{name} must be a nonnegative Integer"
end

#validate_markers!void

This method returns an undefined value.

RBS:

  • () -> void



126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/ibex/tables/compact_productions.rb', line 126

def validate_markers!
  @flags.each_with_index do |value, index|
    borrowed = value.anybits?(BORROWED_VALUES_ACTION)
    values = value.anybits?(VALUES_ACTION)
    positional = value.anybits?(POSITIONAL_ACTION)
    raise ArgumentError, "borrowed production #{index} must be a values action" if borrowed && !values
    if positional && value.anybits?(VALUES_ACTION | LOCATION_ACTION | COMPOSITION_ACTION)
      raise ArgumentError, "positional production #{index} cannot combine action ABI flags"
    end
  end
  @direct_values = @actions.each_index.all? do |index|
    @actions[index].nil? || @flags[index].anybits?(VALUES_ACTION | POSITIONAL_ACTION)
  end
end

#validate_metadata!(metadata, size) ⇒ void

This method returns an undefined value.

RBS:

  • (Hash[Integer, Hash[Symbol, Object?]] metadata, Integer size) -> void

Parameters:

  • metadata (Hash[Integer, Hash[Symbol, Object?]])
  • size (Integer)


142
143
144
145
146
147
148
149
150
151
# File 'lib/ibex/tables/compact_productions.rb', line 142

def validate_metadata!(, size)
  .each do |index, entry|
    unless index.is_a?(Integer) && index.between?(0, size - 1) && entry.is_a?(Hash)
      raise ArgumentError, "compact production metadata is invalid"
    end
    if entry.keys.any? { |key| CORE_FIELDS.include?(key) }
      raise ArgumentError, "compact production metadata cannot replace core fields"
    end
  end
end