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