public override ExpressionSyntax GetEventBufferWriter(RoslynEcsTranslator.IterationContext iterationContext, ExpressionSyntax entity, Type eventType, out StatementSyntax bufferInitialization) { GetEventSystem(iterationContext, eventType); var bufferVariableName = SendEventTranslator.GetBufferVariableName(iterationContext, eventType); var buffersFromEntityVariableName = bufferVariableName + "s"; var cmdBuffer = GetOrDeclareCommandBuffer(true); bufferInitialization = RoslynBuilder.DeclareLocalVariable((Type)null, bufferVariableName, variableDeclarationType: RoslynBuilder.VariableDeclarationType.InferredType, initValue: ConditionalExpression( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(buffersFromEntityVariableName), IdentifierName("Exists"))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName(EntityName))))), ElementAccessExpression( IdentifierName(buffersFromEntityVariableName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(EntityName))))), InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, cmdBuffer, GenericName( Identifier(nameof(EntityCommandBuffer.AddBuffer))) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList <TypeSyntax>( eventType.ToTypeSyntax()))))) .WithArgumentList( ArgumentList( SeparatedList <ArgumentSyntax>( new SyntaxNodeOrToken[] { Argument( IdentifierName(GetJobIndexParameterName())), Token(SyntaxKind.CommaToken), Argument( IdentifierName(EntityName)) }))))); GetCachedValue(buffersFromEntityVariableName, InvocationExpression( GenericName( Identifier(nameof(JobComponentSystem.GetBufferFromEntity))) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( eventType.ToTypeSyntax())))), typeof(BufferFromEntity <>).MakeGenericType(eventType).GenerateTypeHandle(iterationContext.Stencil)); // The BufferFromEntity<EventStruct> is not parallel-write safe. We might have multiple iterations sending // events to the same separate entity, so we run the job on a single thread to be safe m_ScheduleSingleThreaded = true; return(IdentifierName(bufferVariableName)); }
LocalDeclarationStatementSyntax GetCoroutineComponentDeclaration(string loopIndexName) { string compArrayName = GetOrDeclareComponentArray( IterationContext, m_CoroutineComponentName, out var componentDataArrayInitialization, out var componentDataArrayDisposal); if (componentDataArrayInitialization != null) { m_InitComponentDataArrays.Add(componentDataArrayInitialization); } if (componentDataArrayDisposal != null) { m_DisposeComponentDataArrays.Add(componentDataArrayDisposal); } var initValue = ElementAccessExpression(IdentifierName(compArrayName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(loopIndexName))))); return(RoslynBuilder.DeclareLocalVariable( (Type)null, CoroutineContext.BuildCoroutineParameterName(m_CoroutineComponentName), initValue, RoslynBuilder.VariableDeclarationType.InferredType)); }
public override IdentifierNameSyntax GetEventBufferWriter(RoslynEcsTranslator.IterationContext iterationContext, ExpressionSyntax entity, Type eventType, out StatementSyntax bufferInitialization) { bufferInitialization = null; var bufferVariableName = SendEventTranslator.GetBufferVariableName(iterationContext, eventType); iterationContext.WrittenEventTypes.Add(eventType); if (GetEventSystem(iterationContext, eventType)) { // var buffer = EntityManager.GetBuffer<EventType>(entity); var bufferInitValue = InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("EntityManager"), GenericName( Identifier("GetBuffer")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( eventType.ToTypeSyntax()))))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument(entity) ) ) ); bufferInitialization = RoslynBuilder.DeclareLocalVariable((Type)null, bufferVariableName, bufferInitValue, RoslynBuilder.VariableDeclarationType.InferredType); } return(IdentifierName(bufferVariableName)); }
public override string GetOrDeclareComponentArray( RoslynEcsTranslator.IterationContext ctx, ComponentDefinition componentDefinition, out LocalDeclarationStatementSyntax arrayInitialization, out StatementSyntax arrayDisposal) { Type resolvedType = componentDefinition.TypeHandle.Resolve(m_Stencil); var arrayName = ctx.GetComponentDataArrayName(resolvedType); Type arrayType = typeof(NativeArray <>).MakeGenericType(resolvedType); arrayInitialization = RoslynBuilder.DeclareLocalVariable( arrayType, arrayName, MakeInitComponentDataArrayExpression(ctx, resolvedType), RoslynBuilder.VariableDeclarationType.InferredType); arrayDisposal = ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(arrayName), IdentifierName(nameof(IDisposable.Dispose))))) .NormalizeWhitespace(); return(arrayName); }
protected override IEnumerable <StatementSyntax> OnPopContext() { var rootContext = (RootContext)Parent; var build = BuildJobStruct(); if (build != null) { rootContext.AddMember(build); if ((TranslationOptions & RoslynEcsTranslator.TranslationOptions.Tracing) == 0) { yield return(MakeJobSchedulingStatement()); yield break; } var recorderName = $"{IterationContext.GroupName}Recorder"; yield return(RoslynBuilder.DeclareLocalVariable(typeof(GraphStream), recorderName, InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(TracingRecorderSystem)), IdentifierName(nameof(TracingRecorderSystem.GetRecordingStream)))) .WithArgumentList( ArgumentList( SeparatedList( new[] { Argument( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(IterationContext.GroupName), IdentifierName(nameof(EntityQuery.CalculateEntityCount))))), Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(((UnityEngine.Object)IterationContext.Query.GraphModel.AssetModel).GetInstanceID()))) }))))); yield return(MakeJobSchedulingStatement()); yield return(ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(TracingRecorderSystem)), IdentifierName(nameof(TracingRecorderSystem.FlushRecordingStream)))) .WithArgumentList( ArgumentList( SeparatedList( new[] { Argument( IdentifierName(recorderName)), Argument( IdentifierName("inputDeps")) }))))); } }
public override void AddEntityDeclaration(string variableName) { // Entity {m_EntityName} = {IterationContext.EntitiesArrayName}[{IterationContext.IndexVariableName}]; EntityName = variableName; m_EntityDeclaration = RoslynBuilder.DeclareLocalVariable( typeof(Entity), EntityName, ElementAccessExpression(IdentifierName(IterationContext.EntitiesArrayName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(IterationContext.IndexVariableName))))), RoslynBuilder.VariableDeclarationType.InferredType); }
protected override StatementSyntax GetOrDeclareEntityArray(RoslynEcsTranslator.IterationContext iterationContext, out StatementSyntax arrayDisposal) { arrayDisposal = ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(iterationContext.EntitiesArrayName), IdentifierName(nameof(IDisposable.Dispose))))) .NormalizeWhitespace(); return(RoslynBuilder.DeclareLocalVariable( typeof(NativeArray <Entity>), iterationContext.EntitiesArrayName, ForEachContext.MakeInitEntityArray(iterationContext), RoslynBuilder.VariableDeclarationType.InferredType)); }
public override ExpressionSyntax GetSingletonVariable(IVariableDeclarationModel variable) { if (m_SingletonDeclarationSyntax == null) { var init = RoslynBuilder.MethodInvocation( SafeGuardNamingSystem.GetSingletonName, null, Enumerable.Empty <ArgumentSyntax>(), new[] { IdentifierName(SingletonComponentTypeName) }); m_SingletonDeclarationSyntax = RoslynBuilder.DeclareLocalVariable( SingletonComponentTypeName, SingletonVariableName, init); AddStatement(m_SingletonDeclarationSyntax); } return(MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(SingletonVariableName), IdentifierName(variable.VariableName))); }
public override string GetOrDeclareComponentArray(RoslynEcsTranslator.IterationContext ctx, string componentTypeName, out LocalDeclarationStatementSyntax arrayInitialization, out StatementSyntax arrayDisposal) { var arrayName = ctx.GetComponentDataArrayName(componentTypeName); arrayInitialization = RoslynBuilder.DeclareLocalVariable( (Type)null, arrayName, MakeInitComponentDataArrayExpression(ctx, componentTypeName), RoslynBuilder.VariableDeclarationType.InferredType); arrayDisposal = ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(arrayName), IdentifierName(nameof(IDisposable.Dispose))))) .NormalizeWhitespace(); return(arrayName); }
protected override StatementSyntax OnPopContext() { BlockSyntax forBody = Block(); var loopIndexName = IterationContext.IndexVariableName; List <StatementSyntax> reassignComponentDataArrays = new List <StatementSyntax>(); BlockSyntax blockSyntax = Block(); // foreach in a job: the entity array will be declared as a job field, initialized at job creation StatementSyntax initEntitiesArray = GetOrDeclareEntityArray(IterationContext, out var disposeEntitiesArray); foreach (ComponentDefinition definition in IterationContext.FlattenedComponentDefinitions()) { if (!RoslynEcsTranslatorExtensions.ShouldGenerateComponentAccess(definition.TypeHandle, true, out var componentType, IterationContext.Stencil, out bool isShared, out bool isGameObjectComponent) || isGameObjectComponent) { continue; } if (!m_WrittenComponents.TryGetValue(definition.TypeHandle, out var mode)) { mode = RoslynEcsTranslator.AccessMode.None; } if (mode == RoslynEcsTranslator.AccessMode.None) { continue; } ExpressionSyntax initValue; if (isShared) { initValue = InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(EntityManager)), GenericName( Identifier(nameof(EntityManager.GetSharedComponentData))) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( TypeSystem.BuildTypeSyntax(componentType)))))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName(EntityName))))); } else { string compArrayName = GetOrDeclareComponentArray(IterationContext, definition, out var componentDataArrayInitialization, out var componentDataArrayDisposal); if (componentDataArrayInitialization != null) { m_InitComponentDataArrays.Add(componentDataArrayInitialization); } if (componentDataArrayDisposal != null) { m_DisposeComponentDataArrays.Add(componentDataArrayDisposal); } initValue = ElementAccessExpression(IdentifierName(compArrayName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(loopIndexName))))); } // per-entity component variable StatementSyntax componentVarDeclaration = RoslynBuilder.DeclareLocalVariable( componentType, IterationContext.GetComponentDataName(componentType), initValue, RoslynBuilder.VariableDeclarationType.InferredType); forBody = forBody.AddStatements(componentVarDeclaration); if (mode == RoslynEcsTranslator.AccessMode.Write) { reassignComponentDataArrays.Add(ExpressionStatement( GetEntityManipulationTranslator().SetComponent( this, ElementAccessExpression(IdentifierName(IterationContext.EntitiesArrayName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(IterationContext.IndexVariableName))))), componentType, IdentifierName(IterationContext.GetComponentDataName(componentType))) .Cast <ExpressionSyntax>() .Single()) ); } } forBody = forBody.AddStatements(m_UpdateStatements.ToArray()); forBody = forBody.AddStatements(reassignComponentDataArrays.ToArray()); if (forBody.Statements.Count != 0) // strip the iteration loop if empty { forBody = forBody.WithStatements(forBody.Statements.Insert(0, m_EntityDeclaration)); if (initEntitiesArray != null) { blockSyntax = blockSyntax.AddStatements(initEntitiesArray); } blockSyntax = blockSyntax .AddStatements(m_InitComponentDataArrays.ToArray()) .AddStatements(RoslynEcsTranslatorExtensions.ComponentQueryForLoop(forBody, loopIndexName, IterationContext.EntitiesArrayName)) .AddStatements(m_DisposeComponentDataArrays.ToArray()); if (disposeEntitiesArray != null) { blockSyntax = blockSyntax.AddStatements(disposeEntitiesArray); } } return(AddMissingEventBuffers(IterationContext, blockSyntax)); }
StatementSyntax BuildInner() { const string eventBufferName = "eventBuffer"; Type eventType = IterationContext.UpdateMode == UpdateMode.OnEvent ? ((OnEventNodeModel)IterationContext.Query).EventTypeHandle.Resolve(IterationContext.Stencil) : null; List <ParameterSyntax> parameters = new List <ParameterSyntax> { Parameter( Identifier(EntityName)) .WithType(typeof(Entity).ToTypeSyntax()) }; var stateComponentName = IterationContext.UpdateMode == UpdateMode.OnUpdate || IterationContext.UpdateMode == UpdateMode.OnEvent ? null : IncludeTrackingSystemStateComponent(IterationContext.Query.ComponentQueryDeclarationModel, IterationContext.UpdateMode == UpdateMode.OnEnd); var stateComponentParameterName = stateComponentName?.ToLowerInvariant(); switch (IterationContext.UpdateMode) { case UpdateMode.OnUpdate: break; case UpdateMode.OnEvent: // Add it at the end break; case UpdateMode.OnStart: m_UpdateStatements.AddRange(GetEntityManipulationTranslator().AddComponent( this, IdentifierName(EntityName), DefaultExpression(IdentifierName(stateComponentName)), IdentifierName(stateComponentName), false)); break; case UpdateMode.OnEnd: parameters.Add(MakeLambdaParameter( stateComponentParameterName, IdentifierName(stateComponentName), false, false)); m_UpdateStatements.AddRange(GetEntityManipulationTranslator().RemoveComponent( this, IdentifierName(EntityName), IdentifierName(stateComponentName))); break; default: throw new ArgumentOutOfRangeException(); } // SharedComponents should be inserted first in ForEach var sortedComponents = IterationContext.FlattenedComponentDefinitions() .OrderBy(d => !typeof(ISharedComponentData).IsAssignableFrom(d.TypeHandle.Resolve(IterationContext.Stencil))) .ToList(); foreach (ComponentDefinition definition in sortedComponents) { if (!RoslynEcsTranslatorExtensions.ShouldGenerateComponentAccess( definition.TypeHandle, true, out Type componentType, IterationContext.Stencil, out bool _, out bool isGameObjectComponent)) { continue; } if (!m_WrittenComponents.TryGetValue(definition.TypeHandle, out RoslynEcsTranslator.AccessMode mode)) { mode = RoslynEcsTranslator.AccessMode.None; } if (mode == RoslynEcsTranslator.AccessMode.None) { continue; } string componentDataName = IterationContext.GetComponentDataName(componentType); parameters.Add(MakeLambdaParameter( componentDataName, componentType.ToTypeSyntax(), isGameObjectComponent, typeof(ISharedComponentData).IsAssignableFrom(componentType))); } switch (IterationContext.UpdateMode) { case UpdateMode.OnEvent: parameters.Add(MakeLambdaParameter( eventBufferName, GenericName("DynamicBuffer").WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(eventType.ToTypeSyntax()))), false, true)); break; } ExpressionSyntax baseQuery = InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Entities"), IdentifierName("With"))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName(IterationContext.UpdateMode == UpdateMode.OnEvent ? SendEventTranslator.MakeQueryIncludingEventName(IterationContext, eventType) : IterationContext.GroupName))))); if (IterationContext.UpdateMode == UpdateMode.OnEnd) { // REPLACE query baseQuery = IdentifierName("Entities"); m_UpdateStatements.Insert(0, IfStatement( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(stateComponentParameterName), IdentifierName("Processed")), ReturnStatement())); } BlockSyntax innerLambdaBody; if (IterationContext.UpdateMode == UpdateMode.OnEvent) { //for (int event_index = 0; event_index < eventBuffer.Length; event_index++) { T ev = eventBuffer[event_index]; ... } var eventIndexName = "event_index"; m_UpdateStatements.Insert(0, RoslynBuilder.DeclareLocalVariable(eventType, "ev", ElementAccessExpression( IdentifierName(eventBufferName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(eventIndexName))))) .NormalizeWhitespace())); innerLambdaBody = Block(ForStatement( Block(m_UpdateStatements)) .WithDeclaration( VariableDeclaration( PredefinedType( Token(SyntaxKind.IntKeyword))) .WithVariables( SingletonSeparatedList <VariableDeclaratorSyntax>( VariableDeclarator( Identifier(eventIndexName)) .WithInitializer( EqualsValueClause( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0))))))) .WithCondition( BinaryExpression( SyntaxKind.LessThanExpression, IdentifierName(eventIndexName), MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(eventBufferName), IdentifierName("Length")))) .WithIncrementors( SingletonSeparatedList <ExpressionSyntax>( PostfixUnaryExpression( SyntaxKind.PostIncrementExpression, IdentifierName(eventIndexName)))) .NormalizeWhitespace()); } else { innerLambdaBody = Block(m_UpdateStatements); } var parenthesizedLambdaExpressionSyntax = ParenthesizedLambdaExpression( innerLambdaBody) .WithParameterList( ParameterList().AddParameters(parameters.ToArray())); var updateCall = ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, baseQuery, IdentifierName("ForEach"))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( parenthesizedLambdaExpressionSyntax))))); if (IterationContext.UpdateMode == UpdateMode.OnEnd) { var addMissingStateComponents = ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("EntityManager"), IdentifierName("AddComponent"))) .WithArgumentList( ArgumentList( SeparatedList( new [] { Argument( IdentifierName(RootContext.GetQueryAddStateName(IterationContext.GroupName))), Argument( TypeOfExpression( IdentifierName(stateComponentName))) })))); var foreachClearProcessed = ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Entities"), IdentifierName("ForEach"))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( ParenthesizedLambdaExpression( MakeProcessed(false)) .WithParameterList( ParameterList( SingletonSeparatedList( Parameter( Identifier(stateComponentParameterName)) .WithModifiers( TokenList( Token(SyntaxKind.RefKeyword))) .WithType( IdentifierName(stateComponentName)))))))))); var foreachQueryMarkProcessed = ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName("Entities"), IdentifierName("With"))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName(IterationContext.GroupName))))), IdentifierName("ForEach"))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( ParenthesizedLambdaExpression(MakeProcessed(true)) .WithParameterList( ParameterList( SeparatedList(parameters)))))))); return(Block( addMissingStateComponents, foreachClearProcessed, foreachQueryMarkProcessed, updateCall )); } return(updateCall); ParameterSyntax MakeLambdaParameter(string componentDataName, TypeSyntax typeSyntax, bool isGameObjectComponent, bool isSharedComponent) { var modifiers = new List <SyntaxToken>(); if (!isSharedComponent) { modifiers.Add(Token(SyntaxKind.RefKeyword)); } var parameterSyntax = Parameter( Identifier(componentDataName)) .WithType( typeSyntax); if (!isGameObjectComponent) { parameterSyntax = parameterSyntax .WithModifiers(TokenList(modifiers)); } return(parameterSyntax); } AssignmentExpressionSyntax MakeProcessed(bool processed) { return(AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(stateComponentParameterName), IdentifierName("Processed")), LiteralExpression(processed ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression))); } }
MemberDeclarationSyntax MakeJobUpdateOverride(List <ParameterSyntax> functionParameters, List <StatementSyntax> updateStatements, string trackingComponentName, Type eventType) { var blockSyntax = Block(updateStatements); switch (IterationContext.UpdateMode) { case UpdateMode.OnStart: blockSyntax = blockSyntax.AddStatements(GetEntityManipulationTranslator().AddComponent( this, IdentifierName(EntityName), DefaultExpression(IdentifierName(trackingComponentName)), IdentifierName(trackingComponentName), false).ToArray()); break; case UpdateMode.OnEvent: Assert.IsNotNull(eventType); const string eventIndexName = "event_idx"; string eventBufferName = OnEventNodeModel.GetBufferName(eventType); var eventDeclaration = RoslynBuilder.DeclareLocalVariable(eventType, "ev" /* TODO hardcoded event name*/, ElementAccessExpression( IdentifierName(eventBufferName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(eventIndexName)))))); blockSyntax = Block(ForStatement(Block(blockSyntax.Statements.Insert(0, eventDeclaration))) .WithDeclaration( VariableDeclaration( PredefinedType( Token(SyntaxKind.IntKeyword))) .WithVariables( SingletonSeparatedList( VariableDeclarator( Identifier(eventIndexName)) .WithInitializer( EqualsValueClause( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0))))))) .WithCondition( BinaryExpression( SyntaxKind.LessThanExpression, IdentifierName(eventIndexName), MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(eventBufferName), IdentifierName("Length")))) .WithIncrementors( SingletonSeparatedList <ExpressionSyntax>( PostfixUnaryExpression( SyntaxKind.PostIncrementExpression, IdentifierName(eventIndexName))))); break; } var executeMethod = MethodDeclaration( PredefinedType( Token(SyntaxKind.VoidKeyword)), Identifier("Execute")) .WithModifiers( TokenList( Token(SyntaxKind.PublicKeyword))) .WithParameterList( ParameterList( SeparatedList(functionParameters))) .WithBody(blockSyntax); return(executeMethod); }
internal static void BuildCriteria(this IEntityManipulationTranslator self, RoslynEcsTranslator translator, TranslationContext context, ExpressionSyntax entity, IEnumerable <CriteriaModel> criteriaModels, StatementSyntax conditionBreak) { var criteriaList = criteriaModels.ToList(); if (!criteriaList.Any()) { return; } ExpressionSyntax ifExpressionSyntax = null; foreach (var model in criteriaList) { ExpressionSyntax finalExpression = null; foreach (var criterion in model.Criteria) { if (!(criterion is Criterion componentCriterion)) { continue; } var rightValue = componentCriterion.Value is ConstantNodeModel constantNodeModel ? translator.Constant(constantNodeModel.ObjectValue, translator.Stencil, constantNodeModel.Type) : IdentifierName(componentCriterion.Value.DeclarationModel.VariableName); var expression = BinaryExpression( componentCriterion.Operator.ToSyntaxKind(), GetLeftValueFromCriterion(self, context, translator.Stencil, entity, componentCriterion), rightValue) as ExpressionSyntax; // TODO : Temporary. Once Unity.Mathematics have IComparable interface, remove this // and use IComparable and IEquatable methods instead of operators var rightValueType = GetRightValueType(componentCriterion, translator.Stencil); if (rightValueType.Namespace != null && rightValueType.Namespace.StartsWith("Unity.Mathematics")) { expression = RoslynBuilder.MethodInvocation( nameof(math.all), typeof(math).ToTypeSyntax(), new[] { Argument(expression) }, Enumerable.Empty <TypeSyntax>()); } finalExpression = finalExpression == null ? expression : BinaryExpression(SyntaxKind.LogicalAndExpression, finalExpression, expression); } if (finalExpression == null) { continue; } context.AddStatement(RoslynBuilder.DeclareLocalVariable( typeof(bool), model.Name, finalExpression, RoslynBuilder.VariableDeclarationType.InferredType)); var unaryExpression = PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, IdentifierName(model.Name)); if (model != criteriaList.First()) { ifExpressionSyntax = BinaryExpression( SyntaxKind.LogicalAndExpression, ifExpressionSyntax, unaryExpression); } else { ifExpressionSyntax = unaryExpression; } } if (ifExpressionSyntax != null) { BlockSyntax statementSyntax; if ((translator.Options & CompilationOptions.Tracing) != 0 && context is JobContext jobContext) { statementSyntax = Block(List <SyntaxNode>() .Add(jobContext.MakeTracingEndForEachIndexStatement()) .Add(conditionBreak)); } else { statementSyntax = Block(SingletonList(conditionBreak)); } context.AddStatement(IfStatement(ifExpressionSyntax, statementSyntax)); } }
MemberDeclarationSyntax MakeJobUpdateOverride(List <ParameterSyntax> functionParameters, List <StatementSyntax> updateStatements, string trackingComponentName, Type eventType) { var blockSyntax = Block(updateStatements); switch (IterationContext.UpdateMode) { case UpdateMode.OnStart: blockSyntax = blockSyntax.AddStatements(GetEntityManipulationTranslator().AddComponent( this, IdentifierName(EntityName), DefaultExpression(IdentifierName(trackingComponentName)), IdentifierName(trackingComponentName), false).ToArray()); break; case UpdateMode.OnEvent: Assert.IsNotNull(eventType); const string eventIndexName = "event_idx"; string eventBufferName = OnEventNodeModel.GetBufferName(eventType); var eventDeclaration = RoslynBuilder.DeclareLocalVariable(eventType, "ev" /* TODO hardcoded event name*/, ElementAccessExpression( IdentifierName(eventBufferName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(eventIndexName)))))); blockSyntax = Block(ForStatement(Block(blockSyntax.Statements.Insert(0, eventDeclaration))) .WithDeclaration( VariableDeclaration( PredefinedType( Token(SyntaxKind.IntKeyword))) .WithVariables( SingletonSeparatedList( VariableDeclarator( Identifier(eventIndexName)) .WithInitializer( EqualsValueClause( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0))))))) .WithCondition( BinaryExpression( SyntaxKind.LessThanExpression, IdentifierName(eventIndexName), MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(eventBufferName), IdentifierName("Length")))) .WithIncrementors( SingletonSeparatedList <ExpressionSyntax>( PostfixUnaryExpression( SyntaxKind.PostIncrementExpression, IdentifierName(eventIndexName))))); break; } var executeMethod = MethodDeclaration( PredefinedType( Token(SyntaxKind.VoidKeyword)), Identifier("Execute")) .WithModifiers( TokenList( Token(SyntaxKind.PublicKeyword))) .WithParameterList( ParameterList( SeparatedList(functionParameters))) .WithBody(blockSyntax); if ((TranslationOptions & RoslynEcsTranslator.TranslationOptions.Tracing) != 0) { ((SerializableGUID)IterationContext.Query.Guid).ToParts(out var guid1, out var guid2); StatementSyntax beginStatement = ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, m_RecorderJobFieldName, IdentifierName(nameof(GraphStream.Writer.BeginForEachIndex)))) .WithArgumentList( ArgumentList( SeparatedList( new[] { Argument(IdentifierName(EntityName)), Argument(IdentifierName(GetJobIndexParameterName())), Argument(LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(guid1))), Argument(LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(guid2))), })))) // .WithAdditionalAnnotations(Annotations.MakeTracingAnnotation(IterationContext.Query)) ; StatementSyntax endStatement = MakeTracingEndForEachIndexStatement(); executeMethod = executeMethod.WithBody(executeMethod.Body.WithStatements(executeMethod.Body.Statements.Insert(0, beginStatement).Add(endStatement))); } return(executeMethod); }