fix some stuff that was broken or half done
This commit is contained in:
parent
90b8fa2268
commit
e37a293992
|
@ -12,4 +12,10 @@ pub enum EcsError {
|
|||
pub enum ContiguousComponentError {
|
||||
#[error("Index {0} out of bounds {1}")]
|
||||
IndexOutOfBounds(usize, usize),
|
||||
}
|
||||
#[error("Requested {0} exceeds capacity {1}")]
|
||||
OverCapacity(usize, usize),
|
||||
#[error("No available space")]
|
||||
NoSpace,
|
||||
#[error("Id {0} is not in use")]
|
||||
IdNotInUse(usize),
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ impl ComponentStrategy for ContiguousComponent {
|
|||
let count = ids.end - ids.start;
|
||||
// need to test if the requested span is within the range
|
||||
if count > #capacity {
|
||||
return Option::None; // A result instead?
|
||||
return Err(ecs::ContiguousComponentError::OverCapacity(count, #capacity)); // A result instead?
|
||||
}
|
||||
let start = ids.start + #lo;
|
||||
let end = ids.end + #lo;
|
||||
|
@ -119,30 +119,35 @@ impl ComponentStrategy for ContiguousComponent {
|
|||
pub fn #fn_next_free_id(&self) -> Result<usize, ecs::ContiguousComponentError> {
|
||||
for i in 0..#capacity {
|
||||
if !self.#field_entity_has_map[i] {
|
||||
return Some(#lo + i)
|
||||
return Ok(#lo + i)
|
||||
}
|
||||
}
|
||||
None
|
||||
Err(ecs::ContiguousComponentError::NoSpace)
|
||||
}
|
||||
|
||||
pub fn #fn_claim(&mut self) -> Result<usize, ecs::ContiguousComponentError> {
|
||||
match self.#fn_next_free_id() {
|
||||
Some(free_id) => {
|
||||
Ok(free_id) => {
|
||||
self.#field_entity_has_map[free_id] = true;
|
||||
Some(free_id)
|
||||
Ok(free_id)
|
||||
},
|
||||
None => None
|
||||
Err(e) => Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn #fn_release(&mut self) -> Result<#ty, ecs::ContiguousComponentError> {
|
||||
match self.#field_entity_has_map[free_id]
|
||||
match self.#fn_next_free_id() {
|
||||
Some(free_id) => {
|
||||
self.#field_entity_has_map[free_id] = true;
|
||||
Some(free_id)
|
||||
pub fn #fn_release(&mut self, id: usize) -> Result<&#ty, ecs::ContiguousComponentError> {
|
||||
match self.#field_entity_has_map[id] {
|
||||
true => {
|
||||
// this is currently in use, and may be released.
|
||||
self.#field_entity_has_map[id] = false;
|
||||
let val = &self.#name[id];
|
||||
// don't bother clearing that slot. if we reuse it, it'll be initialized then.
|
||||
Ok(val)
|
||||
},
|
||||
None => None
|
||||
false => {
|
||||
// this id isn't in use and we can't release it
|
||||
Err(ecs::ContiguousComponentError::IdNotInUse(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -160,4 +165,4 @@ fn initialize_fixed_length_array(value: &TokenStream, count: usize) -> TokenStre
|
|||
quote! {
|
||||
[#(#values),*]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,12 @@ pub trait ComponentStrategy {
|
|||
fn core(&mut self) -> Result<ComponentImpl, ComponentImplGenError>;
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for dyn ComponentStrategy {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ComponentImpl{
|
||||
pub struct_fields: Vec<ComponentImplField>,
|
||||
|
@ -45,4 +51,4 @@ pub fn parse_component(input: &syn::parse::ParseStream) -> syn::Result<Box<dyn C
|
|||
} else {
|
||||
Err(lookahead.error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use quote::{quote, quote_spanned, format_ident};
|
|||
use syn::{parse_macro_input, Token, Type, Ident, parse::Parse, ExprIndex, ExprParen, LitInt, ExprRange, ExprLit};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{implgen::{ComponentContainer}, error::ComponentImplGenError};
|
||||
use crate::{implgen::{ComponentContainer}, error::ComponentImplGenError, implgen::components::kw};
|
||||
mod ast_viz_debug;
|
||||
mod parsing;
|
||||
mod implgen;
|
||||
|
@ -29,83 +29,11 @@ component_container {
|
|||
pub fn component_container(input: TokenStream) -> TokenStream {
|
||||
let mut container: ComponentContainer = parse_macro_input!(input as ComponentContainer);
|
||||
|
||||
// from merge conflict
|
||||
// let result = TokenStream::from(match container.codegen() {
|
||||
// Ok(cg) => quote! {
|
||||
// #cg
|
||||
// },
|
||||
// Err(ComponentImplGenError::SynError(se)) => se.to_compile_error(),
|
||||
eprintln!("components found: {:#?}", container.components);
|
||||
|
||||
let mut component_struct_items: Vec<_> = vec![];
|
||||
let mut component_struct_impl: Vec<_> = vec![];
|
||||
|
||||
for component in container.components {
|
||||
let Component { name, ty, storage } = component;
|
||||
|
||||
match storage {
|
||||
ComponentStorage::Sparse{sparse_token, num} => {
|
||||
let span = sparse_token.span;
|
||||
let num: usize = match num.lit {
|
||||
syn::Lit::Int(l) => l.base10_parse().unwrap(),
|
||||
_ => panic!("must be a int literal")
|
||||
};
|
||||
component_struct_items.push(quote_spanned! {span=>
|
||||
#name: [Option<#ty>; num]
|
||||
});
|
||||
},
|
||||
ComponentStorage::Dense{dense_token, id_span} => {
|
||||
let lo: usize = match *id_span.from.expect("need lower bound") {
|
||||
syn::Expr::Lit(l) => match l.lit {
|
||||
syn::Lit::Int(l) => l.base10_parse().unwrap(),
|
||||
_ => panic!("it's not a int")
|
||||
},
|
||||
_ => panic!("range must contain int literals"),
|
||||
};
|
||||
let hi: usize = match *id_span.to.expect("need upper bound") {
|
||||
syn::Expr::Lit(h) => match h.lit {
|
||||
syn::Lit::Int(h) => h.base10_parse().unwrap(),
|
||||
_ => panic!("it's not a int")
|
||||
},
|
||||
_ => panic!("range must contain int literals"),
|
||||
};
|
||||
// test hi > lo
|
||||
|
||||
let size = hi - lo;
|
||||
component_struct_items.push(quote_spanned! {dense_token.span=>
|
||||
#name: [#ty; #size]
|
||||
});
|
||||
|
||||
let getter_name = format_ident!("get_{}", name);
|
||||
|
||||
component_struct_impl.push(quote_spanned! {dense_token.span=>
|
||||
fn #getter_name(&self, ids: std::ops::Range<usize>) -> Option<&[#ty]> {
|
||||
let count = ids.end - ids.start;
|
||||
if count > #size {
|
||||
return Option::None; // A result instead?
|
||||
}
|
||||
let start = ids.start + #lo;
|
||||
let end = ids.end + #lo;
|
||||
return Option::Some(&self.#name[start..end]);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
let container_struct = quote!{
|
||||
struct ComponentContainer {
|
||||
#(#component_struct_items),*
|
||||
}
|
||||
|
||||
impl ComponentContainer {
|
||||
#(#component_struct_impl) *
|
||||
}
|
||||
};
|
||||
|
||||
let result = TokenStream::from(quote! {
|
||||
#container_struct
|
||||
let result = TokenStream::from(match container.codegen() {
|
||||
Ok(cg) => quote! {
|
||||
#cg
|
||||
},
|
||||
Err(ComponentImplGenError::SynError(se)) => se.to_compile_error(),
|
||||
});
|
||||
eprintln!("result: {}", result);
|
||||
result
|
||||
|
@ -125,7 +53,7 @@ mod error {
|
|||
#[derive(Debug)]
|
||||
enum ComponentStorage {
|
||||
Sparse{sparse_token: kw::sparse, num: ExprLit},
|
||||
Dense{dense_token: kw::dense, id_span: ExprRange}
|
||||
Dense{dense_token: kw::contiguous, id_span: ExprRange}
|
||||
}
|
||||
|
||||
impl ComponentStorage {
|
||||
|
@ -136,7 +64,7 @@ impl ComponentStorage {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_dense(&self) -> Option<&kw::dense> {
|
||||
pub fn as_dense(&self) -> Option<&kw::contiguous> {
|
||||
match self {
|
||||
ComponentStorage::Dense{dense_token, ..} => Some(dense_token),
|
||||
ComponentStorage::Sparse{..} => None,
|
||||
|
@ -149,9 +77,9 @@ fn parse_storage(input: &syn::parse::ParseStream) -> syn::Result<ComponentStorag
|
|||
if lookahead.peek(kw::sparse) {
|
||||
let span = input.parse::<kw::sparse>()?;
|
||||
let num: ExprLit = input.parse()?;
|
||||
Ok(ComponentStorage::Sparse{sparse_token: span, num});
|
||||
} else if lookahead.peek(kw::dense) {
|
||||
let span = input.parse::<kw::dense>()?;
|
||||
Ok(ComponentStorage::Sparse{sparse_token: span, num})
|
||||
} else if lookahead.peek(kw::contiguous) {
|
||||
let span = input.parse::<kw::contiguous>()?;
|
||||
let id_span: ExprRange = input.parse()?;
|
||||
|
||||
Ok(ComponentStorage::Dense{dense_token: span, id_span})
|
||||
|
@ -167,41 +95,6 @@ struct Component {
|
|||
pub storage: ComponentStorage
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ComponentContainer {
|
||||
pub components: Vec<Component>
|
||||
}
|
||||
|
||||
impl Parse for ComponentContainer {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let mut components = vec![];
|
||||
loop {
|
||||
let storage = parse_storage(&input)?;
|
||||
let name: Ident = input.parse()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
let ty: Type = input.parse()?;
|
||||
|
||||
components.push(Component {
|
||||
name, ty, storage
|
||||
});
|
||||
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
input.parse::<Token![,]>()?;
|
||||
|
||||
if input.is_empty() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ComponentContainer {
|
||||
components
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue