/// <summary> /// Builds a basic block from the provided bound block statement and adds /// it to the list of known blocks. /// </summary> /// <param name="block">The bound block statement.</param> /// <returns>A basic block.</returns> public List <BasicBlock> Build(BoundBlockStatement block) { foreach (var statement in block.Statements) { switch (statement.Kind) { case BoundNodeKind.LabelStatement: StartBlock(); statements.Add(statement); break; case BoundNodeKind.GotoStatement: case BoundNodeKind.ConditionalGotoStatement: case BoundNodeKind.ReturnStatement: statements.Add(statement); StartBlock(); break; case BoundNodeKind.VariableDeclaration: case BoundNodeKind.ExpressionStatement: statements.Add(statement); break; default: throw new Exception($"Unexpected statement: {statement.Kind}"); } } EndBlock(); return(blocks.ToList()); }
/// <summary> /// Rewrites a block statement. /// </summary> /// <param name="node">The block statement to rewrite.</param> /// <returns>The rewritten block statement.</returns> protected virtual BoundStatement RewriteBlockStatement(BoundBlockStatement node) { ImmutableArray <BoundStatement> .Builder builder = null; for (var i = 0; i < node.Statements.Length; i++) { var oldStatement = node.Statements[i]; var newStatement = RewriteStatement(oldStatement); if (newStatement != oldStatement) { if (builder == null) { builder = ImmutableArray.CreateBuilder <BoundStatement>(node.Statements.Length); for (var j = 0; j < i; j++) { builder.Add(node.Statements[j]); } } } if (builder != null) { builder.Add(newStatement); } } if (builder == null) { return(node); } return(new BoundBlockStatement(builder.MoveToImmutable())); }
/// <summary> /// Creates a control flow graph from the provided bound block statement. /// </summary> /// <param name="body">The bound block statement.</param> /// <returns>The control flow graph.</returns> public static ControlFlowGraph Create(BoundBlockStatement body) { var basicBlockBuilder = new BasicBlockBuilder(); var blocks = basicBlockBuilder.Build(body); var graphBuilder = new GraphBuilder(); return(graphBuilder.Build(blocks)); }
/// <summary> /// Initializes a new instance of the <see cref="BoundProgram"/> class. /// </summary> /// <param name="packageName">The package name.</param> /// <param name="diagnostics">The diagnostics.</param> /// <param name="functions">The functions.</param> /// <param name="statement">The statements.</param> public BoundProgram( string packageName, ImmutableArray <Diagnostic> diagnostics, ImmutableDictionary <FunctionSymbol, BoundBlockStatement> functions, BoundBlockStatement statement) { PackageName = packageName; Diagnostics = diagnostics; Functions = functions; Statement = statement; }
/// <summary> /// Reports whether all paths in a bound block statement return or not. /// </summary> /// <param name="body">The bound block statement.</param> /// <returns>Whether all its paths return or not.</returns> public static bool AllPathsReturn(BoundBlockStatement body) { var graph = Create(body); foreach (var branch in graph.End.Incoming) { var lastStatement = branch.From.Statements.LastOrDefault(); if (lastStatement == null || lastStatement.Kind != BoundNodeKind.ReturnStatement) { return(false); } } return(true); }
private static void WriteBlockStatement(BoundBlockStatement node, IndentedTextWriter writer) { writer.WritePunctuation(SyntaxKind.OpenBraceToken); writer.WriteLine(); writer.Indent++; foreach (var s in node.Statements) { s.WriteTo(writer); } writer.Indent--; writer.WritePunctuation(SyntaxKind.CloseBraceToken); writer.WriteLine(); }