Perform type inference for array and indexing expressions

This commit is contained in:
Sofia 2025-07-13 19:26:20 +03:00
parent 64f07002b4
commit 4f8153643b
3 changed files with 51 additions and 3 deletions

View File

@ -40,6 +40,8 @@ pub enum ErrorKind {
TypeNotInferrable(TypeKind), TypeNotInferrable(TypeKind),
#[error("Expected branch type to be {0}, found {1} instead")] #[error("Expected branch type to be {0}, found {1} instead")]
BranchTypesDiffer(TypeKind, TypeKind), BranchTypesDiffer(TypeKind, TypeKind),
#[error("Attempted to index a non-array type of {0}")]
TriedIndexingNonArray(TypeKind),
} }
/// Struct used to implement a type-checking pass that can be performed on the /// Struct used to implement a type-checking pass that can be performed on the

View File

@ -4,7 +4,9 @@
//! must then be passed through TypeCheck with the same [`TypeRefs`] in order to //! must then be passed through TypeCheck with the same [`TypeRefs`] in order to
//! place the correct types from the IDs and check that there are no issues. //! place the correct types from the IDs and check that there are no issues.
use std::iter; use std::{convert::Infallible, iter};
use crate::util::try_all;
use super::{ use super::{
pass::{Pass, PassState, ScopeVariable}, pass::{Pass, PassState, ScopeVariable},
@ -261,8 +263,47 @@ impl Expression {
ReturnKind::Soft => Ok(block_ref.1), ReturnKind::Soft => Ok(block_ref.1),
} }
} }
ExprKind::Index(expression, _) => todo!("type inference for index expression"), ExprKind::Index(expression, _) => {
ExprKind::Array(expressions) => todo!("type inference for array expression"), let expr_ty = expression.infer_types(state, type_refs)?;
let kind = unsafe { expr_ty.resolve_type() };
match kind {
Array(type_kind, _) => Ok(type_refs.from_type(&type_kind).unwrap()),
_ => Err(ErrorKind::TriedIndexingNonArray(kind)),
}
}
ExprKind::Array(expressions) => {
let mut expr_types_result = try_all(
expressions
.iter_mut()
.map(|e| (*e).infer_types(state, type_refs))
.collect(),
);
match &mut expr_types_result {
Ok(expr_types) => {
let mut iter = expr_types.iter_mut();
if let Some(first) = iter.next() {
while let Some(other) = iter.next() {
first.narrow(other);
}
Ok(type_refs
.from_type(&Array(
Box::new(first.as_type()),
expressions.len() as u64,
))
.unwrap())
} else {
todo!();
}
}
Err(errors) => {
for error in errors {
state.ok::<_, Infallible>(Err(error.clone()), self.1);
}
todo!();
}
}
}
} }
} }
} }

View File

@ -140,6 +140,11 @@ impl<'outer> ScopeTypeRefs<'outer> {
self.types.type_refs.borrow().get(inner_idx).cloned()? self.types.type_refs.borrow().get(inner_idx).cloned()?
} }
TypeKind::Vague(_) => self.types.new(ty), TypeKind::Vague(_) => self.types.new(ty),
TypeKind::Array(elem_ty, length) => {
let elem_ty = self.from_type(elem_ty)?;
self.types
.new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length))
}
_ => { _ => {
if let Some(ty_ref) = self.types.find(ty) { if let Some(ty_ref) = self.types.find(ty) {
ty_ref ty_ref