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…` / `%a…` annotations in shipped `.rbs` files.

Slice 1 keeps the registry opaque: it stores the registration metadata (arity, variance, bound) and the un-evaluated definition body (a raw String — Slice 2 introduces the conditional / indexed-access evaluator that parses the body and reduces ‘Type::App` instances against it). 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:



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

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.



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

def definitions
  @definitions
end

#registrationsObject (readonly)

Returns the value of attribute registrations.



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

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.



106
107
108
109
110
111
112
113
114
115
# File 'lib/rigor/inference/hkt_registry.rb', line 106

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.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/rigor/inference/hkt_registry.rb', line 188

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)


131
132
133
# File 'lib/rigor/inference/hkt_registry.rb', line 131

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

#definition(uri) ⇒ Object



139
140
141
# File 'lib/rigor/inference/hkt_registry.rb', line 139

def definition(uri)
  @definitions[uri]
end

#empty?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'lib/rigor/inference/hkt_registry.rb', line 156

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)


147
148
149
150
151
152
153
154
# File 'lib/rigor/inference/hkt_registry.rb', line 147

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.



164
165
166
# File 'lib/rigor/inference/hkt_registry.rb', line 164

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

#registered?(uri) ⇒ Boolean

Returns:

  • (Boolean)


127
128
129
# File 'lib/rigor/inference/hkt_registry.rb', line 127

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

#registration(uri) ⇒ Object



135
136
137
# File 'lib/rigor/inference/hkt_registry.rb', line 135

def registration(uri)
  @registrations[uri]
end