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#[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#[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 ( $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}