use std::rc::Rc;
use std::cell::RefCell;
use serde_json::Value;
use crate::ast::{Parser, AstError};
use crate::env::Env;
#[derive(Debug, thiserror::Error)]
pub enum JseError {
#[error("AST error: {0}")]
AstError(#[from] AstError),
#[error("{0}")]
Message(String),
}
impl JseError {
pub fn msg(s: impl Into<String>) -> Self {
JseError::Message(s.into())
}
}
pub struct Engine {
env: Rc<RefCell<Env>>,
parser: Parser,
}
impl Engine {
pub fn new(env: Rc<RefCell<Env>>) -> Self {
let parser = Parser::new(Rc::clone(&env));
Self { env, parser }
}
pub fn with_env() -> Self {
let env = Rc::new(RefCell::new(Env::new()));
Self::new(env)
}
pub fn with_default_env() -> Self {
let env = Rc::new(RefCell::new(Env::new()));
env.borrow_mut().load(&crate::functors::builtin::builtin_functors());
env.borrow_mut().load(&crate::functors::utils::utils_functors());
Self::new(env)
}
pub fn execute(&self, expr: &Value) -> Result<Value, JseError> {
let ast = self.parser.parse(expr)?;
ast.apply(&self.env).map_err(JseError::from)
}
pub fn env(&self) -> &Rc<RefCell<Env>> {
&self.env
}
}
pub trait AsEnv {
fn as_env_ref(&self) -> &Rc<RefCell<Env>>;
}
impl AsEnv for Rc<RefCell<Env>> {
fn as_env_ref(&self) -> &Rc<RefCell<Env>> {
self
}
}