Add typechecking for arrays

This commit is contained in:
Sofia 2025-07-13 19:39:43 +03:00
parent 4f8153643b
commit b14a62bc34
3 changed files with 60 additions and 8 deletions

View File

@ -2,6 +2,7 @@
//! passes. Passes can be performed on Reid MIR to e.g. typecheck the code. //! passes. Passes can be performed on Reid MIR to e.g. typecheck the code.
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::Infallible;
use std::error::Error as STDError; use std::error::Error as STDError;
use super::*; use super::*;
@ -166,6 +167,16 @@ impl<'st, 'sc, TError: STDError + Clone> PassState<'st, 'sc, TError> {
self.state.ok(result, meta) self.state.ok(result, meta)
} }
pub fn note_errors<TMeta: Into<Metadata> + Clone>(
&mut self,
errors: &Vec<TError>,
meta: TMeta,
) {
for error in errors {
self.ok::<_, Infallible>(Err(error.clone()), meta.clone().into());
}
}
pub fn inner(&mut self) -> PassState<TError> { pub fn inner(&mut self) -> PassState<TError> {
self.inner.push(self.scope.inner()); self.inner.push(self.scope.inner());
let scope = self.inner.last_mut().unwrap(); let scope = self.inner.last_mut().unwrap();

View File

@ -42,6 +42,8 @@ pub enum ErrorKind {
BranchTypesDiffer(TypeKind, TypeKind), BranchTypesDiffer(TypeKind, TypeKind),
#[error("Attempted to index a non-array type of {0}")] #[error("Attempted to index a non-array type of {0}")]
TriedIndexingNonArray(TypeKind), TriedIndexingNonArray(TypeKind),
#[error("Index {0} out of bounds ({1})")]
IndexOutOfBounds(u64, u64),
} }
/// 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
@ -376,8 +378,42 @@ impl Expression {
Ok(collapsed) Ok(collapsed)
} }
ExprKind::Block(block) => block.typecheck(state, &hints, hint_t), ExprKind::Block(block) => block.typecheck(state, &hints, hint_t),
ExprKind::Index(expression, _) => todo!("typechecking for index expression"), ExprKind::Index(expression, idx) => {
ExprKind::Array(expressions) => todo!("typechecking for array expression"), let expr_t = expression.typecheck(state, hints, hint_t)?;
if let TypeKind::Array(elem_t, len) = expr_t {
if len >= *idx {
return Err(ErrorKind::IndexOutOfBounds(*idx, len));
}
Ok(*elem_t)
} else {
Err(ErrorKind::TriedIndexingNonArray(expr_t))
}
}
ExprKind::Array(expressions) => {
let mut expr_result = try_all(
expressions
.iter_mut()
.map(|e| e.typecheck(state, hints, hint_t))
.collect(),
);
match &mut expr_result {
Ok(expr_types) => {
let mut iter = expr_types.iter_mut();
if let Some(first) = iter.next() {
for other in iter {
state.ok(first.collapse_into(other), self.1);
}
Ok(first.clone())
} else {
Ok(Array(Box::new(Void), 0))
}
}
Err(errors) => {
state.note_errors(errors, self.1);
Ok(Array(Box::new(Vague(Unknown)), expressions.len() as u64))
}
}
}
} }
} }
} }

View File

@ -6,7 +6,7 @@
use std::{convert::Infallible, iter}; use std::{convert::Infallible, iter};
use crate::util::try_all; use crate::{mir::TypeKind, util::try_all};
use super::{ use super::{
pass::{Pass, PassState, ScopeVariable}, pass::{Pass, PassState, ScopeVariable},
@ -293,14 +293,19 @@ impl Expression {
)) ))
.unwrap()) .unwrap())
} else { } else {
todo!(); Ok(type_refs
.from_type(&Array(Box::new(TypeKind::Void), 0))
.unwrap())
} }
} }
Err(errors) => { Err(errors) => {
for error in errors { state.note_errors(errors, self.1);
state.ok::<_, Infallible>(Err(error.clone()), self.1); Ok(type_refs
} .from_type(&TypeKind::Array(
todo!(); Box::new(TypeKind::Vague(Unknown)),
expressions.len() as u64,
))
.unwrap())
} }
} }
} }