1use crate::number::Number;
4use crate::symbol::{FuncError, Symbol, SymbolError};
5use std::borrow::Cow;
6
7#[derive(Debug, Default, Clone)]
21pub struct SymTable {
22 symbols: Vec<Symbol>,
23}
24
25impl SymTable {
26 pub fn new() -> Self {
28 Self::default()
29 }
30
31 pub(crate) fn from_symbols(symbols: Vec<Symbol>) -> Self {
34 Self { symbols }
35 }
36
37 pub fn add_const<S: Into<Cow<'static, str>>>(
46 &mut self,
47 name: S,
48 value: Number,
49 local: bool,
50 ) -> Result<&mut Self, SymbolError> {
51 let name = name.into();
52 if self.get_by_name(&name).is_ok() {
53 return Err(SymbolError::DuplicateSymbol(name.to_string()));
54 }
55 self.symbols.push(Symbol::Const {
56 name,
57 value,
58 description: None,
59 local,
60 });
61 Ok(self)
62 }
63
64 pub fn add_func<S: Into<Cow<'static, str>>>(
75 &mut self,
76 name: S,
77 args: usize,
78 variadic: bool,
79 callback: fn(&[Number]) -> Result<Number, FuncError>,
80 local: bool,
81 ) -> Result<&mut Self, SymbolError> {
82 let name = name.into();
83 if self.get_by_name(&name).is_ok() {
84 return Err(SymbolError::DuplicateSymbol(name.to_string()));
85 }
86 self.symbols.push(Symbol::Func {
87 name,
88 args,
89 variadic,
90 callback,
91 description: None,
92 local,
93 });
94 Ok(self)
95 }
96
97 pub fn get_by_name(&self, name: &str) -> Result<&Symbol, SymbolError> {
99 self.symbols
100 .iter()
101 .find(|sym| sym.name().eq_ignore_ascii_case(name))
102 .ok_or_else(|| SymbolError::SymbolNotFound(name.to_string()))
103 }
104
105 pub fn get_with_index(&self, name: &str) -> Result<(usize, &Symbol), SymbolError> {
107 self.symbols
108 .iter()
109 .enumerate()
110 .find(|(_, sym)| sym.name().eq_ignore_ascii_case(name))
111 .ok_or_else(|| SymbolError::SymbolNotFound(name.to_string()))
112 }
113
114 pub fn get_by_index(&self, index: usize) -> Result<&Symbol, SymbolError> {
116 self.symbols
117 .get(index)
118 .ok_or_else(|| SymbolError::SymbolNotFound(index.to_string()))
119 }
120
121 pub fn get_mut_by_index(&mut self, index: usize) -> Result<&mut Symbol, SymbolError> {
123 self.symbols
124 .get_mut(index)
125 .ok_or_else(|| SymbolError::SymbolNotFound(index.to_string()))
126 }
127
128 pub fn symbols(&self) -> impl Iterator<Item = &Symbol> {
130 self.symbols.iter()
131 }
132}