public IEnumerator MovingThenStackDoesntMoveElseOrConditionStacks([Values] TestingMode mode) { var stackModel0 = GraphModel.CreateStack(string.Empty, new Vector2(-100, -100)); IfConditionNodeModel conditionNodeModel = stackModel0.CreateStackedNode <IfConditionNodeModel>("cond"); var thenStack = GraphModel.CreateStack(string.Empty, new Vector2(100, 100)); var elseStack = GraphModel.CreateStack(string.Empty, new Vector2(200, 100)); var joinStack = GraphModel.CreateStack(string.Empty, new Vector2(-100, 200)); GraphModel.CreateEdge(thenStack.InputPorts.First(), conditionNodeModel.ThenPort); GraphModel.CreateEdge(joinStack.InputPorts.First(), thenStack.OutputPorts.First()); GraphModel.CreateEdge(joinStack.InputPorts.First(), elseStack.OutputPorts.First()); yield return(TestMove(mode, mouseDelta: new Vector2(20, 10), movedNodes: new INodeModel[] { thenStack }, expectedMovedDependencies: new INodeModel[] { joinStack }, expectedUnmovedDependencies: new INodeModel[] { stackModel0, elseStack } )); }
// create a function bool IsIntEven(int i) // if ((i % 2) == 0) { return true; } else { return false; } // the goal is to have 2 different return nodes depending on a parameter FunctionModel CreateIsIntEvenFunction() { // define function FunctionModel method = GraphModel.CreateFunction("IsIntEven", Vector2.zero); method.ReturnType = typeof(bool).GenerateTypeHandle(GraphModel.Stencil); VariableDeclarationModel paramI = method.CreateAndRegisterFunctionParameterDeclaration("i", typeof(int).GenerateTypeHandle(GraphModel.Stencil)); // add if/then/else structure IfConditionNodeModel if0 = CreateIfThenElseStacks(method, out var then0, out var else0); // if (i % 2 == 0) var binOpNode = GraphModel.CreateBinaryOperatorNode(BinaryOperatorKind.Modulo, Vector2.zero); IVariableModel varI = GraphModel.CreateVariableNode(paramI, Vector2.left); var const2 = CreateConstantIntNode(2); GraphModel.CreateEdge(binOpNode.InputPortA, varI.OutputPort); GraphModel.CreateEdge(binOpNode.InputPortB, const2.OutputPort); var equalNode = GraphModel.CreateBinaryOperatorNode(BinaryOperatorKind.Equals, Vector2.zero); var const0 = CreateConstantIntNode(0); GraphModel.CreateEdge(equalNode.InputPortA, binOpNode.OutputPort); GraphModel.CreateEdge(equalNode.InputPortB, const0.OutputPort); GraphModel.CreateEdge(if0.IfPort, equalNode.OutputPort); // then return true var returnTrue = then0.CreateStackedNode <ReturnNodeModel>("return true"); var constTrue = CreateConstantBoolNode(true); GraphModel.CreateEdge(returnTrue.InputPort, constTrue.OutputPort); // else return false var returnFalse = else0.CreateStackedNode <ReturnNodeModel>("return false"); var constFalse = CreateConstantBoolNode(false); GraphModel.CreateEdge(returnFalse.InputPort, constFalse.OutputPort); return(method); }
public static IEnumerable <SyntaxNode> BuildIfCondition(this RoslynTranslator translator, IfConditionNodeModel statement, IPortModel portModel) { // this enables more elegant code generation with no duplication // if() { then(); } else { else(); } // codeAfterIf(); // instead of duplicating the code after the if in each branch // find first stack reachable from both then/else stacks var endStack = RoslynTranslator.FindConnectedStacksCommonDescendant(statement); if (endStack != null) { // building the branches will stop at the common descendant translator.EndStack = endStack; // Debug.Log($"If in stack {statement.parentStackModel} Common descendant: {endStack}"); } // ie. follow outputs, find all stacks with multiple inputs, compare them until finding the common one if it exists // BuildStack checks the m_EndStack field, returning when recursing on it // the parent buildStack call will then continue on this end stack StatementSyntax syntax = null; // construct multiple if else if else ... from right to left, starting with the last else foreach (var conditionWithAction in statement.ConditionsWithActionsPorts.Reverse()) { var stack = RoslynTranslator.GetConnectedStack(conditionWithAction.Action); BlockSyntax block = SyntaxFactory.Block(); if (endStack == null || endStack != stack) // stop before the end stack { translator.BuildStack(stack, ref block, StackExitStrategy.Inherit); } if (conditionWithAction.Condition == null) // last else { syntax = block; } else // if = if() { current statement } else { prev statement that might be an if } { var condition = (ExpressionSyntax)translator.BuildPort(conditionWithAction.Condition).SingleOrDefault(); syntax = SyntaxFactory.IfStatement(condition, block) .WithElse(SyntaxFactory.ElseClause(syntax)); } } yield return(syntax); }
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); }
public static GraphElement CreateIfConditionNode(this INodeBuilder builder, Store store, IfConditionNodeModel model) { return(new IfConditionNode(model, store, builder.GraphView)); }
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); }