Skip to content

Commit

Permalink
fix(codegen::system): rename discrim_key to discrim_set
Browse files Browse the repository at this point in the history
  • Loading branch information
SOF3 committed Oct 3, 2023
1 parent 5cf9a84 commit 2dba51d
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 103 deletions.
66 changes: 28 additions & 38 deletions benches/iter_entity_add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,17 @@ struct VelocityZ(f64);

#[system]
fn system_individual_add_system_non_chunked(
mut px: impl system::WriteSimple<test_util::TestArch, PositionX>,
mut py: impl system::WriteSimple<test_util::TestArch, PositionY>,
mut pz: impl system::WriteSimple<test_util::TestArch, PositionZ>,
vx: impl system::ReadSimple<test_util::TestArch, VelocityX>,
vy: impl system::ReadSimple<test_util::TestArch, VelocityY>,
vz: impl system::ReadSimple<test_util::TestArch, VelocityZ>,
entities: impl system::EntityIterator<test_util::TestArch>,
mut px: system::WriteSimple<test_util::TestArch, PositionX>,
mut py: system::WriteSimple<test_util::TestArch, PositionY>,
mut pz: system::WriteSimple<test_util::TestArch, PositionZ>,
vx: system::ReadSimple<test_util::TestArch, VelocityX>,
vy: system::ReadSimple<test_util::TestArch, VelocityY>,
vz: system::ReadSimple<test_util::TestArch, VelocityZ>,
entities: system::EntityIterator<test_util::TestArch>,
) {
for (_, (px, py, pz, vx, vy, vz)) in entities.entities_with((
px.access_mut(),
py.access_mut(),
pz.access_mut(),
vx.access(),
vy.access(),
vz.access(),
)) {
for (_, (px, py, pz, vx, vy, vz)) in
entities.entities_with((&mut px, &mut py, &mut pz, &vx, &vy, &vz))
{
px.0 += vx.0;
py.0 += vy.0;
pz.0 += vz.0;
Expand Down Expand Up @@ -74,22 +69,17 @@ fn iter_entity_add_individual_non_chunked(group: &mut BenchmarkGroup<'_, measure

#[system]
fn system_individual_add_system_chunked(
mut px: impl system::WriteSimple<test_util::TestArch, PositionX>,
mut py: impl system::WriteSimple<test_util::TestArch, PositionY>,
mut pz: impl system::WriteSimple<test_util::TestArch, PositionZ>,
vx: impl system::ReadSimple<test_util::TestArch, VelocityX>,
vy: impl system::ReadSimple<test_util::TestArch, VelocityY>,
vz: impl system::ReadSimple<test_util::TestArch, VelocityZ>,
entities: impl system::EntityIterator<test_util::TestArch>,
mut px: system::WriteSimple<test_util::TestArch, PositionX>,
mut py: system::WriteSimple<test_util::TestArch, PositionY>,
mut pz: system::WriteSimple<test_util::TestArch, PositionZ>,
vx: system::ReadSimple<test_util::TestArch, VelocityX>,
vy: system::ReadSimple<test_util::TestArch, VelocityY>,
vz: system::ReadSimple<test_util::TestArch, VelocityZ>,
entities: system::EntityIterator<test_util::TestArch>,
) {
for (_, (px, py, pz, vx, vy, vz)) in entities.chunks_with((
px.access_chunk_mut(),
py.access_chunk_mut(),
pz.access_chunk_mut(),
vx.access_chunk(),
vy.access_chunk(),
vz.access_chunk(),
)) {
for (_, (px, py, pz, vx, vy, vz)) in
entities.chunks_with((&mut px, &mut py, &mut pz, &vx, &vy, &vz))
{
for (px, (py, (pz, (vx, (vy, vz))))) in
iter::zip(px, iter::zip(py, iter::zip(pz, iter::zip(vx, iter::zip(vy, vz)))))
{
Expand Down Expand Up @@ -136,11 +126,11 @@ struct VelocityArray([f64; 3]);

#[system]
fn system_array_add_system_non_chunked(
mut p: impl system::WriteSimple<test_util::TestArch, PositionArray>,
v: impl system::ReadSimple<test_util::TestArch, VelocityArray>,
entities: impl system::EntityIterator<test_util::TestArch>,
mut p: system::WriteSimple<test_util::TestArch, PositionArray>,
v: system::ReadSimple<test_util::TestArch, VelocityArray>,
entities: system::EntityIterator<test_util::TestArch>,
) {
for (_, (p, v)) in entities.entities_with((p.access_mut(), v.access())) {
for (_, (p, v)) in entities.entities_with((&mut p, &v)) {
for i in 0..3 {
p.0[i] += v.0[i];
}
Expand Down Expand Up @@ -182,11 +172,11 @@ fn iter_entity_add_array_non_chunked(group: &mut BenchmarkGroup<'_, measurement:

#[system]
fn system_array_add_system_chunked(
mut p: impl system::WriteSimple<test_util::TestArch, PositionArray>,
v: impl system::ReadSimple<test_util::TestArch, VelocityArray>,
entities: impl system::EntityIterator<test_util::TestArch>,
mut p: system::WriteSimple<test_util::TestArch, PositionArray>,
v: system::ReadSimple<test_util::TestArch, VelocityArray>,
entities: system::EntityIterator<test_util::TestArch>,
) {
for (_, (p, v)) in entities.chunks_with((p.access_chunk_mut(), v.access_chunk())) {
for (_, (p, v)) in entities.chunks_with((&mut p, &v)) {
for (p, v) in iter::zip(p, v) {
for i in 0..3 {
p.0[i] += v.0[i];
Expand Down
14 changes: 7 additions & 7 deletions codegen/src/system/arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,21 @@ fn isotope_partial_builder(
return Err(Error::new(
args_span,
"Cannot infer archetype and component for component access. Specify explicitly \
with `#[dynec(isotope(arch = X, comp = Y))]`, or use \
`(Read|Write)Isotope(Full|Isotope)<X, Y>`.",
with `#[dynec(isotope(arch = X, comp = Y, [discrim_set = Z]))]`, or use \
`(Read|Write)Isotope(Full|Isotope)<X, Y, [Z]>`.",
));
}

let &arch = args.get(0).expect("args.len() >= 2");
let &comp = args.get(1).expect("args.len() >= 2");
let discrim_key = args.get(2).map(|&ty| Box::new(ty.clone())).ok_or(args_span);
let discrim_set = args.get(2).map(|&ty| Box::new(ty.clone())).ok_or(args_span);

Ok(ArgType::Isotope {
mutable: mutable || ident.starts_with("WriteIsotope"),
arch: Box::new(arch.clone()),
comp: Box::new(comp.clone()),
discrim,
discrim_set: discrim_key,
discrim_set,
maybe_uninit,
})
})
Expand Down Expand Up @@ -288,8 +288,8 @@ fn try_attr_to_arg_type(arg: opt::Arg, attr_span: Span, param_span: Span) -> Res
let discrim = opts.find_one(
|opt| option_match!(opt, opt::IsotopeArg::Discrim(_, discrim) => discrim),
)?;
let discrim_key = opts
.find_one(|opt| option_match!(opt, opt::IsotopeArg::DiscrimKey(_, ty) => ty))?
let discrim_set = opts
.find_one(|opt| option_match!(opt, opt::IsotopeArg::DiscrimSet(_, ty) => ty))?
.ok_or(param_span);
let maybe_uninit = opts.merge_all(|opt| option_match!(opt, opt::IsotopeArg::MaybeUninit(_, tys) => tys.iter().cloned()));

Expand All @@ -300,7 +300,7 @@ fn try_attr_to_arg_type(arg: opt::Arg, attr_span: Span, param_span: Span) -> Res
arch: arch.clone(),
comp: comp.clone(),
discrim: discrim.map(|(_, discrim)| discrim.clone()),
discrim_set: discrim_key.map(|(_, ty)| ty.clone()),
discrim_set: discrim_set.map(|(_, ty)| ty.clone()),
maybe_uninit,
})
}
Expand Down
6 changes: 3 additions & 3 deletions codegen/src/system/opt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ pub(super) enum IsotopeArg {
Arch(syn::Token![=], Box<syn::Type>),
Comp(syn::Token![=], Box<syn::Type>),
Discrim(syn::Token![=], Box<syn::Expr>),
DiscrimKey(syn::Token![=], Box<syn::Type>),
DiscrimSet(syn::Token![=], Box<syn::Type>),
MaybeUninit(syn::token::Paren, Punctuated<syn::Type, syn::Token![,]>),
}

Expand All @@ -180,10 +180,10 @@ impl Parse for Named<IsotopeArg> {
let discrim = input.parse::<syn::Expr>()?;
IsotopeArg::Discrim(eq, Box::new(discrim))
}
"discrim_key" => {
"discrim_set" => {
let eq = input.parse::<syn::Token![=]>()?;
let ty = input.parse::<syn::Type>()?;
IsotopeArg::DiscrimKey(eq, Box::new(ty))
IsotopeArg::DiscrimSet(eq, Box::new(ty))
}
"maybe_uninit" => parse_maybe_uninit(input, IsotopeArg::MaybeUninit)?,
_ => return Err(Error::new_spanned(&name, "Unknown option for #[dynec(isotope)]")),
Expand Down
111 changes: 69 additions & 42 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,22 +341,24 @@ mod global_tests {}
/// ```
///
/// ## Simple components
/// Parameters in the form `impl ReadSimple<A, C>` or `impl WriteSimple<A, C>`,
/// Parameters of type `ReadSimple<A, C>` or `WriteSimple<A, C>`,
/// request access to a [simple component](crate::comp::Simple) of type `C`
/// from entities of the [archetype](crate::Archetype) `A`,
/// exposed through a type that implements [`system::ReadSimple`](crate::system::ReadSimple)
/// or [`system::WriteSimple`](crate::system::WriteSimple).
/// from entities of the [archetype](crate::Archetype) `A`.
/// The latter provides mutable and exclusive access to the component storages.
///
/// ### Using other bounds
/// Other trait bounds for the parameter are also allowed,
/// but the macro would not be able to infer type parameters and mutability.
/// ### Using other aliases
/// Using type aliases/renamed imports for the types is also allowed,
/// but the macro would be unable to infer type parameters and mutability.
/// In such cases, they must be indicated explicitly in the attribute.
/// See the syntax reference below for details.
///
/// ### Uninitialized entity references.
/// Entity creation ordering is automatically enforced if `C` contains entity references,
/// Use the `maybe_uninit` attribute to remove this ordering.
/// ### Uninitialized entity references
/// If `C` contains [references](crate::entity::Referrer) to entities of some archetype `T`,
/// the scheduler automatically enforces that the system runs before
/// any systems that create entities of archetype `T`,
/// because components for entities created through [`EntityCreator`](crate::system::EntityCreator)
/// are uninitialized until the current cycle completes.
/// Use the `maybe_uninit` attribute to remove this ordering limitation.
///
/// See [`EntityCreationPartition`](crate::system::partition::EntityCreationPartition#component-accessors)
/// for more information.
Expand All @@ -366,10 +368,10 @@ mod global_tests {}
/// # /*
/// #[dynec(simple(
/// // Optional, specifies the archetype and component explicitly.
/// // Only required when the parameter type is not `impl ReadSimple`/`impl WriteSimple`.
/// // Only required when the parameter type is not `ReadSimple`/`WriteSimple`.
/// arch = $ty, comp = $ty,
/// // Optional, indicates that the component access is exclusive explicitly.
/// // Only required when the parameter type is not `impl WriteSimple`.
/// // Only required when the parameter type is not `WriteSimple`.
/// mut,
/// // Optional, acknowledges that the entities of the specified archetypes
/// // contained in the simple components may be uninitialized.
Expand All @@ -379,44 +381,48 @@ mod global_tests {}
/// ```
///
/// ## Isotope components
/// Parameters in the form `impl ReadIsotope<A, C>` or `impl WriteIsotope<A, C>`,
/// Parameters of type [`(Read|Write)Isotope(Full|Partial)`](mod@crate::system#types)
/// request access to an [isotope component](crate::comp::Isotope) of type `C`
/// from entities of the [archetype](crate::Archetype) `A`,
/// exposed through a type that implements [`system::ReadIsotope`](crate::system::ReadIsotope)
/// or [`system::WriteIsotope`](crate::system::WriteIsotope).
/// The latter provides mutable and exclusive access to the component storages.
/// from entities of the [archetype](crate::Archetype) `A`.
/// The `Write` variants provide mutable and exclusive access to the component storages.
///
/// ### Partial isotope access
/// By default, all discriminants of the isotope component are requested,
/// such that writes are exclusive with all systems that read any part of the discriminants.
/// The accessor can be made partial instead:
/// If [`ReadIsotopePartial`](crate::system::ReadIsotopePartial) or
/// [`WriteIsotopePartial`](crate::system::WriteIsotopePartial) is used,
/// the system only requests access to specific discriminants of the isotope component.
/// The actual discriminants are specified with an attribute:
///
/// ```
/// # /*
/// #[dynec(isotope(discrim = discrim_set))] param_name: impl ReadIsotope<A, C, K>,
/// # */
/// ```
///
/// The expression `discrim_set` implements
/// <code>[discrim::Set](crate::comp::discrim::Set)<C::[Discrim](crate::comp::Discrim)></code>,
/// which is the set of discriminants that this system uses.
/// The expression can reference local and param states directly.
/// However, since it is only evaluated once before the first run of the system,
/// subsequent writes to the states have no effect on the resolved discriminant set.
/// The expression `discrim_set` contains the set of discriminants requested by this system
/// contained in an implementation of
/// <code>[discrim::Set](crate::comp::discrim::Set)&lt;C::[Discrim](crate::comp::Discrim)&gt;</code>,
/// which is typically an array or a [`Vec`].
/// The expression may reference param states directly.
/// The expression is only evaluated once before the first run of the system,
/// so it will not react to subsequent changes to the param states.
///
/// `K` is the type of the [key](crate::comp::discrim::Set::Key) to index the discriminant set.
///
/// See the documentation of [`discrim::Set`](crate::comp::discrim::Set) for more information.
///
/// ### Using other bounds
/// Other trait bounds for the parameter are also allowed,
/// but the macro would not be able to infer type parameters and mutability.
/// ### Using other aliases
/// Using type aliases/renamed imports for the types is also allowed,
/// but the macro would be unable to infer type parameters and mutability.
/// In such cases, they must be indicated explicitly in the attribute.
/// See the syntax reference below for details.
///
/// ### Uninitialized entity references.
/// Entity creation ordering is automatically enforced if `C` contains entity references,
/// Use the `maybe_uninit` attribute to remove this ordering.
/// ### Uninitialized entity references
/// If `C` contains [references](crate::entity::Referrer) to entities of some archetype `T`,
/// the scheduler automatically enforces that the system runs before
/// any systems that create entities of archetype `T`,
/// because components for entities created through [`EntityCreator`](crate::system::EntityCreator)
/// are uninitialized until the current cycle completes.
/// Use the `maybe_uninit` attribute to remove this ordering limitation.
///
/// See [`EntityCreationPartition`](crate::system::partition::EntityCreationPartition#component-accessors)
/// for more information.
Expand All @@ -425,13 +431,16 @@ mod global_tests {}
/// ```
/// # /*
/// #[dynec(isotope(
/// // Optional, indicates that this accessor only uses the given subset of discriminants.
/// // Required if and only if the type is ReadIsotopePartial or WriteIsotopePartial.
/// discrim = $expr,
/// // Optional, must be the same as the `Key` associated type of the `discrim` expression.
/// // Only required when the parameter type is not `impl ReadIsotope`/`impl WriteIsotope`.
/// discrim_key = $ty,
/// // Optional, must be the same as the type of the `discrim` expression.
/// // Only required when the parameter type is not `ReadIsotopePartial`/`WriteIsotopePartial`.
/// // Note that `ReadIsotopePartial`/`WriteIsotopePartial` have an optional third type parameter
/// // that expects the same type as `discrim_set`,
/// // which is `Vec<C::Discrim>` by default.
/// discrim_set = $ty,
/// // Optional, specifies the archetype and component explicitly.
/// // Only required when the parameter type is not `impl ReadIsotope`/`impl WriteIsotope`.
/// // Only required when the parameter type is not `(Read|Write)Isotope(Full|Partial)`.
/// arch = $ty, comp = $ty,
/// // Optional, indicates that the component access is exclusive explicitly.
/// // Only required when the parameter type is not `impl WriteSimple`.
Expand All @@ -444,7 +453,7 @@ mod global_tests {}
/// ```
///
/// ## Entity creation
/// Parameters that require an implementation of [`EntityCreator`](crate::system::EntityCreator)
/// Parameters that require an [`EntityCreator`](crate::system::EntityCreator)
/// can be used to create entities.
/// The archetype of created entities is specified in the type bounds.
/// Note that entity creation is asynchronous to ensure synchronization,
Expand Down Expand Up @@ -478,7 +487,7 @@ mod global_tests {}
/// ```
///
/// ## Entity deletion
/// Parameters that require an implementation of [`EntityDeleter`](crate::system::EntityDeleter)
/// Parameters that require an [`EntityDeleter`](crate::system::EntityDeleter)
/// can be used to delete entities.
/// The archetype of deleted entities is specified in the type bounds.
/// Note that `EntityDeleter` can only be used to mark entities as "deleting";
Expand All @@ -488,9 +497,11 @@ mod global_tests {}
/// It is advisable to execute finalizer-removing systems
/// after systems that mark entities for deletion finish executing.
/// This allows deletion to happen in the same cycle,
/// thus slightly improving entity deletion performance
/// thus slightly reducing entity deletion latency
/// (but this is not supposed to be critical anyway).
/// Nevertheless, unlike entity creation, entity deletion does not have an automatic partition.
/// Nevertheless, unlike entity creation,
/// the scheduler does not automatically enforce ordering between
/// finalizer-manipulating systems and entity-deleting systems.
///
/// ### Syntax reference
/// ```
Expand All @@ -503,6 +514,22 @@ mod global_tests {}
/// # */
/// ```
///
/// ## Entity iterator
/// Parameters that require an [`EntityIterator`](crate::system::EntityIterator)
/// can be used to iterate over entities and zip multiple component iterators.
/// See the documentation for `EntityIterator` for details.
///
/// ### Syntax reference
/// ```
/// # /*
/// /// This attribute is not required unless `EntityIterator` is aliased.
/// #[dynec(entity_iterator(
/// // Optional, specifies the archetype if `EntityIterator` is aliased.
/// arch = $ty,
/// ))]
/// # */
/// ```
///
/// # Example
/// ```
/// use dynec::system;
Expand Down Expand Up @@ -802,7 +829,7 @@ macro_rules! assert_partition {
}

/// Declares a composite struct that implements
/// [`IntoZip`](crate::system::access:IntoZip), [`Zip`](crate::system::access::Zip)
/// [`IntoZip`](crate::system::access::IntoZip), [`Zip`](crate::system::access::Zip)
/// and [`ZipChunked`](crate::system::access::ZipChunked)
/// by delegation to all fields and reconstructing the same struct with different types.
///
Expand Down
8 changes: 4 additions & 4 deletions src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub trait Storage: Access + Default + Send + Sync + 'static {
/// Non-chunked storages should implement this function by returning a chunk for each entity.
fn iter_chunks_mut(&mut self) -> Self::IterChunksMut<'_>;

/// Return value of [`split_at`](Self::split_at).
/// Return value of [`as_partition`](Self::as_partition).
type Partition<'u>: Partition<'u, RawEntity = Self::RawEntity, Comp = Self::Comp>
where
Self: 'u;
Expand All @@ -77,7 +77,7 @@ pub trait Partition<'t>: Access + Send + Sync + Sized + 't {
Self: 'u;
/// Re-borrows the partition with reduced lifetime.
///
/// This is useful for calling [`iter_mut`](Self::iter_mut)
/// This is useful for calling [`into_iter_mut`](Self::into_iter_mut)
/// and [`split_at`](Self::split_at),
/// which take `self` as receiver to preserve the lifetime.
fn by_ref(&mut self) -> Self::ByRef<'_>;
Expand All @@ -101,10 +101,10 @@ pub trait Partition<'t>: Access + Send + Sync + Sized + 't {

/// Return value of [`into_iter_mut`](Self::into_iter_mut).
type IntoIterMut: Iterator<Item = (Self::RawEntity, &'t mut Self::Comp)>;
/// Same as [`iter_mut`](Access:iter_mut), but moves the partition object into the iterator.
/// Same as [`iter_mut`](Access::iter_mut), but moves the partition object into the iterator.
fn into_iter_mut(self) -> Self::IntoIterMut;

/// Same as [`try_get_mut`](Access::try_get_mut), but returns a reference with lifetime `'t`.
/// Same as [`get_mut`](Access::get_mut), but returns a reference with lifetime `'t`.
fn into_mut(self, entity: Self::RawEntity) -> Option<&'t mut Self::Comp>;
}

Expand Down
Loading

0 comments on commit 2dba51d

Please sign in to comment.