Refactor type checking for globals
Introduces a `global_types` field to `TypeContext` and updates the `TypeChecker` to pass it down. This allows type checking to correctly infer and set types for global variables, removing the previous hardcoded `StaticType::Any` for global addresses.
This commit is contained in:
@@ -11,6 +11,8 @@ struct TypeContext<'a> {
|
|||||||
slots: Vec<StaticType>,
|
slots: Vec<StaticType>,
|
||||||
/// Types of captured variables (passed from outer scope)
|
/// Types of captured variables (passed from outer scope)
|
||||||
upvalue_types: Vec<StaticType>,
|
upvalue_types: Vec<StaticType>,
|
||||||
|
/// Access to global types for unified resolution
|
||||||
|
global_types: &'a std::cell::RefCell<HashMap<u32, StaticType>>,
|
||||||
/// The expected parameters of the current function (for 'again' validation)
|
/// The expected parameters of the current function (for 'again' validation)
|
||||||
current_params_ty: Option<StaticType>,
|
current_params_ty: Option<StaticType>,
|
||||||
}
|
}
|
||||||
@@ -19,12 +21,14 @@ impl<'a> TypeContext<'a> {
|
|||||||
fn new(
|
fn new(
|
||||||
slot_count: u32,
|
slot_count: u32,
|
||||||
upvalue_types: Vec<StaticType>,
|
upvalue_types: Vec<StaticType>,
|
||||||
|
global_types: &'a std::cell::RefCell<HashMap<u32, StaticType>>,
|
||||||
parent: Option<&'a TypeContext<'a>>,
|
parent: Option<&'a TypeContext<'a>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
_parent: parent,
|
_parent: parent,
|
||||||
slots: vec![StaticType::Any; slot_count as usize],
|
slots: vec![StaticType::Any; slot_count as usize],
|
||||||
upvalue_types,
|
upvalue_types,
|
||||||
|
global_types,
|
||||||
current_params_ty: None,
|
current_params_ty: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +40,12 @@ impl<'a> TypeContext<'a> {
|
|||||||
.get(idx as usize)
|
.get(idx as usize)
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or(StaticType::Any),
|
.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
|
Address::Upvalue(idx) => self
|
||||||
.upvalue_types
|
.upvalue_types
|
||||||
.get(idx as usize)
|
.get(idx as usize)
|
||||||
@@ -45,11 +54,19 @@ impl<'a> TypeContext<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_local_type(&mut self, idx: u32, ty: StaticType) {
|
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) {
|
if let Some(slot) = self.slots.get_mut(idx as usize) {
|
||||||
*slot = ty;
|
*slot = ty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Address::Global(idx) => {
|
||||||
|
self.global_types.borrow_mut().insert(idx, ty);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeChecker {
|
pub struct TypeChecker {
|
||||||
@@ -76,8 +93,9 @@ impl TypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Create the specialized context
|
// 2. Create the specialized context
|
||||||
let root_ctx = TypeContext::new(0, vec![], None);
|
let root_ctx = TypeContext::new(0, vec![], &self.global_types, None);
|
||||||
let mut lambda_ctx = TypeContext::new(64, upvalue_types, Some(&root_ctx));
|
let mut lambda_ctx =
|
||||||
|
TypeContext::new(64, upvalue_types, &self.global_types, Some(&root_ctx));
|
||||||
|
|
||||||
// 3. INJECT specialized argument types into slots
|
// 3. INJECT specialized argument types into slots
|
||||||
let arg_tuple_ty = if arg_types.is_empty() {
|
let arg_tuple_ty = if arg_types.is_empty() {
|
||||||
@@ -147,15 +165,7 @@ impl TypeChecker {
|
|||||||
captured_by,
|
captured_by,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
match addr {
|
ctx.set_type(addr, specialized_ty.clone());
|
||||||
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());
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
(
|
(
|
||||||
BoundKind::Define {
|
BoundKind::Define {
|
||||||
name,
|
name,
|
||||||
@@ -261,20 +271,11 @@ impl TypeChecker {
|
|||||||
} => {
|
} => {
|
||||||
let val_typed = self.check_node(*value, ctx)?;
|
let val_typed = self.check_node(*value, ctx)?;
|
||||||
let ty = val_typed.ty.clone();
|
let ty = val_typed.ty.clone();
|
||||||
|
ctx.set_type(addr, 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());
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
(
|
||||||
BoundKind::Define {
|
BoundKind::Define {
|
||||||
name,
|
name: name.clone(),
|
||||||
addr,
|
addr,
|
||||||
kind: decl_kind,
|
kind: decl_kind,
|
||||||
value: Box::new(val_typed),
|
value: Box::new(val_typed),
|
||||||
@@ -285,15 +286,7 @@ impl TypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BoundKind::Get { addr, name } => {
|
BoundKind::Get { addr, name } => {
|
||||||
let ty = if let Address::Global(idx) = addr {
|
let ty = ctx.get_type(addr);
|
||||||
self.global_types
|
|
||||||
.borrow()
|
|
||||||
.get(&idx)
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or(StaticType::Any)
|
|
||||||
} else {
|
|
||||||
ctx.get_type(addr)
|
|
||||||
};
|
|
||||||
(
|
(
|
||||||
BoundKind::Get {
|
BoundKind::Get {
|
||||||
addr,
|
addr,
|
||||||
@@ -306,12 +299,7 @@ impl TypeChecker {
|
|||||||
BoundKind::Set { addr, value } => {
|
BoundKind::Set { addr, value } => {
|
||||||
let val_typed = self.check_node(*value, ctx)?;
|
let val_typed = self.check_node(*value, ctx)?;
|
||||||
let ty = val_typed.ty.clone();
|
let ty = val_typed.ty.clone();
|
||||||
|
ctx.set_type(addr, 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
(
|
(
|
||||||
BoundKind::Set {
|
BoundKind::Set {
|
||||||
@@ -394,7 +382,8 @@ impl TypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Create nested context for lambda body
|
// 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
|
// 3. Check parameters and body
|
||||||
let params_typed =
|
let params_typed =
|
||||||
|
|||||||
Reference in New Issue
Block a user