1#[macro_export]
2macro_rules! extend_module {
3 ( $vm:expr, $module:expr, { $($name:expr => $value:expr),* $(,)? }) => {{
4 $(
5 $vm.__module_set_attr($module, $vm.ctx.intern_str($name), $value).unwrap();
6 )*
7 }};
8}
9
10#[macro_export]
11macro_rules! py_class {
12 ( $ctx:expr, $class_name:expr, $class_base:expr, { $($name:tt => $value:expr),* $(,)* }) => {
13 py_class!($ctx, $class_name, $class_base, $crate::types::PyTypeFlags::BASETYPE, { $($name => $value),* })
14 };
15 ( $ctx:expr, $class_name:expr, $class_base:expr, $flags:expr, { $($name:tt => $value:expr),* $(,)* }) => {
16 {
17 #[allow(unused_mut)]
18 let mut slots = $crate::types::PyTypeSlots::heap_default();
19 slots.flags = $flags;
20 $($crate::py_class!(@extract_slots($ctx, &mut slots, $name, $value));)*
21 let py_class = $ctx.new_class(None, $class_name, $class_base, slots);
22 $($crate::py_class!(@extract_attrs($ctx, &py_class, $name, $value));)*
23 py_class
24 }
25 };
26 (@extract_slots($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {
27 $slots.$slot_name.store(Some($value));
28 };
29 (@extract_slots($ctx:expr, $class:expr, $name:expr, $value:expr)) => {};
30 (@extract_attrs($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {};
31 (@extract_attrs($ctx:expr, $class:expr, $name:expr, $value:expr)) => {
32 $class.set_attr($name, $value);
33 };
34}
35
36#[macro_export]
37macro_rules! extend_class {
38 ( $ctx:expr, $class:expr, { $($name:expr => $value:expr),* $(,)* }) => {
39 $(
40 $class.set_attr($ctx.intern_str($name), $value.into());
41 )*
42 };
43}
44
45#[macro_export]
46macro_rules! py_namespace {
47 ( $vm:expr, { $($name:expr => $value:expr),* $(,)* }) => {
48 {
49 let namespace = $crate::builtins::PyNamespace::new_ref(&$vm.ctx);
50 let obj = $crate::object::AsObject::as_object(&namespace);
51 $(
52 obj.generic_setattr($vm.ctx.intern_str($name), $crate::function::PySetterValue::Assign($value.into()), $vm).unwrap();
53 )*
54 namespace
55 }
56 }
57}
58
59#[macro_export]
111macro_rules! match_class {
112 (match ($obj:expr) { _ => $default:expr $(,)? }) => {
114 $default
115 };
116
117 (match ($obj:expr) { $binding:ident => $default:expr $(,)? }) => {{
119 #[allow(clippy::redundant_locals)]
120 let $binding = $obj;
121 $default
122 }};
123 (match ($obj:expr) { ref $binding:ident => $default:expr $(,)? }) => {{
124 #[allow(clippy::redundant_locals)]
125 let $binding = &$obj;
126 $default
127 }};
128
129 (match ($obj:expr) { $binding:ident @ $class:ty => $expr:block $($rest:tt)* }) => {
133 $crate::match_class!(match ($obj) { $binding @ $class => ($expr), $($rest)* })
134 };
135 (match ($obj:expr) { ref $binding:ident @ $class:ty => $expr:block $($rest:tt)* }) => {
136 $crate::match_class!(match ($obj) { ref $binding @ $class => ($expr), $($rest)* })
137 };
138
139 (match ($obj:expr) { $binding:ident @ $class:ty => $expr:expr, $($rest:tt)* }) => {
142 match $obj.downcast::<$class>() {
143 Ok($binding) => $expr,
144 Err(_obj) => $crate::match_class!(match (_obj) { $($rest)* }),
145 }
146 };
147 (match ($obj:expr) { ref $binding:ident @ $class:ty => $expr:expr, $($rest:tt)* }) => {
148 match $obj.payload::<$class>() {
149 ::std::option::Option::Some($binding) => $expr,
150 ::std::option::Option::None => $crate::match_class!(match ($obj) { $($rest)* }),
151 }
152 };
153
154 (match ($obj:expr) { $class:ty => $expr:block $($rest:tt)* }) => {
157 $crate::match_class!(match ($obj) { $class => ($expr), $($rest)* })
158 };
159
160 (match ($obj:expr) { $class:ty => $expr:expr, $($rest:tt)* }) => {
163 if $obj.payload_is::<$class>() {
164 $expr
165 } else {
166 $crate::match_class!(match ($obj) { $($rest)* })
167 }
168 };
169
170 (match $($rest:tt)*) => {
172 $crate::match_class!(@parse_match () ($($rest)*))
173 };
174 (@parse_match ($($target:tt)*) ({ $($inner:tt)* })) => {
175 $crate::match_class!(match ($($target)*) { $($inner)* })
176 };
177 (@parse_match ($($target:tt)*) ($next:tt $($rest:tt)*)) => {
178 $crate::match_class!(@parse_match ($($target)* $next) ($($rest)*))
179 };
180}
181
182#[macro_export]
183macro_rules! identifier(
184 ($as_ctx:expr, $name:ident) => {
185 $as_ctx.as_ref().names.$name
186 };
187);
188
189macro_rules! vm_trace {
193 ($($arg:tt)+) => {
194 #[cfg(feature = "vm-tracing-logging")]
195 trace!($($arg)+);
196 }
197}
198
199macro_rules! flame_guard {
200 ($name:expr) => {
201 #[cfg(feature = "flame-it")]
202 let _guard = ::flame::start_guard($name);
203 };
204}
205
206#[macro_export]
207macro_rules! class_or_notimplemented {
208 ($t:ty, $obj:expr) => {{
209 let a: &$crate::PyObject = &*$obj;
210 match $crate::PyObject::downcast_ref::<$t>(&a) {
211 Some(pyref) => pyref,
212 None => return Ok($crate::function::PyArithmeticValue::NotImplemented),
213 }
214 }};
215}
216
217#[macro_export]
218macro_rules! named_function {
219 ($ctx:expr, $module:ident, $func:ident) => {{
220 #[allow(unused_variables)] let ctx: &$crate::Context = &$ctx;
222 $crate::__exports::paste::expr! {
223 ctx.new_method_def(
224 stringify!($func),
225 [<$module _ $func>],
226 ::rustpython_vm::function::PyMethodFlags::empty(),
227 )
228 .to_function()
229 .with_module(ctx.intern_str(stringify!($module)).into())
230 .into_ref(ctx)
231 }
232 }};
233}
234
235cfg_if::cfg_if! {
238 if #[cfg(feature = "threading")] {
239 macro_rules! py_dyn_fn {
240 (dyn Fn($($arg:ty),*$(,)*) -> $ret:ty) => {
241 dyn Fn($($arg),*) -> $ret + Send + Sync + 'static
242 };
243 }
244 } else {
245 macro_rules! py_dyn_fn {
246 (dyn Fn($($arg:ty),*$(,)*) -> $ret:ty) => {
247 dyn Fn($($arg),*) -> $ret + 'static
248 };
249 }
250 }
251}