private static void WriteConditionalGotoStatement(BoundConditionalGotoStatement node, IndentedTextWriter writer) { writer.WriteKeyword("goto"); writer.WriteWhiteSpace(); writer.WriteIdentifier(node.Label.Name); writer.WriteWhiteSpace(); writer.WriteKeyword(node.JumpIfTrue ? "if" : "unless"); writer.WriteWhiteSpace(); node.Condition.WriteTo(writer); writer.WriteLine(); }
public ControlFlowGraph Build(List <BasicBlock> blocks) { if (!blocks.Any()) { Connect(start, end); } else { Connect(start, blocks.First()); } foreach (BasicBlock block in blocks) { foreach (var statement in block.Statements) { blockFromStatement.Add(statement, block); if (statement is BoundLabelStatement labelStatement) { blockFromLabel.Add(labelStatement.Label, block); } } } for (int i = 0; i < blocks.Count; i++) { BasicBlock current = blocks[i]; var next = i == blocks.Count - 1 ? end : blocks[i + 1]; foreach (var statement in current.Statements) { bool isLastStatementInBlock = statement == current.Statements.Last(); switch (statement.Kind) { case BoundNodeKind.GotoStatement: BoundGotoStatement gs = (BoundGotoStatement)statement; BasicBlock toBlock = blockFromLabel[gs.Label]; Connect(current, toBlock); break; case BoundNodeKind.ConditionalGotoStatement: BoundConditionalGotoStatement cgs = (BoundConditionalGotoStatement)statement; BasicBlock themBlock = blockFromLabel[cgs.Label]; BasicBlock elseBlock = next; BoundExpression negatedCondition = Negate(cgs.Condition); BoundExpression thenCondition = cgs.JumpIfTrue ? cgs.Condition: negatedCondition; BoundExpression elseCondition = cgs.JumpIfTrue ? negatedCondition: cgs.Condition; Connect(current, themBlock, thenCondition); Connect(current, elseBlock, elseCondition); break; case BoundNodeKind.ReturnStatement: Connect(current, end); break; case BoundNodeKind.LabelStatement: case BoundNodeKind.VariableDeclaration: case BoundNodeKind.ExpressionStatement: if (isLastStatementInBlock) { Connect(current, next); } break; default: throw new Exception($"Unexpected statemend: '{statement.Kind}'."); } } } ScanAgain: foreach (BasicBlock block in blocks) { if (!block.Incoming.Any()) { RemoveBlock(blocks, block); goto ScanAgain; } } blocks.Insert(0, start); blocks.Add(end); return(new ControlFlowGraph(start, end, blocks, branches)); }