From b14a62bc34efef8c5d21e480f28ce7028d38d92c Mon Sep 17 00:00:00 2001 From: sofia Date: Sun, 13 Jul 2025 19:39:43 +0300 Subject: [PATCH] Add typechecking for arrays --- reid/src/mir/pass.rs | 11 ++++++++++ reid/src/mir/typecheck.rs | 40 +++++++++++++++++++++++++++++++++-- reid/src/mir/typeinference.rs | 17 +++++++++------ 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/reid/src/mir/pass.rs b/reid/src/mir/pass.rs index 8da3abc..ff1e421 100644 --- a/reid/src/mir/pass.rs +++ b/reid/src/mir/pass.rs @@ -2,6 +2,7 @@ //! passes. Passes can be performed on Reid MIR to e.g. typecheck the code. use std::collections::HashMap; +use std::convert::Infallible; use std::error::Error as STDError; use super::*; @@ -166,6 +167,16 @@ impl<'st, 'sc, TError: STDError + Clone> PassState<'st, 'sc, TError> { self.state.ok(result, meta) } + pub fn note_errors + Clone>( + &mut self, + errors: &Vec, + meta: TMeta, + ) { + for error in errors { + self.ok::<_, Infallible>(Err(error.clone()), meta.clone().into()); + } + } + pub fn inner(&mut self) -> PassState { self.inner.push(self.scope.inner()); let scope = self.inner.last_mut().unwrap(); diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 3c48be6..e8d070b 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -42,6 +42,8 @@ pub enum ErrorKind { BranchTypesDiffer(TypeKind, TypeKind), #[error("Attempted to index a non-array type of {0}")] 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 @@ -376,8 +378,42 @@ impl Expression { Ok(collapsed) } ExprKind::Block(block) => block.typecheck(state, &hints, hint_t), - ExprKind::Index(expression, _) => todo!("typechecking for index expression"), - ExprKind::Array(expressions) => todo!("typechecking for array expression"), + ExprKind::Index(expression, idx) => { + 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)) + } + } + } } } } diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index 42ea667..8920d3b 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -6,7 +6,7 @@ use std::{convert::Infallible, iter}; -use crate::util::try_all; +use crate::{mir::TypeKind, util::try_all}; use super::{ pass::{Pass, PassState, ScopeVariable}, @@ -293,14 +293,19 @@ impl Expression { )) .unwrap()) } else { - todo!(); + Ok(type_refs + .from_type(&Array(Box::new(TypeKind::Void), 0)) + .unwrap()) } } Err(errors) => { - for error in errors { - state.ok::<_, Infallible>(Err(error.clone()), self.1); - } - todo!(); + state.note_errors(errors, self.1); + Ok(type_refs + .from_type(&TypeKind::Array( + Box::new(TypeKind::Vague(Unknown)), + expressions.len() as u64, + )) + .unwrap()) } } }