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