use derive_more::From;
use crate::semantics::cfg::Cfg;
use crate::semantics::ctx::CtxAccess;
use crate::semantics::func::ConstCompFunc;
use crate::semantics::func::ConstFn;
use crate::semantics::func::ConstPrimFunc;
use crate::semantics::func::FreeCompFunc;
use crate::semantics::func::FreeFn;
use crate::semantics::func::FreePrimFunc;
use crate::semantics::func::MutCompFunc;
use crate::semantics::func::MutFn;
use crate::semantics::func::MutPrimFunc;
use crate::semantics::val::Val;
use crate::type_::ConstRef;
use crate::type_::DynRef;
use crate::type_::wrap::rc_wrap;
#[derive(Clone, PartialEq, Eq, From)]
pub enum FuncVal {
FreePrim(FreePrimFuncVal),
FreeComp(FreeCompFuncVal),
ConstPrim(ConstPrimFuncVal),
ConstComp(ConstCompFuncVal),
MutPrim(MutPrimFuncVal),
MutComp(MutCompFuncVal),
}
rc_wrap!(pub FreePrimFuncVal(FreePrimFunc));
rc_wrap!(pub FreeCompFuncVal(FreeCompFunc));
rc_wrap!(pub ConstPrimFuncVal(ConstPrimFunc));
rc_wrap!(pub ConstCompFuncVal(ConstCompFunc));
rc_wrap!(pub MutPrimFuncVal(MutPrimFunc));
rc_wrap!(pub MutCompFuncVal(MutCompFunc));
macro_rules! match_func_val {
($self:ident, $name:ident => $body:expr) => {
match $self {
FuncVal::FreePrim($name) => $body,
FuncVal::FreeComp($name) => $body,
FuncVal::ConstPrim($name) => $body,
FuncVal::ConstComp($name) => $body,
FuncVal::MutPrim($name) => $body,
FuncVal::MutComp($name) => $body,
}
};
}
impl FreeFn<Cfg, Val, Val> for FuncVal {
fn free_call(&self, cfg: &mut Cfg, input: Val) -> Val {
match_func_val!(self, f => f.free_call(cfg,input))
}
}
impl ConstFn<Cfg, Val, Val, Val> for FuncVal {
fn const_call(&self, cfg: &mut Cfg, ctx: ConstRef<Val>, input: Val) -> Val {
match self {
FuncVal::FreePrim(f) => f.free_call(cfg, input),
FuncVal::FreeComp(f) => f.free_call(cfg, input),
FuncVal::ConstPrim(f) => f.const_call(cfg, ctx, input),
FuncVal::ConstComp(f) => f.const_call(cfg, ctx, input),
FuncVal::MutPrim(f) => f.const_call(cfg, ctx, input),
FuncVal::MutComp(f) => f.const_call(cfg, ctx, input),
}
}
fn opt_const_call(&self, cfg: &mut Cfg, ctx: Option<ConstRef<Val>>, input: Val) -> Val {
match self {
FuncVal::FreePrim(f) => f.free_call(cfg, input),
FuncVal::FreeComp(f) => f.free_call(cfg, input),
FuncVal::ConstPrim(f) => f.opt_const_call(cfg, ctx, input),
FuncVal::ConstComp(f) => f.opt_const_call(cfg, ctx, input),
FuncVal::MutPrim(f) => f.opt_const_call(cfg, ctx, input),
FuncVal::MutComp(f) => f.opt_const_call(cfg, ctx, input),
}
}
}
impl MutFn<Cfg, Val, Val, Val> for FuncVal {
fn mut_call(&self, cfg: &mut Cfg, ctx: &mut Val, input: Val) -> Val {
match self {
FuncVal::FreePrim(f) => f.free_call(cfg, input),
FuncVal::FreeComp(f) => f.free_call(cfg, input),
FuncVal::ConstPrim(f) => f.const_call(cfg, ConstRef::new(ctx), input),
FuncVal::ConstComp(f) => f.const_call(cfg, ConstRef::new(ctx), input),
FuncVal::MutPrim(f) => f.mut_call(cfg, ctx, input),
FuncVal::MutComp(f) => f.mut_call(cfg, ctx, input),
}
}
fn dyn_call(&self, cfg: &mut Cfg, ctx: DynRef<Val>, input: Val) -> Val {
match self {
FuncVal::FreePrim(f) => f.free_call(cfg, input),
FuncVal::FreeComp(f) => f.free_call(cfg, input),
FuncVal::ConstPrim(f) => f.const_call(cfg, ctx.into_const(), input),
FuncVal::ConstComp(f) => f.const_call(cfg, ctx.into_const(), input),
FuncVal::MutPrim(f) => f.dyn_call(cfg, ctx, input),
FuncVal::MutComp(f) => f.dyn_call(cfg, ctx, input),
}
}
fn opt_dyn_call(&self, cfg: &mut Cfg, ctx: Option<DynRef<Val>>, input: Val) -> Val {
match self {
FuncVal::FreePrim(f) => f.free_call(cfg, input),
FuncVal::FreeComp(f) => f.free_call(cfg, input),
FuncVal::ConstPrim(f) => f.opt_const_call(cfg, ctx.map(DynRef::into_const), input),
FuncVal::ConstComp(f) => f.opt_const_call(cfg, ctx.map(DynRef::into_const), input),
FuncVal::MutPrim(f) => f.opt_dyn_call(cfg, ctx, input),
FuncVal::MutComp(f) => f.opt_dyn_call(cfg, ctx, input),
}
}
}
impl FuncVal {
pub fn raw_input(&self) -> bool {
match_func_val!(self, f => f.raw_input)
}
pub fn prelude(&self) -> Option<&Val> {
match self {
FuncVal::FreePrim(_) => None,
FuncVal::FreeComp(f) => Some(&f.comp.prelude),
FuncVal::ConstPrim(_) => None,
FuncVal::ConstComp(f) => Some(&f.comp.prelude),
FuncVal::MutPrim(_) => None,
FuncVal::MutComp(f) => Some(&f.comp.prelude),
}
}
pub fn is_primitive(&self) -> bool {
match self {
FuncVal::FreePrim(_) => true,
FuncVal::FreeComp(_) => false,
FuncVal::ConstPrim(_) => true,
FuncVal::ConstComp(_) => false,
FuncVal::MutPrim(_) => true,
FuncVal::MutComp(_) => false,
}
}
pub fn ctx_access(&self) -> CtxAccess {
match self {
FuncVal::FreePrim(_) => CtxAccess::Free,
FuncVal::FreeComp(_) => CtxAccess::Free,
FuncVal::ConstPrim(_) => CtxAccess::Const,
FuncVal::ConstComp(_) => CtxAccess::Const,
FuncVal::MutPrim(_) => CtxAccess::Mut,
FuncVal::MutComp(_) => CtxAccess::Mut,
}
}
}
impl Default for FreePrimFuncVal {
fn default() -> Self {
Self::from(FreePrimFunc::default())
}
}
impl Default for FuncVal {
fn default() -> Self {
Self::FreePrim(FreePrimFuncVal::default())
}
}