Module: Ibex::Codegen::GeneratedActionABI

Defined in:
lib/ibex/codegen/generated_action_abi.rb,
sig/ibex/codegen/generated_action_abi.rbs

Overview

Selects the smallest generated semantic-action ABI that preserves the action's declared inputs. rubocop:disable Metrics/ModuleLength -- ABI proof and source rewriting must evolve together.

Defined Under Namespace

Classes: Cache

Constant Summary collapse

LEGACY_PARAMETERS =

Returns:

  • (Array[String])
%w[
  _values
  _ibex_locations
  _ibex_location_stack
  _ibex_location
  _ibex_lookahead_location
].freeze
SIMPLE_POSITIONAL_READ =

Signature:

  • Array[String]

Returns:

  • (Regexp)
/(?<![.\w@$])val\[\s*(\d+)\s*\]/
SIMPLE_POSITIONAL_UNSAFE =

Signature:

  • Regexp

Returns:

  • (Regexp)
%r{['"`#%/\\]|<<}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.borrowed_values?(production, analysis: self) ⇒ Boolean

The direct runtime can share one reduction-values array with an action and a hook installed by that action only when the action cannot mutate or retain the array itself. Element reads and parallel assignment copy values out without exposing the container.

RBS:

  • (IR::Production production, ?analysis: singleton(GeneratedActionABI) | Cache) -> bool

Returns:

  • (Boolean)


86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ibex/codegen/generated_action_abi.rb', line 86

def borrowed_values?(production, analysis: self)
  return false unless analysis.values_only?(production)

  action = production.action
  return false unless action

  maximum = production.rhs.length
  source = ActionLocations.new(action.code, maximum: maximum, location: action.location).rewrite
  return true if simple_indexed_values_action?(source)

  require "ripper"
  syntax = Object.const_get(:Ripper).__send__(:sexp, source)
  !syntax.nil? && read_only_value_references?(syntax)
end

.positional_action_source(production, analysis: self) ⇒ Object

Return semantic source rewritten for zero-to-four positional RHS arguments, or nil when the values container remains observable.

RBS:

  • (IR::Production production, ?analysis: singleton(GeneratedActionABI) | Cache) -> String?



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/ibex/codegen/generated_action_abi.rb', line 104

def positional_action_source(production, analysis: self)
  return nil unless analysis.values_only?(production)
  return nil unless production.rhs.length <= 4

  action = production.action
  return "" unless action
  return nil unless analysis.borrowed_values?(production)

  parameters = Array.new(production.rhs.length) { |index| "v#{index}" }
  return nil if action.named_refs.any? { |reference| parameters.include?(reference[:name]) }

  maximum = production.rhs.length
  source = ActionLocations.new(action.code, maximum: maximum, location: action.location).rewrite
  simple = fast_positional_action_source(source, parameters)
  return simple unless simple.nil?

  require "ripper"
  tokens = Object.const_get(:Ripper).__send__(:lex, source)
  return nil unless tokens.map { |_position, _event, token, _state| token }.join == source

  rewrite_positional_values(tokens, parameters)
end

.positional_values?(production) ⇒ Boolean

RBS:

  • (IR::Production production) -> bool

Returns:

  • (Boolean)


137
138
139
# File 'lib/ibex/codegen/generated_action_abi.rb', line 137

def positional_values?(production)
  !positional_action_source(production).nil?
end

.values_only?(production) ⇒ Boolean

RBS:

  • (IR::Production production) -> bool

Returns:

  • (Boolean)


69
70
71
72
73
74
75
76
77
78
79
# File 'lib/ibex/codegen/generated_action_abi.rb', line 69

def values_only?(production)
  return false if production.action&.composition

  action = production.action
  return true unless action
  return false if action.context_length.positive?

  maximum = production.rhs.length
  locations = ActionLocations.new(action.code, maximum: maximum, location: action.location)
  !locations.references? && !references_legacy_parameter?(action.code)
end

Instance Method Details

#self?.borrowed_values?Boolean

The direct runtime can share one reduction-values array with an action and a hook installed by that action only when the action cannot mutate or retain the array itself. Element reads and parallel assignment copy values out without exposing the container.

RBS:

  • (IR::Production production, ?analysis: singleton(GeneratedActionABI) | Cache) -> bool

Parameters:

Returns:

  • (Boolean)


47
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 47

def self?.borrowed_values?: (IR::Production production, ?analysis: singleton(GeneratedActionABI) | Cache) -> bool

#self?.fast_positional_action_sourceString?

RBS:

  • (String source, Array[String] parameters) -> String?

Parameters:

  • source (String)
  • parameters (Array[String])

Returns:

  • (String, nil)


55
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 55

def self?.fast_positional_action_source: (String source, Array[String] parameters) -> String?

#self?.positional_action_sourceString?

Return semantic source rewritten for zero-to-four positional RHS arguments, or nil when the values container remains observable.

RBS:

  • (IR::Production production, ?analysis: singleton(GeneratedActionABI) | Cache) -> String?

Parameters:

Returns:

  • (String, nil)


52
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 52

def self?.positional_action_source: (IR::Production production, ?analysis: singleton(GeneratedActionABI) | Cache) -> String?

#self?.positional_value_reference[ String, Integer ]?

RBS:

  • (Array[untyped] tokens, Integer index, Array[String] parameters) -> [String, Integer]?

Parameters:

  • tokens (Array[untyped])
  • index (Integer)
  • parameters (Array[String])

Returns:

  • ([ String, Integer ], nil)


83
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 83

def self?.positional_value_reference: (Array[untyped] tokens, Integer index, Array[String] parameters) -> [ String, Integer ]?

#self?.positional_values?Boolean

RBS:

  • (IR::Production production) -> bool

Parameters:

Returns:

  • (Boolean)


58
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 58

def self?.positional_values?: (IR::Production production) -> bool

#self?.read_only_value_references?Boolean

RBS:

  • (untyped node, ?untyped parent, ?Integer? child_index) -> bool

Parameters:

  • node (Object)
  • parent (Object)
  • child_index (Integer, nil)

Returns:

  • (Boolean)


92
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 92

def self?.read_only_value_references?: (untyped node, ?untyped parent, ?Integer? child_index) -> bool

#self?.receiver_before_value?Boolean

RBS:

  • (Array[untyped] tokens, Integer index) -> bool

Parameters:

  • tokens (Array[untyped])
  • index (Integer)

Returns:

  • (Boolean)


86
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 86

def self?.receiver_before_value?: (Array[untyped] tokens, Integer index) -> bool

#self?.references_legacy_parameter?Boolean

RBS:

  • (String source) -> bool

Parameters:

  • source (String)

Returns:

  • (Boolean)


89
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 89

def self?.references_legacy_parameter?: (String source) -> bool

#self?.rewrite_positional_valuesString?

RBS:

  • (Array[untyped] tokens, Array[String] parameters) -> String?

Parameters:

  • tokens (Array[untyped])
  • parameters (Array[String])

Returns:

  • (String, nil)


80
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 80

def self?.rewrite_positional_values: (Array[untyped] tokens, Array[String] parameters) -> String?

#self?.safe_value_reference?Boolean

RBS:

  • (untyped parent, Integer? child_index) -> bool

Parameters:

  • parent (Object)
  • child_index (Integer, nil)

Returns:

  • (Boolean)


98
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 98

def self?.safe_value_reference?: (untyped parent, Integer? child_index) -> bool

#self?.simple_indexed_positional_action_sourceString?

Rewrite the common string/comment/regexp-free action shape without loading Ripper. The borrowed-values proof has already rejected writes and escaping uses of the values container.

RBS:

  • (String source, Array[String] parameters) -> String?

Parameters:

  • source (String)
  • parameters (Array[String])

Returns:

  • (String, nil)


77
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 77

def self?.simple_indexed_positional_action_source: (String source, Array[String] parameters) -> String?

#self?.simple_indexed_values_action?Boolean

Avoid loading a Ruby parser for the overwhelmingly common generated action shape. This accepts only a single result assignment (or a bare expression), simple numeric val reads, and no further assignment. Anything less obvious falls back to Ripper below.

RBS:

  • (String source) -> bool

Parameters:

  • source (String)

Returns:

  • (Boolean)


65
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 65

def self?.simple_indexed_values_action?: (String source) -> bool

#self?.simple_positional_action_sourceString?

Keep the most common identity action off the Ripper load path. The whole-source match excludes strings, comments, receivers, and compound expressions before replacing the one direct read.

RBS:

  • (String source, Array[String] parameters) -> String?

Parameters:

  • source (String)
  • parameters (Array[String])

Returns:

  • (String, nil)


71
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 71

def self?.simple_positional_action_source: (String source, Array[String] parameters) -> String?

#self?.value_reference?Boolean

RBS:

  • (untyped node) -> bool

Parameters:

  • node (Object)

Returns:

  • (Boolean)


95
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 95

def self?.value_reference?: (untyped node) -> bool

#self?.values_only?Boolean

RBS:

  • (IR::Production production) -> bool

Parameters:

Returns:

  • (Boolean)


40
# File 'sig/ibex/codegen/generated_action_abi.rbs', line 40

def self?.values_only?: (IR::Production production) -> bool