test: function call semantics

This commit is contained in:
Fernando Araoz 2024-10-02 17:20:04 -05:00
parent 3475b55db5
commit 6bfe840314
2 changed files with 84 additions and 25 deletions

View File

@ -23,7 +23,10 @@ impl SemanticCheck for FunctionCall<'_> {
let Type::Function(parameters, _) = function_datatype else { let Type::Function(parameters, _) = function_datatype else {
let (error_start, error_end) = fun.get_position(); let (error_start, error_end) = fun.get_position();
let label = ErrorLabel { let label = ErrorLabel {
message: format!("Expected a function type, got {:?}", function_datatype), message: format!(
"Expected this expression to be a function, found a {:?}",
function_datatype
),
start: error_start, start: error_start,
end: error_end, end: error_end,
}; };
@ -88,3 +91,81 @@ impl SemanticCheck for FunctionCall<'_> {
Ok(()) Ok(())
} }
} }
#[cfg(test)]
mod tests {
use crate::{
error_handling::error_messages::{
SEMANTIC_INVALID_REFERENCE, SEMANTIC_MISMATCHED_TYPES, SEMANTIC_MISSING_REFERENCE,
},
lexic::{get_tokens, token::Token},
semantic::{
impls::SemanticCheck,
symbol_table::SymbolTable,
types::{global::INT, Type},
},
syntax::{
ast::{functions::FunctionCall, Expression},
parseable::Parseable,
},
};
fn t(i: &str) -> Vec<Token> {
get_tokens(&i.into()).unwrap()
}
fn exp<'a>(t: &'a Vec<Token>) -> FunctionCall<'a> {
let e = Expression::try_parse(t, 0).unwrap().0;
match e {
Expression::FunctionCall(f) => f,
_ => panic!("Expected to parse a function call"),
}
}
#[test]
fn should_fail_on_ref_not_exist() {
let b = t("my_fun()");
let expr = exp(&b);
let scope = SymbolTable::new();
let output = expr.check_semantics(&scope);
match output {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.error_code, SEMANTIC_MISSING_REFERENCE);
assert_eq!(err.error_offset, 0);
let label = &err.labels[0];
assert_eq!(label.message, "Cannot find this identifier in this scope");
assert_eq!(label.start, 0);
assert_eq!(label.end, 6);
}
}
}
#[test]
fn should_fail_on_ref_not_a_function() {
let b = t("my_fun()");
let expr = exp(&b);
let scope = SymbolTable::new();
scope.insert(String::from("my_fun"), Type::Value(INT.into()));
let output = expr.check_semantics(&scope);
match output {
Ok(_) => panic!("Expected an error"),
Err(err) => {
assert_eq!(err.error_code, SEMANTIC_MISMATCHED_TYPES);
assert_eq!(err.error_offset, 0);
let label = &err.labels[0];
assert_eq!(
label.message,
"Expected this expression to be a function, found a `Int`"
);
assert_eq!(label.start, 0);
assert_eq!(label.end, 6);
}
}
}
}

View File

@ -1,9 +1,6 @@
use crate::{ use crate::{
error_handling::{ error_handling::{
error_messages::{ error_messages::{COMPILER_TODO, SEMANTIC_INVALID_REFERENCE, SEMANTIC_MISMATCHED_TYPES},
COMPILER_TODO, SEMANTIC_INVALID_REFERENCE, SEMANTIC_MISMATCHED_ARGUMENT_COUNT,
SEMANTIC_MISMATCHED_TYPES,
},
ErrorContainer, ErrorLabel, MistiError, ErrorContainer, ErrorLabel, MistiError,
}, },
semantic::{ semantic::{
@ -272,7 +269,7 @@ impl SemanticCheck for Expression<'_> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{
lexic::{self, get_tokens, token::Token}, lexic::{get_tokens, token::Token},
semantic::{impls::SemanticCheck, std::populate, symbol_table::SymbolTable}, semantic::{impls::SemanticCheck, std::populate, symbol_table::SymbolTable},
syntax::{ syntax::{
ast::{ ast::{
@ -290,25 +287,6 @@ mod tests {
Expression::try_parse(t, 0).unwrap().0 Expression::try_parse(t, 0).unwrap().0
} }
#[test]
fn should_error_on_undefined_symbol() {
// source code: `print()`
let b = t("print()");
let expr = exp(&b);
let scope = SymbolTable::new();
let output = expr.check_semantics(&scope);
match output {
Ok(_) => panic!("Expected an error"),
Err(err) => {
//assert_eq!(err.reason, "Cannot find `print` in this scope.");
assert_eq!(err.error_offset, 0);
//assert_eq!(err.error_end, 5);
}
}
}
#[test] #[test]
fn should_error_on_invalid_function_argument() { fn should_error_on_invalid_function_argument() {
// source code: `print(322)` // source code: `print(322)`