summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/GraphVisualizer.java')
-rw-r--r--src/main/java/com/seaofnodes/simple/GraphVisualizer.java71
1 files changed, 39 insertions, 32 deletions
diff --git a/src/main/java/com/seaofnodes/simple/GraphVisualizer.java b/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
index f5fa1350..de6d65a3 100644
--- a/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
+++ b/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
@@ -1,10 +1,11 @@
package com.seaofnodes.simple;
-import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.node.*;
import java.util.*;
+import static com.seaofnodes.simple.Utils.TODO;
+
/**
* Simple visualizer that outputs GraphViz dot format.
* The dot output must be saved to a file and run manually via dot to generate the SVG output.
@@ -80,7 +81,7 @@ public class GraphVisualizer {
// Just the Nodes first, in a cluster no edges
sb.append(doCtrl ? "\tsubgraph cluster_Controls {\n" : "\tsubgraph cluster_Nodes {\n"); // Magic "cluster_" in the subgraph name
for (Node n : all) {
- if (n instanceof ProjNode || n instanceof CProjNode || n instanceof ScopeNode || n==Parser.XCTRL)
+ if (n instanceof ProjNode || n instanceof CProjNode || n instanceof ScopeMinNode || n==Parser.XCTRL)
continue; // Do not emit, rolled into MultiNode or Scope cluster already
if( _separateControlCluster && doCtrl && !(n instanceof CFGNode) ) continue;
if( _separateControlCluster && !doCtrl && (n instanceof CFGNode) ) continue;
@@ -154,26 +155,34 @@ public class GraphVisualizer {
// Build a nested scope display, walking the _prev edge
private void scope( StringBuilder sb, ScopeNode scope ) {
sb.append("\tnode [shape=plaintext];\n");
- int level=1;
- for( int idx = scope._idxs.size()-1; idx>=0; idx-- ) {
- var syms = scope._idxs.get(idx);
+ int last = scope.nIns();
+ int max = scope._lexSize.size();
+ for( int i = 0; i < max; i++ ) {
+ int level = max-i-1;
String scopeName = makeScopeName(scope, level);
sb.append("\tsubgraph cluster_").append(scopeName).append(" {\n"); // Magic "cluster_" in the subgraph name
+ // Special for memory ScopeMinNode
+ if( level==0 ) {
+ ScopeMinNode n = scope.mem();
+ sb.append("\t\t").append(n.uniqueName()).append(" [label=\"").append(n.glabel()).append("\"];\n");
+ }
sb.append("\t\t").append(scopeName).append(" [label=<\n");
sb.append("\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n");
// Add the scope level
- int scopeLevel = scope._idxs.size()-level;
- sb.append("\t\t\t<TR><TD BGCOLOR=\"cyan\">").append(scopeLevel).append("</TD>");
- for(String name: syms.keySet())
- sb.append("<TD PORT=\"").append(makePortName(scopeName, name)).append("\">").append(name).append("</TD>");
+ sb.append("\t\t\t<TR><TD BGCOLOR=\"cyan\">").append(level).append("</TD>");
+ int lexStart=scope._lexSize.at(level);
+ for( int j=lexStart; j<last; j++ ) {
+ var v = scope._vars.at(j);
+ sb.append("<TD PORT=\"").append(makePortName(scopeName, v._name)).append("\">").append(v._name).append("</TD>");
+ }
+ last = lexStart;
sb.append("</TR>\n");
sb.append("\t\t\t</TABLE>>];\n");
- level++;
}
// Scope clusters nest, so the graphics shows the nested scopes, so
// they are not closed as they are printed; so they just keep nesting.
// We close them all at once here.
- sb.append( "\t}\n".repeat( level-1 ) ); // End all Scope clusters
+ sb.append( "\t}\n".repeat( max ) ); // End all Scope clusters
}
private String makeScopeName(ScopeNode sn, int level) { return sn.uniqueName() + "_" + level; }
@@ -229,27 +238,25 @@ public class GraphVisualizer {
// Walk the scope edges
private void scopeEdges( StringBuilder sb, ScopeNode scope ) {
sb.append("\tedge [style=dashed color=cornflowerblue];\n");
- int level=1;
- for( int i = scope._idxs.size()-1; i>=0; i-- ) {
- var syms = scope._idxs.get(i);
- String scopeName = makeScopeName(scope, level);
- for( String name : syms.keySet() ) {
- int idx = syms.get(name);
- Node def = scope.in(idx);
- while( def instanceof ScopeNode lazy )
- def = lazy.in(idx);
- if( def==null ) continue;
- sb.append("\t")
- .append(scopeName).append(":")
- .append('"').append(makePortName(scopeName, name)).append('"') // wrap port name with quotes because $ctrl is not valid unquoted
- .append(" -> ");
- if( def instanceof CProjNode proj ) {
- String mname = proj.ctrl().uniqueName();
- sb.append(mname).append(":p").append(proj._idx);
- } else sb.append(def.uniqueName());
- sb.append(";\n");
- }
- level++;
+ int level=0;
+ for( var v : scope._vars ) {
+ Node def = scope.in(v._idx);
+ while( def instanceof ScopeNode lazy )
+ def = lazy.in(v._idx);
+ if( def==null ) continue;
+ while( level < scope._lexSize.size() && v._idx >= scope._lexSize.at(level) )
+ level++;
+ String scopeName = makeScopeName(scope, level-1);
+ sb.append("\t")
+ .append(scopeName).append(":")
+ .append('"').append(makePortName(scopeName, v._name)).append('"') // wrap port name with quotes because $ctrl is not valid unquoted
+ .append(" -> ");
+ if( def instanceof CProjNode proj ) {
+ sb.append(def.in(0).uniqueName()).append(":p").append(proj._idx);
+ } else if( def instanceof ProjNode proj ) {
+ sb.append(def.in(0).uniqueName()).append(":p").append(proj._idx);
+ } else sb.append(def.uniqueName());
+ sb.append(";\n");
}
}