use std::rc::Rc;
use crate::lang::{EvalResult, Signal};
use crate::object::*;
use crate::{error::*, internal_err};
pub trait Context: std::fmt::Debug + std::fmt::Display {
#[inline]
fn get(&mut self, name: String) -> EvalResult {
(*self).env().get(name)
}
#[inline]
fn get_mut(&mut self, name: String) -> EvalResult {
self.get(name)
}
#[inline]
fn get_ellipsis(&mut self) -> EvalResult {
let err = Err(Signal::Error(Error::IncorrectContext("...".to_string())));
self.get("...".to_string()).or(err)
}
#[inline]
fn assign_lazy(&mut self, _to: Expr, _from: Expr) -> EvalResult {
Err(Signal::Error(Error::IncorrectContext("<-".to_string())))
}
#[inline]
fn assign(&mut self, _to: Expr, _from: Obj) -> EvalResult {
Err(Signal::Error(Error::IncorrectContext("<-".to_string())))
}
fn env(&self) -> Rc<Environment>;
#[inline]
fn eval_call(&mut self, expr: Expr) -> EvalResult {
self.eval(expr)
}
#[inline]
fn eval_call_mut(&mut self, expr: Expr) -> EvalResult {
Error::CannotEvaluateAsMutable(expr.clone()).into()
}
#[inline]
fn eval(&mut self, expr: Expr) -> EvalResult {
self.env().eval(expr)
}
#[inline]
fn eval_mut(&mut self, expr: Expr) -> EvalResult {
Error::CannotEvaluateAsMutable(expr.clone()).into()
}
#[inline]
fn eval_in(&mut self, expr: Expr, mut env: Rc<Environment>) -> EvalResult {
env.eval(expr)
}
#[inline]
fn eval_and_finalize(&mut self, expr: Expr) -> EvalResult {
self.eval(expr)
}
#[inline]
fn eval_binary(&mut self, exprs: (Expr, Expr)) -> Result<(Obj, Obj), Signal> {
Ok((
self.eval_and_finalize(exprs.0)?,
self.eval_and_finalize(exprs.1)?,
))
}
fn eval_list_lazy(&mut self, l: ExprList) -> EvalResult {
Ok(Obj::List(List::from(
l.into_iter()
.map(|pair| match pair {
(_, Expr::Ellipsis(None)) => {
if let Ok(Obj::List(ellipsis)) = self.get_ellipsis() {
Ok(ellipsis.iter_pairs())
} else {
Ok(List::new().iter_pairs())
}
}
(_, Expr::Ellipsis(Some(name))) => {
if let Ok(Obj::List(more)) = self.get(name) {
Ok(more.iter_pairs())
} else {
internal_err!()
}
}
(k, Expr::Symbol(s)) => match self.env().get(s.clone()) {
Ok(c @ Obj::Promise(..)) => {
let k = k.map_or(OptionNA::NA, OptionNA::Some);
Ok(List::from(vec![(k, c)]).iter_pairs())
}
_ => {
let k = k.map_or(OptionNA::NA, OptionNA::Some);
Ok(List::from(vec![(
k,
Obj::Promise(None, Expr::Symbol(s), self.env()),
)])
.iter_pairs())
}
},
(k, c @ Expr::Call(..)) => {
let k = k.map_or(OptionNA::NA, OptionNA::Some);
let elem = vec![(k, Obj::Promise(None, c, self.env()))];
Ok(List::from(elem).iter_pairs())
}
(k, v) => {
Ok(List::from(vec![(k, Obj::Promise(None, v, self.env()))]).iter_pairs())
}
})
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flatten()
.collect::<Vec<_>>(),
)))
}
}