1
2use crate::{CalcError, CalcErrorType};
3
4mod builtins;
5
6#[cfg(test)]
7mod tests;
8
9pub struct Context {
12 var_table: Vec<VarTableEntry>,
13 pub prev_ans: Option<f64>,
16 function_table: Vec<Function>
17}
18
19impl Context {
20 pub fn new() -> Self {
21 Self {
22 var_table: builtins::get_consts(),
23 function_table: builtins::get_functions(),
24 prev_ans: None,
25 }
26 }
27
28 pub fn lookup_var(&self, query: &String) -> Option<Result<f64, CalcError>> {
32 if query.eq("ans") {
34 if let Some(ans) = self.prev_ans {
35 return Some(Ok(ans));
36 } else {
37 return Some(Err(CalcError {
38 error_type: CalcErrorType::CalculationError,
39 msg: "Cannot use \'ans\' without a previous evaluated equation".to_string(),
40 }));
41 }
42 }
43
44 for entry in &self.var_table {
46 if entry.name.eq(query) {
47 return Some(Ok(entry.value));
48 }
49 }
50 return None;
51 }
52
53 pub fn try_function(&self, name: &String, args: Vec<f64>) -> Option<Result<f64, CalcError>> {
58 for f in self.function_table.iter() {
59 if !f.name.eq(name) { continue; }
60 if f.num_args != 0 && f.num_args != args.len() {
61 return Some(Err(CalcError {
62 error_type: CalcErrorType::ArgumentError,
63 msg: "Invalid number of arguments".to_string(),
64 }));
65 }
66 return Some((f.closure)(args));
67 }
68 return None;
69 }
70
71 pub fn assign_var(&mut self, query: &String, val: f64) -> Result<(), CalcError> {
74 for entry in &mut self.var_table {
75 if entry.name.eq(query) {
76 if entry.constant {
77 return Err(CalcError {
78 error_type: CalcErrorType::AssignmentError,
79 msg: format!("Can't assign value to constant \'{}\'", entry.name).to_string()
80 });
81 }
82 entry.value = val;
83 return Ok(());
84 }
85 }
86 self.var_table.push(VarTableEntry {
87 name: query.clone(),
88 value: val,
89 constant: false,
90 });
91 return Ok(());
92
93 }
94}
95
96struct VarTableEntry {
98 pub name: String,
99 pub value: f64,
100 pub constant: bool,
101}
102
103struct Function {
106 name: String,
107 num_args: usize,
108 closure: Box<dyn Fn(Vec<f64>) -> Result<f64, CalcError>>
109}