use crate::parser::{Expression, Function, Constant}; use crate::quantity::freeunit_from_string; use std::collections::HashMap; #[derive(Debug)] #[derive(Clone)] pub struct Config { // How to color terminal text. // 0: No colors // 1: ANSI-compatible, 8 colors // 2: Full 256 color and special styles pub term_color_type: u8, // Should we accept input and print in unicode? //pub enable_unicode: bool, // Should we replace certain strings (like "pi") // with prettier unicode alternatives? // // Automatically disabled if enable_unicode is off. pub enable_substituion: bool, // Should we print simple powers // as unicode superscript chars? // // Automatically disables if enable_unicode is off. pub enable_super_powers: bool, // Should we write "one-over" fractions // as -1 powers? // // Automatically disabled if enable_super_powers is off. pub enable_one_over_power: bool, } impl Config { pub fn new() -> Config { Config{ term_color_type: 2, enable_substituion: true, //enable_unicode: true, enable_super_powers: true, enable_one_over_power: true } } pub fn check(&mut self) { //if !self.enable_unicode { // self.enable_substituion = false; // self.enable_super_powers = false; //} if !self.enable_super_powers { self.enable_one_over_power = false } } } #[derive(Debug)] #[derive(Clone)] pub struct Context { pub config: Config, history: Vec, variables: HashMap, functions: HashMap, Expression)>, // Shadow variables, for function evaluation. shadow: HashMap> } // General functions impl Context { pub fn new() -> Context { Context{ config: Config::new(), history: Vec::new(), variables: HashMap::new(), functions: HashMap::new(), shadow: HashMap::new(), } } pub fn push_hist(&mut self, t: Expression) { self.history.push(t); } pub fn delete(&mut self, s: &String) -> Result<(), ()> { if !(self.is_varible(s) || self.is_function(s)) { return Err(()) }; if self.is_varible(s) { self.variables.remove(s); } if self.is_function(s) { self.functions.remove(s); } return Ok(()); } } // Variable manipulation impl Context { pub fn push_variable(&mut self, s: String, t: Expression) -> Result<(), ()> { if self.valid_varible(&s) { self.functions.remove(&s); self.variables.insert(s, t); return Ok(()); } else { return Err(()); } } // Returns None if this is a "floating" variable pub fn get_variable(&self, s: &String) -> Option { if self.shadow.contains_key(s) { return self.shadow.get(s).unwrap().clone(); } let v: Option<&Expression>; if s == "ans" { v = self.history.last(); } else { v = self.variables.get(s); } if v.is_some() { return Some(v.unwrap().clone()); } else { panic!() } } // Can we define a new variable with this name? pub fn valid_varible(&self, s: &str) -> bool { if { Function::from_string(s).is_some() || Constant::from_string(s).is_some() || freeunit_from_string(s).is_some() } { return false } for c in s.to_lowercase().chars() { if !"abcdefghijklmnopqrtstuvwxyz_".contains(c) { return false; } } return match s { "ans" => false, _ => true } } // Can we get a value fro mthis variable name? pub fn is_varible(&self, s: &str) -> bool { return { ( s == "ans" && self.history.len() != 0 ) || ( self.valid_varible(s) && (self.variables.contains_key(s) || self.shadow.contains_key(s)) ) }; } pub fn get_variables(&self) -> &HashMap { return &self.variables } pub fn add_shadow(&mut self, s: String, v: Option) { if !self.valid_varible(&s) { panic!() } self.shadow.insert(s, v); } pub fn clear_shadow(&mut self) { self.shadow = HashMap::new(); } } // Function manipulation impl Context { pub fn valid_function(&self, s: &str) -> bool { return self.valid_varible(s); } pub fn push_function(&mut self, s: String, a: Vec, t: Expression) -> Result<(), ()> { if self.valid_function(&s) { self.variables.remove(&s); self.functions.insert(s, (a, t)); return Ok(()); } else { return Err(()); } } pub fn get_function(&self, s: &String) -> Option<(Vec, Expression)> { return Some(self.functions.get(s).unwrap().clone()); } pub fn is_function(&self, s: &str) -> bool { return self.valid_function(s) && self.functions.contains_key(s); } pub fn get_functions(&self) -> &HashMap, Expression)> { return &self.functions } }