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.
 | ||||
| 
 | ||||
| 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<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> { | ||||
|         self.inner.push(self.scope.inner()); | ||||
|         let scope = self.inner.last_mut().unwrap(); | ||||
|  | ||||
| @ -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)) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -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()) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user