typed_eval/compiler/
method_calls.rs

1use 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}