/// <summary>
        /// Removed error/continue edges which we know cannot happen due to type info
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="types"></param>
        /// <returns></returns>
        public static IControlFlowGraph TypeDrivenEdgeTrimming(this IControlFlowGraph graph, ITypeAssignments types)
        {
            return(graph.Trim(edge => {
                // Find last statement in previous block
                var stmt = edge.Start.Statements.LastOrDefault();
                var tass = stmt as TypedAssignment;
                var err = stmt as ErrorStatement;

                // If type is unassigned we can't make a judgement
                if (tass?.Type == Execution.Type.Unassigned)
                {
                    return true;
                }

                if (edge.Type == EdgeType.RuntimeError)
                {
                    // If it's an error statement keep it
                    if (err != null)
                    {
                        return true;
                    }

                    // If there is no statement at all then it can't be an error
                    if (tass == null)
                    {
                        return false;
                    }

                    // Only keep edge if type has an error
                    return tass.Type.HasFlag(Execution.Type.Error);
                }
                else
                {
                    // If it's an error statement remove it
                    if (err != null)
                    {
                        return false;
                    }

                    // If there is no typed assignment we can't judge
                    if (tass == null)
                    {
                        return true;
                    }

                    return tass.Type != Execution.Type.Error;
                }
            }));
        }
        /// <summary>
        /// Remove blocks that cannot be reached from the entry node
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        public static IControlFlowGraph RemoveUnreachableBlocks(this IControlFlowGraph graph)
        {
            var reachable = new HashSet <IBasicBlock>();
            var queue     = new Queue <IBasicBlock>();

            void Mark(IBasicBlock block)
            {
                if (reachable.Add(block))
                {
                    foreach (var edge in block.Outgoing)
                    {
                        queue.Enqueue(edge.End);
                    }
                }
            }

            queue.Enqueue(graph.Vertices.Single(v => v.Type == BasicBlockType.Entry));
            while (queue.Count > 0)
            {
                Mark(queue.Dequeue());
            }

            return(graph.Trim(reachable.Contains));
        }