use std::any::Any;
use std::collections::HashMap;
use crate::Registry;
use crate::ast::value::Value;
use crate::error::EvalError;
pub trait EvalContext: Any {
fn resolve_variable(&self, scope: &str, name: &str) -> Result<Option<Value>, EvalError>;
fn set_variable(&mut self, scope: &str, name: &str, value: Value) -> Result<(), EvalError>;
fn fire_trigger(&mut self, entry_id: &str, registry: &Registry) -> Result<String, EvalError>;
fn resolve_document(
&mut self,
document_id: &str,
registry: &Registry,
) -> Result<String, EvalError>;
}
pub struct SimpleContext {
variables: HashMap<String, HashMap<String, Value>>,
triggers: HashMap<String, String>,
documents: HashMap<String, String>,
}
impl SimpleContext {
pub fn new() -> Self {
Self {
variables: HashMap::new(),
triggers: HashMap::new(),
documents: HashMap::new(),
}
}
pub fn set(&mut self, scope: &str, name: &str, value: impl Into<Value>) {
self.variables
.entry(scope.to_string())
.or_default()
.insert(name.to_string(), value.into());
}
pub fn set_trigger(&mut self, entry_id: &str, content: &str) {
self.triggers
.insert(entry_id.to_string(), content.to_string());
}
pub fn set_document(&mut self, document_id: &str, content: &str) {
self.documents
.insert(document_id.to_string(), content.to_string());
}
}
impl Default for SimpleContext {
fn default() -> Self {
Self::new()
}
}
impl EvalContext for SimpleContext {
fn resolve_variable(&self, scope: &str, name: &str) -> Result<Option<Value>, EvalError> {
Ok(self
.variables
.get(scope)
.and_then(|vars| vars.get(name))
.cloned())
}
fn set_variable(&mut self, scope: &str, name: &str, value: Value) -> Result<(), EvalError> {
self.variables
.entry(scope.to_string())
.or_default()
.insert(name.to_string(), value);
Ok(())
}
fn fire_trigger(&mut self, entry_id: &str, _registry: &Registry) -> Result<String, EvalError> {
self.triggers
.get(entry_id)
.cloned()
.ok_or_else(|| EvalError::host_error(format!("unknown trigger entry: {entry_id}")))
}
fn resolve_document(
&mut self,
document_id: &str,
_registry: &Registry,
) -> Result<String, EvalError> {
self.documents
.get(document_id)
.cloned()
.ok_or_else(|| EvalError::host_error(format!("unknown document: {document_id}")))
}
}