error when reserved function name is used for a user defined function

This commit is contained in:
Shautvast 2025-11-21 17:11:41 +01:00
parent d766ec775a
commit 73d8f6182f
4 changed files with 23 additions and 11 deletions

View file

@ -18,6 +18,7 @@ use crate::value::Value;
use crate::{DATE_FORMAT_TIMEZONE, Expr, Stmt, SymbolTable}; use crate::{DATE_FORMAT_TIMEZONE, Expr, Stmt, SymbolTable};
use log::debug; use log::debug;
use std::collections::HashMap; use std::collections::HashMap;
use crate::builtins::globals::GLOBAL_FUNCTIONS;
pub fn compile( pub fn compile(
path: Option<&str>, path: Option<&str>,
@ -235,6 +236,9 @@ impl AstCompiler {
fn function_declaration(&mut self, symbol_table: &mut SymbolTable) -> Stmt { fn function_declaration(&mut self, symbol_table: &mut SymbolTable) -> Stmt {
let name_token = self.consume(&Identifier, Expected("function name."))?; 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."))?; self.consume(&LeftParen, Expected("'(' after function name."))?;
let mut parameters = vec![]; let mut parameters = vec![];
while !self.check(&RightParen) { while !self.check(&RightParen) {

View file

@ -1,7 +1,7 @@
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::compiler::{compile, run}; use crate::compiler::{compile, run};
use crate::errors::CompilerError::IllegalArgumentsException; use crate::errors::CompilerError::{IllegalArgumentsException, ReservedFunctionName};
use crate::errors::CompilerErrorAtLine; use crate::errors::CompilerErrorAtLine;
use crate::errors::RuntimeError::{IllegalArgumentException, IndexOutOfBounds}; use crate::errors::RuntimeError::{IllegalArgumentException, IndexOutOfBounds};
use crate::errors::TipiLangError::{Compiler, Runtime}; use crate::errors::TipiLangError::{Compiler, Runtime};
@ -417,6 +417,12 @@ sum
assert!(DateTime::parse_from_str(&date_time_string, DATE_FORMAT_TIMEZONE).is_ok()); 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] // #[test]
// fn package() { // fn package() {
// assert_eq!(run(r#"a.b.c()"#), Ok(Value::U32(48))); // assert_eq!(run(r#"a.b.c()"#), Ok(Value::U32(48)));

View file

@ -46,10 +46,10 @@ pub fn map_underlying() -> fn(std::io::Error) -> TipiLangError {
pub fn compile(src: &str) -> Result<HashMap<String, AsmChunk>, TipiLangError> { pub fn compile(src: &str) -> Result<HashMap<String, AsmChunk>, TipiLangError> {
let tokens = compiler::scan_pass::scan(src)?; let tokens = scan_pass::scan(src)?;
let mut asm_registry = HashMap::new(); let mut asm_registry = HashMap::new();
let mut symbol_table = 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); symbol_builder::build("", &ast, &mut symbol_table);
assembly_pass::compile(None, &ast, &symbol_table, &mut asm_registry)?; assembly_pass::compile(None, &ast, &symbol_table, &mut asm_registry)?;
Ok(asm_registry) Ok(asm_registry)
@ -57,9 +57,9 @@ pub fn compile(src: &str) -> Result<HashMap<String, AsmChunk>, TipiLangError> {
#[cfg(test)] #[cfg(test)]
pub(crate) fn run(src: &str) -> Result<crate::value::Value, TipiLangError> { pub(crate) fn run(src: &str) -> Result<crate::value::Value, TipiLangError> {
let tokens = compiler::scan_pass::scan(src)?; let tokens = scan_pass::scan(src)?;
let mut symbol_table = 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); symbol_builder::build("", &ast, &mut symbol_table);
let mut asm_registry = HashMap::new(); let mut asm_registry = HashMap::new();
assembly_pass::compile(None, &ast, &symbol_table, &mut asm_registry)?; assembly_pass::compile(None, &ast, &symbol_table, &mut asm_registry)?;

View file

@ -14,14 +14,14 @@ pub enum TipiLangError {
} }
#[derive(Error, Debug, PartialEq)] #[derive(Error, Debug, PartialEq)]
pub struct CompilerErrorAtLine{ pub struct CompilerErrorAtLine {
pub error: CompilerError, pub error: CompilerError,
pub line: usize pub line: usize,
} }
impl CompilerErrorAtLine { impl CompilerErrorAtLine {
pub(crate) fn raise(error:CompilerError, line: usize) -> Self{ pub(crate) fn raise(error: CompilerError, line: usize) -> Self {
Self {error, line} Self { error, line }
} }
} }
@ -70,7 +70,9 @@ pub enum CompilerError {
#[error("Illegal argument: '{0}' cannot be indexed")] #[error("Illegal argument: '{0}' cannot be indexed")]
IllegalTypeToIndex(String), IllegalTypeToIndex(String),
#[error("The number of of arguments for {0} is not correct. Should be {1}, got {2}")] #[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)] #[derive(Error, Debug, PartialEq)]
@ -84,7 +86,7 @@ pub enum RuntimeError {
#[error("Function {0} not found")] #[error("Function {0} not found")]
FunctionNotFound(String), FunctionNotFound(String),
#[error("The number of of arguments for {0} is not correct. Should be {1}, got {2}")] #[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}")] #[error("{0}")]
IllegalArgumentException(String), IllegalArgumentException(String),
#[error("Expected {0}")] #[error("Expected {0}")]