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; } }
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; }