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, untyped]]

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, untyped]]) -> void

Parameters:

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


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

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, untyped]] productions) -> CompactProductions

Parameters:

  • productions (Array[Hash[Symbol, untyped]])

Returns:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 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, untyped]]
  productions.each_with_index do |production, index|
    lhs_ids << production.fetch(:lhs)
    lengths << production.fetch(:length)
    actions << production[: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, untyped]]) -> CompactProductions

Parameters:

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

Returns:



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/ibex/tables/compact_productions.rb', line 49

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:

  • (untyped value) -> Symbol?

Parameters:

  • value (Object)

Returns:

  • (Symbol, nil)


109
110
111
112
113
# File 'lib/ibex/tables/compact_productions.rb', line 109

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, untyped]

RBS:

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

Parameters:

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

Returns:

  • (Hash[Symbol, untyped])


151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/ibex/tables/compact_productions.rb', line 151

def decode(index, )
  entry = {} #: Hash[Symbol, untyped]
  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)


95
96
97
# File 'lib/ibex/tables/compact_productions.rb', line 95

def direct_values?
  @direct_values
end

#flags!(value) ⇒ Integer

RBS:

  • (untyped value) -> Integer

Parameters:

  • value (Object)

Returns:

  • (Integer)


116
117
118
119
120
# File 'lib/ibex/tables/compact_productions.rb', line 116

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:

  • (untyped value, String name) -> Integer

Parameters:

  • value (Object)
  • name (String)

Returns:

  • (Integer)


102
103
104
105
106
# File 'lib/ibex/tables/compact_productions.rb', line 102

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



123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/ibex/tables/compact_productions.rb', line 123

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, untyped]] metadata, Integer size) -> void

Parameters:

  • metadata (Hash[Integer, Hash[Symbol, untyped]])
  • size (Integer)


139
140
141
142
143
144
145
146
147
148
# File 'lib/ibex/tables/compact_productions.rb', line 139

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