2021-09-02 18:21:37 +00:00
|
|
|
use super::EngineState;
|
2021-10-25 16:58:58 +00:00
|
|
|
use std::collections::HashMap;
|
2021-08-15 22:33:34 +00:00
|
|
|
|
2021-10-09 01:02:01 +00:00
|
|
|
use crate::{Example, ShellError, Signature, Value, VarId};
|
2021-08-15 22:33:34 +00:00
|
|
|
|
2021-09-03 02:57:18 +00:00
|
|
|
#[derive(Clone)]
|
2021-09-02 18:21:37 +00:00
|
|
|
pub struct EvaluationContext {
|
2021-10-25 04:01:02 +00:00
|
|
|
pub engine_state: Box<EngineState>,
|
2021-08-15 22:33:34 +00:00
|
|
|
pub stack: Stack,
|
|
|
|
}
|
|
|
|
|
2021-09-02 18:21:37 +00:00
|
|
|
impl EvaluationContext {
|
2021-08-15 22:33:34 +00:00
|
|
|
pub fn get_var(&self, var_id: VarId) -> Result<Value, ShellError> {
|
|
|
|
self.stack.get_var(var_id)
|
|
|
|
}
|
|
|
|
|
2021-09-02 18:21:37 +00:00
|
|
|
pub fn enter_scope(&self) -> EvaluationContext {
|
2021-08-15 22:33:34 +00:00
|
|
|
Self {
|
2021-09-02 08:25:22 +00:00
|
|
|
engine_state: self.engine_state.clone(),
|
2021-08-15 22:33:34 +00:00
|
|
|
stack: self.stack.clone().enter_scope(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-25 04:01:02 +00:00
|
|
|
pub fn add_var(&mut self, var_id: VarId, value: Value) {
|
2021-08-15 22:33:34 +00:00
|
|
|
self.stack.add_var(var_id, value);
|
|
|
|
}
|
|
|
|
|
2021-10-25 04:01:02 +00:00
|
|
|
pub fn add_env_var(&mut self, var: String, value: String) {
|
2021-08-15 22:33:34 +00:00
|
|
|
self.stack.add_env_var(var, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn print_stack(&self) {
|
|
|
|
self.stack.print_stack();
|
|
|
|
}
|
2021-10-01 21:53:13 +00:00
|
|
|
|
2021-10-09 01:02:01 +00:00
|
|
|
pub fn get_signatures(&self) -> Vec<Signature> {
|
2021-10-25 04:01:02 +00:00
|
|
|
self.engine_state.get_signatures()
|
2021-10-09 01:02:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_signatures_with_examples(&self) -> Vec<(Signature, Vec<Example>)> {
|
2021-10-25 04:01:02 +00:00
|
|
|
self.engine_state.get_signatures_with_examples()
|
2021-10-01 21:53:13 +00:00
|
|
|
}
|
2021-08-15 22:33:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-25 04:01:02 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2021-08-15 22:33:34 +00:00
|
|
|
pub struct StackFrame {
|
|
|
|
pub vars: HashMap<VarId, Value>,
|
|
|
|
pub env_vars: HashMap<String, String>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
2021-10-25 04:01:02 +00:00
|
|
|
pub struct Stack(Vec<StackFrame>);
|
2021-08-15 22:33:34 +00:00
|
|
|
|
|
|
|
impl Default for Stack {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Stack {
|
|
|
|
pub fn new() -> Stack {
|
2021-10-25 04:01:02 +00:00
|
|
|
Stack(vec![StackFrame {
|
2021-08-15 22:33:34 +00:00
|
|
|
vars: HashMap::new(),
|
|
|
|
env_vars: HashMap::new(),
|
2021-10-25 04:01:02 +00:00
|
|
|
}])
|
2021-08-15 22:33:34 +00:00
|
|
|
}
|
|
|
|
pub fn get_var(&self, var_id: VarId) -> Result<Value, ShellError> {
|
2021-10-25 04:01:02 +00:00
|
|
|
for frame in self.0.iter().rev() {
|
|
|
|
if let Some(v) = frame.vars.get(&var_id) {
|
|
|
|
return Ok(v.clone());
|
2021-08-15 22:33:34 +00:00
|
|
|
}
|
|
|
|
}
|
2021-10-25 04:01:02 +00:00
|
|
|
Err(ShellError::InternalError("variable not found".into()))
|
2021-08-15 22:33:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-25 04:01:02 +00:00
|
|
|
pub fn add_var(&mut self, var_id: VarId, value: Value) {
|
|
|
|
let frame = self
|
|
|
|
.0
|
|
|
|
.last_mut()
|
|
|
|
.expect("internal error: can't access stack frame");
|
|
|
|
frame.vars.insert(var_id, value);
|
2021-08-15 22:33:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-25 04:01:02 +00:00
|
|
|
pub fn add_env_var(&mut self, var: String, value: String) {
|
|
|
|
let frame = self
|
|
|
|
.0
|
|
|
|
.last_mut()
|
|
|
|
.expect("internal error: can't access stack frame");
|
|
|
|
frame.env_vars.insert(var, value);
|
2021-08-15 22:33:34 +00:00
|
|
|
}
|
|
|
|
|
2021-10-25 04:01:02 +00:00
|
|
|
pub fn enter_scope(&self) -> Stack {
|
|
|
|
// FIXME: VERY EXPENSIVE to clone entire stack
|
|
|
|
let mut output = self.clone();
|
|
|
|
output.0.push(StackFrame {
|
2021-08-15 22:33:34 +00:00
|
|
|
vars: HashMap::new(),
|
|
|
|
env_vars: HashMap::new(),
|
2021-10-25 04:01:02 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
output
|
2021-08-15 22:33:34 +00:00
|
|
|
}
|
|
|
|
|
2021-09-19 19:29:58 +00:00
|
|
|
pub fn get_env_vars(&self) -> HashMap<String, String> {
|
2021-10-25 04:01:02 +00:00
|
|
|
let mut output = HashMap::new();
|
|
|
|
|
|
|
|
for frame in &self.0 {
|
|
|
|
output.extend(frame.env_vars.clone().into_iter());
|
|
|
|
}
|
|
|
|
|
|
|
|
output
|
2021-09-19 19:29:58 +00:00
|
|
|
}
|
|
|
|
|
2021-10-02 13:10:28 +00:00
|
|
|
pub fn get_env_var(&self, name: &str) -> Option<String> {
|
2021-10-25 04:01:02 +00:00
|
|
|
for frame in self.0.iter().rev() {
|
|
|
|
if let Some(v) = frame.env_vars.get(name) {
|
|
|
|
return Some(v.to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
2021-10-02 13:10:28 +00:00
|
|
|
}
|
|
|
|
|
2021-08-15 22:33:34 +00:00
|
|
|
pub fn print_stack(&self) {
|
2021-10-25 04:01:02 +00:00
|
|
|
for frame in self.0.iter().rev() {
|
|
|
|
println!("===frame===");
|
|
|
|
println!("vars:");
|
|
|
|
for (var, val) in &frame.vars {
|
|
|
|
println!(" {}: {:?}", var, val);
|
|
|
|
}
|
|
|
|
println!("env vars:");
|
|
|
|
for (var, val) in &frame.env_vars {
|
|
|
|
println!(" {}: {:?}", var, val);
|
|
|
|
}
|
2021-08-15 22:33:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|