rune_core/
macros.rs

1#![allow(clippy::crate_in_macro_def)]
2//! Redefinition of the `macro_exported` macros to avoid namespace
3//! colision when the macros have the same name as modules.
4//!
5//! An example of that is the `crate::error` module, and the [`macro@error`] macro.
6#[macro_export]
7#[doc(hidden)]
8macro_rules! __define_unbox {
9    ($ident:ident, $ty:ty) => {
10        define_unbox!($ident, $ident, $ty);
11    };
12    ($ident:ident, $ty:ident, $self:ty) => {
13        #[allow(unused_qualifications)]
14        impl<'ob> std::convert::TryFrom<crate::object::Object<'ob>> for $self {
15            type Error = crate::error::TypeError;
16            fn try_from(obj: crate::object::Object<'ob>) -> Result<Self, Self::Error> {
17                match obj.untag() {
18                    crate::object::Object::$ident(x) => Ok(x),
19                    _ => Err(crate::error::TypeError::new(crate::error::Type::$ty, obj)),
20                }
21            }
22        }
23        #[allow(unused_qualifications)]
24        impl<'ob> std::convert::TryFrom<crate::object::Object<'ob>> for Option<$self> {
25            type Error = crate::error::TypeError;
26            fn try_from(obj: crate::object::Object<'ob>) -> Result<Self, Self::Error> {
27                match obj.untag() {
28                    crate::object::Object::NIL => Ok(None),
29                    crate::object::Object::$ident(x) => Ok(Some(x)),
30                    _ => Err(crate::error::TypeError::new(crate::error::Type::$ty, obj)),
31                }
32            }
33        }
34    };
35}
36
37#[macro_export]
38#[doc(hidden)]
39macro_rules! __list {
40    ($x:expr; $cx:expr) => {
41        crate::core::object::Object::from(crate::core::cons::Cons::new1($x, $cx))
42    };
43    ($x:expr, $($y:expr),+ $(,)? ; $cx:expr) => {
44        crate::core::object::Object::from(crate::core::cons::Cons::new($x, list!($($y),+ ; $cx), $cx))
45    };
46}
47
48#[macro_export]
49#[doc(hidden)]
50macro_rules! __error {
51    ($msg:literal $(,)?  $($args:expr),* $(,)?) => (crate::eval::EvalError::new_error(anyhow::anyhow!($msg, $($args),*)));
52    ($err:expr) => (crate::eval::EvalError::new($err));
53}
54
55#[macro_export]
56#[doc(hidden)]
57macro_rules! __bail_err {
58    ($($args:expr),* $(,)?) => (return Err($crate::macros::error!($($args),*)));
59}
60
61#[macro_export]
62#[doc(hidden)]
63macro_rules! __root {
64    ($ident:ident, $cx:ident) => {
65        rune_core::macros::root!(@ $ident, unsafe { crate::core::gc::IntoRoot::into_root($ident) }, $cx);
66    };
67    ($ident:ident, init($init:expr), $cx:ident) => {
68        let value = $init;
69        rune_core::macros::root!(@ $ident, value, $cx);
70    };
71    ($ident:ident, new($path:tt$(<$ty:ty>)?), $cx:ident) => {
72        let value = $path$(::<$ty>)?::default();
73        rune_core::macros::root!(@ $ident, value, $cx);
74    };
75    ($ident:ident, $value:expr, $cx:ident) => {
76        rune_core::macros::root!(@ $ident, unsafe { crate::core::gc::IntoRoot::into_root($value) }, $cx);
77    };
78    (@ $ident:ident, $value:expr, $cx:ident) => {
79        let mut rooted = $value;
80        let mut root =
81            unsafe { crate::core::gc::__StackRoot::new(&mut rooted, $cx.get_root_set()) };
82        let $ident = root.as_mut();
83    };
84}
85
86#[macro_export]
87#[doc(hidden)]
88macro_rules! __last {
89    ($arg:expr) => { $arg };
90    ($head:expr, $($rest:expr),+) => {
91        $crate::macros::last!($($rest),+)
92    };
93}
94
95#[macro_export]
96#[doc(hidden)]
97macro_rules! __rebind {
98    // rebind!(func(x, cx)?)
99    ($($path:ident).*($($arg:expr),+)$($x:tt)?) => {{
100        rebind!($($path).*($($arg),+)$($x)?, $crate::macros::last!($($arg),+))
101    }};
102    // rebind!(func(x, cx))
103    ($($path:ident).*($($arg:expr),+)) => {{
104        rebind!($($path).*($($arg),+), $crate::macros::last!($($arg),+))
105    }};
106    // rebind!(func(x, cx).unwrap())
107    ($($path:ident).*($($arg:expr),+).unwrap()) => {{
108        rebind!($($path).*($($arg),+).unwrap(), $crate::macros::last!($($arg),+))
109    }};
110    // rebind!(x, cx)
111    ($value:expr, $cx:expr) => {{
112        // Eval value outside the unsafe block
113        let unbound = match $value {
114            v => unsafe { crate::core::object::WithLifetime::<'static>::with_lifetime(v) }
115        };
116        $cx.bind(unbound)
117    }};
118}
119
120#[macro_export]
121#[doc(hidden)]
122macro_rules! __call {
123    ($fn:ident $(,$args:expr)* ; $env:expr, $cx:expr) => {{
124        let frame = &mut crate::core::env::CallFrame::new($env);
125        $(frame.push_arg($args);)*
126        crate::core::gc::Rt::<crate::core::gc::Slot<crate::core::object::Gc::<crate::core::object::FunctionType>>>::call(
127            $fn, frame, None, $cx
128        )
129    }};
130    ($fn:ident $(,$args:expr)* ; $name:expr, $env:expr, $cx:expr) => {{
131        let frame = &mut crate::core::env::CallFrame::new($env);
132        $(frame.push_arg($args);)*
133        crate::core::gc::Rt::<crate::core::gc::Slot<crate::core::object::Gc::<crate::core::object::FunctionType>>>::call(
134            $fn, frame, Some($name), $cx
135        )
136    }};
137}
138
139/// TODO: Document
140#[doc(inline)]
141pub use __bail_err as bail_err;
142
143/// TODO: Document
144#[doc(inline)]
145pub use __define_unbox as define_unbox;
146
147/// TODO: Document
148#[doc(inline)]
149pub use __error as error;
150
151/// TODO: Document
152#[doc(inline)]
153pub use __list as list;
154
155/// Helper macro for the `rebind!` macro
156#[doc(inline)]
157pub use __last as last;
158
159/// Helper macro to call a function with arguments
160#[doc(inline)]
161pub use __call as call;
162
163/// Rebinds an object so that it is bound to an immutable borrow of `crate::gc::Context`
164/// instead of a mutable borrow. This can release the mutable borrow and allow
165/// Context to be used for other things.
166///
167/// # Examples
168///
169/// ```ignore
170/// let object = rebind!(func1(&mut cx));
171/// func2(&mut cx);
172/// let object2 = object;
173/// ```
174///
175/// wthout this macro the above code would not compile because `object` can't
176/// outlive the call to func2.
177#[doc(inline)]
178pub use __rebind as rebind;
179
180/// Creates a new root that will be traced during garbage collection. The value
181/// returned by this macro is no longer bound to the `Context` and so can be
182/// used outside of the `Context`'s lifetime. The root is tied to the stack, and
183/// will be unrooted when it goes out of scope.
184#[doc(inline)]
185pub use __root as root;