summaryrefslogtreecommitdiff
path: root/chapter04
diff options
context:
space:
mode:
Diffstat (limited to 'chapter04')
-rw-r--r--chapter04/Makefile11
-rw-r--r--chapter04/README.md4
-rw-r--r--chapter04/docs/04-grammar.md4
-rw-r--r--chapter04/docs/04-post-peephole.gv2
-rw-r--r--chapter04/docs/04-pre-peephole.gv2
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/GraphVisualizer.java212
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/Parser.java19
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/node/AddNode.java2
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/node/BoolNode.java3
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/node/DivNode.java2
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/node/MinusNode.java2
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/node/MulNode.java2
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/node/Node.java6
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/node/NotNode.java2
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/node/SubNode.java2
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/print/JSViewer.java26
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java2
-rw-r--r--chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java26
-rw-r--r--chapter04/src/test/java/com/seaofnodes/simple/Chapter02Test.java4
-rw-r--r--chapter04/src/test/java/com/seaofnodes/simple/Chapter03Test.java4
-rw-r--r--chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java20
21 files changed, 44 insertions, 313 deletions
diff --git a/chapter04/Makefile b/chapter04/Makefile
index 931ad8ef..060e0cfd 100644
--- a/chapter04/Makefile
+++ b/chapter04/Makefile
@@ -36,10 +36,7 @@ CLZDIR:= build/classes
main_javas := $(wildcard $(SRC)/$(SIMPLE)/*java $(SRC)/$(SIMPLE)/*/*java)
test_javas := $(wildcard $(TST)/$(SIMPLE)/*java $(TST)/$(SIMPLE)/*/*java)
main_classes := $(patsubst $(SRC)/%java,$(CLZDIR)/main/%class,$(main_javas))
-# Compile the common adapter into this chapter without copying its sources.
-GRAPH_DIR := $(firstword $(wildcard ../graph graph))
-graph_javas := $(wildcard $(GRAPH_DIR)/src/main/java/com/seaofnodes/graph/*.java)
-main_javas += $(graph_javas)
+include $(firstword $(wildcard ../graph/graph.mk graph/graph.mk))
test_classes := $(patsubst $(TST)/%java,$(CLZDIR)/test/%class,$(test_javas))
test_cp := $(patsubst $(TST)/$(SIMPLE)/%.java,com.seaofnodes.simple.%,$(wildcard $(TST)/$(SIMPLE)/*Test.java))
classes = $(main_classes) $(test_classes)
@@ -81,10 +78,6 @@ fuzzer: $(default_targets)
@echo "fuzzing " $(test_cp)
@$(JVM) org.junit.runner.JUnitCore com.seaofnodes.simple.FuzzerWrap
-.PHONY: view
-view: build
- java -ea -cp "$(CLZDIR)/main" com.seaofnodes.simple.print.JSViewer
-
.PHONY: clean
clean:
@@ -109,4 +102,4 @@ tags: $(main_javas) $(test_javas)
@rm -f TAGS
@$(CTAGS) -e --recurse=yes --extra=+q --fields=+fksaiS $(SRC) $(TST)
-include ../build-support/chapter-release.mk
+include $(firstword $(wildcard ../build-support/chapter-release.mk build-support/chapter-release.mk))
diff --git a/chapter04/README.md b/chapter04/README.md
index 272d0b8d..2c7f7e9c 100644
--- a/chapter04/README.md
+++ b/chapter04/README.md
@@ -108,7 +108,7 @@ tests can (and do) pass in other integer values by calling `new Parser` with
an argument:
```java
-Parser parser = new Parser("return arg; #showGraph;", TypeInteger.constant(2));
+Parser parser = new Parser("return arg; ", TypeInteger.constant(2));
```
The graph:
@@ -151,7 +151,7 @@ public final Node peephole( ) {
If you don't pass an argument you get `TypeInteger.BOT`
```java
- Parser parser = new Parser("return arg; #showGraph;");
+ Parser parser = new Parser("return arg; ");
...
public Parser(String source) {
diff --git a/chapter04/docs/04-grammar.md b/chapter04/docs/04-grammar.md
index 48facd4c..0600679e 100644
--- a/chapter04/docs/04-grammar.md
+++ b/chapter04/docs/04-grammar.md
@@ -12,12 +12,8 @@ statement
| declStatement
| blockStatment
| expressionStatement
- | metaStatement
;
-metaStatement
- : '#showGraph' ';'
- ;
expressionStatement
: IDENTIFIER '=' expression ';'
diff --git a/chapter04/docs/04-post-peephole.gv b/chapter04/docs/04-post-peephole.gv
index 0a9f8e93..b893874f 100644
--- a/chapter04/docs/04-post-peephole.gv
+++ b/chapter04/docs/04-post-peephole.gv
@@ -1,6 +1,6 @@
digraph chapter04 {
/*
-return 1+arg+2; #showGraph;
+return 1+arg+2;
*/
rankdir=BT;
ordering="in";
diff --git a/chapter04/docs/04-pre-peephole.gv b/chapter04/docs/04-pre-peephole.gv
index aefd81c4..d0d7cb0c 100644
--- a/chapter04/docs/04-pre-peephole.gv
+++ b/chapter04/docs/04-pre-peephole.gv
@@ -1,6 +1,6 @@
digraph chapter04 {
/*
-return 1+arg+2; #showGraph;
+return 1+arg+2;
*/
rankdir=BT;
ordering="in";
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/GraphVisualizer.java b/chapter04/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
deleted file mode 100644
index 62b434f3..00000000
--- a/chapter04/src/main/java/com/seaofnodes/simple/GraphVisualizer.java
+++ /dev/null
@@ -1,212 +0,0 @@
-package com.seaofnodes.simple;
-
-import com.seaofnodes.simple.node.*;
-
-import java.util.*;
-
-/**
- * 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.
- * Currently, this is done manually.
- */
-public class GraphVisualizer {
-
- public String generateDotOutput(Parser parser) {
-
- // Since the graph has cycles, we need to create a flat list of all the
- // nodes in the graph.
- Collection<Node> all = findAll(parser);
- StringBuilder sb = new StringBuilder();
- sb.append("digraph chapter04 {\n");
- sb.append("/*\n");
- sb.append(parser.src());
- sb.append("\n*/\n");
-
- // To keep the Scopes below the graph and pointing up into the graph we
- // need to group the Nodes in a subgraph cluster, and the scopes into a
- // different subgraph cluster. THEN we can draw edges between the
- // scopes and nodes. If we try to cross subgraph cluster borders while
- // still making the subgraphs DOT gets confused.
- sb.append("\trankdir=BT;\n"); // Force Nodes before Scopes
-
- // Preserve node input order
- sb.append("\tordering=\"in\";\n");
-
- // Merge multiple edges hitting the same node. Makes common shared
- // nodes much prettier to look at.
- sb.append("\tconcentrate=\"true\";\n");
-
- // Just the Nodes first, in a cluster no edges
- nodes(sb, all);
-
- // Now the scopes, in a cluster no edges
- scopes(sb, parser._scope);
-
- // Walk the Node edges
- nodeEdges(sb, all);
-
- // Walk the Scope edges
- scopeEdges(sb, parser._scope);
-
- sb.append("}\n");
- return sb.toString();
- }
-
-
- private void nodes(StringBuilder sb, Collection<Node> all) {
- // Just the Nodes first, in a cluster no edges
- sb.append("\tsubgraph cluster_Nodes {\n"); // Magic "cluster_" in the subgraph name
- for( Node n : all ) {
- if( n instanceof ProjNode || n instanceof ScopeNode )
- continue; // Do not emit, rolled into MultiNode or Scope cluster already
- sb.append("\t\t").append(n.uniqueName()).append(" [ ");
- String lab = n.glabel();
- if( n instanceof MultiNode ) {
- // Make a box with the MultiNode on top, and all the projections on the bottom
- sb.append("shape=plaintext label=<\n");
- sb.append("\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">\n");
- sb.append("\t\t\t<TR><TD BGCOLOR=\"yellow\">").append(lab).append("</TD></TR>\n");
- sb.append("\t\t\t<TR>");
- boolean doProjTable = false;
- for( Node use : n._outputs ) {
- if( use instanceof ProjNode proj ) {
- if (!doProjTable) {
- doProjTable = true;
- sb.append("<TD>").append("\n");
- sb.append("\t\t\t\t<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">").append("\n");
- sb.append("\t\t\t\t<TR>");
- }
- sb.append("<TD PORT=\"p").append(proj._idx).append("\"");
- if( proj.isCFG() ) sb.append(" BGCOLOR=\"yellow\"");
- sb.append(">").append(proj.glabel()).append("</TD>");
- }
- }
- if (doProjTable) {
- sb.append("</TR>").append("\n");
- sb.append("\t\t\t\t</TABLE>").append("\n");
- sb.append("\t\t\t</TD>");
- }
- sb.append("</TR>\n");
- sb.append("\t\t\t</TABLE>>\n\t\t");
-
- } else {
- // control nodes have box shape
- // other nodes are ellipses, i.e. default shape
- if( n.isCFG() )
- sb.append("shape=box style=filled fillcolor=yellow ");
- sb.append("label=\"").append(lab).append("\" ");
- }
- sb.append("];\n");
- }
- sb.append("\t}\n"); // End Node cluster
- }
-
- private void scopes( StringBuilder sb, ScopeNode scopenode) {
- sb.append("\tnode [shape=plaintext];\n");
- int level=0;
- for( HashMap<String,Integer> scope : scopenode._scopes ) {
- String scopeName = makeScopeName(scopenode, level);
- sb.append("\tsubgraph cluster_").append(scopeName).append(" {\n"); // Magic "cluster_" in the subgraph name
- 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
- sb.append("\t\t\t<TR><TD BGCOLOR=\"cyan\">").append(level).append("</TD>");
- for( String name : scope.keySet() )
- sb.append("<TD PORT=\"").append(makePortName(scopeName, name)).append("\">").append(name).append("</TD>");
- 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 ) ); // End all Scope clusters
- }
-
- private String makeScopeName(ScopeNode sn, int level) { return sn.uniqueName() + "_" + level; }
- private String makePortName(String scopeName, String varName) { return scopeName + "_" + varName; }
-
- // Walk the node edges
- private void nodeEdges(StringBuilder sb, Collection<Node> all) {
- // All them edge labels
- sb.append("\tedge [ fontname=Helvetica, fontsize=8 ];\n");
- for( Node n : all ) {
- // Do not display the Constant->Start edge;
- // ProjNodes handled by Multi;
- // ScopeNodes are done separately
- if( n instanceof ConstantNode || n instanceof ProjNode || n instanceof ScopeNode )
- continue;
- int i=0;
- for( Node def : n._inputs ) {
- if( def != null ) {
- // Most edges land here use->def
- sb.append('\t').append(n.uniqueName()).append(" -> ");
- if( def instanceof ProjNode proj ) {
- String mname = proj.ctrl().uniqueName();
- sb.append(mname).append(":p").append(proj._idx);
- } else sb.append(def.uniqueName());
- // Number edges, so we can see how they track
- sb.append("[taillabel=").append(i);
- // control edges are colored red
- if( def.isCFG() )
- sb.append(" color=red");
- sb.append("];\n");
- }
- i++;
- }
- }
- }
-
- // Walk the scope edges
- private void scopeEdges( StringBuilder sb, ScopeNode scopenode ) {
- sb.append("\tedge [style=dashed color=cornflowerblue];\n");
- int level=0;
- for( HashMap<String,Integer> scope : scopenode._scopes ) {
- String scopeName = makeScopeName(scopenode, level);
- for( String name : scope.keySet() ) {
- Node def = scopenode.in(scope.get(name));
- 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 ProjNode proj ) {
- String mname = proj.ctrl().uniqueName();
- sb.append(mname).append(":p").append(proj._idx);
- } else sb.append(def.uniqueName());
- sb.append(";\n");
- }
- level++;
- }
- }
-
- /**
- * Finds all nodes in the graph.
- */
- private Collection<Node> findAll(Parser parser) {
- final StartNode start = Parser.START;
- final HashMap<Integer, Node> all = new HashMap<>();
- for( Node n : start._outputs )
- walk(all, n);
- // Scan symbol tables
- for( HashMap<String,Integer> scope : parser._scope._scopes )
- for (Integer i : scope.values())
- walk(all, parser._scope.in(i));
- return all.values();
- }
-
- /**
- * Walk a subgraph and populate distinct nodes in the all list.
- */
- private void walk(HashMap<Integer, Node> all, Node n) {
- if(n == null ) return;
- if (all.get(n._nid) != null) return; // Been there, done that
- all.put(n._nid, n);
- for (Node c : n._inputs)
- if (c != null)
- walk(all, c);
- for (Node c : n._outputs)
- if (c != null)
- walk(all, c);
- }
-}
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/Parser.java b/chapter04/src/main/java/com/seaofnodes/simple/Parser.java
index 360a7be9..487afee9 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/Parser.java
@@ -27,7 +27,6 @@ public class Parser {
// Current compilation context, like START; the observer belongs to the parser.
public static Parser PARSER;
public GraphObserver<Node> _obs;
- public ReturnNode _ret;
public int pos() { return _lexer._position; }
// The Lexer. Thin wrapper over a byte[] buffer with a cursor.
@@ -73,8 +72,7 @@ public class Parser {
private Node ctrl(Node n) { return _scope.ctrl(n); }
- public ReturnNode parse() { return parse(false); }
- public ReturnNode parse(boolean show) {
+ public ReturnNode parse() {
// Enter a new scope for the initial control and arguments
_scope.push();
_scope.define(ScopeNode.CTRL, new ProjNode(START, 0, ScopeNode.CTRL).peephole());
@@ -82,9 +80,6 @@ public class Parser {
var ret = (ReturnNode) parseBlock();
_scope.pop();
if (!_lexer.isEOF()) throw error("Syntax error, unexpected " + _lexer.getAnyNextToken());
- if( show ) showGraph();
- _ret = ret;
- if( _obs != null ) _obs.phase("Parse");
return ret;
}
@@ -103,7 +98,7 @@ public class Parser {
Node n = null;
while (!peek('}') && !_lexer.isEOF()) {
Node n0 = parseStatement();
- if (n0 != null) n = n0; // Allow null returns from eg showGraph
+ if (n0 != null) n = n0; // Empty statements can return null
};
// Exit scope
_scope.pop();
@@ -122,7 +117,6 @@ public class Parser {
if (matchx("return") ) return parseReturn();
else if (matchx("int")) return parseDecl();
else if (match ("{" )) return require(parseBlock(),"}");
- else if (matchx("#showGraph")) return require(showGraph(),";");
else if (matchx(";")) return null; // Empty statement
else return parseExpressionStatement();
}
@@ -143,14 +137,7 @@ public class Parser {
return ret;
}
- /**
- * Dumps out the node graph
- * @return {@code null}
- */
- private Node showGraph() {
- System.out.println(new GraphVisualizer().generateDotOutput(this));
- return null;
- }
+
/**
* Parses an expression statement
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter04/src/main/java/com/seaofnodes/simple/node/AddNode.java
index 7e08a207..f568416c 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -7,8 +7,6 @@ public class AddNode extends Node {
@Override public String label() { return "Add"; }
- @Override public String glabel() { return "+"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter04/src/main/java/com/seaofnodes/simple/node/BoolNode.java
index 05495790..af0d22b7 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/node/BoolNode.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/node/BoolNode.java
@@ -15,9 +15,6 @@ abstract public class BoolNode extends Node {
public String label() { return getClass().getSimpleName(); }
@Override
- public String glabel() { return op(); }
-
- @Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
in(2)._print0(sb.append(op()));
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/node/DivNode.java b/chapter04/src/main/java/com/seaofnodes/simple/node/DivNode.java
index 3b3a4436..c7276710 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/node/DivNode.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/node/DivNode.java
@@ -8,8 +8,6 @@ public class DivNode extends Node {
@Override public String label() { return "Div"; }
- @Override public String glabel() { return "//"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter04/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index 0d59ef25..b83c41a5 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -8,8 +8,6 @@ public class MinusNode extends Node {
@Override public String label() { return "Minus"; }
- @Override public String glabel() { return "-"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("(-"));
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter04/src/main/java/com/seaofnodes/simple/node/MulNode.java
index 36d5eb3e..68ba9025 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/node/MulNode.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/node/MulNode.java
@@ -8,8 +8,6 @@ public class MulNode extends Node {
@Override public String label() { return "Mul"; }
- @Override public String glabel() { return "*"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter04/src/main/java/com/seaofnodes/simple/node/Node.java
index 58516151..eb7d8333 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -67,13 +67,9 @@ public abstract class Node {
// Easy reading label for debugger, e.g. "Add" or "Region" or "EQ"
public abstract String label();
- // Unique label for graph visualization, e.g. "Add12" or "Region30" or "EQ99"
+ // Unique label for debugging, e.g. "Add12" or "Region30" or "EQ99"
public String uniqueName() { return label() + _nid; }
- // Graphical label, e.g. "+" or "Region" or "=="
- public String glabel() { return label(); }
-
-
// ------------------------------------------------------------------------
// Debugger Printing.
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter04/src/main/java/com/seaofnodes/simple/node/NotNode.java
index e3683646..83c63244 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/node/NotNode.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/node/NotNode.java
@@ -8,8 +8,6 @@ public class NotNode extends Node {
@Override public String label() { return "Not"; }
- @Override public String glabel() { return "!"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("(!"));
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/node/SubNode.java b/chapter04/src/main/java/com/seaofnodes/simple/node/SubNode.java
index 58d757ea..c12e7388 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/node/SubNode.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/node/SubNode.java
@@ -8,8 +8,6 @@ public class SubNode extends Node {
@Override public String label() { return "Sub"; }
- @Override public String glabel() { return "-"; }
-
@Override
StringBuilder _print1(StringBuilder sb) {
in(1)._print0(sb.append("("));
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/print/JSViewer.java b/chapter04/src/main/java/com/seaofnodes/simple/print/JSViewer.java
deleted file mode 100644
index 43b0be2f..00000000
--- a/chapter04/src/main/java/com/seaofnodes/simple/print/JSViewer.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.seaofnodes.simple.print;
-
-import com.seaofnodes.graph.*;
-import com.seaofnodes.simple.Parser;
-import java.io.IOException;
-
-public class JSViewer extends GraphViewer {
- public static void main(String[] args) throws IOException {
- try( var view = new JSViewer() ) { view.run(); }
- }
- JSViewer() throws IOException {}
-
- @Override protected void compile(String src) {
- Parser parser = new Parser(src);
- parser._obs = new SimpleGraphObserver(parser) {
- @Override protected void frame(GraphSnapshot snap, int pos, GraphEvent evt) throws IOException {
- JSViewer.this.frame(snap, pos, evt);
- }
- };
- try {
- parser.parse();
- } finally {
- parser._obs = null;
- }
- }
-}
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java b/chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
index 72a11a87..a0ad7be0 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
@@ -17,7 +17,7 @@ public class SimpleGraphAdapter extends GraphAdapter<Node> {
@Override protected Node out(Node n, int idx) { return n.out(idx); }
private ArrayList<Edge> edges(Node n) {
- String[] names = n instanceof ScopeNode scope ? scope.reverseNames() : null;
+ String[] names = n instanceof ScopeNode scope && n.nIns() != 0 ? scope.reverseNames() : null;
var edges = new ArrayList<Edge>();
for( int i = 0; i < n.nIns(); i++ ) {
Role role = n instanceof ScopeNode || n instanceof ConstantNode ? Role.ASSOC
diff --git a/chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java b/chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
index 865d1e20..f2ca7888 100644
--- a/chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
+++ b/chapter04/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
@@ -1,20 +1,36 @@
package com.seaofnodes.simple.print;
import com.seaofnodes.graph.GraphCapture;
+import com.seaofnodes.graph.GraphViewer;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.node.Node;
import java.util.ArrayList;
+import java.io.IOException;
/** Chapter 4 needs only a parser; it has no worklist or distant dependencies. */
-public abstract class SimpleGraphObserver extends GraphCapture<Node> {
- private final Parser _parser;
- protected SimpleGraphObserver(Parser parser) { super(new SimpleGraphAdapter()); _parser = parser; }
+public class SimpleGraphObserver extends GraphCapture<Node> {
+ private Parser _parser;
+ private Node _ret;
+ public SimpleGraphObserver() { super(new SimpleGraphAdapter()); }
+ public static void main(String[] args) throws IOException {
+ GraphViewer.run(new SimpleGraphObserver());
+ }
+ @Override protected void compile(String src) {
+ _parser = new Parser(src);
+ _parser._obs = this;
+ _ret = _parser.parse();
+ phase("Parse");
+ }
@Override protected String phase() { return "Parse"; }
@Override protected int pos() { return _parser.pos(); }
- @Override protected void detach() { _parser._obs = null; }
+ @Override protected void detach() {
+ if( _parser != null ) _parser._obs = null;
+ _parser = null;
+ _ret = null;
+ }
@Override protected void roots(ArrayList<Node> roots) {
roots.add(Parser.START);
roots.add(_parser._scope);
- roots.add(_parser._ret);
+ roots.add(_ret);
}
}
diff --git a/chapter04/src/test/java/com/seaofnodes/simple/Chapter02Test.java b/chapter04/src/test/java/com/seaofnodes/simple/Chapter02Test.java
index 60ee8874..9de09d21 100644
--- a/chapter04/src/test/java/com/seaofnodes/simple/Chapter02Test.java
+++ b/chapter04/src/test/java/com/seaofnodes/simple/Chapter02Test.java
@@ -14,8 +14,6 @@ public class Chapter02Test {
Node._disablePeephole = true; // disable peephole so we can observe full graph
ReturnNode ret = parser.parse();
assertEquals("return (1+((2*3)+(-5)));", ret.print());
- GraphVisualizer gv = new GraphVisualizer();
- System.out.println(gv.generateDotOutput(parser));
Node._disablePeephole = false;
}
@@ -59,8 +57,6 @@ public class Chapter02Test {
Parser parser = new Parser("return 1+2*3+-5;");
ReturnNode ret = parser.parse();
assertEquals("return 2;", ret.print());
- GraphVisualizer gv = new GraphVisualizer();
- System.out.println(gv.generateDotOutput(parser));
}
}
diff --git a/chapter04/src/test/java/com/seaofnodes/simple/Chapter03Test.java b/chapter04/src/test/java/com/seaofnodes/simple/Chapter03Test.java
index fc8e97b6..6a5d7072 100644
--- a/chapter04/src/test/java/com/seaofnodes/simple/Chapter03Test.java
+++ b/chapter04/src/test/java/com/seaofnodes/simple/Chapter03Test.java
@@ -31,7 +31,7 @@ public class Chapter03Test {
@Test
public void testVarScopeNoPeephole() {
- Parser parser = new Parser("int a=1; int b=2; int c=0; { int b=3; c=a+b; #showGraph; } return c; #showGraph;");
+ Parser parser = new Parser("int a=1; int b=2; int c=0; { int b=3; c=a+b; } return c; ");
Node._disablePeephole = true;
ReturnNode ret = parser.parse();
Node._disablePeephole = false;
@@ -40,7 +40,7 @@ public class Chapter03Test {
@Test
public void testVarDist() {
- Parser parser = new Parser("int x0=1; int y0=2; int x1=3; int y1=4; return (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1); #showGraph;");
+ Parser parser = new Parser("int x0=1; int y0=2; int x1=3; int y1=4; return (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1); ");
ReturnNode ret = parser.parse();
assertEquals("return 8;", ret.print());
}
diff --git a/chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java b/chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java
index faae0aee..28912d5d 100644
--- a/chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java
+++ b/chapter04/src/test/java/com/seaofnodes/simple/Chapter04Test.java
@@ -10,7 +10,7 @@ public class Chapter04Test {
@Test
public void testPeephole() {
- Parser parser = new Parser("return 1+arg+2; #showGraph;");
+ Parser parser = new Parser("return 1+arg+2; ");
ReturnNode ret = parser.parse();
assertEquals("return (arg+3);", ret.print());
}
@@ -38,7 +38,7 @@ public class Chapter04Test {
@Test
public void testPeephole3() {
- Parser parser = new Parser("return 1+arg+2+arg+3; #showGraph;");
+ Parser parser = new Parser("return 1+arg+2+arg+3; ");
ReturnNode ret = parser.parse();
assertEquals("return ((arg*2)+6);", ret.print());
}
@@ -52,7 +52,7 @@ public class Chapter04Test {
@Test
public void testVarArg() {
- Parser parser = new Parser("return arg; #showGraph;", TypeInteger.BOT);
+ Parser parser = new Parser("return arg; ", TypeInteger.BOT);
ReturnNode ret = parser.parse();
assertTrue(ret.in(0) instanceof ProjNode);
assertTrue(ret.in(1) instanceof ProjNode);
@@ -60,49 +60,49 @@ public class Chapter04Test {
@Test
public void testConstantArg() {
- Parser parser = new Parser("return arg; #showGraph;", TypeInteger.constant(2));
+ Parser parser = new Parser("return arg; ", TypeInteger.constant(2));
ReturnNode ret = parser.parse();
assertEquals("return 2;", ret.print());
}
@Test
public void testCompEq() {
- Parser parser = new Parser("return 3==3; #showGraph;");
+ Parser parser = new Parser("return 3==3; ");
ReturnNode ret = parser.parse();
assertEquals("return 1;", ret.print());
}
@Test
public void testCompEq2() {
- Parser parser = new Parser("return 3==4; #showGraph;");
+ Parser parser = new Parser("return 3==4; ");
ReturnNode ret = parser.parse();
assertEquals("return 0;", ret.print());
}
@Test
public void testCompNEq() {
- Parser parser = new Parser("return 3!=3; #showGraph;");
+ Parser parser = new Parser("return 3!=3; ");
ReturnNode ret = parser.parse();
assertEquals("return 0;", ret.print());
}
@Test
public void testCompNEq2() {
- Parser parser = new Parser("return 3!=4; #showGraph;");
+ Parser parser = new Parser("return 3!=4; ");
ReturnNode ret = parser.parse();
assertEquals("return 1;", ret.print());
}
@Test
public void testBug1() {
- Parser parser = new Parser("int a=arg+1; int b=a; b=1; return a+2; #showGraph;");
+ Parser parser = new Parser("int a=arg+1; int b=a; b=1; return a+2; ");
ReturnNode ret = parser.parse();
assertEquals("return (arg+3);", ret.print());
}
@Test
public void testBug2() {
- Parser parser = new Parser("int a=arg+1; a=a; return a; #showGraph;");
+ Parser parser = new Parser("int a=arg+1; a=a; return a; ");
ReturnNode ret = parser.parse();
assertEquals("return (arg+1);", ret.print());
}