Skip to content

Commit 7222cbe

Browse files
committed
WIP
1 parent 164f7d1 commit 7222cbe

File tree

5 files changed

+179
-48
lines changed

5 files changed

+179
-48
lines changed

crates/bevy_mod_scripting_core/src/bindings/function/type_dependencies.rs

Lines changed: 33 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,57 +8,20 @@ use crate::{
88
bindings::{ReflectReference, WorldGuard},
99
error::InteropError,
1010
};
11-
use bevy::reflect::{FromReflect, GetTypeRegistration, TypeRegistry, Typed};
12-
use std::collections::HashMap;
11+
use bevy::reflect::{FromReflect, GetTypeRegistration, TypeRegistration, TypeRegistry, Typed};
12+
use bevy_mod_scripting_derive::{impl_get_type_dependencies, GetTypeDependencies};
13+
use std::{collections::HashMap, hash::Hash};
1314

1415
/// Functionally identical to [`GetTypeRegistration`] but without the 'static bound
1516
pub trait GetTypeDependencies {
17+
/// In the majority of the implementations, this will be `Self`
18+
/// However some types might be `facades` for other types, in which case this will be the underlying type
19+
type Underlying;
20+
1621
/// Registers the type dependencies of the implementing type with the given [`TypeRegistry`].
1722
fn register_type_dependencies(registry: &mut TypeRegistry);
1823
}
1924

20-
#[macro_export]
21-
/// A macro for implementing [`GetTypeDependencies`] for types with no type dependencies.
22-
macro_rules! no_type_dependencies {
23-
($($path:path),*) => {
24-
$(
25-
impl $crate::bindings::function::type_dependencies::GetTypeDependencies for $path {
26-
fn register_type_dependencies(_registry: &mut bevy::reflect::TypeRegistry) {}
27-
}
28-
)*
29-
};
30-
}
31-
32-
#[macro_export]
33-
/// A macro for implementing [`GetTypeDependencies`] for types that only depend on themselves.
34-
macro_rules! self_type_dependency_only {
35-
($($path:ty),*) => {
36-
$(
37-
impl $crate::bindings::function::type_dependencies::GetTypeDependencies for $path {
38-
fn register_type_dependencies(registry: &mut bevy::reflect::TypeRegistry) {
39-
registry.register::<$path>();
40-
}
41-
}
42-
)*
43-
};
44-
}
45-
46-
macro_rules! recursive_type_dependencies {
47-
($( ($path:ty where $($bound:ident : $($bound_val:path);*),* $(,,const $const:ident : $const_ty:ty)? $(=> with $self_:ident)?) ),* ) => {
48-
$(
49-
impl<$($bound : $($bound_val +)*),* , $(const $const : $const_ty )?> GetTypeDependencies for $path {
50-
fn register_type_dependencies(registry: &mut TypeRegistry) {
51-
$(
52-
registry.register::<$bound>();
53-
)*
54-
$(
55-
registry.register::<$self_>();
56-
)?
57-
}
58-
}
59-
)*
60-
};
61-
}
6225

6326
macro_rules! register_tuple_dependencies {
6427
($($ty:ident),*) => {
@@ -72,6 +35,26 @@ macro_rules! register_tuple_dependencies {
7235
};
7336
}
7437

38+
39+
impl GetTypeDependencies for InteropError {
40+
type Underlying = Self;
41+
42+
fn register_type_dependencies(registry: &mut TypeRegistry) {
43+
todo!()
44+
}
45+
}
46+
47+
48+
49+
impl_get_type_dependencies!(
50+
#[derive(GetTypeDependencies)]
51+
#[get_type_dependencies(bms_core_path=crate)]
52+
struct HashMap<K,V> {
53+
54+
}
55+
);
56+
57+
7558
no_type_dependencies!(InteropError);
7659
no_type_dependencies!(WorldGuard<'static>);
7760
self_type_dependency_only!(FunctionCallContext, ReflectReference);
@@ -97,14 +80,17 @@ where
9780
}
9881
}
9982

100-
impl <K, V> GetTypeDependencies for HashMap<K, V>
83+
impl <Uk, Uv, K, V> GetTypeDependencies<HashMap<Uk,Uv>> for HashMap<K, V>
10184
where
102-
K: GetTypeDependencies,
103-
V: GetTypeDependencies
85+
K: GetTypeDependencies<Uk>,
86+
V: GetTypeDependencies<Uv>,
87+
Uk: GetTypeRegistration + FromReflect + Eq + Hash + Typed,
88+
Uv: GetTypeRegistration + FromReflect + Eq + Hash + Typed,
10489
{
10590
fn register_type_dependencies(registry: &mut TypeRegistry) {
10691
K::register_type_dependencies(registry);
10792
V::register_type_dependencies(registry);
93+
TypeRegistration::of::<HashMap<Uk,Uv>>();
10894
}
10995
}
11096

crates/bevy_mod_scripting_core/src/error.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use bevy::{
1818
prelude::Entity,
1919
reflect::{PartialReflect, Reflect},
2020
};
21+
use bevy_mod_scripting_derive::GetTypeDependencies;
2122
use std::{
2223
any::TypeId,
2324
borrow::Cow,
@@ -313,8 +314,9 @@ impl Display for MissingResourceError {
313314

314315
impl std::error::Error for MissingResourceError {}
315316

316-
#[derive(Debug, Clone, PartialEq, Reflect)]
317+
#[derive(Debug, Clone, PartialEq, Reflect, GetTypeDependencies)]
317318
#[reflect(opaque)]
319+
#[get_type_dependencies(bms_core_path=crate)]
318320
/// An error thrown when interoperating with scripting languages.
319321
pub struct InteropError(Arc<InteropErrorInner>);
320322

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use proc_macro2::TokenStream;
2+
use quote::quote_spanned;
3+
use syn::{parse_quote, DeriveInput};
4+
5+
6+
7+
8+
/// Generate a GetTypeDependencies impl like below:
9+
/// For type:
10+
///
11+
/// ```rust,ignore
12+
/// #[derive(GetTypeDependencies)]
13+
/// #[get_type_dependencies(remote)]
14+
/// struct TargetType<T1: CustomBoundsT1, T2: CustomBoundsT2>{
15+
/// ...
16+
/// }
17+
/// ```
18+
///
19+
/// ```rust,ignore
20+
/// impl <T1,T2> GetTypeDependencies for TargetType
21+
/// where
22+
/// T1: GetTypeDependencies,
23+
/// T2: GetTypeDependencies,
24+
/// T1::Underlying: bevy::reflect::GetTypeRegistration + CustomBoundsT1,
25+
/// T2::Underlying: bevy::reflect::GetTypeRegistration + CustomBoundsT2,
26+
/// {
27+
/// type Underlying = TargetType<T1::Underlying, T2::Underlying>;
28+
/// pub fn get_type_dependencies(registry: &mut bevy::reflect::TypeRegistry) {
29+
/// T1::get_type_dependencies(registry);
30+
/// T2::get_type_dependencies(registry);
31+
///
32+
/// registry.register::<TargetType<T1::Underlying, T2::Underlying>>();
33+
/// }
34+
/// }
35+
/// ```
36+
fn get_type_dependencies_from_input(derive_input: DeriveInput) -> TokenStream {
37+
let args = match Args::parse(&derive_input.attrs) {
38+
Ok(args) => args,
39+
Err(error) => return error.to_compile_error(),
40+
};
41+
42+
let bms_core = &args.bms_core_path;
43+
44+
// we enrich the where clause with our bounds
45+
let mut where_conditions = Vec::default();
46+
47+
for param in derive_input.generics.type_params() {
48+
let param_name = &param.ident;
49+
where_conditions.push(
50+
quote_spanned!(param.ident.span()=> #param_name: GetTypeDependencies),
51+
);
52+
where_conditions.push(
53+
quote_spanned!(param.ident.span()=> #param_name::Underlying: bevy::reflect::GetTypeRegistration),
54+
);
55+
}
56+
57+
let (impl_generics, type_generics, _) = derive_input.generics.split_for_impl();
58+
let name = &derive_input.ident;
59+
60+
61+
let generic_names = derive_input.generics.type_params().map(|param| &param.ident).collect::<Vec<_>>();
62+
63+
64+
quote_spanned! {derive_input.ident.span()=>
65+
impl #impl_generics #bms_core::bindings::GetTypeDependencies for #name #type_generics where
66+
#(
67+
#where_conditions
68+
),*
69+
{
70+
type Underyling = #name<
71+
#( #generic_names::Underlying ),*
72+
>;
73+
fn register_type_dependencies(registry: &mut bevy::reflect::TypeRegistry) {
74+
#(
75+
<#generic_names as #bms_core::bindings::GetTypeDependencies>::register_type_dependencies(registry);
76+
)*
77+
78+
registry.register::<#name<
79+
#( #generic_names::Underlying ),*
80+
>>();
81+
}
82+
}
83+
}
84+
}
85+
86+
pub fn get_type_dependencies(input: TokenStream) -> TokenStream {
87+
let derive_input: DeriveInput = match syn::parse2(input) {
88+
Ok(input) => input,
89+
Err(e) => return e.into_compile_error(),
90+
};
91+
92+
get_type_dependencies_from_input(derive_input)
93+
}
94+
95+
96+
97+
98+
struct Args {
99+
bms_core_path: syn::Path,
100+
}
101+
102+
impl Args {
103+
fn parse(attrs: &[syn::Attribute]) -> syn::Result<Self> {
104+
let mut bms_core_path = parse_quote!(bevy_mod_scripting_core);
105+
106+
for attr in attrs {
107+
// find attr with name `get_type_dependencies`
108+
// then parse its meta
109+
if attr.path().is_ident("get_type_dependencies") {
110+
attr.parse_nested_meta(|meta| {
111+
if meta.path.is_ident("bms_core_path") {
112+
let value = meta.value()?;
113+
bms_core_path = value.parse()?;
114+
}
115+
Ok(())
116+
})?;
117+
}
118+
}
119+
120+
Ok(Self { bms_core_path })
121+
}
122+
}

crates/bevy_mod_scripting_derive/src/derive/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod into_script;
22
mod script_bindings;
33
mod script_globals;
44
mod typed_through;
5+
mod get_type_dependencies;
56

67
use proc_macro2::{Span, TokenStream};
78
use quote::{quote_spanned, ToTokens};
@@ -10,6 +11,7 @@ use syn::{Ident, ImplItemFn, ItemImpl};
1011
pub use self::{
1112
into_script::into_script, script_bindings::script_bindings, script_globals::script_globals,
1213
typed_through::typed_through,
14+
get_type_dependencies::get_type_dependencies
1315
};
1416

1517
pub(crate) fn impl_fn_to_namespace_builder_registration(fun: &ImplItemFn) -> TokenStream {

crates/bevy_mod_scripting_derive/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
33
mod derive;
44

5+
6+
57
#[proc_macro_derive(TypedThrough)]
68
/// Default implementation for the `TypedThrough` trait
79
pub fn typed_through(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
@@ -49,3 +51,20 @@ pub fn script_globals(
4951
) -> proc_macro::TokenStream {
5052
derive::script_globals(args, input)
5153
}
54+
55+
/// Derive macro for generating `GetTypeDependencies` implementations.
56+
#[proc_macro_derive(GetTypeDependencies, attributes(get_type_dependencies))]
57+
pub fn get_type_dependencies(
58+
input: proc_macro::TokenStream,
59+
) -> proc_macro::TokenStream {
60+
derive::get_type_dependencies(input.into()).into()
61+
}
62+
63+
/// Proc macro equivalent of `GetTypeDependencies` which does not generate a type, purely the impl.
64+
/// Useful for generating implementations against remote types.
65+
#[proc_macro]
66+
pub fn impl_get_type_dependencies(
67+
input: proc_macro::TokenStream,
68+
) -> proc_macro::TokenStream {
69+
derive::get_type_dependencies(input.into()).into()
70+
}

0 commit comments

Comments
 (0)