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).unwrap())
103    ($($path:ident).*($($arg:expr),+).unwrap()) => {{
104        rebind!($($path).*($($arg),+).unwrap(), $crate::macros::last!($($arg),+))
105    }};
106    // rebind!(x, cx)
107    ($value:expr, $cx:expr) => {{
108        // Eval value outside the unsafe block
109        let unbound = match $value {
110            v => unsafe { crate::core::object::WithLifetime::<'static>::with_lifetime(v) }
111        };
112        $cx.bind(unbound)
113    }};
114}
115
116#[macro_export]
117#[doc(hidden)]
118macro_rules! __call {
119    ($fn:ident $(,$args:expr)* ; $env:expr, $cx:expr) => {{
120        let frame = &mut crate::core::env::CallFrame::new($env);
121        $(frame.push_arg($args);)*
122        crate::core::gc::Rt::<crate::core::gc::Slot<crate::core::object::Gc::<crate::core::object::FunctionType>>>::call(
123            $fn, frame, None, $cx
124        )
125    }};
126    ($fn:ident $(,$args:expr)* ; $name:expr, $env:expr, $cx:expr) => {{
127        let frame = &mut crate::core::env::CallFrame::new($env);
128        $(frame.push_arg($args);)*
129        crate::core::gc::Rt::<crate::core::gc::Slot<crate::core::object::Gc::<crate::core::object::FunctionType>>>::call(
130            $fn, frame, Some($name), $cx
131        )
132    }};
133}
134
135/// TODO: Document
136#[doc(inline)]
137pub use __bail_err as bail_err;
138
139/// TODO: Document
140#[doc(inline)]
141pub use __define_unbox as define_unbox;
142
143/// TODO: Document
144#[doc(inline)]
145pub use __error as error;
146
147/// TODO: Document
148#[doc(inline)]
149pub use __list as list;
150
151/// Helper macro for the `rebind!` macro
152#[doc(inline)]
153pub use __last as last;
154
155/// Helper macro to call a function with arguments
156#[doc(inline)]
157pub use __call as call;
158
159/// Rebinds an object so that it is bound to an immutable borrow of `crate::gc::Context`
160/// instead of a mutable borrow. This can release the mutable borrow and allow
161/// Context to be used for other things.
162///
163/// # Examples
164///
165/// ```ignore
166/// let object = rebind!(func1(&mut cx));
167/// func2(&mut cx);
168/// let object2 = object;
169/// ```
170///
171/// wthout this macro the above code would not compile because `object` can't
172/// outlive the call to func2.
173#[doc(inline)]
174pub use __rebind as rebind;
175
176/// Creates a new root that will be traced during garbage collection. The value
177/// returned by this macro is no longer bound to the `Context` and so can be
178/// used outside of the `Context`'s lifetime. The root is tied to the stack, and
179/// will be unrooted when it goes out of scope.
180#[doc(inline)]
181pub use __root as root;