use std::{
fmt, any,
};
use crate::{
func::{AvidFunc, Builtin, Callable},
parser::Operation, Stack, ErrorKind, Builder,
};
#[allow(unused_imports)]
use crate::Avid;
#[derive(Debug)]
pub struct Ast<'a> {
pub(crate) ops: Vec<Operation>,
pub(crate) provided: Vec<Option<SendCallable<'a>>>,
}
impl<'a> Ast<'a> {
pub fn new(src: &'a str) -> crate::Result<Self> {
Builder::new_ast(src).build()
}
}
assert_send!(Ast);
#[doc(hidden)]
pub enum SendCallable<'a> {
Builtin(Builtin),
Unknown {
name: Option<String>,
func: Box<dyn SendFunc + 'a>,
},
}
impl<'a> From<Builtin> for SendCallable<'a> {
fn from(b: Builtin) -> Self {
Self::Builtin(b)
}
}
impl<'a, T: Send + FnMut(&mut Stack) -> crate::Result<(), ErrorKind> + 'a> From<T> for SendCallable<'a> {
fn from(f: T) -> Self {
Self::Unknown {
name: Some(any::type_name::<T>().to_owned()),
func: Box::new(f) as Box<dyn SendFunc + 'a>
}
}
}
impl AvidFunc for SendCallable<'_> {
fn call(&mut self, stack: &mut Stack) -> crate::Result<(), ErrorKind> {
match self {
SendCallable::Builtin(b) => b.call(stack),
SendCallable::Unknown { name: _, func } => func.call(stack),
}
}
fn name(&self) -> String {
match self {
SendCallable::Builtin(b) => b.name(),
SendCallable::Unknown { name, func } => name.clone().unwrap_or_else(|| func.name()),
}
}
}
impl fmt::Debug for SendCallable<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Builtin(arg0) => f.debug_tuple("Builtin").field(arg0).finish(),
Self::Unknown { name, func } => f
.debug_struct("Unknown")
.field("name", &name.clone().unwrap_or_else(|| func.name()))
.finish(),
}
}
}
assert_send!(SendCallable);
#[doc(hidden)]
pub trait SendFunc: Send + AvidFunc {}
impl<T: Send + AvidFunc> SendFunc for T {}
impl<'a> From<SendCallable<'a>> for Callable<'a, 'a> {
fn from(s: SendCallable<'a>) -> Self {
match s {
SendCallable::Builtin(b) => Self::Builtin(b),
SendCallable::Unknown { name, func } => Self::UnknownSend { name, func },
}
}
}