use crate::wrap::{DeLiteral, EValue, EgglogNode, EgglogTy};
use egglog::ast::Literal;
pub trait EgglogFuncInput {
type Ref<'a>: EgglogFuncInputRef;
fn as_evalue(&self) -> &dyn EValue;
}
pub trait EgglogFuncInputs {
type Ref<'a>: EgglogFuncInputsRef;
fn as_evalues(&self) -> Box<[&dyn EValue]>;
}
pub trait EgglogFuncInputRef {
type DeRef: EgglogFuncInput + EValue;
fn as_evalue(&self) -> &dyn EValue;
}
pub trait EgglogFuncInputsRef {
type DeRef: EgglogFuncInputs;
fn as_evalues(&self) -> Box<[&dyn EValue]>;
}
pub trait EgglogFuncOutput: 'static + Clone + OutputFromLiteral<Output = Self> + EgglogTy {
type Ref<'a>: EgglogFuncOutputRef;
fn as_evalue(&self) -> &dyn EValue;
fn clone_downcast(&self) -> Self;
}
pub trait OutputFromLiteral {
type Output;
fn from_literal(lit: &Literal) -> Self::Output;
}
impl<T: EgglogNode + EgglogTy> OutputFromLiteral for T {
type Output = Self;
fn from_literal(lit: &Literal) -> Self::Output {
panic!("can't transfrom literal {} into {}", lit, T::TY_NAME)
}
}
impl<T> EgglogFuncOutput for T
where
T: EgglogNode + 'static + Sized + EgglogTy + Clone,
{
type Ref<'a> = &'a dyn AsRef<T>;
fn as_evalue(&self) -> &dyn EValue {
self
}
fn clone_downcast(&self) -> T {
self.clone()
}
}
impl<T: EgglogFuncOutput + EgglogNode + 'static> EgglogFuncOutputRef for &dyn AsRef<T> {
type DeRef = T;
fn as_evalue(&self) -> &dyn EValue {
self.as_ref()
}
fn deref(&self) -> &Self::DeRef {
self.as_ref()
}
}
pub trait EgglogFuncOutputRef {
type DeRef: EgglogFuncOutput;
fn as_evalue(&self) -> &dyn EValue;
fn deref(&self) -> &Self::DeRef;
}
pub trait EgglogFunc {
type Input: EgglogFuncInputs;
type Output: EgglogFuncOutput;
const FUNC_NAME: &'static str;
}
impl<T> EgglogFuncInput for T
where
T: EgglogNode + 'static,
{
type Ref<'a> = &'a dyn AsRef<T>;
fn as_evalue(&self) -> &dyn EValue {
self
}
}
impl<T> EgglogFuncInputRef for &dyn AsRef<T>
where
T: EgglogNode + 'static,
{
type DeRef = T;
fn as_evalue(&self) -> &dyn EValue {
self.as_ref()
}
}
macro_rules! impl_egglog_for_primitive {
($type:ty) => {
impl EgglogFuncInput for $type {
type Ref<'a> = &'a $type;
fn as_evalue(&self) -> &dyn EValue {
self
}
}
impl EgglogFuncInputRef for &$type {
type DeRef = $type;
fn as_evalue(&self) -> &dyn EValue {
*self
}
}
impl EgglogFuncOutput for $type {
type Ref<'a> = &'a $type;
fn as_evalue(&self) -> &dyn EValue {
self
}
fn clone_downcast(&self) -> Self {
self.clone()
}
}
impl EgglogFuncOutputRef for &$type {
type DeRef = $type;
fn as_evalue(&self) -> &dyn EValue {
*self
}
fn deref(&self) -> &Self::DeRef {
self
}
}
impl OutputFromLiteral for $type {
type Output = $type;
fn from_literal(lit: &Literal) -> Self::Output {
lit.deliteral()
}
}
};
}
impl_egglog_for_primitive!(i64);
impl_egglog_for_primitive!(String);
impl_egglog_for_primitive!(bool);
macro_rules! impl_input_for_tuples {
() => {
#[allow(unused)]
impl EgglogFuncInputs for () {
type Ref<'a> = ();
fn as_evalues(&self) -> Box<[&dyn EValue]>{
Box::new([])
}
}
};
($($T:ident),*) => {
#[allow(unused)]
impl<$($T: EValue + EgglogFuncInput),*> EgglogFuncInputs for ($($T),*) {
type Ref<'a> = ($($T::Ref<'a>),*);
fn as_evalues(&self) -> Box<[&dyn EValue]> {
#[allow(non_snake_case)]
let ($($T),*) = self;
Box::new([$($T),*])
}
}
};
}
macro_rules! impl_input_ref_for_tuples {
() => {
#[allow(unused)]
impl EgglogFuncInputsRef for () {
type DeRef = ();
fn as_evalues(&self) -> Box<[&dyn EValue]> {
Box::new([])
}
}
};
($($T:ident),*) => {
#[allow(unused)]
impl<$($T: EgglogFuncInputRef),*> EgglogFuncInputsRef for ($($T),*) {
type DeRef = ($($T::DeRef),*);
#[allow(non_snake_case)]
fn as_evalues(&self) -> Box<[&dyn EValue]> {
let ($($T),*) = self;
Box::new([$($T.as_evalue()),*])
}
}
};
}
macro_rules! impl_for_tuples {
($($T:ident),*) => {
impl_input_for_tuples!($($T),*);
impl_input_ref_for_tuples!($($T),*);
};
}
impl_for_tuples!();
impl_for_tuples!(T0);
impl_for_tuples!(T0, T1);
impl_for_tuples!(T0, T1, T2);
impl_for_tuples!(T0, T1, T2, T3);
impl_for_tuples!(T0, T1, T2, T3, T4);
impl_for_tuples!(T0, T1, T2, T3, T4, T5);
impl_for_tuples!(T0, T1, T2, T3, T4, T5, T6);
impl_for_tuples!(T0, T1, T2, T3, T4, T5, T6, T7);
impl_for_tuples!(T0, T1, T2, T3, T4, T5, T6, T7, T8);