Core: IAutoEnumerator Source Generator #42
Labels
challenging
This task requires some technical competence
open to contributors
Want to contribute? This task is available.
IAutoEnumerator Source Generator
Iterator methods (methods that contain
yield return
expressions) are anexpressive way to describe sequences of logic spread over a period of time, a
complex data structure, or decision tree. However, such methods are not
compatible with Burst. Let’s fix that!
Task is Prerequisite For
Base Requirements
Additions and modifications for the source generator should be made to this
repository.
Given the user-written code:
Generate the following using an incremental source generator:
The generator must be an
IIncrementalGenerator
.The generator should produce error messages using the same mechanism as the
existing
CollectionComponentGenerator
andManagedStructComponentGenerator
use.
Introductory logic can exist either in
SetEnumerator
orMoveNext
. User codebetween invocations of
SetEnumerator
andMoveNext
which interact with anycontainer arguments of
SetEnumerator
is considered undefined behavior.Any
Entity
,BlobAssetReference<>
, orUnsafeUntypedBlobAssetReference
mustbe preserved as an explicit field such that Unity can serialize the expanded
struct.
Unless the user code is marked unsafe, the generated code may not use any unsafe
semantics. If unsafe code is needed for the implementation apart from user code,
it can be implemented with utility methods inside the Latios Core module within
Latios.InternalSourceGen.StaticAPI
.IAutoEnumerator
interface
should be defined in the Core module inside theGameplayToolkit directory.
Example
This is a basic example of what an implementation might produce. Note that there
are potentially multiple correct implementations.
Input:
Output:
In this implementation, every local variable becomes a member variable. And
every loop start, end, and yield creates a new case. An alternate implementation
would be to copy local variables to members for the given scope, and then
restore them so that the original lines of code could be copied as-is.
Optimizations
Optimization is not required, but encouraged if you are able to.
When optimizing, the size of the expanded enumerator struct is what matters
above all else. It is desirable to make it as small as possible.
Not all local variables need to be converted to member fields. If the variable’s
lifetime does not stretch across a yield statement, it can be kept local. In the
example above,
__item
could be kept local.There is no strict definition as to whether initial logic is in
SetEnumerator
or
MoveNext
. Consequently, in the example above,__array
could also beeliminated by moving some of the logic into
SetEnumerator
.In more complicated enumerations, it may be possible to recycle member fields.
Member field ordering can have an impact on the size of the structure, as fields
have to be placed according to their alignment, which can sometimes result in
padding being inserted between fields. For example, the sequence
int, int, int, short, bool, bool
, is 8 bytes smaller than the sequenceint, bool, int, short, int, bool
.The text was updated successfully, but these errors were encountered: