Typecheck function block

master
Araozu 2024-05-30 16:05:31 -05:00
parent ab782b828d
commit 18f3f21eec
8 changed files with 44 additions and 11 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
target target
examples examples
tarpaulin-report.html

View File

@ -2,6 +2,7 @@
## TODO ## TODO
- Implement functions as first class citizens
- Implement AST transformation before codegen: - Implement AST transformation before codegen:
Create a new AST to represent PHP source code Create a new AST to represent PHP source code
and a THP ast -> PHP ast process, so that the and a THP ast -> PHP ast process, so that the
@ -23,18 +24,25 @@
- Simple language server - Simple language server
- Decide how to handle comments in the syntax (?)(should comments mean something like in rust?) - Decide how to handle comments in the syntax (?)(should comments mean something like in rust?)
- Not ignore comments & whitespace, for code formatting - Not ignore comments & whitespace, for code formatting
- Abstract the parsing of datatypes, such that in the future generics can be implemented in a single place
## v0.0.13
- [ ] Define a formal grammar
- [ ] Define the top level constructs
- [ ] Implement a hello world until semantic analysis
- [ ] Refactor code
## v0.0.12 ## v0.0.12
- [x] Infer datatype of an identifier - [x] Infer datatype of an identifier
- [x] Infer datatype of a binary operatior - [x] Infer datatype of a binary operatior
- [x] Infer datatype of unary operator - [x] Infer datatype of unary operator
- [ ] Infer datatype of a function call expression - [x] Infer datatype of binary operators
- [ ] Infer datatype of binary operators
- [x] Infer Int & Float as different types - [x] Infer Int & Float as different types
- [ ] Execute semantic analysis on the function's block - [x] Execute semantic analysis on the function's block
- [ ] Write tests - [x] Write tests
- [ ] Abstract the parsing of datatypes, such that in the future generics can be implemented in a single place
## v0.0.11 ## v0.0.11

2
Cargo.lock generated
View File

@ -20,7 +20,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "thp" name = "thp"
version = "0.0.11" version = "0.0.12"
dependencies = [ dependencies = [
"colored", "colored",
] ]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "thp" name = "thp"
version = "0.0.11" version = "0.0.12"
edition = "2021" edition = "2021"

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
error_handling::{semantic_error::SemanticError, MistiError}, error_handling::{semantic_error::SemanticError, MistiError},
semantic::{impls::SemanticCheck, symbol_table::SymbolEntry}, semantic::{impls::SemanticCheck, symbol_table::{SymbolEntry, SymbolTable}},
syntax::ast::FunctionDeclaration, syntax::ast::{statement::Statement, FunctionDeclaration},
}; };
impl SemanticCheck for FunctionDeclaration<'_> { impl SemanticCheck for FunctionDeclaration<'_> {
@ -25,8 +25,23 @@ impl SemanticCheck for FunctionDeclaration<'_> {
return Err(MistiError::Semantic(error)); return Err(MistiError::Semantic(error));
} }
// TODO: Check the return type of the function // Create a new scope and use it in the function block
let function_scope = SymbolTable::new_from_parent(scope);
// TODO: Check the return type of the function body // TODO: Check the return type of the function body
// This should be the last expression in the block
for stmt in self.block.statements.iter() {
match stmt {
Statement::Binding(b) => {
if let Err(err) = b.check_semantics(&function_scope) {
return Err(err)
}
}
Statement::FunctionCall(_) => panic!("FunctionCall semantic check not implemented")
}
}
// TODO: Check the return type of the function
scope.insert( scope.insert(
function_name, function_name,

View File

@ -29,7 +29,13 @@ impl Typed for Expression<'_> {
Ok(datatype) Ok(datatype)
} }
Expression::FunctionCall(_) => todo!(), Expression::FunctionCall(_f) => {
// TODO: Must implement functions as first class citizens
// for this to work
// TODO: check the parameter types
panic!("Not implemented: Get datatype of function call")
}
Expression::UnaryOperator(op, exp) => { Expression::UnaryOperator(op, exp) => {
let expr_type = match exp.get_type(scope) { let expr_type = match exp.get_type(scope) {
Ok(t) => t, Ok(t) => t,

View File

@ -10,6 +10,7 @@ pub struct ModuleAST<'a> {
pub declarations: Vec<TopLevelDeclaration<'a>>, pub declarations: Vec<TopLevelDeclaration<'a>>,
} }
// TODO: this and Statement should merge
#[derive(Debug)] #[derive(Debug)]
pub enum TopLevelDeclaration<'a> { pub enum TopLevelDeclaration<'a> {
Binding(var_binding::Binding<'a>), Binding(var_binding::Binding<'a>),
@ -27,6 +28,7 @@ pub struct FunctionDeclaration<'a> {
#[derive(Debug)] #[derive(Debug)]
pub struct Block<'a> { pub struct Block<'a> {
// TODO: this should be a Vec of Statement|Expression
pub statements: Vec<statement::Statement<'a>>, pub statements: Vec<statement::Statement<'a>>,
} }

View File

@ -1,5 +1,6 @@
use super::{functions::FunctionCall, var_binding::Binding}; use super::{functions::FunctionCall, var_binding::Binding};
// TODO: this and TopLevelDeclaration should merge
#[derive(Debug)] #[derive(Debug)]
pub enum Statement<'a> { pub enum Statement<'a> {
FunctionCall(FunctionCall<'a>), FunctionCall(FunctionCall<'a>),