Improved history storage

pull/2/head
Mark 2023-06-14 14:36:58 -07:00
parent e571d2bebf
commit 5ffad0cc4e
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
5 changed files with 47 additions and 20 deletions

31
src/context.rs Normal file
View File

@ -0,0 +1,31 @@
use crate::parser::Token;
use std::collections::HashMap;
#[derive(Debug)]
pub struct Context {
history: Vec<Token>,
variables: HashMap<String, Token>
}
impl Context {
pub fn new() -> Context {
Context{ history: Vec::new(), variables: HashMap::new() }
}
pub fn push_hist(&mut self, t: Token) { self.history.push(t); }
pub fn push_var(&mut self, s: String, t: Token) { self.variables.insert(s, t); }
pub fn del_var(&mut self, s: &String) { self.variables.remove(s); }
pub fn get_variable(&self, s: String) -> Option<Token> {
let v: Option<&Token>;
if s == "ans" {
v = self.history.last();
} else {
v = self.variables.get(&s);
}
if v.is_some() { Some(v.unwrap().clone()) } else { None }
}
}

View File

@ -13,20 +13,18 @@ use termion::{
};
use super::promptbuffer::PromptBuffer;
//use crate::tokens::EvalError;
use crate::parser;
use crate::command;
use crate::evaluate::evaluate;
use crate::evaluate::EvalError;
use crate::context::Context;
#[inline(always)]
fn do_expression(
stdout: &mut RawTerminal<std::io::Stdout>,
s: &String,
history: &Vec<parser::Token>
context: &Context
) -> Result<parser::Token, ()> {
#[cfg(debug_assertions)]
RawTerminal::suspend_raw_mode(&stdout).unwrap();
@ -62,7 +60,7 @@ fn do_expression(
// Evaluate expression
#[cfg(debug_assertions)]
RawTerminal::suspend_raw_mode(&stdout).unwrap();
let g = evaluate(&g, history);
let g = evaluate(&g, context);
#[cfg(debug_assertions)]
RawTerminal::activate_raw_mode(&stdout).unwrap();
@ -158,7 +156,7 @@ pub fn main() -> Result<(), std::io::Error> {
//write!(stdout, "{:?}", size).unwrap();
let mut pb: PromptBuffer = PromptBuffer::new(64);
let mut history: Vec<parser::Token> = Vec::new();
let mut context: Context = Context::new();
'outer: loop {
@ -179,8 +177,8 @@ pub fn main() -> Result<(), std::io::Error> {
} else if command::is_command(&in_str) {
command::do_command(&mut stdout, &in_str)?;
} else {
let r = do_expression(&mut stdout, &in_str, &history);
if let Ok(t) = r { history.push(t); }
let r = do_expression(&mut stdout, &in_str, &context);
if let Ok(t) = r { context.push_hist(t); }
}
break;

View File

@ -1,12 +1,13 @@
use crate::parser::Token;
use crate::parser::Operator;
use crate::context::Context;
use super::operator::eval_operator;
use super::function::eval_function;
use super::EvalError;
pub fn evaluate(t: &Token, history: &Vec<Token>) -> Result<Token, EvalError> {
pub fn evaluate(t: &Token, context: &Context) -> Result<Token, EvalError> {
let mut g = t.clone();
let mut coords: Vec<usize> = Vec::with_capacity(16);
coords.push(0);
@ -31,17 +32,13 @@ pub fn evaluate(t: &Token, history: &Vec<Token>) -> Result<Token, EvalError> {
loop {
e = match e {
Token::Quantity(_) => { break; },
Token::Constant(c) => { evaluate(&c.value(), history).unwrap() },
Token::Constant(c) => { evaluate(&c.value(), context).unwrap() },
Token::Operator(Operator::Function(f), v) => { eval_function(&f, &v)? },
Token::Operator(o, v) => { eval_operator(&o, &v)? },
Token::Variable(s) => {
if s == "ans" {
if history.len() == 0 {
if let Some(t) = context.get_variable(s) { t } else {
return Err(EvalError::NoHistory);
} else {
history.last().unwrap().clone()
}
} else { panic!(); }
}
};
}

View File

@ -2,7 +2,7 @@ pub mod parser;
pub mod command;
pub mod quantity;
pub mod evaluate;
pub mod context;
mod entry;
use crate::entry::main_e;

View File

@ -1,6 +1,7 @@
// Many of these have been borrowed from insect.
use crate::parser;
use crate::evaluate::evaluate;
use crate::context::Context;
fn eval_to_str(s: &str) -> Result<String, ()> {
let g = match parser::parse(&String::from(s)) {
@ -9,7 +10,7 @@ fn eval_to_str(s: &str) -> Result<String, ()> {
};
//let out_str = g.print();
return match evaluate(&g, &Vec::new()) {
return match evaluate(&g, &Context::new()) {
Ok(x) => Ok(x.to_string_outer()),
Err(_) => Err(())
};