Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ControlFlow #626

Merged
merged 2 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 101 additions & 86 deletions crates/rune-macros/src/any.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::BTreeMap;

use proc_macro2::TokenStream;
use proc_macro2::{Span, TokenStream};
use quote::{quote, quote_spanned, ToTokens};
use rune_core::Hash;
use syn::punctuated::Punctuated;
Expand Down Expand Up @@ -51,8 +51,7 @@ impl InternalCall {
};

let name = syn::LitStr::new(&name.to_string(), name.span());

expand_any(&self.path, type_hash, &name, &[], &tokens, &generics)
expand_any(None, &self.path, type_hash, &name, &[], &tokens, &generics)
}
}

Expand Down Expand Up @@ -110,7 +109,15 @@ impl Derive {

let name = syn::LitStr::new(&name.to_string(), name.span());

expand_any(ident, type_hash, &name, &installers, &tokens, generics)
expand_any(
attr.builtin,
ident,
type_hash,
&name,
&installers,
&tokens,
generics,
)
}
}

Expand Down Expand Up @@ -334,7 +341,7 @@ fn expand_enum_install_with(
enum_.variant_mut(#variant_index)?.make_named(&[#(#field_names),*])?.static_docs(&#variant_docs)
});

variants.push((None, attr));
variants.push((None, variant_attr));
}
syn::Fields::Unnamed(fields) => {
let mut fields_len = 0usize;
Expand Down Expand Up @@ -373,7 +380,7 @@ fn expand_enum_install_with(
None
};

variants.push((constructor, attr));
variants.push((constructor, variant_attr));
}
syn::Fields::Unit => {
variant_metas.push(quote! {
Expand All @@ -386,7 +393,7 @@ fn expand_enum_install_with(
None
};

variants.push((constructor, attr));
variants.push((constructor, variant_attr));
}
}
}
Expand Down Expand Up @@ -463,6 +470,7 @@ fn expand_enum_install_with(

/// Expand the necessary implementation details for `Any`.
pub(super) fn expand_any<T>(
builtin: Option<Span>,
ident: T,
type_hash: Hash,
name: &syn::LitStr,
Expand Down Expand Up @@ -522,20 +530,6 @@ where
}
};

let type_hash = type_hash.into_inner();

let make_hash = if !generic_names.is_empty() {
quote!(#hash::new_with_type_parameters(#type_hash, #hash::parameters([#(<#generic_names as #type_of>::type_hash()),*])))
} else {
quote!(#hash::new(#type_hash))
};

let type_parameters = if !generic_names.is_empty() {
quote!(#hash::parameters([#(<#generic_names as #type_of>::type_hash()),*]))
} else {
quote!(#hash::EMPTY)
};

let install_with = quote! {
#[automatically_derived]
impl #impl_generics #install_with for #ident #type_generics #where_clause {
Expand All @@ -546,92 +540,113 @@ where
}
};

Ok(quote! {
#[automatically_derived]
impl #impl_generics #any for #ident #type_generics #where_clause {
fn type_hash() -> #hash {
#make_hash
}
}
let any = if builtin.is_none() {
let type_hash = type_hash.into_inner();

#install_with
#impl_named
let make_hash = if !generic_names.is_empty() {
quote!(#hash::new_with_type_parameters(#type_hash, #hash::parameters([#(<#generic_names as #type_of>::type_hash()),*])))
} else {
quote!(#hash::new(#type_hash))
};

#[automatically_derived]
impl #impl_generics #type_of for #ident #type_generics #where_clause {
#[inline]
fn type_hash() -> #hash {
<Self as #any>::type_hash()
}
let type_parameters = if !generic_names.is_empty() {
quote!(#hash::parameters([#(<#generic_names as #type_of>::type_hash()),*]))
} else {
quote!(#hash::EMPTY)
};

#[inline]
fn type_parameters() -> #hash {
#type_parameters
Some(quote! {
#[automatically_derived]
impl #impl_generics #any for #ident #type_generics #where_clause {
fn type_hash() -> #hash {
#make_hash
}
}

#[inline]
fn type_info() -> #type_info {
#type_info::Any(#any_type_info::__private_new(
#raw_str::from_str(core::any::type_name::<Self>()),
<Self as #type_of>::type_hash(),
))
#[automatically_derived]
impl #impl_generics #type_of for #ident #type_generics #where_clause {
#[inline]
fn type_hash() -> #hash {
<Self as #any>::type_hash()
}

#[inline]
fn type_parameters() -> #hash {
#type_parameters
}

#[inline]
fn type_info() -> #type_info {
#type_info::Any(#any_type_info::__private_new(
#raw_str::from_str(core::any::type_name::<Self>()),
<Self as #type_of>::type_hash(),
))
}
}
}

#[automatically_derived]
impl #impl_generics #maybe_type_of for #ident #type_generics #where_clause {
#[inline]
fn maybe_type_of() -> Option<#full_type_of> {
Some(<Self as #type_of>::type_of())
#[automatically_derived]
impl #impl_generics #maybe_type_of for #ident #type_generics #where_clause {
#[inline]
fn maybe_type_of() -> Option<#full_type_of> {
Some(<Self as #type_of>::type_of())
}
}
}

#[automatically_derived]
impl #impl_generics #unsafe_to_ref for #ident #type_generics #where_clause {
type Guard = #raw_into_ref;
#[automatically_derived]
impl #impl_generics #unsafe_to_ref for #ident #type_generics #where_clause {
type Guard = #raw_into_ref;

unsafe fn unsafe_to_ref<'a>(value: #value) -> #vm_result<(&'a Self, Self::Guard)> {
let (value, guard) = match value.into_any_ptr() {
#vm_result::Ok(value) => value,
#vm_result::Err(err) => return #vm_result::Err(err),
};
unsafe fn unsafe_to_ref<'a>(value: #value) -> #vm_result<(&'a Self, Self::Guard)> {
let (value, guard) = match value.into_any_ptr() {
#vm_result::Ok(value) => value,
#vm_result::Err(err) => return #vm_result::Err(err),
};

#vm_result::Ok((&*value, guard))
#vm_result::Ok((&*value, guard))
}
}
}

#[automatically_derived]
impl #impl_generics #unsafe_to_mut for #ident #type_generics #where_clause {
type Guard = #raw_into_mut;
#[automatically_derived]
impl #impl_generics #unsafe_to_mut for #ident #type_generics #where_clause {
type Guard = #raw_into_mut;

unsafe fn unsafe_to_mut<'a>(value: #value) -> #vm_result<(&'a mut Self, Self::Guard)> {
let (value, guard) = match value.into_any_mut() {
#vm_result::Ok(value) => value,
#vm_result::Err(err) => return #vm_result::Err(err),
};
unsafe fn unsafe_to_mut<'a>(value: #value) -> #vm_result<(&'a mut Self, Self::Guard)> {
let (value, guard) = match value.into_any_mut() {
#vm_result::Ok(value) => value,
#vm_result::Err(err) => return #vm_result::Err(err),
};

#vm_result::Ok((&mut *value, guard))
#vm_result::Ok((&mut *value, guard))
}
}
}

#[automatically_derived]
impl #impl_generics #unsafe_to_value for &#ident #type_generics #where_clause {
type Guard = #pointer_guard;
#[automatically_derived]
impl #impl_generics #unsafe_to_value for &#ident #type_generics #where_clause {
type Guard = #pointer_guard;

unsafe fn unsafe_to_value(self) -> #vm_result<(#value, Self::Guard)> {
let (shared, guard) = #shared::from_ref(self);
#vm_result::Ok((#value::from(shared), guard))
unsafe fn unsafe_to_value(self) -> #vm_result<(#value, Self::Guard)> {
let (shared, guard) = #shared::from_ref(self);
#vm_result::Ok((#value::from(shared), guard))
}
}
}

#[automatically_derived]
impl #impl_generics #unsafe_to_value for &mut #ident #type_generics #where_clause {
type Guard = #pointer_guard;
#[automatically_derived]
impl #impl_generics #unsafe_to_value for &mut #ident #type_generics #where_clause {
type Guard = #pointer_guard;

unsafe fn unsafe_to_value(self) -> #vm_result<(#value, Self::Guard)> {
let (shared, guard) = #shared::from_mut(self);
#vm_result::Ok((#value::from(shared), guard))
unsafe fn unsafe_to_value(self) -> #vm_result<(#value, Self::Guard)> {
let (shared, guard) = #shared::from_mut(self);
#vm_result::Ok((#value::from(shared), guard))
}
}
}
})
} else {
None
};

Ok(quote! {
#install_with
#impl_named
#any
})
}
5 changes: 5 additions & 0 deletions crates/rune-macros/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ pub(crate) struct TypeAttr {
pub(crate) constructor: bool,
/// Parsed documentation.
pub(crate) docs: Vec<syn::Expr>,
/// Indicates that this is a builtin type, so don't generate an `Any`
/// implementation for it.
pub(crate) builtin: Option<Span>,
}

/// Parsed variant attributes.
Expand Down Expand Up @@ -450,6 +453,8 @@ impl Context {
attr.install_with = Some(parse_path_compat(meta.input)?);
} else if meta.path == CONSTRUCTOR {
attr.constructor = true;
} else if meta.path == BUILTIN {
attr.builtin = Some(meta.path.span());
} else {
return Err(syn::Error::new_spanned(
&meta.path,
Expand Down
1 change: 1 addition & 0 deletions crates/rune-macros/src/internals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub const MODULE: Symbol = Symbol("module");
pub const INSTALL_WITH: Symbol = Symbol("install_with");

pub const CONSTRUCTOR: Symbol = Symbol("constructor");
pub const BUILTIN: Symbol = Symbol("builtin");
pub const GET: Symbol = Symbol("get");
pub const SET: Symbol = Symbol("set");
pub const COPY: Symbol = Symbol("copy");
Expand Down
2 changes: 2 additions & 0 deletions crates/rune/src/modules/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ fn is_readable(value: Value) -> bool {
Value::RangeToInclusive(value) => value.is_readable(),
Value::RangeTo(value) => value.is_readable(),
Value::Range(value) => value.is_readable(),
Value::ControlFlow(value) => value.is_readable(),
Value::Future(value) => value.is_readable(),
Value::Stream(value) => value.is_readable(),
Value::Generator(value) => value.is_readable(),
Expand Down Expand Up @@ -132,6 +133,7 @@ fn is_writable(value: Value) -> bool {
Value::RangeToInclusive(value) => value.is_writable(),
Value::RangeTo(value) => value.is_writable(),
Value::Range(value) => value.is_writable(),
Value::ControlFlow(value) => value.is_writable(),
Value::Future(value) => value.is_writable(),
Value::Stream(value) => value.is_writable(),
Value::Generator(value) => value.is_writable(),
Expand Down
Loading