typed_eval/compiler/
method_calls.rs1use super::try_insert;
2use crate::{DynFn, Error, EvalType, MethodCallData, RegistryAccess, Result};
3
4macro_rules! register_method_call {
5 ($name:ident, $count:tt $(, $arg:ident : $idx:tt )* ) => {
6 pub fn $name<$($arg,)* Ret>(
7 &mut self,
8 method: &'static str,
9 method_fn: for<'a> fn(&'a T $(, $arg::RefType<'a> )* ) -> Ret::RefType<'a>,
10 ) -> Result<()>
11 where
12 $($arg: EvalType,)*
13 Ret: EvalType,
14 {
15 $(
16 self.register_type::<$arg>()?;
17 )*
18 self.register_type::<Ret>()?;
19
20 let compile_fn = Box::new(
21 #[allow(unused_mut, non_snake_case)]
22 move |object: DynFn, mut args: Vec<DynFn>| -> Result<DynFn> {
23 if args.len() != $count {
24 Err(Error::InternalArgCountMismatch { expected: $count, got: args.len() })?;
25 }
26
27 $(
28 let $arg = args[$idx]
29 .downcast::<Ctx, $arg>()?;
30 )*
31
32 let object = object
33 .downcast::<Ctx, T>()?;
34
35 Ok(Ret::make_dyn_fn(move |ctx: &Ctx| {
36 method_fn(object(ctx) $(, $arg(ctx) )* )
37 }))
38 },
39 );
40
41 let ty = T::type_info();
42 let arg_types = vec![$($arg::type_info(),)*];
43
44 let data = MethodCallData {
45 compile_fn,
46 arg_types,
47 };
48
49 try_insert(
50 &mut self.registry.method_calls,
51 (ty, method),
52 data,
53 || Error::DuplicateMethod { ty, method }
54 )
55 }
56 };
57}
58
59impl<'r, Ctx, T> RegistryAccess<'r, Ctx, T>
60where
61 Ctx: EvalType,
62 T: for<'a> EvalType<RefType<'a> = &'a T>,
63{
64 register_method_call!(register_method_call_0, 0);
65 register_method_call!(register_method_call_1, 1, A1: 0);
66 register_method_call!(register_method_call_2, 2, A1: 0, A2: 1);
67 register_method_call!(register_method_call_3, 3, A1: 0, A2: 1, A3: 2);
68 register_method_call!(register_method_call_4, 4, A1: 0, A2: 1, A3: 2, A4: 3);
69 register_method_call!(register_method_call_5, 5, A1: 0, A2: 1, A3: 2, A4: 3, A5: 4);
70}