diff --git a/src/semantic/checks/expression/funtion_call.rs b/src/semantic/checks/expression/funtion_call.rs index 0577857..2c8dcbb 100644 --- a/src/semantic/checks/expression/funtion_call.rs +++ b/src/semantic/checks/expression/funtion_call.rs @@ -23,7 +23,10 @@ impl SemanticCheck for FunctionCall<'_> { let Type::Function(parameters, _) = function_datatype else { let (error_start, error_end) = fun.get_position(); 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, end: error_end, }; @@ -88,3 +91,81 @@ impl SemanticCheck for FunctionCall<'_> { 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 { + get_tokens(&i.into()).unwrap() + } + fn exp<'a>(t: &'a Vec) -> 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); + } + } + } +} diff --git a/src/semantic/checks/expression/mod.rs b/src/semantic/checks/expression/mod.rs index a3e3036..f935f8f 100644 --- a/src/semantic/checks/expression/mod.rs +++ b/src/semantic/checks/expression/mod.rs @@ -1,9 +1,6 @@ use crate::{ error_handling::{ - error_messages::{ - COMPILER_TODO, SEMANTIC_INVALID_REFERENCE, SEMANTIC_MISMATCHED_ARGUMENT_COUNT, - SEMANTIC_MISMATCHED_TYPES, - }, + error_messages::{COMPILER_TODO, SEMANTIC_INVALID_REFERENCE, SEMANTIC_MISMATCHED_TYPES}, ErrorContainer, ErrorLabel, MistiError, }, semantic::{ @@ -272,7 +269,7 @@ impl SemanticCheck for Expression<'_> { #[cfg(test)] mod tests { use crate::{ - lexic::{self, get_tokens, token::Token}, + lexic::{get_tokens, token::Token}, semantic::{impls::SemanticCheck, std::populate, symbol_table::SymbolTable}, syntax::{ ast::{ @@ -290,25 +287,6 @@ mod tests { 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] fn should_error_on_invalid_function_argument() { // source code: `print(322)`