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 firstThenStack = RoslynTranslator.GetConnectedStack(statement, 0); var firstElseStack = RoslynTranslator.GetConnectedStack(statement, 1); var endStack = RoslynTranslator.FindCommonDescendant(statement.ParentStackModel, firstThenStack, firstElseStack); 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 var origBuiltStacks = translator.BuiltStacks; translator.BuiltStacks = new HashSet <IStackModel>(origBuiltStacks); HashSet <IStackModel> partialStacks = new HashSet <IStackModel>(); 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)); } partialStacks.UnionWith(translator.BuiltStacks); translator.BuiltStacks = new HashSet <IStackModel>(origBuiltStacks); } translator.BuiltStacks = partialStacks; 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); }