Class: Rigor::Inference::HktReducer
- Inherits:
-
Object
- Object
- Rigor::Inference::HktReducer
- Defined in:
- lib/rigor/inference/hkt_reducer.rb
Overview
ADR-20 Slice 2a — reducer that walks a ‘Definition`’s ‘body_tree` against a concrete `Type::App` and returns a fully-typed `Rigor::Type`.
Reduction is the operational interpretation of ADR-20 § D4 (“Evaluation rules”):
-
**Resolve ‘F`.** Look up the registered body via `registry.definition(uri)`.
-
**Substitute arguments.** Walk the body tree, replacing ‘Rigor::Inference::HktBody::Param` nodes with the matching positional arg from the application.
-
**Build types.** ‘Rigor::Inference::HktBody::TypeLeaf` returns its wrapped type as-is; `Rigor::Inference::HktBody::Union` and `Rigor::Inference::HktBody::NominalApp` route their reduced children through `Type::Combinator.union` / `.nominal_of` so normalization applies.
-
**Recurse on ‘Rigor::Inference::HktBody::AppRef` nodes.** Reduce the args first; if the resulting `(uri, args)` matches an App already on the current reduction stack, return the in-progress `Type::App` carrier as-is (lazy self-reference handling — the standard “tying the knot” trick for recursive type aliases like `json::value`). Otherwise build a fresh `Type::App` and recursively reduce it against the same registry, sharing the fuel budget.
-
**Fuel budget.** Each visited node consumes one unit. On exhaustion, reduction unwinds to ‘app.bound`.
The reducer is pure with respect to its inputs (the registry + the App) but uses a per-call mutable state bag for fuel + cycle tracking. Concurrent reductions MUST allocate fresh reducers (or fresh ‘_reduce` calls) — the per-call state is not shared.
Defined Under Namespace
Classes: FuelExhausted, State
Constant Summary collapse
- DEFAULT_FUEL =
64
Instance Method Summary collapse
-
#initialize(registry) ⇒ HktReducer
constructor
A new instance of HktReducer.
-
#reduce(app, fuel: DEFAULT_FUEL) ⇒ Rigor::Type
Reduce ‘app` against the registry.
Constructor Details
#initialize(registry) ⇒ HktReducer
Returns a new instance of HktReducer.
46 47 48 49 50 |
# File 'lib/rigor/inference/hkt_reducer.rb', line 46 def initialize(registry) raise ArgumentError, "registry must be an HktRegistry" unless registry.is_a?(HktRegistry) @registry = registry end |
Instance Method Details
#reduce(app, fuel: DEFAULT_FUEL) ⇒ Rigor::Type
Reduce ‘app` against the registry.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/rigor/inference/hkt_reducer.rb', line 61 def reduce(app, fuel: DEFAULT_FUEL) raise ArgumentError, "expected a Rigor::Type::App, got #{app.class}" unless app.is_a?(Type::App) definition = @registry.definition(app.uri) return app.bound if definition.nil? || definition.body_tree.nil? return app.bound if definition.params.size != app.args.size state = State.new(fuel: fuel) begin state.with_in_progress(app.uri, app.args, app) do walk(definition.body_tree, bindings: bindings_for(definition, app.args), state: state) || app.bound end rescue FuelExhausted app.bound end end |