expr_solver/symbol/
mod.rs

1//! Symbol table for constants and functions.
2//!
3//! This module provides symbol table functionality with type-specific implementations
4//! for different numeric backends:
5//!
6//! - `f64.rs` - Standard f64 floating-point with relaxed error handling
7//! - `decimal.rs` - High-precision 128-bit Decimal with strict validation
8//!
9//! The appropriate implementation is selected at compile-time via feature flags.
10
11use crate::number::Number;
12use std::borrow::Cow;
13use thiserror::Error;
14
15// Type-specific implementations
16#[cfg(feature = "decimal-precision")]
17mod decimal;
18#[cfg(feature = "f64-floats")]
19mod f64;
20
21/// Errors that can occur during function evaluation.
22#[derive(Error, Debug, Clone)]
23pub enum FuncError {
24    #[error("Conversion error: failed to convert number to f64")]
25    ToF64Conversion,
26    #[error("Conversion error: failed to convert f64 result back to number")]
27    FromF64Conversion,
28    #[error("Square root of negative number: {value}")]
29    NegativeSqrt { value: Number },
30    #[error("Domain error in function '{function}': invalid input {input}")]
31    DomainError { function: String, input: Number },
32    #[error("Math error: {message}")]
33    MathError { message: String },
34}
35
36/// Errors that can occur during symbol table operations.
37#[derive(Error, Debug, Clone, PartialEq, Eq)]
38pub enum SymbolError {
39    /// A symbol with this name already exists in the table.
40    #[error("Duplicate symbol definition: '{0}'")]
41    DuplicateSymbol(String),
42
43    /// Fired when no symbol with given name exists
44    #[error("Symbol '{0}' not found")]
45    SymbolNotFound(String),
46}
47
48/// A symbol representing either a constant or function.
49///
50/// Symbols are stored in a [`SymTable`] and referenced during evaluation.
51#[derive(Debug, Clone)]
52pub enum Symbol {
53    /// Named constant (e.g., `pi`).
54    Const {
55        name: Cow<'static, str>,
56        value: Number,
57        description: Option<Cow<'static, str>>,
58        /// Whether this is a local constant (from let) or global (from stdlib)
59        local: bool,
60    },
61    /// Function with specified arity and callback.
62    Func {
63        name: Cow<'static, str>,
64        /// Minimum number of arguments
65        args: usize,
66        /// Whether the function accepts additional arguments
67        variadic: bool,
68        callback: fn(&[Number]) -> Result<Number, FuncError>,
69        description: Option<Cow<'static, str>>,
70        /// Whether this is a local function (reserved for future use) or global (from stdlib)
71        local: bool,
72    },
73}
74
75impl Symbol {
76    /// Returns the name of the symbol.
77    pub fn name(&self) -> &str {
78        match self {
79            Symbol::Const { name, .. } => name,
80            Symbol::Func { name, .. } => name,
81        }
82    }
83
84    /// Returns the description of the symbol, if available.
85    pub fn description(&self) -> Option<&str> {
86        match self {
87            Symbol::Const { description, .. } => description.as_deref(),
88            Symbol::Func { description, .. } => description.as_deref(),
89        }
90    }
91
92    /// Returns whether this symbol is local (from let) or global (from stdlib).
93    pub fn is_local(&self) -> bool {
94        match self {
95            Symbol::Const { local, .. } => *local,
96            Symbol::Func { local, .. } => *local,
97        }
98    }
99}