diff --git a/src/ast/compiler/call_hooks.rs b/src/ast/compiler/call_hooks.rs index b6190a2..8ef4daf 100644 --- a/src/ast/compiler/call_hooks.rs +++ b/src/ast/compiler/call_hooks.rs @@ -35,16 +35,6 @@ pub trait InferenceAccess { fn get_slot_type(&self, addr: Address) -> StaticType; } -/// Maps a concrete type to its element type for index-constraint propagation. -/// Called by `bind_var` when a TypeVar with an index constraint is bound. -/// -/// Returns `Some(elem_ty)` if `ty` supports integer-index access (e.g. `Series`), -/// or `None` for all non-indexable types. -/// -/// Register the appropriate implementation via `TypeChecker::new`. Each indexable -/// type (Series, and in future Stream) contributes a match arm here. -pub type IndexElementFn = fn(&StaticType) -> Option; - /// Called after the call's return type is resolved. /// May replace the return type and/or perform unification side-effects (e.g. push). pub type PostCallHook = fn( diff --git a/src/ast/compiler/type_checker.rs b/src/ast/compiler/type_checker.rs index 00dc1b2..f8c001d 100644 --- a/src/ast/compiler/type_checker.rs +++ b/src/ast/compiler/type_checker.rs @@ -1,4 +1,4 @@ -use crate::ast::compiler::call_hooks::{CallHooks, InferenceAccess, IndexElementFn}; +use crate::ast::compiler::call_hooks::{CallHooks, InferenceAccess}; use crate::ast::nodes::{ Address, AssignBinding, BoundLike, BoundPhase, DefBinding, IdentifierBinding, LambdaBinding, Node, NodeKind, TypedNode, TypedPhase, VirtualId, @@ -182,12 +182,8 @@ pub struct TypeChecker { /// the series lookback pattern `(s 0)` — we record the pairing here instead /// of eagerly unifying `TypeVar = Series(elem)`. The constraint is evaluated /// lazily in `bind_var`: when the callee TypeVar is bound to a concrete type, - /// `index_element_fn` determines the element type (if any) and propagates it. + /// the element type is extracted directly from the `Series` variant. index_constraints: std::cell::RefCell>, - /// Resolves the element type of an indexable type for index-constraint propagation. - /// Registered at construction; keeps the type-checker core free of type-specific logic. - /// See [`IndexElementFn`] for the contract. - index_element_fn: IndexElementFn, /// Type-inference and finalization hooks keyed by global slot index. /// Populated from the frozen RTL snapshot; empty for non-RTL call sites. call_hooks: Rc>, @@ -197,14 +193,12 @@ impl TypeChecker { pub fn new( root_types: Rc>>, call_hooks: Rc>, - index_element_fn: IndexElementFn, ) -> Self { Self { root_types, var_counter: Cell::new(0), subst: std::cell::RefCell::new(HashMap::new()), index_constraints: std::cell::RefCell::new(HashMap::new()), - index_element_fn, call_hooks, } } @@ -217,17 +211,17 @@ impl TypeChecker { } /// Binds a TypeVar to a concrete type in the substitution, then propagates - /// any pending index-call constraints registered by Step 9. + /// any pending index-call constraints registered for the series lookback pattern. /// - /// If `index_constraints[id]` is set and `index_element_fn` returns an element - /// type for `ty`, the result TypeVar is bound to that element type — connecting - /// the callee TypeVar to its element type without the eager over-constraint of - /// unification. For non-indexable types the result TypeVar stays unresolved. + /// When `index_constraints[id]` is set and `ty` is a `Series`, the result TypeVar + /// is bound to the element type — connecting the callee TypeVar to its element type + /// without the eager over-constraint of unification. Non-indexable types leave the + /// result TypeVar unresolved. fn bind_var(&self, id: u32, ty: StaticType) { self.subst.borrow_mut().insert(id, ty.clone()); let ret_id = self.index_constraints.borrow().get(&id).copied(); - if let (Some(ret_id), Some(elem_ty)) = (ret_id, (self.index_element_fn)(&ty)) { - self.subst.borrow_mut().insert(ret_id, elem_ty); + if let (Some(ret_id), StaticType::Series(elem)) = (ret_id, &ty) { + self.subst.borrow_mut().insert(ret_id, *elem.clone()); } } diff --git a/src/ast/environment.rs b/src/ast/environment.rs index 9a15a22..29de487 100644 --- a/src/ast/environment.rs +++ b/src/ast/environment.rs @@ -23,7 +23,6 @@ use crate::ast::compiler::macros::{MacroEvaluator, MacroExpander, MacroRegistry} use crate::ast::compiler::optimizer::Optimizer; use crate::ast::compiler::specializer::{FunctionRegistry, MonoCache, RtlLookupFunc, Specializer}; use crate::ast::rtl::{self, intrinsics}; -use crate::ast::rtl::series::series_element_type; use crate::ast::rtl::docs::{PipelineGenerator, RtlDocEntry, RtlRegistration}; use crate::ast::types::{ CommentLine, NativeFunction, NodeIdentity, Purity, SourceLocation, StaticType, Value, @@ -133,7 +132,7 @@ impl MacroEvaluator for RuntimeMacroEvaluator { let (bound_ast, captures, _, _) = Binder::bind_root(initial_scopes, initial_slot_count, self.fixed_scope_idx, node, &mut diag)?; let bound_ast = CapturePass::apply(bound_ast, &captures); - let checker = TypeChecker::new(self.root_types.clone(), Rc::clone(&self.call_hooks), series_element_type); + let checker = TypeChecker::new(self.root_types.clone(), Rc::clone(&self.call_hooks)); let typed_ast = checker.check(&bound_ast, &[], &mut diag); if diag.has_errors() { @@ -481,7 +480,7 @@ impl Environment { LambdaCollector::collect(&bound_ast, &mut self.function_registry.borrow_mut()); - let checker = TypeChecker::new(self.root_types.clone(), Rc::clone(&self.rtl.call_hooks), series_element_type); + let checker = TypeChecker::new(self.root_types.clone(), Rc::clone(&self.rtl.call_hooks)); let wrapped_ast = if let NodeKind::Lambda { .. } = bound_ast.kind { bound_ast } else { @@ -835,7 +834,7 @@ impl Environment { arg_types: &[StaticType]| -> Result<(Value, StaticType), String> { let mut diag = Diagnostics::new(); - let checker = TypeChecker::new(root_types.clone(), Rc::clone(&call_hooks), series_element_type); + let checker = TypeChecker::new(root_types.clone(), Rc::clone(&call_hooks)); // Monomorphization: re-type-check the function template with the concrete // call-site argument types, producing a specialized TypedNode. diff --git a/src/ast/rtl/series/mod.rs b/src/ast/rtl/series/mod.rs index 7a0251f..c0d0240 100644 --- a/src/ast/rtl/series/mod.rs +++ b/src/ast/rtl/series/mod.rs @@ -15,21 +15,6 @@ use crate::ast::types::{NativeFunction, NodeIdentity, Purity, Signature, SourceL // 4. Type-Inference Hooks (registered via RTL bootstrap, no name coupling) // ============================================================================ -/// Index-element hook for the `Series` type. -/// -/// Returns the element type of a `Series(inner)`, or `None` for all other types. -/// Registered with `TypeChecker` so that the core type-checker remains agnostic -/// about which concrete types support integer-index access. -/// -/// When `Stream` (or future indexable types) is added, extend this function -/// with additional match arms rather than touching the type-checker. -pub(crate) fn series_element_type(ty: &StaticType) -> Option { - match ty { - StaticType::Series(inner) => Some(*inner.clone()), - _ => None, - } -} - /// Post-call hook for `(series n)`. /// Replaces the `Series(Any)` return type with a fresh TypeVar so that /// subsequent `push` calls can unify the element type (HM inference).