1#[derive(Clone, Copy)]
3pub struct FnMeta {
4 pub name: &'static str,
5 pub arity: u8,
6 pub addr: *const u8,
7 pub mod_path: &'static str,
8 pub uses_ctx: bool,
9 pub ctx_type_id_fn: Option<fn() -> ::core::any::TypeId>,
10}
11
12unsafe impl Sync for FnMeta {}
14
15inventory::collect!(FnMeta);
16
17pub trait HasCtx {
19 type Ctx;
20}
21
22impl<Ctx> HasCtx for crate::engine::Tabula<Ctx> {
23 type Ctx = Ctx;
24}
25
26#[macro_export]
27macro_rules! register_functions {
28 ($eng:expr, $($name:ident),+ $(,)?) => {{
29 #[allow(dead_code)]
31 fn __tabulon_engine_ctx_type_id<E: $crate::HasCtx>(_: &E) -> ::core::any::TypeId
32 where
33 <E as $crate::HasCtx>::Ctx: 'static,
34 {
35 ::core::any::TypeId::of::<<E as $crate::HasCtx>::Ctx>()
36 }
37 let __eng_tid = __tabulon_engine_ctx_type_id(&$eng);
38
39 let mut res: Result<(), $crate::JitError> = Ok(());
40 let wanted: &[&str] = &[ $( stringify!($name) ),+ ];
41 for meta in $crate::inventory::iter::<$crate::FnMeta> {
42 if wanted.contains(&meta.name) {
43 if meta.uses_ctx {
45 if let Some(ctx_tid_fn) = meta.ctx_type_id_fn {
46 if (ctx_tid_fn)() != __eng_tid {
47 res = Err($crate::JitError::Internal(format!(
48 "context type mismatch when registering {}: engine Ctx does not match function's Ctx",
49 meta.name
50 )));
51 break;
52 }
53 }
54 }
55 res = res.and_then(|_| unsafe {
56 match meta.arity {
57 0 => $eng.register_nullary(meta.name, std::mem::transmute::<*const u8, $crate::Fn0>(meta.addr), meta.uses_ctx),
58 1 => $eng.register_unary(meta.name, std::mem::transmute::<*const u8, $crate::Fn1>(meta.addr), meta.uses_ctx),
59 2 => $eng.register_binary(meta.name, std::mem::transmute::<*const u8, $crate::Fn2>(meta.addr), meta.uses_ctx),
60 3 => $eng.register_ternary(meta.name, std::mem::transmute::<*const u8, $crate::Fn3>(meta.addr), meta.uses_ctx),
61 _ => Err($crate::JitError::Internal(format!("unsupported arity {} for {}", meta.arity, meta.name))),
62 }
63 });
64 }
65 }
66 res
67 }};
68}
69
70#[macro_export]
71macro_rules! register_functions_typed {
72 ($eng:expr, $($marker:path),+ $(,)?) => {{
73 let mut res: Result<(), $crate::JitError> = Ok(());
74 $(
75 res = res.and_then(|_| $eng.register_typed::<$marker>());
76 )+
77 res
78 }};
79}
80
81pub trait SameAs<T> {}
83impl<T> SameAs<T> for T {}
84
85pub trait FunctionForEngineCtx<EngineCtx> {
87 const NAME: &'static str;
88 const ARITY: u8;
89 const USES_CTX: bool;
90 fn addr() -> *const u8;
91}
92
93pub trait ResolverForEngineCtx<EngineCtx> {
95 const NAME: &'static str;
97 fn addr() -> *const u8;
99}
100
101#[macro_export]
102macro_rules! register_resolver_typed {
103 ($eng:expr, $marker:path) => {{
104 $eng.set_var_getter_typed::<$marker>()
105 }};
106}