#[derive(Clone, Copy)]
pub struct FnMeta {
pub name: &'static str,
pub arity: u8,
pub addr: *const u8,
pub mod_path: &'static str,
pub uses_ctx: bool,
pub ctx_type_id_fn: Option<fn() -> ::core::any::TypeId>,
}
unsafe impl Sync for FnMeta {}
inventory::collect!(FnMeta);
pub trait HasCtx {
type Ctx;
}
impl<Ctx> HasCtx for crate::engine::Tabula<Ctx> {
type Ctx = Ctx;
}
#[macro_export]
macro_rules! register_functions {
($eng:expr, $($name:ident),+ $(,)?) => {{
#[allow(dead_code)]
fn __tabulon_engine_ctx_type_id<E: $crate::HasCtx>(_: &E) -> ::core::any::TypeId
where
<E as $crate::HasCtx>::Ctx: 'static,
{
::core::any::TypeId::of::<<E as $crate::HasCtx>::Ctx>()
}
let __eng_tid = __tabulon_engine_ctx_type_id(&$eng);
let mut res: Result<(), $crate::JitError> = Ok(());
let wanted: &[&str] = &[ $( stringify!($name) ),+ ];
for meta in $crate::inventory::iter::<$crate::FnMeta> {
if wanted.contains(&meta.name) {
if meta.uses_ctx {
if let Some(ctx_tid_fn) = meta.ctx_type_id_fn {
if (ctx_tid_fn)() != __eng_tid {
res = Err($crate::JitError::Internal(format!(
"context type mismatch when registering {}: engine Ctx does not match function's Ctx",
meta.name
)));
break;
}
}
}
res = res.and_then(|_| unsafe {
match meta.arity {
0 => $eng.register_nullary(meta.name, std::mem::transmute::<*const u8, $crate::Fn0>(meta.addr), meta.uses_ctx),
1 => $eng.register_unary(meta.name, std::mem::transmute::<*const u8, $crate::Fn1>(meta.addr), meta.uses_ctx),
2 => $eng.register_binary(meta.name, std::mem::transmute::<*const u8, $crate::Fn2>(meta.addr), meta.uses_ctx),
3 => $eng.register_ternary(meta.name, std::mem::transmute::<*const u8, $crate::Fn3>(meta.addr), meta.uses_ctx),
_ => Err($crate::JitError::Internal(format!("unsupported arity {} for {}", meta.arity, meta.name))),
}
});
}
}
res
}};
}
#[macro_export]
macro_rules! register_functions_typed {
($eng:expr, $($marker:path),+ $(,)?) => {{
let mut res: Result<(), $crate::JitError> = Ok(());
$(
res = res.and_then(|_| $eng.register_typed::<$marker>());
)+
res
}};
}
pub trait SameAs<T> {}
impl<T> SameAs<T> for T {}
pub trait FunctionForEngineCtx<EngineCtx> {
const NAME: &'static str;
const ARITY: u8;
const USES_CTX: bool;
fn addr() -> *const u8;
}
pub trait ResolverForEngineCtx<EngineCtx> {
const NAME: &'static str;
fn addr() -> *const u8;
}
#[macro_export]
macro_rules! register_resolver_typed {
($eng:expr, $marker:path) => {{
$eng.set_var_getter_typed::<$marker>()
}};
}