protected virtual string GetNodeAttributes(ExecutionTreeNode node) { var attr = string.Format("shape=record,label=\"State:{0}", node.State.Id); if (node.CreatedAt != null) { attr += string.Format("\\nCreated at line {0}\\n{1}", node.CreatedAt.LineNumber, node.CreatedAt.ToString()); } bool terminated = (node.ChildrenCount == 0) && node.State.TerminationType != null; if (terminated) { // FIXME: Fix trailing \n properly attr += "\\nTermination:" + EscapeLabelText(node.State.TerminationType.GetMessage().TrimEnd('\n')); } // Close label attr += "\""; if (terminated) { attr += ",style=filled, fillcolor="; if (node.State.TerminationType is TerminatedWithoutError) { attr += "\"green\""; } else { attr += "\"red\""; } } return(attr); }
protected virtual void PrintNode(TextWriter TW, ExecutionTreeNode node) { // Declare node TW.Write("{0} [", GetNodeID(node)); // Write node attributes TW.Write(GetNodeAttributes(node)); TW.WriteLine("];"); if (node.ChildrenCount == 0) { return; } // Visit Children for (int index = 0; index < node.ChildrenCount; ++index) { PrintNode(TW, node.GetChild(index)); } // Write edges. We can do this now because all child nodes have been declared TW.WriteLine(""); for (int index = 0; index < node.ChildrenCount; ++index) { TW.WriteLine("{0} -> {1};", GetNodeID(node), GetNodeID(node.GetChild(index))); } }
public ExecutionTreePrinter(ExecutionTreeNode root, int indent = 2) { Debug.Assert(indent >= 0, "Indent cannot be negative"); Debug.Assert(root != null, "root cannot be null"); this.Root = root; this.Indent = indent; }
protected override void PrintAdditionalEdges(TextWriter TW, ExecutionTreeNode root) { int counter = 0; TW.WriteLine("/* Context changes */"); foreach (var pair in this.ContextChanges) { TW.WriteLine("{0} -> {1} [color=red, label=\"{2}\"];", GetNodeID(pair.Item1), GetNodeID(pair.Item2), counter); ++counter; } }
protected virtual void PrintNodeRankings(TextWriter TW, ExecutionTreeNode root) { TW.WriteLine("/* Node rankings to enforce tree structure */"); // Use BFS to group all nodes at the same depth together var queue = new Queue <ExecutionTreeNode>(); int currentDepth = root.State.ExplicitBranchDepth - 1; // This forces the first creation of a new level bool isFirst = true; queue.Enqueue(root); while (queue.Count > 0) { var node = queue.Dequeue(); if (node.Depth > currentDepth) { currentDepth = node.Depth; if (!isFirst) { PopIndent(TW); TW.WriteLine("}"); } TW.WriteLine("{"); PushIndent(TW); TW.WriteLine("rank=same;"); isFirst = false; } // Output this node TW.WriteLine(GetNodeID(node) + ";"); // Add its children for (int index = 0; index < node.ChildrenCount; ++index) { queue.Enqueue(node.GetChild(index)); } } // emit last closing brace if we created at least one. if (!isFirst) { PopIndent(TW); TW.WriteLine("}"); } }
public ExecutionTreeNode(ExecutionState self, ExecutionTreeNode parent, ProgramLocation createdAt) { Debug.Assert(self != null, "self cannot be null!"); this.State = self; if (parent == null) { this.Parent = null; } else { this.Parent = parent; // Add this as a child of the parent this.Parent.AddChild(this); } this.Depth = self.ExplicitBranchDepth; this.CreatedAt = createdAt; Children = new List <ExecutionTreeNode>(); // Should we lazily create this? }
public void AddChild(ExecutionTreeNode node) { Debug.Assert(node != null, "Child cannot be null"); Debug.Assert(node != this, "Cannot have cycles"); Children.Add(node); }
protected virtual string GetNodeID(ExecutionTreeNode node) { var id = string.Format("S{0}_{1}", (node.State.Id < 0)?("m" + (node.State.Id * -1).ToString()):node.State.Id.ToString(), node.Depth); return(id); }
protected virtual void PrintAdditionalEdges(TextWriter TW, ExecutionTreeNode root) { // For clients to override }
public ExecutionTreePrinterWithContextChanges(ExecutionTreeNode root, int indent, IList <Tuple <ExecutionTreeNode, ExecutionTreeNode> > contextChanges) : base(root, indent) { this.ContextChanges = contextChanges; }