Beispiel #1
0
        public override void BuildStack(IStackModel stack, ref BlockSyntax block,
                                        StackExitStrategy exitStrategy = StackExitStrategy.Return)
        {
            switch (stack)
            {
            case null:
                return;

            case IIteratorStackModel iteratorStack when iteratorStack.ContainsCoroutine():
                BuildCoroutineStack(iteratorStack, ref block);

                return;

            default:
                base.BuildStack(stack, ref block, exitStrategy);
                break;
            }
        }
Beispiel #2
0
        public virtual void BuildStack(IStackModel stack, ref BlockSyntax blockNode,
                                       StackExitStrategy exitStrategy = StackExitStrategy.Return)
        {
            if (stack == null || stack.State == ModelState.Disabled)
            {
                return;
            }

            RegisterBuiltStack(stack);

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

            StackExitStrategy origStackExitStrategy = m_StackExitStrategy;

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

//            Debug.Log($"Build stack {stack}");
            // m_EndStack might get changed by recursive BuildNode() calls
            StackBaseModel origEndStack = EndStack;
            var            statements   = new List <StatementSyntax>();

            foreach (var statement in stack.NodeModels)
            {
                if (statement.State == ModelState.Disabled)
                {
                    continue;
                }
                var syntaxNodes = BuildNode(statement);
                foreach (var syntaxNode in syntaxNodes)
                {
                    switch (syntaxNode)
                    {
                    case StatementSyntax statementNode:
                        statements.Add(statementNode);
                        break;

                    case ExpressionSyntax expressionNode:
                        statements.Add(ExpressionStatement(expressionNode)
                                       .WithAdditionalAnnotations(new SyntaxAnnotation(Annotations.AnnotationKind,
                                                                                       statement.Guid.ToString()))
                                       );
                        break;

                    default:
                        throw new InvalidOperationException($"Expected a statement or expression node, found a {syntaxNode.GetType()} when building {statement}");
                    }
                }
            }

            blockNode = blockNode.AddStatements(statements.ToArray());

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

//                Debug.Log($"Stack {stack} delegates ports. nextStack {nextStack} origEndStack {origEndStack}");

                // if a nested node changed the end stack, but found the same common descendant,
                // let the parent call handle it
                if (EndStack == origEndStack)
                {
                    return;
                }

                EndStack = origEndStack;
                BuildStack(nextStack, ref blockNode, exitStrategy);

                return;
            }

            bool anyConnection = false;

            foreach (var outputPort in stack.OutputPorts)
            {
                foreach (var connectedStack in outputPort.ConnectionPortModels)
                {
                    if (connectedStack.NodeModel is IStackModel nextStack)
                    {
                        anyConnection = true;
                        if (!ReferenceEquals(nextStack, EndStack))
                        {
                            BuildStack(nextStack, ref blockNode, StackExitStrategy.Inherit);
                        }
                    }
                }
            }


            // TODO use function default return value
            StatementSyntax lastStatementSyntax = blockNode.Statements.LastOrDefault();

            if (!anyConnection && !(lastStatementSyntax is ReturnStatementSyntax) && !(lastStatementSyntax is ContinueStatementSyntax))
            {
                //TODO we had that for a reason
//                lastStatementSyntax = StatementFromExitStrategy(m_StackExitStrategy, null);

//                if(lastStatementSyntax != null)
//                    blockNode = blockNode.AddStatements(lastStatementSyntax);
            }

            m_StackExitStrategy = origStackExitStrategy;
        }
        public virtual void BuildStack(IStackModel stack, ref BlockSyntax blockNode,
                                       StackExitStrategy exitStrategy = StackExitStrategy.Return)
        {
            if (stack == null || stack.State == ModelState.Disabled)
            {
                return;
            }

            RegisterBuiltStack(stack);

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

            StackExitStrategy origStackExitStrategy = m_StackExitStrategy;

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

            //            Debug.Log($"Build stack {stack}");
            // m_EndStack might get changed by recursive BuildNode() calls
            StackBaseModel origEndStack = EndStack;
            var            statements   = new List <StatementSyntax>();

            foreach (var statement in stack.NodeModels)
            {
                if (statement.State == ModelState.Disabled)
                {
                    continue;
                }
                var syntaxNodes = BuildNode(statement);
                foreach (var syntaxNode in syntaxNodes)
                {
                    StatementSyntax resultingStatement;
                    switch (syntaxNode)
                    {
                    case StatementSyntax statementNode:
                        resultingStatement = statementNode;
                        break;

                    case ExpressionSyntax expressionNode:
                        resultingStatement = ExpressionStatement(expressionNode);
                        break;

                    default:
                        throw new InvalidOperationException($"Expected a statement or expression node, found a {syntaxNode.GetType()} when building {statement}");
                    }

                    // TODO: RecordValue codegen counter instead of counting them after the fact
                    if ((Options & UnityEngine.Modifier.VisualScripting.CompilationOptions.Tracing) != 0)
                    {
                        var recordValueCount    = syntaxNode.GetAnnotations(Annotations.RecordValueCountKind).FirstOrDefault();
                        int recordedValuesCount = recordValueCount == null
                            ? syntaxNode.GetAnnotatedNodes(Annotations.RecordValueKind).Count()
                            : int.Parse(recordValueCount.Data);

                        statements.Add(InstrumentForInEditorDebugging.BuildLastCallFrameExpression(recordedValuesCount, statement.Guid, this.GetRecorderName()));
                    }
                    statements.Add(resultingStatement);
                }
            }

            blockNode = blockNode.AddStatements(statements.ToArray());

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

                //                Debug.Log($"Stack {stack} delegates ports. nextStack {nextStack} origEndStack {origEndStack}");

                // if a nested node changed the end stack, but found the same common descendant,
                // let the parent call handle it
                if (EndStack == origEndStack)
                {
                    return;
                }

                EndStack = origEndStack;
                BuildStack(nextStack, ref blockNode, exitStrategy);

                return;
            }

            bool anyConnection = false;

            foreach (var outputPort in stack.OutputPorts)
            {
                foreach (var connectedStack in outputPort.ConnectionPortModels)
                {
                    if (connectedStack.NodeModel is IStackModel nextStack)
                    {
                        anyConnection = true;
                        if (!ReferenceEquals(nextStack, EndStack))
                        {
                            BuildStack(nextStack, ref blockNode, StackExitStrategy.Inherit);
                        }
                    }
                }
            }


            // TODO use function default return value
            StatementSyntax lastStatementSyntax = blockNode.Statements.LastOrDefault();

            if (!anyConnection && !(lastStatementSyntax is ReturnStatementSyntax) && !(lastStatementSyntax is ContinueStatementSyntax))
            {
                //TODO we had that for a reason
                //                lastStatementSyntax = StatementFromExitStrategy(m_StackExitStrategy, null);

                //                if(lastStatementSyntax != null)
                //                    blockNode = blockNode.AddStatements(lastStatementSyntax);
            }

            m_StackExitStrategy = origStackExitStrategy;
        }
        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;
        }