Remove IndexElementFn and series_element_type
The `IndexElementFn` trait and its associated `series_element_type` function have been removed. The `TypeChecker` now directly inspects the `StaticType::Series` variant to extract the element type when propagating index constraints. This simplifies the type-checking logic by removing an unnecessary layer of indirection and adhering to the project rule of keeping the AST simple and pushing complexity into the system.
This commit is contained in:
@@ -35,16 +35,6 @@ pub trait InferenceAccess {
|
||||
fn get_slot_type(&self, addr: Address<VirtualId>) -> 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<StaticType>;
|
||||
|
||||
/// 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(
|
||||
|
||||
@@ -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<HashMap<u32, u32>>,
|
||||
/// 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<HashMap<u32, CallHooks>>,
|
||||
@@ -197,14 +193,12 @@ impl TypeChecker {
|
||||
pub fn new(
|
||||
root_types: Rc<std::cell::RefCell<Vec<StaticType>>>,
|
||||
call_hooks: Rc<HashMap<u32, CallHooks>>,
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<StaticType> {
|
||||
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).
|
||||
|
||||
Reference in New Issue
Block a user