use std::collections::HashMap;
use std::any::{TypeId, Any};
use crate::ast::SyntaxNode;
use crate::units::Position;
pub trait Evaluator {
fn evaluate(&self, syntax_node: &SyntaxNode, context: &mut Context) -> Result<String, SyntaxError>;
}
pub struct Context {
variables: HashMap<String, String>,
states: HashMap<TypeId, Box<dyn Any>>,
}
impl Context {
pub fn empty() -> Context {
Context {
variables: HashMap::new(),
states: HashMap::new(),
}
}
pub fn with_variables(variables: HashMap<String, String>) -> Context {
Context {
variables,
states: HashMap::new(),
}
}
pub fn set_variable(&mut self, name: &str, value: &str) {
self.variables.insert(name.to_string(), value.to_string());
}
pub fn get_variable(&self, name: &str) -> Option<&String> {
self.variables.get(name)
}
pub fn save_state<T: Any>(&mut self, state: T) {
let key = TypeId::of::<T>();
self.states.insert(key, Box::new(state));
}
pub fn get_state<T: Any>(&self) -> Option<&T> {
let key = TypeId::of::<T>();
self.states.get(&key)
.map(|it|
it.downcast_ref::<T>()
.unwrap()
)
}
}
#[derive(Debug, PartialEq)]
pub struct SyntaxError {
pub relative_pos: Position,
pub invocation_pos: Position,
pub description: EvaluationError,
}
impl SyntaxError {
pub fn new(error: EvaluationError) -> SyntaxError {
SyntaxError {
relative_pos: Position::Unknown,
invocation_pos: Position::Unknown,
description: error,
}
}
pub fn at_position(position: Position, error: EvaluationError) -> SyntaxError {
SyntaxError {
relative_pos: position,
invocation_pos: Position::Unknown,
description: error
}
}
}
#[derive(Debug, PartialEq)]
pub enum EvaluationError {
UnexpectedElements {
last_expected: Option<SyntaxNode>,
unexpected_elements: Vec<SyntaxNode>,
},
UnknownSymbol {
symbol: String,
},
InvalidArguments {
description: Option<String>,
arguments: Vec<SyntaxNode>,
},
InvalidValues {
description: Option<String>,
values: Vec<String>,
},
}
pub trait Function {
fn evaluate(&self, evaluator: &dyn Evaluator, parameters: &[SyntaxNode], context: &mut Context) -> Result<String, SyntaxError>;
}
impl<F> Function for F where F: Fn(&dyn Evaluator, &[SyntaxNode], &mut Context) -> Result<String, SyntaxError> {
fn evaluate(&self, evaluator: &dyn Evaluator, parameters: &[SyntaxNode], context: &mut Context) -> Result<String, SyntaxError> {
self(evaluator, ¶meters, context)
}
}