diff --git a/src/ast/compiler/type_checker.rs b/src/ast/compiler/type_checker.rs index 31d8adb..5b20680 100644 --- a/src/ast/compiler/type_checker.rs +++ b/src/ast/compiler/type_checker.rs @@ -11,6 +11,8 @@ struct TypeContext<'a> { slots: Vec, /// Types of captured variables (passed from outer scope) upvalue_types: Vec, + /// Access to global types for unified resolution + global_types: &'a std::cell::RefCell>, /// The expected parameters of the current function (for 'again' validation) current_params_ty: Option, } @@ -19,12 +21,14 @@ impl<'a> TypeContext<'a> { fn new( slot_count: u32, upvalue_types: Vec, + global_types: &'a std::cell::RefCell>, parent: Option<&'a TypeContext<'a>>, ) -> Self { Self { _parent: parent, slots: vec![StaticType::Any; slot_count as usize], upvalue_types, + global_types, current_params_ty: None, } } @@ -36,7 +40,12 @@ impl<'a> TypeContext<'a> { .get(idx as usize) .cloned() .unwrap_or(StaticType::Any), - Address::Global(_) => StaticType::Any, // Globals are dynamic for now + Address::Global(idx) => self + .global_types + .borrow() + .get(&idx) + .cloned() + .unwrap_or(StaticType::Any), Address::Upvalue(idx) => self .upvalue_types .get(idx as usize) @@ -45,9 +54,17 @@ impl<'a> TypeContext<'a> { } } - fn set_local_type(&mut self, idx: u32, ty: StaticType) { - if let Some(slot) = self.slots.get_mut(idx as usize) { - *slot = ty; + fn set_type(&mut self, addr: Address, ty: StaticType) { + match addr { + Address::Local(idx) => { + if let Some(slot) = self.slots.get_mut(idx as usize) { + *slot = ty; + } + } + Address::Global(idx) => { + self.global_types.borrow_mut().insert(idx, ty); + } + _ => {} } } } @@ -76,8 +93,9 @@ impl TypeChecker { } // 2. Create the specialized context - let root_ctx = TypeContext::new(0, vec![], None); - let mut lambda_ctx = TypeContext::new(64, upvalue_types, Some(&root_ctx)); + let root_ctx = TypeContext::new(0, vec![], &self.global_types, None); + let mut lambda_ctx = + TypeContext::new(64, upvalue_types, &self.global_types, Some(&root_ctx)); // 3. INJECT specialized argument types into slots let arg_tuple_ty = if arg_types.is_empty() { @@ -147,15 +165,7 @@ impl TypeChecker { captured_by, .. } => { - match addr { - Address::Local(slot) => ctx.set_local_type(slot, specialized_ty.clone()), - Address::Global(global_index) => { - self.global_types - .borrow_mut() - .insert(global_index, specialized_ty.clone()); - } - _ => {} - } + ctx.set_type(addr, specialized_ty.clone()); ( BoundKind::Define { name, @@ -261,20 +271,11 @@ impl TypeChecker { } => { let val_typed = self.check_node(*value, ctx)?; let ty = val_typed.ty.clone(); - - match addr { - Address::Local(slot) => ctx.set_local_type(slot, ty.clone()), - Address::Global(global_index) => { - self.global_types - .borrow_mut() - .insert(global_index, ty.clone()); - } - _ => {} - } + ctx.set_type(addr, ty.clone()); ( BoundKind::Define { - name, + name: name.clone(), addr, kind: decl_kind, value: Box::new(val_typed), @@ -285,15 +286,7 @@ impl TypeChecker { } BoundKind::Get { addr, name } => { - let ty = if let Address::Global(idx) = addr { - self.global_types - .borrow() - .get(&idx) - .cloned() - .unwrap_or(StaticType::Any) - } else { - ctx.get_type(addr) - }; + let ty = ctx.get_type(addr); ( BoundKind::Get { addr, @@ -306,12 +299,7 @@ impl TypeChecker { BoundKind::Set { addr, value } => { let val_typed = self.check_node(*value, ctx)?; let ty = val_typed.ty.clone(); - - if let Address::Local(idx) = addr { - ctx.set_local_type(idx, ty.clone()); - } else if let Address::Global(idx) = addr { - self.global_types.borrow_mut().insert(idx, ty.clone()); - } + ctx.set_type(addr, ty.clone()); ( BoundKind::Set { @@ -394,7 +382,8 @@ impl TypeChecker { } // 2. Create nested context for lambda body - let mut lambda_ctx = TypeContext::new(64, upvalue_types, Some(ctx)); + let mut lambda_ctx = + TypeContext::new(64, upvalue_types, ctx.global_types, Some(ctx)); // 3. Check parameters and body let params_typed =