예제 #1
0
        public override TranslationContext PushContext(IIteratorStackModel query,
                                                       RoslynEcsTranslator roslynEcsTranslator, UpdateMode mode, bool isCoroutine = false)
        {
            if (isCoroutine)
            {
                return(new CoroutineContext(this, roslynEcsTranslator));
            }

            return(new ForEachContext(query, this, mode));
        }
 public void BuildCriteria(RoslynEcsTranslator translator, TranslationContext context, ExpressionSyntax entity,
                           IEnumerable <CriteriaModel> criteriaModels)
 {
     this.BuildCriteria(
         translator,
         context,
         entity,
         criteriaModels.Where(x => x.Criteria.Any()),
         ContinueStatement()
         );
 }
예제 #3
0
        public override TranslationContext PushContext(IIteratorStackModel query, RoslynEcsTranslator roslynEcsTranslator, UpdateMode mode)
        {
            if (roslynEcsTranslator.GameObjectCodeGen || !m_TranslationOptions.HasFlag(RoslynEcsTranslator.TranslationOptions.UseJobs))
            {
                m_NeedToCompleteDependenciesFirst = true;
                return(new ForEachLambdaContext(query, this, mode));
            }

            return(new JobContext(query, this, mode)
            {
                BurstCompileJobs = m_TranslationOptions.HasFlag(RoslynEcsTranslator.TranslationOptions.BurstCompile)
            });
        }
예제 #4
0
        public static IEnumerable <SyntaxNode> BuildSetVariable(this RoslynEcsTranslator translator, SetVariableNodeModel statement, IPortModel portModel)
        {
            if (statement.InstancePort.ConnectionPortModels.First().NodeModel is VariableNodeModel variableNode &&
                variableNode.ReferencedObject is IVariableDeclarationModel &&
                variableNode.DeclarationModel.VariableType == VariableType.GraphVariable)
            {
                translator.context.RequestSingletonUpdate();
            }

            var decl  = translator.BuildPort(statement.InstancePort).SingleOrDefault();
            var value = translator.BuildPort(statement.ValuePort).SingleOrDefault();

            yield return(decl == null || value == null ? null : RoslynBuilder.Assignment(decl, value));
        }
예제 #5
0
        public void BuildComponent(RoslynEcsTranslator translator)
        {
            // Create coroutine component
            var members = BuildComponentMembers(translator);

            DeclareComponent <ISystemStateComponentData>(m_ComponentTypeName, members);

            // Add coroutine in the query archetype
            IncludeCoroutineComponent(IterationContext, m_ComponentTypeName);

            // Add coroutine component
            var rootContext = (RootContext)Parent.Parent;

            rootContext.PrependStatement(BuildAddCoroutineComponent(IterationContext, m_ComponentTypeName));
        }
예제 #6
0
        public override void BuildComponent(IStackModel stack, RoslynEcsTranslator translator)
        {
            // Build stack
            BuildStack(translator, stack, 0);

            // Create coroutine component
            var members = BuildComponentMembers();

            DeclareComponent <ISystemStateComponentData>(m_ComponentTypeName, members);

            // Create coroutine update method
            DeclareSystemMethod(BuildUpdateCoroutineMethod());

            // Add a nestedCoroutine field in the parent coroutine component
            ((CoroutineContext)Parent).AddComponentField(m_ComponentTypeName, NestedCoroutineFieldName);
        }
        public static IEnumerable <SyntaxNode> BuildReturn(this RoslynEcsTranslator translator, ReturnNodeModel returnModel, IPortModel portModel)
        {
            // TODO Implement Return statement in coroutine
            if (translator.context is CoroutineContext)
            {
                translator.AddError(returnModel, "Return node isn't allowed in Coroutine (e.g. Wait) execution stack for now. This feature is coming in a further release");
                yield break;
            }

            if (returnModel.InputPort == null)
            {
                yield return(ReturnStatement());
            }
            else
            {
                yield return(ReturnStatement(
                                 translator.BuildPort(returnModel.InputPort).FirstOrDefault() as ExpressionSyntax));
            }
        }
        public virtual void BuildComponent(IStackModel stack, RoslynEcsTranslator translator)
        {
            // Build stack
            BuildStack(translator, stack, 0);

            // Create coroutine component
            var members = BuildComponentMembers();

            DeclareComponent <ISystemStateComponentData>(m_ComponentTypeName, members);

            // Add coroutine in the lambda/job execute method
            IncludeCoroutineComponent(IterationContext, m_ComponentTypeName);

            // Add coroutine component
            PrependStatement(BuildAddCoroutineComponent(IterationContext, m_ComponentTypeName));

            // Create coroutine update method
            DeclareSystemMethod(BuildUpdateCoroutineMethod());
        }
예제 #9
0
        public static IEnumerable <SyntaxNode> BuildIfCondition(this RoslynEcsTranslator translator, IfConditionNodeModel statement, IPortModel portModel)
        {
            // TODO: de-duplicate code after if stacks
            var firstThenStack = RoslynTranslator.GetConnectedStack(statement, 0);
            var firstElseStack = RoslynTranslator.GetConnectedStack(statement, 1);

            // this enables more elegant code generation with no duplication
            // find first stack reachable from both then/else stacks
            var endStack = RoslynTranslator.FindCommonDescendant(firstThenStack, firstElseStack);

            if (endStack != null)
            {
//                Debug.Log($"If in stack {statement.parentStackModel} Common descendant: {endStack}");
                // building the branches will stop at the common descendant
                translator.EndStack = endStack;
            }

            // ie. follow outputs, find all stacks with multiple inputs, compare them until finding the common one if it exists
            // BuildStack should take an abort stack parameter, returning when recursing on it
            // the parent buildStack call will then continue on this end stack

            var thenBlock = Block();

            if (endStack != firstThenStack)
            {
                translator.BuildStack(firstThenStack, ref thenBlock, StackExitStrategy.Inherit);
            }

            var elseBlock = Block();

            if (endStack != firstElseStack)
            {
                translator.BuildStack(firstElseStack, ref elseBlock, StackExitStrategy.Inherit);
            }

            var ifNode = RoslynBuilder.IfStatement(
                translator.BuildPort(statement.IfPort).SingleOrDefault(),
                thenBlock,
                elseBlock);

            yield return(ifNode);
        }
        void BuildCoroutineNode(CoroutineNodeModel node, RoslynEcsTranslator translator, ref int currentIndex)
        {
            foreach (var variable in node.Fields.Where(v => !m_ComponentVariables.ContainsKey(v.Key)))
            {
                m_ComponentVariables.Add(variable.Key, variable.Value);
            }

            // Coroutine initialization state
            var initState = m_States[currentIndex];

            initState.Statements.AddRange(CoroutineTranslator.BuildInitState(node, translator));

            var nextStateIndex = initState.NextStateIndex;

            initState.NextStateIndex = m_States.Count;

            // Coroutine update state
            var updateState = RequestNewState();

            updateState.SkipStateBuilding = true;

            var hasNextNode = node.ParentStackModel.NodeModels.Last() != node;
            var nextStack   = GetNextStack(node.ParentStackModel);
            int nextIndex;

            if (hasNextNode || nextStack != null && !m_StackIndexes.ContainsKey(nextStack))
            {
                nextIndex = m_States.Count;
                var newState = RequestNewState();
                newState.NextStateIndex = nextStateIndex;
            }
            else
            {
                nextIndex = nextStateIndex == 0 ? m_States.Count : nextStateIndex;
            }

            node.NextStateIndex = nextIndex;
            updateState.Statements.AddRange(translator.BuildNode(node).Cast <StatementSyntax>());
            currentIndex = GetCurrentStateIndex();
        }
예제 #11
0
        public static IEnumerable <SyntaxNode> BuildFunctionRefCall(this RoslynEcsTranslator translator,
                                                                    FunctionRefCallNodeModel call, IPortModel portModel)
        {
            if (!call.Function)
            {
                yield break;
            }

            ExpressionSyntax instance = translator.BuildArgumentList(call, out var argumentList);

            if (!call.Function.IsInstanceMethod)
            {
                instance = IdentifierName(((VSGraphModel)call.Function.GraphModel).TypeName);
            }

            var invocationExpressionSyntax =
                instance == null ||
                instance is LiteralExpressionSyntax && instance.IsKind(SyntaxKind.NullLiteralExpression)
                ? InvocationExpression(IdentifierName(call.Function.CodeTitle))
                : InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        instance,
                        IdentifierName(call.Function.CodeTitle)));

            invocationExpressionSyntax = invocationExpressionSyntax.WithArgumentList(
                ArgumentList(SeparatedList(argumentList)));

            if (portModel == null)
            {
                yield return(ExpressionStatement(invocationExpressionSyntax).NormalizeWhitespace());
            }
            else
            {
                yield return(invocationExpressionSyntax.NormalizeWhitespace());
            }
        }
예제 #12
0
        public static IEnumerable <SyntaxNode> BuildBinaryOperator(this RoslynEcsTranslator translator, BinaryOperatorNodeModel model, IPortModel portModel)
        {
            if (model.kind == BinaryOperatorKind.Equals)
            {
                yield return(InvocationExpression(
                                 MemberAccessExpression(
                                     SyntaxKind.SimpleMemberAccessExpression,
                                     PredefinedType(Token(SyntaxKind.ObjectKeyword)),
                                     IdentifierName("Equals")))
                             .WithArgumentList(
                                 ArgumentList(
                                     SeparatedList(new[] {
                    Argument((ExpressionSyntax)translator.BuildPort(model.InputPortA).SingleOrDefault()),
                    Argument((ExpressionSyntax)translator.BuildPort(model.InputPortB).SingleOrDefault())
                }))));
            }

            else
            {
                yield return(RoslynBuilder.BinaryOperator(model.kind,
                                                          translator.BuildPort(model.InputPortA).SingleOrDefault(),
                                                          translator.BuildPort(model.InputPortB).SingleOrDefault()));
            }
        }
예제 #13
0
        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));
            }
        }
        protected void BuildStack(RoslynEcsTranslator translator, IStackModel stack, int currentStateIndex,
                                  StackExitStrategy exitStrategy = StackExitStrategy.Return)
        {
            if (stack == null || stack.State == ModelState.Disabled)
            {
                return;
            }

            translator.RegisterBuiltStack(stack);

            if (m_StackIndexes.TryGetValue(stack, out var endStackIndex))
            {
                currentStateIndex = endStackIndex;
            }

            // JUST in case... until we validate the previous failsafe
            if (m_BuiltStackCounter++ > 10000)
            {
                throw new InvalidOperationException("Infinite loop while building the script, aborting");
            }

            var origStackExitStrategy = m_StackExitStrategy;

            if (exitStrategy != StackExitStrategy.Inherit)
            {
                m_StackExitStrategy = exitStrategy;
            }

            if (m_States.Count == 0)
            {
                var state = RequestNewState();
                state.NextStateIndex = GetCurrentStateIndex();
            }

            var origEndStack = translator.EndStack;

            foreach (var node in stack.NodeModels)
            {
                if (node.State == ModelState.Disabled)
                {
                    continue;
                }

                switch (node)
                {
                case CoroutineNodeModel coroutineNode:
                    BuildCoroutineNode(coroutineNode, translator, ref currentStateIndex);
                    continue;

                case IfConditionNodeModel ifConditionNodeModel:
                    BuildIfConditionNode(ifConditionNodeModel, translator, currentStateIndex);
                    continue;

                default:
                {
                    var blocks       = translator.BuildNode(node);
                    var currentState = m_States[currentStateIndex];
                    currentState.SkipStateBuilding = currentState.SkipStateBuilding || SkipStateBuilding;
                    currentState.Statements.AddRange(ConvertNodesToSyntaxList(node, blocks, translator.Options));

                    if (!SkipStateBuilding && stack.NodeModels.Last() == node && !HasConnectedStack(stack))
                    {
                        currentState.SkipStateBuilding = true;
                        currentState.Statements.Add(ReturnStatement(
                                                        LiteralExpression(SyntaxKind.FalseLiteralExpression)));
                    }

                    SkipStateBuilding = false;
                    break;
                }
                }
            }

            if (stack.DelegatesOutputsToNode(out _))
            {
                var nextStack = translator.EndStack;
                m_StackExitStrategy = origStackExitStrategy;

                if (translator.EndStack == origEndStack)
                {
                    return;
                }

                translator.EndStack = origEndStack;

                if (nextStack != null)
                {
                    BuildStack(translator, nextStack, m_StackIndexes[nextStack], exitStrategy);
                }

                return;
            }

            foreach (var outputPort in stack.OutputPorts)
            {
                foreach (var connectedStack in outputPort.ConnectionPortModels)
                {
                    if (connectedStack.NodeModel is IStackModel nextStack)
                    {
                        if (!ReferenceEquals(nextStack, translator.EndStack))
                        {
                            BuildStack(translator, nextStack, currentStateIndex, exitStrategy);
                        }
                    }
                }
            }

            m_StackExitStrategy = origStackExitStrategy;
        }
예제 #15
0
 public static IEnumerable <SyntaxNode> BuildReturn(this RoslynEcsTranslator translator, ReturnNodeModel returnModel, IPortModel portModel)
 {
     yield return(ReturnStatement(
                      translator.BuildPort(returnModel.InputPort).FirstOrDefault() as ExpressionSyntax));
 }
예제 #16
0
 public static IEnumerable <SyntaxNode> BuildThisNode(this RoslynEcsTranslator translator, ThisNodeModel model, IPortModel portModel)
 {
     yield return(ThisExpression());
 }
예제 #17
0
 public ReplaceExpressionPorts(RoslynEcsTranslator translator, InlineExpressionNodeModel model)
 {
     m_Translator = translator;
     m_Model      = model;
 }
예제 #18
0
 public abstract TranslationContext PushContext(IIteratorStackModel query, RoslynEcsTranslator roslynEcsTranslator, UpdateMode mode);
 public abstract TranslationContext PushContext(IIteratorStackModel query,
                                                RoslynEcsTranslator roslynEcsTranslator, UpdateMode mode, bool isCoroutine = false);
예제 #20
0
 public CoroutineContext(TranslationContext parent, RoslynEcsTranslator translator)
     : base(parent)
 {
     IterationContext    = parent.IterationContext;
     m_ComponentTypeName = translator.MakeUniqueName($"{IterationContext.GroupName}Coroutine").ToPascalCase();
 }
        void BuildIfConditionNode(IfConditionNodeModel node, RoslynEcsTranslator translator, int stateIndex)
        {
            translator.BuildNode(node);

            var firstThenStack = RoslynTranslator.GetConnectedStack(node, 0);
            var firstElseStack = RoslynTranslator.GetConnectedStack(node, 1);
            var ifState        = m_States[stateIndex];
            var ifIndex        = GetCurrentStateIndex();

            var endStackIndex = 0;

            if (translator.EndStack != null)
            {
                m_StackIndexes.TryGetValue(translator.EndStack, out endStackIndex);
            }

            // Reserve then/else/complete states first
            var       thenIndex = ifIndex;
            var       thenBlock = Block().AddStatements(ReturnStatement(LiteralExpression(SyntaxKind.FalseLiteralExpression)));
            StateData thenState = null;

            if (firstThenStack != null)
            {
                if (firstThenStack == translator.EndStack && endStackIndex != 0)
                {
                    thenBlock = Block().AddStatements(BuildGoToState(endStackIndex));
                }
                else
                {
                    thenIndex += 1;
                    thenState  = RequestNewState();
                    TryAddStackIndex(firstThenStack, thenIndex);
                    thenBlock = Block().AddStatements(BuildGoToState(thenIndex));
                }
            }

            var       elseIndex = thenIndex + 1;
            var       elseBlock = Block().AddStatements(ReturnStatement(LiteralExpression(SyntaxKind.FalseLiteralExpression)));
            StateData elseState = null;

            if (firstElseStack != null)
            {
                if (firstElseStack == translator.EndStack && endStackIndex != 0)
                {
                    elseBlock = Block().AddStatements(BuildGoToState(endStackIndex));
                }
                else
                {
                    elseState = RequestNewState();
                    TryAddStackIndex(firstElseStack, elseIndex);
                    elseBlock = Block().AddStatements(BuildGoToState(elseIndex));
                }
            }

            // Then Build stacks
            ifState.Statements.Add(RoslynBuilder.IfStatement(
                                       translator.BuildPort(node.IfPort).SingleOrDefault(),
                                       thenBlock,
                                       elseBlock)
                                   .WithAdditionalAnnotations(
                                       new SyntaxAnnotation(Annotations.VSNodeMetadata, node.Guid.ToString())));
            ifState.Statements.Add(ReturnStatement(LiteralExpression(SyntaxKind.TrueLiteralExpression)));
            ifState.SkipStateBuilding = true;

            var reserveEndStackState = translator.EndStack != null &&
                                       translator.EndStack != firstElseStack &&
                                       translator.EndStack != firstThenStack &&
                                       endStackIndex == 0;

            if (reserveEndStackState)
            {
                var endState = RequestNewState();
                endState.NextStateIndex = GetNextStateIndex(translator.EndStack);
                TryAddStackIndex(translator.EndStack, GetCurrentStateIndex());
            }

            var origBuiltStacks = translator.BuiltStacks;

            translator.BuiltStacks = new HashSet <IStackModel>(origBuiltStacks);

            if (translator.EndStack != firstThenStack)
            {
                if (translator.EndStack != null && thenState != null)
                {
                    thenState.NextStateIndex = m_StackIndexes[translator.EndStack];
                }
                BuildStack(translator, firstThenStack, thenIndex, StackExitStrategy.Inherit);
            }

            var partialStacks = translator.BuiltStacks;

            translator.BuiltStacks = new HashSet <IStackModel>(origBuiltStacks);

            if (translator.EndStack != firstElseStack)
            {
                if (translator.EndStack != null && elseState != null)
                {
                    elseState.NextStateIndex = m_StackIndexes[translator.EndStack];
                }
                BuildStack(translator, firstElseStack, elseIndex, StackExitStrategy.Inherit);
            }

            translator.BuiltStacks.UnionWith(partialStacks);
        }
        public ClassDeclarationSyntax Build(RoslynTranslator translator, VSGraphModel graphModel)
        {
            var baseClass = m_NeedToCompleteDependenciesFirst ? nameof(ComponentSystem) : nameof(JobComponentSystem);

            m_ClassDeclaration = m_ClassDeclaration.WithBaseList(
                BaseList(
                    SingletonSeparatedList <BaseTypeSyntax>(
                        SimpleBaseType(
                            IdentifierName(baseClass)))));

            foreach (var queryTracking in m_QueryHasStateTracking)
            {
                var trackingMembers = new List <MemberDeclarationSyntax>();
                if (queryTracking.Value.Tracking)
                {
                    trackingMembers.Add(
                        FieldDeclaration(
                            VariableDeclaration(
                                PredefinedType(
                                    Token(SyntaxKind.BoolKeyword)))
                            .WithVariables(
                                SingletonSeparatedList(
                                    VariableDeclarator(
                                        Identifier("Processed")))))
                        .WithModifiers(
                            TokenList(
                                Token(SyntaxKind.InternalKeyword))));
                }

                DeclareComponent <ISystemStateComponentData>(queryTracking.Value.ComponentName, trackingMembers);
            }

            foreach (var eventSystem in m_EventSystems)
            {
                //  ClearEvents<TestEvent2>.Initialize(World);
                InitializationStatements.Add(ExpressionStatement(InvocationExpression(
                                                                     MemberAccessExpression(
                                                                         SyntaxKind.SimpleMemberAccessExpression,
                                                                         GenericName(
                                                                             Identifier("EventSystem"))
                                                                         .WithTypeArgumentList(
                                                                             TypeArgumentList(
                                                                                 SingletonSeparatedList <TypeSyntax>(
                                                                                     IdentifierName(eventSystem.FullName)))),
                                                                         IdentifierName("Initialize")))
                                                                 .WithArgumentList(
                                                                     ArgumentList(
                                                                         SingletonSeparatedList(
                                                                             Argument(
                                                                                 IdentifierName("World")))))));
            }

            if ((TranslationOptions & RoslynEcsTranslator.TranslationOptions.Tracing) != 0)
            {
                DeclareAndInitField(typeof(TracingRecorderSystem), nameof(TracingRecorderSystem), initValue: InvocationExpression(
                                        MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            IdentifierName("World"),
                                            GenericName(
                                                Identifier(nameof(World.GetExistingSystem)))
                                            .WithTypeArgumentList(
                                                TypeArgumentList(
                                                    SingletonSeparatedList <TypeSyntax>(
                                                        IdentifierName(nameof(TracingRecorderSystem))))))));
            }
            HashSet <string> declaredQueries = new HashSet <string>();

            foreach (var group in m_WrittenComponentsPerGroup)
            {
                declaredQueries.Add(group.Key.Query.ComponentQueryDeclarationModel.GetId());
                DeclareEntityQueries(group.Value);
            }

            // declare unused queries in case there's a Count Entities In Query node somewhere
            foreach (var graphVariable in graphModel.GraphVariableModels.OfType <ComponentQueryDeclarationModel>().Where(q => !declaredQueries.Contains(q.GetId())))
            {
                var args = graphVariable.Components.Select(c => SyntaxFactory.Argument(
                                                               InvocationExpression(
                                                                   MemberAccessExpression(
                                                                       SyntaxKind.SimpleMemberAccessExpression,
                                                                       IdentifierName("ComponentType"),
                                                                       GenericName(
                                                                           Identifier("ReadOnly"))
                                                                       .WithTypeArgumentList(
                                                                           TypeArgumentList(
                                                                               SingletonSeparatedList <TypeSyntax>(
                                                                                   IdentifierName(c.Component.TypeHandle.Resolve(graphModel.Stencil)
                                                                                                  .FullName))))))
                                                               ));
                var initValue = MakeInitQueryExpression(args);

                DeclareAndInitField(typeof(EntityQuery), graphVariable.VariableName, initValue: initValue);
            }


            var singletonMembers = new List <FieldDeclarationSyntax>();
            var initArguments    = new List <AssignmentExpressionSyntax>();

            foreach (var graphVariable in graphModel.GraphVariableModels
                     .Where(g => g.VariableType == VariableType.GraphVariable))
            {
                singletonMembers.Add(graphVariable.DeclareField(translator, false)
                                     .WithAdditionalAnnotations(new SyntaxAnnotation(Annotations.VariableAnnotationKind)));
                initArguments.Add(RoslynBuilder.Assignment(
                                      IdentifierName(graphVariable.VariableName),
                                      translator.Constant(graphVariable.InitializationModel.ObjectValue, m_Stencil)));
            }

            if (singletonMembers.Any())
            {
                DeclareComponent <IComponentData>(SingletonComponentTypeName, singletonMembers);
                InitializationStatements.Add(ExpressionStatement(
                                                 RoslynBuilder.MethodInvocation(
                                                     nameof(EntityManager.CreateEntity),
                                                     IdentifierName(nameof(EntityManager)),
                                                     new[]
                {
                    Argument(TypeOfExpression(IdentifierName(SingletonComponentTypeName)))
                },
                                                     Enumerable.Empty <TypeSyntax>())));
                InitializationStatements.Add(
                    ExpressionStatement(
                        RoslynBuilder.MethodInvocation(
                            SafeGuardNamingSystem.SetSingletonName,
                            null,
                            new[]
                {
                    Argument(RoslynBuilder.DeclareNewObject(
                                 IdentifierName(SingletonComponentTypeName),
                                 Enumerable.Empty <ArgumentSyntax>(),
                                 initArguments))
                },
                            Enumerable.Empty <TypeSyntax>())));
            }

            // TODO : Remove this once there is real Systems' dependency tool
            var attributes = new List <AttributeListSyntax>();

            foreach (var assetModel in m_Stencil.UpdateAfter.Where(a => a.GraphModel.Stencil is EcsStencil))
            {
                RegisterAttributes <UpdateAfterAttribute>(attributes, assetModel.Name);
            }

            foreach (var assetModel in m_Stencil.UpdateBefore.Where(a => a.GraphModel.Stencil is EcsStencil))
            {
                RegisterAttributes <UpdateBeforeAttribute>(attributes, assetModel.Name);
            }

            m_ClassDeclaration = m_ClassDeclaration
                                 .AddAttributeLists(attributes.ToArray())
                                 .AddMembers(m_ClassMembers.OrderBy(x => x is FieldDeclarationSyntax ? 0 : 1).ToArray());

            if (m_InitializationStatements != null)
            {
                var onCreateManagerOverride = RoslynBuilder.DeclareMethod(
                    SafeGuardNamingSystem.OnCreateManagerName,
                    AccessibilityFlags.Protected | AccessibilityFlags.Override,
                    typeof(void));
                m_ClassDeclaration = m_ClassDeclaration
                                     .AddMembers(
                    onCreateManagerOverride.WithBody(
                        Block(m_InitializationStatements)));
            }

            if (m_SingletonUpdateSyntax != null)
            {
                AddStatement(m_SingletonUpdateSyntax);
            }

            var onUpdateBlock = Block(m_UpdateStatements);

            return(m_ClassDeclaration.AddMembers(
                       RoslynEcsTranslator.MakeOnUpdateOverride(
                           onUpdateBlock,
                           m_NeedToCompleteDependenciesFirst,
                           m_CreatedManagers)));
        }
예제 #23
0
 public override TranslationContext PushContext(IIteratorStackModel query, RoslynEcsTranslator roslynEcsTranslator, UpdateMode mode)
 {
     return(new ForEachContext(query, this, mode));
 }
        protected override IEnumerable <StatementSyntax> OnPopContext()
        {
            var syntax = RoslynEcsTranslator.MakeCondition(m_BodyConditions, BuildInner());

            yield return(AddMissingEventBuffers(IterationContext, syntax));
        }
 public void BuildCriteria(RoslynEcsTranslator translator, TranslationContext context, ExpressionSyntax entity,
                           IEnumerable <CriteriaModel> criteriaModels)
 {
     this.BuildCriteria(translator, context, entity, criteriaModels, ReturnStatement());
 }
        public static IEnumerable <SyntaxNode> BuildVariable(this RoslynEcsTranslator translator, IVariableModel v, IPortModel portModel)
        {
            if (v is IConstantNodeModel model)
            {
                if (model.ObjectValue != null)
                {
                    yield return(translator.Constant(model.ObjectValue, translator.Stencil, model.Type));
                }

                yield break;
            }

            if (translator.InMacro.Count > 0 && v.DeclarationModel.VariableType == VariableType.GraphVariable && v.DeclarationModel.Modifiers == ModifierFlags.ReadOnly)
            {
                MacroRefNodeModel oldValue = translator.InMacro.Pop();

                var syntaxNodes = translator.BuildPort(oldValue.InputsById[v.DeclarationModel.VariableName]);
                translator.InMacro.Push(oldValue);
                foreach (var syntaxNode in syntaxNodes)
                {
                    yield return(syntaxNode);
                }
                yield break;
            }

            switch (v.DeclarationModel.VariableType)
            {
            case VariableType.GraphVariable:
                yield return(translator.context.GetSingletonVariable(v.DeclarationModel));

                break;

            case VariableType.FunctionVariable:
            case VariableType.ComponentQueryField:
                yield return(RoslynBuilder.LocalVariableReference(v.DeclarationModel.VariableName));

                break;

            case VariableType.FunctionParameter:
                var variableDeclarationModel = v.DeclarationModel;
                if (variableDeclarationModel.IsGeneratedEcsComponent(out var groupDeclaration))
                {
                    var relevantContext = translator.FindContext(groupDeclaration);
                    if (relevantContext == null)
                    {
                        var variableName = v.DeclarationModel.Name;
                        translator.AddError(v, $"Could not find a matching component query for variable \"{variableName}\"");
                        throw new InvalidOperationException("No matching translation context for Declaration");
                    }
                    translator.context.RecordComponentAccess(relevantContext, v.DeclarationModel.DataType, translator.IsRecordingComponentAccesses);
                    yield return(RoslynBuilder.ArgumentReference(translator.context.GetComponentVariableName(groupDeclaration, variableDeclarationModel.DataType)));
                }
                else
                {
                    if (variableDeclarationModel.IsGeneratedEntity())
                    {
                        translator.context.RecordEntityAccess(variableDeclarationModel);
                    }
                    yield return(RoslynBuilder.ArgumentReference(variableDeclarationModel.VariableName));
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }