Infer datatype of another identifier

master
Araozu 2024-05-05 16:01:11 -05:00
parent c8d16fc77f
commit 4f7fa0f5e3
5 changed files with 62 additions and 8 deletions

View File

@ -8,6 +8,7 @@
codegen section can focus only in codegen, not in codegen section can focus only in codegen, not in
translation of thp->php. translation of thp->php.
- Parse __more__ binary operators - Parse __more__ binary operators
- Store tokens for the semantic analysis phase, to have actual error reporting
- Parse more complex bindings - Parse more complex bindings
- Watch mode - Watch mode
- Improve error messages - Improve error messages
@ -24,8 +25,12 @@
## v0.0.12 ## v0.0.12
- [x] Infer datatype of an identifier
- [ ] Infer datatype of a binary operatior
- [ ] Infer datatype of unary operator
- [ ] Infer datatype of a function call expression - [ ] Infer datatype of a function call expression
- [ ] Infer datatype of binary operators - [ ] Infer datatype of binary operators
- [ ] Infer Int & Float as different types
- [ ] Execute semantic analysis on the function's block - [ ] Execute semantic analysis on the function's block
- [ ] Write tests - [ ] Write tests
- [ ] Abstract the parsing of datatypes, such that in the future generics can be implemented in a single place - [ ] Abstract the parsing of datatypes, such that in the future generics can be implemented in a single place

View File

@ -28,7 +28,7 @@ impl SemanticCheck for Binding<'_> {
// This gets the datatype of the assigned expression, // This gets the datatype of the assigned expression,
// to compare it later with the declared datatype. // to compare it later with the declared datatype.
let expression_datatype = self.expression.get_type(); let expression_datatype = self.expression.get_type(scope)?;
let datatype = match self.datatype { let datatype = match self.datatype {
Some(t) => t.value.clone(), Some(t) => t.value.clone(),

View File

@ -45,6 +45,11 @@ impl SymbolTable {
pub fn test(&self, key: &String) -> bool { pub fn test(&self, key: &String) -> bool {
self.node.borrow_mut().test(key) self.node.borrow_mut().test(key)
} }
/// Gets the datatype of a symbol, if it exists
pub fn get_type(&self, key: &String) -> Option<String> {
self.node.borrow_mut().get_type(key)
}
} }
impl SymbolTableNode { impl SymbolTableNode {
@ -83,6 +88,27 @@ impl SymbolTableNode {
None => false, None => false,
} }
} }
/// Returns the symbol's datatype
pub fn get_type(&mut self, key: &String) -> Option<String> {
// Try to get the type in the current scope
if let Some(entry) = self.scope.get(key) {
// TODO: Change to allow other types of datatypes: functions, classes, maps
return match entry {
SymbolEntry::Variable(t) => Some(t.clone()),
SymbolEntry::Function(_, _) => None,
}
}
// Try to get the type in the parent scope
match &self.parent {
Some(parent) => {
let mut parent = parent.as_ref().borrow_mut();
parent.get_type(key)
}
None => None,
}
}
} }
impl SymbolEntry { impl SymbolEntry {

View File

@ -1,15 +1,34 @@
use crate::syntax::ast::Expression; use crate::{
error_handling::{semantic_error::SemanticError, MistiError},
semantic::symbol_table::SymbolTable,
syntax::ast::Expression,
};
use super::Typed; use super::Typed;
impl Typed for Expression<'_> { impl Typed for Expression<'_> {
fn get_type(&self) -> String { /// Attempts to get the datatype for an expression.
fn get_type(&self, scope: &SymbolTable) -> Result<String, MistiError> {
match self { match self {
// TODO: Distinguish between Int & Float // TODO: Distinguish between Int & Float
Expression::Number(_) => "Int".into(), Expression::Number(_) => Ok("Int".into()),
Expression::String(_) => "String".into(), Expression::String(_) => Ok("String".into()),
Expression::Boolean(_) => "Bool".into(), Expression::Boolean(_) => Ok("Bool".into()),
Expression::Identifier(_) => todo!(), Expression::Identifier(identifier) => {
// Attempt to get the datatype of the identifier in the current scope
let datatype = match scope.get_type(identifier) {
Some(x) => x,
None => {
return Err(MistiError::Semantic(SemanticError {
error_start: 0,
error_end: 1,
reason: format!("The identifier {} does not exist.", identifier),
}))
}
};
Ok(datatype)
}
Expression::FunctionCall(_) => todo!(), Expression::FunctionCall(_) => todo!(),
Expression::UnaryOperator(_, _) => todo!(), Expression::UnaryOperator(_, _) => todo!(),
Expression::BinaryOperator(_, _, _) => todo!(), Expression::BinaryOperator(_, _, _) => todo!(),

View File

@ -1,8 +1,12 @@
// This crate provides an interface and implementations // This crate provides an interface and implementations
// for determining the datatypes of the language constructs. // for determining the datatypes of the language constructs.
use crate::error_handling::MistiError;
use super::symbol_table::SymbolTable;
mod expression; mod expression;
pub trait Typed { pub trait Typed {
fn get_type(&self) -> String; fn get_type(&self, scope: &SymbolTable) -> Result<String, MistiError>;
} }