sphinx/
macros.rs

1
2
3#[doc(hidden)]
4#[macro_export]
5macro_rules! __namespace_item {
6    ( $namespace:expr, let $name:tt $value:tt ) => {
7        $namespace.create(
8            stringify!($name).into(), 
9            crate::runtime::module::Access::ReadOnly, 
10            crate::runtime::Variant::from($value)
11        );
12    };
13    
14    ( $namespace:expr, var $name:tt $value:tt ) => {
15        $namespace.create(
16            stringify!($name).into(), 
17            crate::runtime::module::Access::ReadWrite, 
18            crate::runtime::Variant::from($value)
19        );
20    };
21    
22    ( $namespace:expr, fun _ $func:expr ) => {
23        let func = $func;
24        let name = func.signature().name().unwrap();
25        $namespace.create(
26            name, 
27            crate::language::Access::ReadOnly, 
28            crate::runtime::Variant::from(func)
29        );
30    };
31    
32    ( $namespace:expr, fun $name:tt $func:expr ) => {
33        $namespace.create(
34            stringify!($name).into(), 
35            crate::runtime::module::Access::ReadOnly, 
36            crate::runtime::Variant::from($func)
37        );
38    };
39}
40
41
42/// Helper to create a namespace
43#[macro_export]
44macro_rules! namespace_insert {
45    ( $namespace:expr, { $( $item:tt $name:tt = $value:expr ; )* } ) => {
46        $(
47            __namespace_item!($namespace, $item $name $value );
48        )*
49    };
50}
51
52
53/// Helper macros for creating native functions
54#[doc(hidden)]
55#[macro_export]
56macro_rules! __count {
57    () => (0usize);
58    ( $x:tt $($xs:tt)* ) => (1usize + __count!($($xs)*));
59}
60
61#[doc(hidden)]
62#[macro_export]
63macro_rules! __variadic {
64    () => { None };
65    ( $name:tt ) => {
66        Some(crate::runtime::function::Parameter::new(
67            stringify!($name), crate::language::Access::ReadWrite
68        ))
69    };
70}
71
72#[doc(hidden)]
73#[macro_export]
74macro_rules! __defaults {
75    () => { None };
76    ( $( $default_value:tt )+ ) => { 
77        Some(vec![ $( crate::runtime::Variant::from($default_value) ),+ ].into_boxed_slice())
78    };
79}
80
81#[macro_export]
82macro_rules! native_function {
83    
84    // with default params
85    ( $func_name:tt, $env:expr $( , this ( $self_name:tt ) )? $( , vm ( $vm_name:tt ) )? $( , params ( $( $required:tt ),+ ) )? $( , defaults ( $( $default:tt = $default_value:expr ),+ ) )? $( , variadic ( $variadic:tt ) )? => $body:expr ) => {
86        {
87            type Variant = crate::runtime::Variant;
88            type Signature = crate::runtime::function::Signature;
89            type Parameter = crate::runtime::function::Parameter;
90            type NativeFunction = crate::runtime::function::NativeFunction;
91            type VirtualMachine<'a> = crate::runtime::vm::VirtualMachine<'a>;
92            type ExecResult<T> = crate::runtime::errors::ExecResult<T>;
93            
94            let signature = Signature::new(
95                Some(stringify!($func_name)),
96                vec![ $( $( Parameter::new(stringify!($required), crate::language::Access::ReadWrite) ),+ )? ],
97                vec![ $( $( Parameter::new(stringify!($default), crate::language::Access::ReadWrite) ),+ )? ],
98                __variadic!( $( $variadic )? ),
99            );
100            
101            let defaults = __defaults!( $( $( $default_value )+ )? );
102            
103            fn body(self_fun: &NativeFunction, _vm: &mut VirtualMachine<'_>, args: &[Variant]) -> ExecResult<Variant> {
104                const _ARGC: usize = __count!( $( $( $required )+ )? $( $( $default )+ )? );
105                
106                let mut _argbuf = [Variant::Nil; _ARGC];
107                let _bound = self_fun.signature().bind_args(args, self_fun.defaults(), &mut _argbuf);
108                let _rest = _bound.args;
109                
110                $( let $self_name = self_fun; )?
111                $( let $vm_name = _vm; )?
112                $( $( let ($required, _rest) = _rest.split_first().unwrap(); )+ )?
113                $( $( let ($default, _rest) = _rest.split_first().unwrap(); )+ )?
114                $( let $variadic = _bound.varargs; )?
115                
116                $body
117            }
118            
119            NativeFunction::new(signature, defaults, $env, body)
120        }
121    };
122
123
124}