Skip to content

Commit

Permalink
Rework the module and function traits
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed May 6, 2023
1 parent fc61152 commit 7848041
Show file tree
Hide file tree
Showing 23 changed files with 654 additions and 741 deletions.
4 changes: 0 additions & 4 deletions crates/rune-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,5 @@ syn = { version = "2.0.15", features = ["full"] }
quote = "1.0.26"
proc-macro2 = { version = "1.0.56", features = ["span-locations"] }

[dev-dependencies]
rune = { version = "0.12.3", path = "../rune" }

[lib]
proc-macro = true
path = "src/lib.rs"
223 changes: 0 additions & 223 deletions crates/rune-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,28 +39,6 @@ mod spanned;
mod to_tokens;
mod to_value;

/// Macro helper function for quoting the token stream as macro output.
///
/// Is capable of quoting everything in Rune, except for the following:
/// * Labels, which must be created using `Label::new`.
/// * Dynamic quoted strings and other literals, which must be created using
/// `Lit::new`.
///
/// ```
/// use rune::macros::quote;
///
/// quote!(hello self);
/// ```
///
/// # Interpolating values
///
/// Values are interpolated with `#value`, or `#(value + 1)` for expressions.
///
/// # Iterators
///
/// Anything that can be used as an iterator can be iterated over with
/// `#(iter)*`. A token can also be used to join inbetween each iteration, like
/// `#(iter),*`.
#[proc_macro]
pub fn quote(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = proc_macro2::TokenStream::from(input);
Expand All @@ -74,111 +52,6 @@ pub fn quote(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
output.into()
}

/// Macro used to annotate native functions which can be loaded into rune.
///
/// This macro automatically performs the following things:
/// * Rust documentation comments are captured so that it can be used in
/// generated Rune documentation.
/// * The name of arguments is captured to improve documentation generation.
/// * If an instance function is annotated this is detected (if the function
/// receives `self`). This behavior can be forced using `#[rune(instance)]` if
/// the function doesn't take `self`.
///
/// # Examples
///
/// A simple free function:
///
/// ```
/// use rune::{Module, ContextError};
///
/// /// This is a pretty neat function which is called `std::str::to_uppercase("hello")`.
/// #[rune::function]
/// fn to_uppercase(string: &str) -> String {
/// string.to_uppercase()
/// }
///
/// fn module() -> Result<Module, ContextError> {
/// let mut m = Module::new();
/// m.function_meta(to_uppercase)?;
/// Ok(m)
/// }
/// ```
///
/// A free instance function:
///
/// ```
/// use rune::{Module, ContextError};
///
/// /// This is a pretty neat function, which is called like `"hello".to_uppercase()`.
/// #[rune::function(instance)]
/// fn to_uppercase(string: &str) -> String {
/// string.to_uppercase()
/// }
///
/// /// This is a pretty neat function, which is called like `string::to_uppercase2("hello")`.
/// #[rune::function(path = string)]
/// fn to_uppercase2(string: &str) -> String {
/// string.to_uppercase()
/// }
///
/// fn module() -> Result<Module, ContextError> {
/// let mut m = Module::new();
/// m.function_meta(to_uppercase)?;
/// m.function_meta(to_uppercase2)?;
/// Ok(m)
/// }
/// ```
///
/// A regular instance function:
///
/// ```
/// use rune::{Any, Module, ContextError};
///
/// #[derive(Any)]
/// struct String {
/// inner: std::string::String
/// }
///
/// impl String {
/// /// Construct a new string wrapper.
/// #[rune::function(path = Self::new)]
/// fn new(string: &str) -> Self {
/// Self {
/// inner: string.into()
/// }
/// }
///
/// /// Construct a new string wrapper.
/// #[rune::function(path = Self::new2)]
/// fn new2(string: &str) -> Self {
/// Self {
/// inner: string.into()
/// }
/// }
///
/// /// Uppercase the string inside of the string wrapper.
/// ///
/// /// # Examples
/// ///
/// /// ```rune
/// /// let string = String::new("hello");
/// /// assert_eq!(string.to_uppercase(), "HELLO");
/// /// ```
/// #[rune::function]
/// fn to_uppercase(&self) -> std::string::String {
/// self.inner.to_uppercase()
/// }
/// }
///
/// fn module() -> Result<Module, ContextError> {
/// let mut m = Module::new();
/// m.ty::<String>()?;
/// m.function_meta(String::new)?;
/// m.function_meta(String::new2)?;
/// m.function_meta(String::to_uppercase)?;
/// Ok(m)
/// }
/// ```
#[proc_macro_attribute]
pub fn function(
attrs: proc_macro::TokenStream,
Expand Down Expand Up @@ -211,77 +84,41 @@ pub fn macro_(
output.into()
}

/// Helper derive to implement `ToTokens`.
#[proc_macro_derive(ToTokens, attributes(rune))]
#[doc(hidden)]
pub fn to_tokens(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let derive = syn::parse_macro_input!(input as to_tokens::Derive);
derive.expand().unwrap_or_else(to_compile_errors).into()
}

/// Helper derive to implement `Parse`.
#[proc_macro_derive(Parse, attributes(rune))]
#[doc(hidden)]
pub fn parse(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let derive = syn::parse_macro_input!(input as parse::Derive);
derive.expand().unwrap_or_else(to_compile_errors).into()
}

/// Helper derive to implement `Spanned`.
#[proc_macro_derive(Spanned, attributes(rune))]
#[doc(hidden)]
pub fn spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let derive = syn::parse_macro_input!(input as spanned::Derive);
derive.expand().unwrap_or_else(to_compile_errors).into()
}

/// Helper derive to implement `OptionSpanned`.
#[proc_macro_derive(OptionSpanned, attributes(rune))]
#[doc(hidden)]
pub fn option_spanned(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let derive = syn::parse_macro_input!(input as option_spanned::Derive);
derive.expand().unwrap_or_else(to_compile_errors).into()
}

/// Helper derive to implement `Opaque`.
#[proc_macro_derive(Opaque, attributes(rune))]
#[doc(hidden)]
pub fn opaque(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let derive = syn::parse_macro_input!(input as opaque::Derive);
derive.expand().unwrap_or_else(to_compile_errors).into()
}

/// Derive macro for the `FromValue` trait for converting types from the dynamic
/// `Value` container.
///
/// # Examples
///
/// ```
/// use rune::{FromValue, Vm};
/// use std::sync::Arc;
///
/// #[derive(FromValue)]
/// struct Foo {
/// field: u64,
/// }
///
/// let mut sources = rune::sources! {
/// entry => {
/// pub fn main() {
/// #{field: 42}
/// }
/// }
/// };
///
/// let unit = rune::prepare(&mut sources).build()?;
///
/// let mut vm = Vm::without_runtime(Arc::new(unit));
/// let foo = vm.call(["main"], ())?;
/// let foo: Foo = rune::from_value(foo)?;
///
/// assert_eq!(foo.field, 42);
/// # Ok::<_, rune::Error>(())
/// ```
#[proc_macro_derive(FromValue, attributes(rune))]
pub fn from_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput);
Expand All @@ -290,37 +127,6 @@ pub fn from_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
.into()
}

/// Derive macro for the `FromValue` trait for converting types into the dynamic
/// `Value` container.
///
/// # Examples
///
/// ```
/// use rune::{ToValue, Vm};
/// use std::sync::Arc;
///
/// #[derive(ToValue)]
/// struct Foo {
/// field: u64,
/// }
///
/// let mut sources = rune::sources! {
/// entry => {
/// pub fn main(foo) {
/// foo.field + 1
/// }
/// }
/// };
///
/// let unit = rune::prepare(&mut sources).build()?;
///
/// let mut vm = Vm::without_runtime(Arc::new(unit));
/// let value = vm.call(["main"], (Foo { field: 42 },))?;
/// let value: u64 = rune::from_value(value)?;
///
/// assert_eq!(value, 43);
/// # Ok::<_, rune::Error>(())
/// ```
#[proc_macro_derive(ToValue, attributes(rune))]
pub fn to_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = syn::parse_macro_input!(input as syn::DeriveInput);
Expand All @@ -329,40 +135,12 @@ pub fn to_value(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
.into()
}

/// Macro to mark a value as external, which will implement all the appropriate
/// traits.
///
/// This is required to support the external type as a type argument in a
/// registered function.
///
/// ## `#[rune(name = "..")]` attribute
///
/// The name of a type defaults to its identifiers, so `struct Foo {}` would be
/// given the name `"Foo"`.
///
/// This can be overrided with the `#[rune(name = "...")]` attribute:
///
/// ```
/// use rune::Any;
///
/// #[derive(Any)]
/// #[rune(name = "Bar")]
/// struct Foo {
/// }
///
/// fn install() -> Result<rune::Module, rune::ContextError> {
/// let mut module = rune::Module::new();
/// module.ty::<Foo>()?;
/// Ok(module)
/// }
/// ```
#[proc_macro_derive(Any, attributes(rune))]
pub fn any(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let derive = syn::parse_macro_input!(input as any::Derive);
derive.expand().unwrap_or_else(to_compile_errors).into()
}

/// Internal macro to implement external.
#[proc_macro]
#[doc(hidden)]
pub fn __internal_impl_any(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
Expand All @@ -373,7 +151,6 @@ pub fn __internal_impl_any(input: proc_macro::TokenStream) -> proc_macro::TokenS
.into()
}

/// Internal macro to instrument a function which is threading AST.
#[proc_macro_attribute]
#[doc(hidden)]
pub fn __instrument_ast(
Expand Down
27 changes: 27 additions & 0 deletions crates/rune/src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,33 @@ use core::any;
use crate::compile::Named;
use crate::hash::Hash;

/// Macro to mark a value as external, which will implement all the appropriate
/// traits.
///
/// This is required to support the external type as a type argument in a
/// registered function.
///
/// ## `#[rune(name = "..")]` attribute
///
/// The name of a type defaults to its identifiers, so `struct Foo {}` would be
/// given the name `"Foo"`.
///
/// This can be overrided with the `#[rune(name = "...")]` attribute:
///
/// ```
/// use rune::Any;
///
/// #[derive(Any)]
/// #[rune(name = "Bar")]
/// struct Foo {
/// }
///
/// fn install() -> Result<rune::Module, rune::ContextError> {
/// let mut module = rune::Module::new();
/// module.ty::<Foo>()?;
/// Ok(module)
/// }
/// ```
pub use rune_macros::Any;

/// A trait which can be stored inside of an [AnyObj](crate::runtime::AnyObj).
Expand Down
6 changes: 5 additions & 1 deletion crates/rune/src/ast/spanned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ use crate::no_std::vec::Vec;
use crate::ast::Span;
use crate::parse::{Id, NonZeroId};

pub use rune_macros::{OptionSpanned, Spanned};
/// Helper derive to implement [`OptionSpanned`].
pub use rune_macros::OptionSpanned;

/// Helper derive to implement [`Spanned`].
pub use rune_macros::Spanned;

/// Types for which we can get a span.
pub trait Spanned {
Expand Down
Loading

0 comments on commit 7848041

Please sign in to comment.