robinpath 0.2.0

RobinPath - A lightweight, fast scripting language interpreter for automation and data processing
Documentation
use std::fmt;

#[derive(Debug, Clone)]
pub struct SourceLocation {
    pub line: usize,
    pub column: usize,
}

impl fmt::Display for SourceLocation {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "line {}, column {}", self.line, self.column)
    }
}

#[derive(Debug, thiserror::Error)]
pub enum RobinPathError {
    #[error("Lexer error at {location}: {message}")]
    LexerError {
        message: String,
        location: SourceLocation,
    },

    #[error("Parse error at {location}: {message}")]
    ParseError {
        message: String,
        location: SourceLocation,
    },

    #[error("Runtime error: {message}")]
    RuntimeError { message: String },

    #[error("Runtime error at {location}: {message}")]
    RuntimeErrorAt {
        message: String,
        location: SourceLocation,
    },

    #[error("Type error: {message}")]
    TypeError { message: String },

    #[error("Unknown function: {name}")]
    UnknownFunction {
        name: String,
        suggestions: Vec<String>,
    },

    #[error("Constant reassignment: cannot reassign constant '{name}'")]
    ConstantReassignment { name: String },

    #[error("Recursion limit exceeded for function '{name}' (max depth: {max_depth})")]
    RecursionLimit { name: String, max_depth: usize },

    #[error("Assertion failed: {message}")]
    AssertionError { message: String },

    #[error("Internal error: {0}")]
    Internal(String),
}

impl RobinPathError {
    pub fn lexer(message: impl Into<String>, line: usize, column: usize) -> Self {
        Self::LexerError {
            message: message.into(),
            location: SourceLocation { line, column },
        }
    }

    pub fn parse(message: impl Into<String>, line: usize, column: usize) -> Self {
        Self::ParseError {
            message: message.into(),
            location: SourceLocation { line, column },
        }
    }

    pub fn runtime(message: impl Into<String>) -> Self {
        Self::RuntimeError {
            message: message.into(),
        }
    }

    pub fn runtime_at(message: impl Into<String>, line: usize, column: usize) -> Self {
        Self::RuntimeErrorAt {
            message: message.into(),
            location: SourceLocation { line, column },
        }
    }

    pub fn type_error(message: impl Into<String>) -> Self {
        Self::TypeError {
            message: message.into(),
        }
    }

    pub fn unknown_function(name: impl Into<String>, suggestions: Vec<String>) -> Self {
        Self::UnknownFunction {
            name: name.into(),
            suggestions,
        }
    }
}