use crate::semantics::cfg::Cfg;
use crate::semantics::core::form::CellForm;
use crate::semantics::core::form::ListForm;
use crate::semantics::core::form::MapForm;
use crate::semantics::core::form::PairForm;
use crate::semantics::core::key::KeyEval;
use crate::semantics::func::DynFunc;
use crate::semantics::val::CallVal;
use crate::semantics::val::CellVal;
use crate::semantics::val::ListVal;
use crate::semantics::val::MapVal;
use crate::semantics::val::PairVal;
use crate::semantics::val::QuoteVal;
use crate::semantics::val::SolveVal;
use crate::semantics::val::Val;
use crate::type_::Call;
use crate::type_::Key;
use crate::type_::Quote;
use crate::type_::Solve;
pub(crate) struct QuoteEval;
impl DynFunc<Cfg, Val, QuoteVal, Val> for QuoteEval {
fn call(&self, _cfg: &mut Cfg, _ctx: &mut Val, quote: QuoteVal) -> Val {
let quote = Quote::from(quote);
quote.value
}
}
pub(crate) struct CallEval<'a, Func, Input> {
pub(crate) func: &'a Func,
pub(crate) input: &'a Input,
}
impl<'a, Func, Input> DynFunc<Cfg, Val, CallVal, Val> for CallEval<'a, Func, Input>
where
Func: DynFunc<Cfg, Val, Val, Val>,
Input: DynFunc<Cfg, Val, Val, Val>,
{
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, call: CallVal) -> Val {
let call = Call::from(call);
let func = self.func.call(cfg, ctx, call.func);
let Val::Func(func) = func else {
cfg.abort();
return Val::default();
};
let input = self.input.call(cfg, ctx, call.input);
if cfg.is_aborted() {
return Val::default();
}
func.call(cfg, ctx, input)
}
}
pub(crate) struct SolveEval<'a, Func, Output> {
pub(crate) func: &'a Func,
pub(crate) output: &'a Output,
}
impl<'a, Func, Output> DynFunc<Cfg, Val, SolveVal, Val> for SolveEval<'a, Func, Output>
where
Func: DynFunc<Cfg, Val, Val, Val>,
Output: DynFunc<Cfg, Val, Val, Val>,
{
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, solve: SolveVal) -> Val {
let solve = Solve::from(solve);
let func = self.func.call(cfg, ctx, solve.func);
let Val::Func(func) = func else {
cfg.abort();
return Val::default();
};
let output = self.output.call(cfg, ctx, solve.output);
if cfg.is_aborted() {
return Val::default();
}
let Some(input) = cfg.fact_solve(func, output) else {
cfg.abort();
return Val::default();
};
input
}
}
#[derive(Default, Copy, Clone)]
pub struct Eval;
impl DynFunc<Cfg, Val, Val, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, val: Val) -> Val {
if cfg.is_aborted() {
return Val::default();
}
match val {
Val::Key(key) => self.call(cfg, ctx, key),
Val::Cell(cell) => self.call(cfg, ctx, cell),
Val::Pair(pair) => self.call(cfg, ctx, pair),
Val::List(list) => self.call(cfg, ctx, list),
Val::Map(map) => self.call(cfg, ctx, map),
Val::Quote(quote) => self.call(cfg, ctx, quote),
Val::Call(call) => self.call(cfg, ctx, call),
Val::Solve(solve) => self.call(cfg, ctx, solve),
v => v,
}
}
}
impl DynFunc<Cfg, Val, Key, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, key: Key) -> Val {
KeyEval.call(cfg, ctx, key)
}
}
impl DynFunc<Cfg, Val, CellVal, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, cell: CellVal) -> Val {
Val::Cell(CellForm { value: self }.call(cfg, ctx, cell))
}
}
impl DynFunc<Cfg, Val, PairVal, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, pair: PairVal) -> Val {
Val::Pair(PairForm { left: self, right: self }.call(cfg, ctx, pair))
}
}
impl DynFunc<Cfg, Val, ListVal, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, list: ListVal) -> Val {
Val::List(ListForm { item: self }.call(cfg, ctx, list))
}
}
impl DynFunc<Cfg, Val, MapVal, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, map: MapVal) -> Val {
Val::Map(MapForm { value: self }.call(cfg, ctx, map))
}
}
impl DynFunc<Cfg, Val, QuoteVal, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, quote: QuoteVal) -> Val {
QuoteEval.call(cfg, ctx, quote)
}
}
impl DynFunc<Cfg, Val, CallVal, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, call: CallVal) -> Val {
CallEval { func: self, input: self }.call(cfg, ctx, call)
}
}
impl DynFunc<Cfg, Val, SolveVal, Val> for Eval {
fn call(&self, cfg: &mut Cfg, ctx: &mut Val, solve: SolveVal) -> Val {
SolveEval { func: self, output: self }.call(cfg, ctx, solve)
}
}