diff --git a/Cargo.lock b/Cargo.lock index a271023..2be0314 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,7 +20,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "thp" -version = "0.0.9" +version = "0.0.10" dependencies = [ "colored", ] diff --git a/Cargo.toml b/Cargo.toml index 7a7ae36..c4de58b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "thp" -version = "0.0.9" +version = "0.0.10" edition = "2021" diff --git a/src/semantic/checks/binding.rs b/src/semantic/checks/binding.rs new file mode 100644 index 0000000..a00b7ec --- /dev/null +++ b/src/semantic/checks/binding.rs @@ -0,0 +1,58 @@ +use crate::{ + error_handling::{semantic_error::SemanticError, MistiError}, + semantic::{impls::SemanticCheck, symbol_table::SymbolEntry}, + syntax::ast::var_binding::Binding, +}; + +impl SemanticCheck for Binding<'_> { + fn check_semantics( + &self, + scope: &crate::semantic::symbol_table::SymbolTable, + ) -> Result<(), crate::error_handling::MistiError> { + let binding_name = &self.identifier.value; + + // TODO: Define if variables can be redeclared. + // If so, it is irrelevant to check if the variable is already defined + if scope.test(binding_name) { + let error = SemanticError { + error_start: self.identifier.position, + error_end: self.identifier.get_end_position(), + reason: format!( + "Duplicated: A symbol with name {} was already defined", + binding_name + ), + }; + + return Err(MistiError::Semantic(error)); + } + + todo!(""); + /* + let expression_datatype = self.expression.get_type(); + + let datatype = match self.datatype { + Some(t) => t.value.clone(), + // If the datatype is not defined, we use the expression datatype + None => expression_datatype.clone(), + }; + + // Both the declared & actual datatypes must be the same + if datatype != expression_datatype { + let error = SemanticError { + error_start: self.identifier.position, + error_end: self.identifier.get_end_position(), + reason: format!( + "The variable `{}` was declared as `{}` but its expression has type `{}`", + binding_name, datatype, expression_datatype + ), + }; + + return Err(MistiError::Semantic(error)); + } + + scope.insert(binding_name.clone(), SymbolEntry::new_variable(datatype)); + + Ok(()) + */ + } +} diff --git a/src/semantic/checks/function_declaration.rs b/src/semantic/checks/function_declaration.rs new file mode 100644 index 0000000..97cb697 --- /dev/null +++ b/src/semantic/checks/function_declaration.rs @@ -0,0 +1,38 @@ +use crate::{ + error_handling::{semantic_error::SemanticError, MistiError}, + semantic::{impls::SemanticCheck, symbol_table::SymbolEntry}, + syntax::ast::FunctionDeclaration, +}; + +impl SemanticCheck for FunctionDeclaration<'_> { + fn check_semantics( + &self, + scope: &crate::semantic::symbol_table::SymbolTable, + ) -> Result<(), crate::error_handling::MistiError> { + let function_name = self.identifier.value.clone(); + + // Check that the function is not already defined + if scope.test(&function_name) { + let error = SemanticError { + error_start: self.identifier.position, + error_end: self.identifier.get_end_position(), + reason: format!( + "Duplicated: A symbol with name {} was already defined", + function_name + ), + }; + + return Err(MistiError::Semantic(error)); + } + + // TODO: Check the return type of the function + // TODO: Check the return type of the function body + + scope.insert( + function_name, + SymbolEntry::new_function(vec![], "Unit".into()), + ); + + Ok(()) + } +} diff --git a/src/semantic/checks/mod.rs b/src/semantic/checks/mod.rs new file mode 100644 index 0000000..959ff3d --- /dev/null +++ b/src/semantic/checks/mod.rs @@ -0,0 +1,2 @@ +pub mod binding; +pub mod function_declaration; diff --git a/src/semantic/mod.rs b/src/semantic/mod.rs index 37045d2..a90af5c 100644 --- a/src/semantic/mod.rs +++ b/src/semantic/mod.rs @@ -2,6 +2,7 @@ use crate::{error_handling::MistiError, syntax::ast::ModuleAST}; mod impls; mod symbol_table; +mod checks; use impls::SemanticCheck;