Module: Rigor::Inference::MacroBlockSelfType
- Defined in:
- lib/rigor/inference/macro_block_self_type.rb
Overview
ADR-16 Tier A — engine hook. Consults every registered plugin manifest’s ‘block_as_methods` entries to decide whether a block call site qualifies for `Scope#self_type` narrowing.
The match contract for a class-level DSL like Sinatra’s ‘class MyApp < Sinatra::Base; get ’/foo’ do … end; end`:
-
the call’s lexical receiver type is ‘Singleton` (the implicit-self in a class body, or an explicit `MyApp.get(…)` call);
-
the underlying class ‘X` equals or inherits from the entry’s ‘receiver_constraint`;
-
the call’s method name is in the entry’s ‘verbs`.
On a match the helper returns the instance type of the receiver class (‘Nominal`) — the narrowed `self_type` for the block body, matching Sinatra’s runtime semantics where ‘Sinatra::Base#generate_method` turns the block into an instance method of the user’s app class.
Slice 1b ships the floor only (per ADR-16 § WD13): bare-identifier method lookups inside the block resolve through the inference engine’s normal ‘self_type`-driven path, so methods declared on `Sinatra::Base` (RBS or otherwise) become visible. Precision additions —parameter-typed block params, declared per-verb argument contracts — are ceiling concerns for later slices.
Class Method Summary collapse
- .instance_type_for(class_name, environment) ⇒ Object
-
.narrow_self_type_for(scope:, call_node:, receiver_type:) ⇒ Rigor::Type?
The narrowed self-type, or ‘nil` when no registered entry matches the call shape.
- .receiver_class_inherits_from?(class_name, constraint, environment) ⇒ Boolean
-
.singleton_receiver_class_name(receiver_type) ⇒ Object
Tier A’s match contract is intentionally narrow: class-level DSL calls (receiver is ‘Singleton`) only.
Class Method Details
.instance_type_for(class_name, environment) ⇒ Object
90 91 92 |
# File 'lib/rigor/inference/macro_block_self_type.rb', line 90 def instance_type_for(class_name, environment) environment.nominal_for_name(class_name) || Type::Nominal.new(class_name) end |
.narrow_self_type_for(scope:, call_node:, receiver_type:) ⇒ Rigor::Type?
Returns the narrowed self-type, or ‘nil` when no registered entry matches the call shape.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/rigor/inference/macro_block_self_type.rb', line 44 def narrow_self_type_for(scope:, call_node:, receiver_type:) return nil if receiver_type.nil? environment = scope&.environment registry = environment&.plugin_registry return nil if registry.nil? || registry.empty? receiver_class_name = singleton_receiver_class_name(receiver_type) return nil if receiver_class_name.nil? # ADR-52 WD1 — the verb-keyed table compiled at registry build # replaces the per-call plugins × block_as_methods linear scan. # Entries arrive in (plugin registration, declaration) order, so # the first ancestry match below is the same entry the previous # walk returned; the verb membership the old `matches?` checked # is guaranteed by the table key. entries = registry.contribution_index.block_entries_for(call_node.name) entries.each do |entry| if receiver_class_inherits_from?(receiver_class_name, entry.receiver_constraint, environment) return instance_type_for(receiver_class_name, environment) end end nil end |
.receiver_class_inherits_from?(class_name, constraint, environment) ⇒ Boolean
81 82 83 84 85 86 87 88 |
# File 'lib/rigor/inference/macro_block_self_type.rb', line 81 def receiver_class_inherits_from?(class_name, constraint, environment) return true if class_name == constraint ordering = environment.class_ordering(class_name, constraint) %i[equal subclass].include?(ordering) rescue StandardError false end |
.singleton_receiver_class_name(receiver_type) ⇒ Object
Tier A’s match contract is intentionally narrow: class-level DSL calls (receiver is ‘Singleton`) only. Instance-receiver calls and DSL forms whose block body binds a different `self` (Concern’s ‘included do`, `instance_eval { … }`) are handled by later slices (Concern walker, Tier D, etc.) — not Tier A.
75 76 77 78 79 |
# File 'lib/rigor/inference/macro_block_self_type.rb', line 75 def singleton_receiver_class_name(receiver_type) return nil unless receiver_type.is_a?(Type::Singleton) receiver_type.class_name end |