Added shadow variables

pull/2/head
Mark 2023-08-04 16:06:43 -07:00
parent 602fde4441
commit 837f256347
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
5 changed files with 42 additions and 23 deletions

View File

@ -6,7 +6,10 @@ use std::collections::HashMap;
pub struct Context {
history: Vec<Expression>,
variables: HashMap<String, Expression>,
functions: HashMap<String, (Vec<String>, Expression)>
functions: HashMap<String, (Vec<String>, Expression)>,
// Shadow variables, for function evaluation.
shadow: HashMap<String, Option<Expression>>
}
// General functions
@ -16,6 +19,7 @@ impl Context {
history: Vec::new(),
variables: HashMap::new(),
functions: HashMap::new(),
shadow: HashMap::new(),
}
}
@ -42,14 +46,22 @@ impl Context {
} else { return Err(()); }
}
// Returns None if this is a "floating" variable
pub fn get_variable(&self, s: &String) -> Option<Expression> {
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() { Some(v.unwrap().clone()) } else { None }
if v.is_some() {
return Some(v.unwrap().clone());
} else { panic!() }
}
pub fn valid_varible(&self, s: &str) -> bool {
@ -72,13 +84,25 @@ impl Context {
}
pub fn is_varible(&self, s: &str) -> bool {
return self.valid_varible(s) && self.variables.contains_key(s);
return self.valid_varible(s) && (
self.variables.contains_key(s) ||
self.shadow.contains_key(s)
);
}
pub fn get_variables(&self) -> &HashMap<String, Expression> {
return &self.variables
}
pub fn add_shadow(&mut self, s: String, v: Option<Expression>) {
if !self.valid_varible(&s) { panic!() }
self.shadow.insert(s, v);
}
pub fn clear_shadow(&mut self) {
self.shadow = HashMap::new();
}
}

View File

@ -40,7 +40,7 @@ fn do_expression(
// Evaluate expression
#[cfg(debug_assertions)]
RawTerminal::suspend_raw_mode(&stdout).unwrap();
let g_evaluated = evaluate::evaluate(&g, context, false)?;
let g_evaluated = evaluate::evaluate(&g, context)?;
#[cfg(debug_assertions)]
RawTerminal::activate_raw_mode(&stdout).unwrap();

View File

@ -10,8 +10,7 @@ use super::function::eval_function;
pub fn evaluate(
t: &Expression,
context: &mut Context,
allow_incomplete: bool
context: &mut Context
) -> Result<
Expression,
(LineLocation, DaisyError)
@ -52,19 +51,17 @@ pub fn evaluate(
let new = match g {
Expression::Quantity(_, _) => None,
Expression::Tuple(_, _) => None,
Expression::Constant(_, c) => { Some(evaluate(&c.value(), context, false).unwrap()) },
Expression::Constant(_, c) => { Some(evaluate(&c.value(), context).unwrap()) },
Expression::Variable(l, s) => {
// Don't move up, re-evaluate
// This makes variables containing floating variables work properly
// (For example, try x = a + 2, a = 2, x. x should evaluate to 4.)
move_up = false;
let v = context.get_variable(&s);
if !context.is_varible(&s) {
return Err((*l, DaisyError::Undefined(s.clone())));
}
// Error if variable is undefined.
// Comment this to allow floating varables.
if v.is_none() { return Err((*l, DaisyError::Undefined(s.clone()))); }
v
context.get_variable(&s)
},
Expression::Operator(_, Operator::Function(_), _) => { Some(eval_function(g)?) },
Expression::Operator(_, _, _) => { eval_operator(g, context)? },
@ -80,13 +77,13 @@ pub fn evaluate(
*g = new;
} else {
if !allow_incomplete {
if let Expression::Quantity(_, _) = g {}
else {
let l = g.get_linelocation();
return Err((l, DaisyError::EvaluationError))
}
/*
if let Expression::Quantity(_, _) = g {}
else {
let l = g.get_linelocation();
return Err((l, DaisyError::EvaluationError))
}
*/
// Always move up if we couldn't evaluate this node.
move_up = true;

View File

@ -78,15 +78,13 @@ impl Token {
},
Token::Word(l, s) => {
let c = Constant::from_string(&s);
if c.is_some() { return Ok(Expression::Constant(l, c.unwrap())); }
let c = Unit::from_string(&s);
if c.is_some() { return Ok(Expression::Quantity(l, c.unwrap())); }
let c = context.get_variable(&s);
if c.is_some() { return Ok(Expression::Variable(l, s)); }
if context.is_varible(&s) { return Ok(Expression::Variable(l, s)); }
return Ok(Expression::Variable(l, s));
}

View File

@ -10,7 +10,7 @@ fn eval_to_str(s: &str) -> Result<String, ()> {
};
//let out_str = g.print();
return match evaluate(&g, &mut Context::new(), false) {
return match evaluate(&g, &mut Context::new()) {
Ok(x) => Ok(x.to_string_outer()),
Err(_) => Err(())
};