From 73d8f6182fd64968fbcf621250794c0b31b6800f Mon Sep 17 00:00:00 2001 From: Shautvast Date: Fri, 21 Nov 2025 17:11:41 +0100 Subject: [PATCH] error when reserved function name is used for a user defined function --- src/compiler/ast_pass.rs | 4 ++++ src/compiler/compiler_tests.rs | 8 +++++++- src/compiler/mod.rs | 8 ++++---- src/errors.rs | 14 ++++++++------ 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/compiler/ast_pass.rs b/src/compiler/ast_pass.rs index 5a56476..c51fb47 100644 --- a/src/compiler/ast_pass.rs +++ b/src/compiler/ast_pass.rs @@ -18,6 +18,7 @@ use crate::value::Value; use crate::{DATE_FORMAT_TIMEZONE, Expr, Stmt, SymbolTable}; use log::debug; use std::collections::HashMap; +use crate::builtins::globals::GLOBAL_FUNCTIONS; pub fn compile( path: Option<&str>, @@ -235,6 +236,9 @@ impl AstCompiler { fn function_declaration(&mut self, symbol_table: &mut SymbolTable) -> Stmt { let name_token = self.consume(&Identifier, Expected("function name."))?; + if GLOBAL_FUNCTIONS.contains_key(name_token.lexeme.as_str()) { + return Err(self.raise(CompilerError::ReservedFunctionName(name_token.lexeme.clone()))) + } self.consume(&LeftParen, Expected("'(' after function name."))?; let mut parameters = vec![]; while !self.check(&RightParen) { diff --git a/src/compiler/compiler_tests.rs b/src/compiler/compiler_tests.rs index a77ae46..db5f208 100644 --- a/src/compiler/compiler_tests.rs +++ b/src/compiler/compiler_tests.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod tests { use crate::compiler::{compile, run}; - use crate::errors::CompilerError::IllegalArgumentsException; + use crate::errors::CompilerError::{IllegalArgumentsException, ReservedFunctionName}; use crate::errors::CompilerErrorAtLine; use crate::errors::RuntimeError::{IllegalArgumentException, IndexOutOfBounds}; use crate::errors::TipiLangError::{Compiler, Runtime}; @@ -417,6 +417,12 @@ sum assert!(DateTime::parse_from_str(&date_time_string, DATE_FORMAT_TIMEZONE).is_ok()); } + #[test] + fn global_fns_are_not_allowed() { + let value = run(r#"fn now():"#); + assert_eq!(value, Err(Compiler(CompilerErrorAtLine { error: ReservedFunctionName("now".to_string()), line: 1 }))); + } + // #[test] // fn package() { // assert_eq!(run(r#"a.b.c()"#), Ok(Value::U32(48))); diff --git a/src/compiler/mod.rs b/src/compiler/mod.rs index 1874e98..3b784ac 100644 --- a/src/compiler/mod.rs +++ b/src/compiler/mod.rs @@ -46,10 +46,10 @@ pub fn map_underlying() -> fn(std::io::Error) -> TipiLangError { pub fn compile(src: &str) -> Result, TipiLangError> { - let tokens = compiler::scan_pass::scan(src)?; + let tokens = scan_pass::scan(src)?; let mut asm_registry = HashMap::new(); let mut symbol_table = HashMap::new(); - let ast = compiler::ast_pass::compile(None, tokens, &mut symbol_table)?; + let ast = ast_pass::compile(None, tokens, &mut symbol_table)?; symbol_builder::build("", &ast, &mut symbol_table); assembly_pass::compile(None, &ast, &symbol_table, &mut asm_registry)?; Ok(asm_registry) @@ -57,9 +57,9 @@ pub fn compile(src: &str) -> Result, TipiLangError> { #[cfg(test)] pub(crate) fn run(src: &str) -> Result { - let tokens = compiler::scan_pass::scan(src)?; + let tokens = scan_pass::scan(src)?; let mut symbol_table = HashMap::new(); - let ast = compiler::ast_pass::compile(None, tokens, &mut symbol_table)?; + let ast = ast_pass::compile(None, tokens, &mut symbol_table)?; symbol_builder::build("", &ast, &mut symbol_table); let mut asm_registry = HashMap::new(); assembly_pass::compile(None, &ast, &symbol_table, &mut asm_registry)?; diff --git a/src/errors.rs b/src/errors.rs index 8f74ed0..6cf92c4 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -14,14 +14,14 @@ pub enum TipiLangError { } #[derive(Error, Debug, PartialEq)] -pub struct CompilerErrorAtLine{ +pub struct CompilerErrorAtLine { pub error: CompilerError, - pub line: usize + pub line: usize, } impl CompilerErrorAtLine { - pub(crate) fn raise(error:CompilerError, line: usize) -> Self{ - Self {error, line} + pub(crate) fn raise(error: CompilerError, line: usize) -> Self { + Self { error, line } } } @@ -70,7 +70,9 @@ pub enum CompilerError { #[error("Illegal argument: '{0}' cannot be indexed")] IllegalTypeToIndex(String), #[error("The number of of arguments for {0} is not correct. Should be {1}, got {2}")] - IllegalArgumentsException(String,usize,usize), + IllegalArgumentsException(String, usize, usize), + #[error("Function name {0} is a global function and cannot be used here.")] + ReservedFunctionName(String), } #[derive(Error, Debug, PartialEq)] @@ -84,7 +86,7 @@ pub enum RuntimeError { #[error("Function {0} not found")] FunctionNotFound(String), #[error("The number of of arguments for {0} is not correct. Should be {1}, got {2}")] - IllegalArgumentsException(String,usize,usize), + IllegalArgumentsException(String, usize, usize), #[error("{0}")] IllegalArgumentException(String), #[error("Expected {0}")]