Finish type checking and inferrence for arrays

This commit is contained in:
Sofia 2025-07-13 20:15:03 +03:00
parent b14a62bc34
commit 515c031f19
3 changed files with 58 additions and 19 deletions

View File

@ -93,6 +93,7 @@ pub fn compile(source: &str) -> Result<String, ReidError> {
let state = mir_context.pass(&mut TypeInference { refs: &refs }); let state = mir_context.pass(&mut TypeInference { refs: &refs });
dbg!(&state, &refs); dbg!(&state, &refs);
dbg!(&mir_context);
println!("{}", &mir_context); println!("{}", &mir_context);
let state = mir_context.pass(&mut TypeCheck { refs: &refs }); let state = mir_context.pass(&mut TypeCheck { refs: &refs });

View File

@ -254,17 +254,19 @@ impl Expression {
) -> Result<TypeKind, ErrorKind> { ) -> Result<TypeKind, ErrorKind> {
match &mut self.0 { match &mut self.0 {
ExprKind::Variable(var_ref) => { ExprKind::Variable(var_ref) => {
let existing = state.or_else( let existing = state
state .or_else(
.scope state
.variables .scope
.get(&var_ref.1) .variables
.map(|var| &var.ty) .get(&var_ref.1)
.cloned() .map(|var| &var.ty)
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())), .cloned()
Vague(Unknown), .ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
var_ref.2, Vague(Unknown),
); var_ref.2,
)
.resolve_hinted(hints);
// Update typing to be more accurate // Update typing to be more accurate
var_ref.0 = state.or_else( var_ref.0 = state.or_else(
@ -339,9 +341,9 @@ impl Expression {
.collapse_into(&function_call.return_type.resolve_hinted(hints))?; .collapse_into(&function_call.return_type.resolve_hinted(hints))?;
// Update typing to be more accurate // Update typing to be more accurate
function_call.return_type = ret_t.clone(); function_call.return_type = ret_t.clone();
Ok(ret_t) Ok(ret_t.resolve_hinted(hints))
} else { } else {
Ok(function_call.return_type.clone()) Ok(function_call.return_type.clone().resolve_hinted(hints))
} }
} }
ExprKind::If(IfExpression(cond, lhs, rhs)) => { ExprKind::If(IfExpression(cond, lhs, rhs)) => {
@ -379,9 +381,15 @@ impl Expression {
} }
ExprKind::Block(block) => block.typecheck(state, &hints, hint_t), ExprKind::Block(block) => block.typecheck(state, &hints, hint_t),
ExprKind::Index(expression, idx) => { ExprKind::Index(expression, idx) => {
// Try to unwrap hint type from array if possible
let hint_t = hint_t.map(|t| match t {
Array(type_kind, _) => &type_kind,
_ => t,
});
let expr_t = expression.typecheck(state, hints, hint_t)?; let expr_t = expression.typecheck(state, hints, hint_t)?;
if let TypeKind::Array(elem_t, len) = expr_t { if let TypeKind::Array(elem_t, len) = expr_t {
if len >= *idx { if len < *idx {
return Err(ErrorKind::IndexOutOfBounds(*idx, len)); return Err(ErrorKind::IndexOutOfBounds(*idx, len));
} }
Ok(*elem_t) Ok(*elem_t)
@ -390,6 +398,12 @@ impl Expression {
} }
} }
ExprKind::Array(expressions) => { ExprKind::Array(expressions) => {
// Try to unwrap hint type from array if possible
let hint_t = hint_t.map(|t| match t {
Array(type_kind, _) => &type_kind,
_ => t,
});
let mut expr_result = try_all( let mut expr_result = try_all(
expressions expressions
.iter_mut() .iter_mut()
@ -403,7 +417,7 @@ impl Expression {
for other in iter { for other in iter {
state.ok(first.collapse_into(other), self.1); state.ok(first.collapse_into(other), self.1);
} }
Ok(first.clone()) Ok(Array(Box::new(first.clone()), expressions.len() as u64))
} else { } else {
Ok(Array(Box::new(Void), 0)) Ok(Array(Box::new(Void), 0))
} }
@ -479,9 +493,13 @@ impl TypeKind {
} }
fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind { fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind {
match self { let resolved = match self {
Vague(TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(), Vague(TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(),
_ => self.clone(), _ => self.clone(),
};
match resolved {
Array(t, len) => Array(Box::new(t.resolve_hinted(hints)), len),
_ => resolved,
} }
} }
} }

View File

@ -4,6 +4,8 @@ use std::{
rc::Rc, rc::Rc,
}; };
use crate::mir::VagueType;
use super::{ use super::{
typecheck::{Collapsable, ErrorKind}, typecheck::{Collapsable, ErrorKind},
BinaryOperator, TypeKind, BinaryOperator, TypeKind,
@ -15,12 +17,22 @@ pub struct TypeRef<'scope>(TypeIdRef, &'scope ScopeTypeRefs<'scope>);
impl<'scope> TypeRef<'scope> { impl<'scope> TypeRef<'scope> {
pub unsafe fn resolve_type(&self) -> TypeKind { pub unsafe fn resolve_type(&self) -> TypeKind {
unsafe { unsafe {
self.1 let resolved = self
.1
.types .types
.hints .hints
.borrow() .borrow()
.get_unchecked(*self.0.borrow()) .get_unchecked(*self.0.borrow())
.clone() .clone();
match resolved {
TypeKind::Array(elem_ty, len) => {
let resolved_elem_ty = self.1.from_type(&elem_ty).unwrap().resolve_type();
dbg!(&elem_ty, &resolved_elem_ty);
TypeKind::Array(Box::new(resolved_elem_ty), len)
}
_ => resolved,
}
} }
} }
@ -96,7 +108,15 @@ impl TypeRefs {
pub fn retrieve_type(&self, idx: usize) -> Option<TypeKind> { pub fn retrieve_type(&self, idx: usize) -> Option<TypeKind> {
let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() }; let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() };
self.hints.borrow().get(inner_idx).cloned() self.hints
.borrow()
.get(inner_idx)
.cloned()
.map(|t| match t {
TypeKind::Vague(VagueType::TypeRef(id)) => self.retrieve_type(id),
_ => Some(t),
})
.flatten()
} }
} }