fix some stuff that was broken or half done

This commit is contained in:
Viv Lim 2024-01-07 03:21:17 -08:00
parent 90b8fa2268
commit e37a293992
4 changed files with 44 additions and 134 deletions

View File

@ -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),
}

View File

@ -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),*]
}
}
}

View File

@ -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())
}
}
}

View File

@ -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
})
}
}
/*