Add typechecking for arrays
This commit is contained in:
parent
4f8153643b
commit
b14a62bc34
@ -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();
|
||||||
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user