Add function double-definition checking
This commit is contained in:
		
							parent
							
								
									954f3438d3
								
							
						
					
					
						commit
						89002f34e4
					
				| @ -129,7 +129,9 @@ pub fn perform_all_passes<'map>( | ||||
|     dbg!(&context); | ||||
| 
 | ||||
|     for module in &mut context.modules { | ||||
|         module.1.functions.extend(form_intrinsics()); | ||||
|         for intrinsic in form_intrinsics() { | ||||
|             module.1.functions.insert(0, intrinsic); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     #[cfg(debug_assertions)] | ||||
|  | ||||
| @ -26,8 +26,8 @@ pub enum ErrorKind { | ||||
|     FunctionNotDefined(String), | ||||
|     #[error("Expected a return type of {0}, got {1} instead")] | ||||
|     ReturnTypeMismatch(TypeKind, TypeKind), | ||||
|     #[error("Function already defined: {0}")] | ||||
|     FunctionAlreadyDefined(String), | ||||
|     #[error("Function {0} already defined {1}")] | ||||
|     FunctionAlreadyDefined(String, ErrorTypedefKind), | ||||
|     #[error("Variable already defined: {0}")] | ||||
|     VariableAlreadyDefined(String), | ||||
|     #[error("Variable {0} is not declared as mutable")] | ||||
| @ -80,6 +80,16 @@ pub struct TypeCheck<'t> { | ||||
| 
 | ||||
| type TypecheckPassState<'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>; | ||||
| 
 | ||||
| #[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum ErrorTypedefKind { | ||||
|     #[error("locally")] | ||||
|     Local, | ||||
|     #[error("as an extern")] | ||||
|     Extern, | ||||
|     #[error("as an intrinsic")] | ||||
|     Intrinsic, | ||||
| } | ||||
| 
 | ||||
| impl<'t> Pass for TypeCheck<'t> { | ||||
|     type Data = (); | ||||
|     type TError = ErrorKind; | ||||
| @ -116,10 +126,9 @@ impl<'t> Pass for TypeCheck<'t> { | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let seen = HashSet::new(); | ||||
|         for typedef in defmap.values() { | ||||
|             let mut curr = seen.clone(); | ||||
|             curr.insert(typedef.name.clone()); | ||||
|             let mut seen_types = HashSet::new(); | ||||
|             seen_types.insert(typedef.name.clone()); | ||||
|             check_typedefs_for_recursion(&defmap, typedef, HashSet::new(), &mut state); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -4,13 +4,13 @@ | ||||
| //! 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.
 | ||||
| 
 | ||||
| use std::{convert::Infallible, iter}; | ||||
| use std::{collections::HashMap, convert::Infallible, iter}; | ||||
| 
 | ||||
| use crate::{mir::TypeKind, util::try_all}; | ||||
| 
 | ||||
| use super::{ | ||||
|     pass::{Pass, PassResult, PassState}, | ||||
|     typecheck::ErrorKind, | ||||
|     typecheck::{ErrorKind, ErrorTypedefKind}, | ||||
|     typerefs::{ScopeTypeRefs, TypeRef, TypeRefs}, | ||||
|     Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, | ||||
|     IfExpression, Module, ReturnKind, StmtKind, | ||||
| @ -33,6 +33,28 @@ impl<'t> Pass for TypeInference<'t> { | ||||
|     type TError = ErrorKind; | ||||
| 
 | ||||
|     fn module(&mut self, module: &mut Module, mut state: TypeInferencePassState) -> PassResult { | ||||
|         let mut seen_functions = HashMap::new(); | ||||
|         for function in &mut module.functions { | ||||
|             if let Some(kind) = seen_functions.get(&function.name) { | ||||
|                 state.note_errors( | ||||
|                     &vec![ErrorKind::FunctionAlreadyDefined( | ||||
|                         function.name.clone(), | ||||
|                         *kind, | ||||
|                     )], | ||||
|                     function.signature(), | ||||
|                 ); | ||||
|             } else { | ||||
|                 seen_functions.insert( | ||||
|                     function.name.clone(), | ||||
|                     match function.kind { | ||||
|                         FunctionDefinitionKind::Local(..) => ErrorTypedefKind::Local, | ||||
|                         FunctionDefinitionKind::Extern(..) => ErrorTypedefKind::Extern, | ||||
|                         FunctionDefinitionKind::Intrinsic(..) => ErrorTypedefKind::Intrinsic, | ||||
|                     }, | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         for function in &mut module.functions { | ||||
|             let res = function.infer_types(&self.refs, &mut state.inner()); | ||||
|             state.ok(res, function.block_meta()); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user