Sfoglia il codice sorgente

Implemented Derive for SystemData

master
Bergmann89 5 anni fa
parent
commit
0b0622b17c
12 ha cambiato i file con 178 aggiunte e 13 eliminazioni
  1. +7
    -11
      Cargo.toml
  2. +13
    -0
      async-ecs-derive/Cargo.toml
  3. +21
    -0
      async-ecs-derive/src/lib.rs
  4. +122
    -0
      async-ecs-derive/src/system_data.rs
  5. +13
    -0
      async-ecs/Cargo.toml
  6. +0
    -0
      async-ecs/src/lib.rs
  7. +0
    -0
      async-ecs/src/main.rs
  8. +0
    -0
      async-ecs/src/resources/cell.rs
  9. +0
    -0
      async-ecs/src/resources/mod.rs
  10. +0
    -0
      async-ecs/src/system/accessor.rs
  11. +0
    -0
      async-ecs/src/system/mod.rs
  12. +2
    -2
      async-ecs/src/system/system_data.rs

+ 7
- 11
Cargo.toml Vedi File

@@ -1,12 +1,8 @@
[package]
name = "async-ecs"
version = "0.1.0"
authors = ["Bergmann89 <info@bergmann89.de>"]
edition = "2018"
[workspace]
members = [
"async-ecs",
"async-ecs-derive"
]

[dependencies]
env_logger = "0.8"
log = "0.4"
mopa = "0.2"
rand = "0.7"
thiserror = "1.0"
[patch.crates-io]
async-ecs-derive = { path = "async-ecs-derive" }

+ 13
- 0
async-ecs-derive/Cargo.toml Vedi File

@@ -0,0 +1,13 @@
[package]
name = "async-ecs-derive"
version = "0.1.0"
authors = ["Bergmann89 <info@bergmann89.de>"]
edition = "2018"

[dependencies]
syn = "1.0"
quote = "1.0"
proc-macro2 = "1.0"

[lib]
proc-macro = true

+ 21
- 0
async-ecs-derive/src/lib.rs Vedi File

@@ -0,0 +1,21 @@
#![recursion_limit = "256"]

extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
#[macro_use]
extern crate syn;

mod system_data;

use proc_macro::TokenStream;

#[proc_macro_derive(SystemData)]
pub fn system_data(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();

let gen = system_data::execute(&ast);

gen.into()
}

+ 122
- 0
async-ecs-derive/src/system_data.rs Vedi File

@@ -0,0 +1,122 @@
use syn::{
punctuated::Punctuated, token::Comma, Data, DataStruct, DeriveInput, Field, Fields,
FieldsNamed, FieldsUnnamed, Ident, Lifetime, Type, WhereClause, WherePredicate,
};

pub fn execute(ast: &DeriveInput) -> proc_macro2::TokenStream {
let name = &ast.ident;
let mut generics = ast.generics.clone();

let (fetch_return, tys) = gen_from_body(&ast.data, name);
let tys = &tys;
let def_fetch_lt = ast
.generics
.lifetimes()
.next()
.expect("There has to be at least one lifetime");
let impl_fetch_lt = &def_fetch_lt.lifetime;

{
let where_clause = generics.make_where_clause();
constrain_system_data_types(where_clause, impl_fetch_lt, tys);
}

let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

quote! {
impl #impl_generics
async_ecs::system::SystemData< #impl_fetch_lt >
for #name #ty_generics #where_clause
{
fn setup(resources: &mut async_ecs::resources::Resources) {
#(
<#tys as async_ecs::system::SystemData> :: setup(world);
)*
}

fn fetch(world: & #impl_fetch_lt async_ecs::resources::Resources) -> Self {
#fetch_return
}

fn reads() -> Vec<async_ecs::resources::ResourceId> {
let mut r = Vec::new();

#( {
let mut reads = <#tys as async_ecs::system::SystemData> :: reads();
r.append(&mut reads);
} )*

r
}

fn writes() -> Vec<async_ecs::resources::ResourceId> {
let mut r = Vec::new();

#( {
let mut writes = <#tys as async_ecs::system::SystemData> :: writes();
r.append(&mut writes);
} )*

r
}
}
}
}

fn collect_field_types(fields: &Punctuated<Field, Comma>) -> Vec<Type> {
fields.iter().map(|x| x.ty.clone()).collect()
}

fn gen_identifiers(fields: &Punctuated<Field, Comma>) -> Vec<Ident> {
fields.iter().map(|x| x.ident.clone().unwrap()).collect()
}

fn constrain_system_data_types(clause: &mut WhereClause, fetch_lt: &Lifetime, tys: &[Type]) {
for ty in tys.iter() {
let where_predicate: WherePredicate = parse_quote!(#ty : async_ecs::system::SystemData< #fetch_lt >);
clause.predicates.push(where_predicate);
}
}

fn gen_from_body(ast: &Data, name: &Ident) -> (proc_macro2::TokenStream, Vec<Type>) {
enum DataType {
Struct,
Tuple,
}

let (body, fields) = match *ast {
Data::Struct(DataStruct {
fields: Fields::Named(FieldsNamed { named: ref x, .. }),
..
}) => (DataType::Struct, x),
Data::Struct(DataStruct {
fields: Fields::Unnamed(FieldsUnnamed { unnamed: ref x, .. }),
..
}) => (DataType::Tuple, x),
_ => panic!("Enums are not supported"),
};

let tys = collect_field_types(fields);

let fetch_return = match body {
DataType::Struct => {
let identifiers = gen_identifiers(fields);

quote! {
#name {
#( #identifiers: async_ecs::system::SystemData::fetch(world) ),*
}
}
}
DataType::Tuple => {
let count = tys.len();
let fetch = vec![quote! { async_ecs::system::SystemData::fetch(world) }; count];

quote! {
#name ( #( #fetch ),* )
}
}
};

(fetch_return, tys)
}

+ 13
- 0
async-ecs/Cargo.toml Vedi File

@@ -0,0 +1,13 @@
[package]
name = "async-ecs"
version = "0.1.0"
authors = ["Bergmann89 <info@bergmann89.de>"]
edition = "2018"

[dependencies]
async-ecs-derive = "0.1"
env_logger = "0.8"
log = "0.4"
mopa = "0.2"
rand = "0.7"
thiserror = "1.0"

src/lib.rs → async-ecs/src/lib.rs Vedi File


src/main.rs → async-ecs/src/main.rs Vedi File


src/resources/cell.rs → async-ecs/src/resources/cell.rs Vedi File


src/resources/mod.rs → async-ecs/src/resources/mod.rs Vedi File


src/system/accessor.rs → async-ecs/src/system/accessor.rs Vedi File


src/system/mod.rs → async-ecs/src/system/mod.rs Vedi File


src/system/system_data.rs → async-ecs/src/system/system_data.rs Vedi File

@@ -5,9 +5,9 @@ use crate::resources::{ResourceId, Resources};
use super::accessor::{Accessor, StaticAccessor};

pub trait SystemData<'a> {
fn setup(world: &mut Resources);
fn setup(resources: &mut Resources);

fn fetch(world: &'a Resources) -> Self;
fn fetch(resources: &'a Resources) -> Self;

fn reads() -> Vec<ResourceId>;


Caricamento…
Annulla
Salva