Class: Rigor::Inference::HktRegistry

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/inference/hkt_registry.rb

Overview

ADR-20 § "Decision D1 / D2" — registry of Lightweight HKT tag registrations + type-function bodies parsed off the %a{rigor:v1:hkt_register: ...} / %a{rigor:v1:hkt_define: ...} annotations in shipped .rbs files.

The registry stores registration metadata (arity, variance, bound) and the definition body as both a raw String and an evaluable HktBody node tree. HktReducer (Slice 2a) and HktBodyParser (Slice 2b) are both shipped and reduce Type::App instances against the definition. The carrier never needs to read from the registry because Slice 1's Type::App carries its bound directly; the registry exists at this slice solely so the parser round-trip and downstream slices have a stable target API.

The registry is immutable after construction. Callers that need to extend it (e.g. plugin registrations layered on top of stdlib registrations) MUST build a new registry via merge rather than mutating an existing one. This keeps the registry shareable across Ractor boundaries per ADR-15.

Defined Under Namespace

Classes: Definition, Registration

Constant Summary collapse

EMPTY =
new.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(registrations: [], definitions: []) ⇒ HktRegistry

Returns a new instance of HktRegistry.

Parameters:



104
105
106
107
108
# File 'lib/rigor/inference/hkt_registry.rb', line 104

def initialize(registrations: [], definitions: [])
  @registrations = registrations.to_h { |r| [r.uri, r] }.freeze
  @definitions = definitions.to_h { |d| [d.uri, d] }.freeze
  freeze
end

Instance Attribute Details

#definitionsObject (readonly)

Returns the value of attribute definitions.



100
101
102
# File 'lib/rigor/inference/hkt_registry.rb', line 100

def definitions
  @definitions
end

#registrationsObject (readonly)

Returns the value of attribute registrations.



100
101
102
# File 'lib/rigor/inference/hkt_registry.rb', line 100

def registrations
  @registrations
end

Class Method Details

.definition_with_body_tree(uri:, params:, body_tree:, source_path: nil, source_line: nil) ⇒ Object

Convenience constructor for callers that have a body tree but no raw String — typically Rigor-bundled HKT overlays that build the body programmatically. The raw body slot is filled with an empty placeholder so existing consumers keep their type contract.



89
90
91
92
93
94
95
96
97
98
# File 'lib/rigor/inference/hkt_registry.rb', line 89

def self.definition_with_body_tree(uri:, params:, body_tree:, source_path: nil, source_line: nil)
  Definition.new(
    uri: uri,
    params: params,
    body: "",
    body_tree: body_tree,
    source_path: source_path,
    source_line: source_line
  )
end

.scan_rbs_loader(rbs_loader, base: EMPTY, name_scope: nil, reporter: nil) ⇒ Object

ADR-20 slice 2e — scan a Rigor RbsLoader for rigor:v1:hkt_register / rigor:v1:hkt_define annotations attached to class- or module-level declarations in the loaded RBS env, parse them via RbsExtended::HktDirectives, and return a new registry that is the union of base and every parsed entry. Last-write-wins on URI collisions per #merge's contract. Fail-soft on per-annotation parse errors (the reporter records an :info entry; the other annotations still apply).

Parameters:

  • rbs_loader (Rigor::Environment::RbsLoader)
  • base (HktRegistry) (defaults to: EMPTY)

    starting registry (typically the bundled Rigor::Builtins::HktBuiltins.registry).

  • name_scope (Rigor::Environment::NameScope, nil) (defaults to: nil)

    threaded through to the bound resolver for class-name lookups; safe to omit during scanning since hkt bounds are typically untyped or stdlib classes.

  • reporter (#record, nil) (defaults to: nil)

    same fail-soft reporter contract the other RBS-extended parsers use.



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/rigor/inference/hkt_registry.rb', line 163

def self.scan_rbs_loader(rbs_loader, base: EMPTY, name_scope: nil, reporter: nil)
  return base if rbs_loader.nil?

  # Required lazily here to avoid a hard circular require between hkt_registry /
  # hkt_directives; HktDirectives requires HktRegistry to construct its value objects.
  require_relative "../rbs_extended/hkt_directives"

  registrations = []
  definitions = []

  rbs_loader.each_class_decl_annotation do |annotation_string, source_location|
    reg = Rigor::RbsExtended::HktDirectives.parse_register(
      annotation_string, name_scope: name_scope, reporter: reporter, source_location: source_location
    )
    registrations << reg if reg

    defn = Rigor::RbsExtended::HktDirectives.parse_define(
      annotation_string, reporter: reporter, source_location: source_location
    )
    definitions << defn if defn
  end

  return base if registrations.empty? && definitions.empty?

  overlay = new(registrations: registrations, definitions: definitions)
  base.merge(overlay)
end

Instance Method Details

#defined?(uri) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
# File 'lib/rigor/inference/hkt_registry.rb', line 114

def defined?(uri)
  @definitions.key?(uri)
end

#definition(uri) ⇒ Object



122
123
124
# File 'lib/rigor/inference/hkt_registry.rb', line 122

def definition(uri)
  @definitions[uri]
end

#empty?Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/rigor/inference/hkt_registry.rb', line 137

def empty?
  @registrations.empty? && @definitions.empty?
end

#merge(other) ⇒ HktRegistry

Returns a new registry whose entries are the union of this registry's and other's. On URI collisions other's entries win (last-write-wins; OQ3 tentative).

Returns:

  • (HktRegistry)

    a new registry whose entries are the union of this registry's and other's. On URI collisions other's entries win (last-write-wins; OQ3 tentative).

Raises:

  • (ArgumentError)


128
129
130
131
132
133
134
135
# File 'lib/rigor/inference/hkt_registry.rb', line 128

def merge(other)
  raise ArgumentError, "merge target must be an HktRegistry, got #{other.class}" unless other.is_a?(HktRegistry)

  self.class.new(
    registrations: @registrations.merge(other.registrations).values,
    definitions: @definitions.merge(other.definitions).values
  )
end

#reduce(app, fuel: HktReducer::DEFAULT_FUEL) ⇒ Object

ADR-20 Slice 2a — reduce an App against this registry. Convenience wrapper around HktReducer.new(self).reduce. Each call allocates a fresh reducer; concurrent reductions are safe.



144
145
146
# File 'lib/rigor/inference/hkt_registry.rb', line 144

def reduce(app, fuel: HktReducer::DEFAULT_FUEL)
  HktReducer.new(self).reduce(app, fuel: fuel)
end

#registered?(uri) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/rigor/inference/hkt_registry.rb', line 110

def registered?(uri)
  @registrations.key?(uri)
end

#registration(uri) ⇒ Object



118
119
120
# File 'lib/rigor/inference/hkt_registry.rb', line 118

def registration(uri)
  @registrations[uri]
end