diff options
Diffstat (limited to 'graph/src')
5 files changed, 60 insertions, 6 deletions
diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphCapture.java b/graph/src/main/java/com/seaofnodes/graph/GraphCapture.java index 1a9c8c62..966dd701 100644 --- a/graph/src/main/java/com/seaofnodes/graph/GraphCapture.java +++ b/graph/src/main/java/com/seaofnodes/graph/GraphCapture.java @@ -12,8 +12,10 @@ public abstract class GraphCapture<N> extends GraphObserver<N> { private String _comp; private GraphSocket _server; private final ArrayList<Peep> _peeps = new ArrayList<>(); + private final BitSet _pre = new BitSet(); private long _next, _step; private boolean _off = true; + private boolean _err; protected GraphCapture(GraphAdapter<N> graph) { _graph = graph; } @@ -32,8 +34,13 @@ public abstract class GraphCapture<N> extends GraphObserver<N> { _next = _step = 0; _server = server; _off = false; + _err = false; try { compile(src); + } catch( RuntimeException e ) { + // Type checking already emitted its diagnostic with the final graph. + if( !_err ) throw e; + System.err.println(e); } finally { _off = true; try { @@ -68,6 +75,10 @@ public abstract class GraphCapture<N> extends GraphObserver<N> { // Buffer until we know that this attempt (or a nested one) made progress. // Include n explicitly: parse-time nodes need not have any uses yet. p.pre = snap(n, true); + if( p.up == 0 ) { + _pre.clear(); + for( var node : p.pre.nodes() ) _pre.set(node.id()); + } } @Override public void after(N n, N repl, boolean applied) { @@ -106,6 +117,13 @@ public abstract class GraphCapture<N> extends GraphObserver<N> { emit(snap(null, false), pos(), new GraphEvent(GraphEvent.Kind.PHASE, 0, 0, phase, 0, 0, new int[0])); } + @Override public void error(N node, String msg) { + if( _off ) return; + _err = true; + emit(snap(node, false), pos(), new GraphEvent(GraphEvent.Kind.ERROR, 0, 0, + phase(), _graph.ref(node), 0, new int[0], new int[0], msg)); + } + private GraphEvent evt(Peep p, GraphEvent.Kind kind, int repl) { return new GraphEvent(kind, p.id, p.up, p.phase, _graph.id(p.node), repl, p.near.stream().toArray()); } @@ -137,6 +155,14 @@ public abstract class GraphCapture<N> extends GraphObserver<N> { private void emit(GraphSnapshot snap, int pos, GraphEvent evt) { if( _off ) return; + if( evt.up() != 0 ) { + // Nested peepholes can create userless results before their caller + // returns. These belong to the peep, not the parser's expression. + int[] temps = snap.nodes().stream().mapToInt(GraphSnapshot.Node::id) + .filter(id -> !_pre.get(id)).toArray(); + evt = new GraphEvent(evt.kind(), evt.peep(), evt.up(), evt.phase(), + evt.node(), evt.repl(), evt.near(), temps); + } // Assign steps on emission; attempts without progress do not consume frames. snap = new GraphSnapshot(snap.ver(), _comp, _step++, snap.roots(), snap.scope(), snap.nodes(), snap.groups()); try { diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphEvent.java b/graph/src/main/java/com/seaofnodes/graph/GraphEvent.java index 7d889b21..d52213c2 100644 --- a/graph/src/main/java/com/seaofnodes/graph/GraphEvent.java +++ b/graph/src/main/java/com/seaofnodes/graph/GraphEvent.java @@ -2,9 +2,19 @@ package com.seaofnodes.graph; /** IDs refer to nodes in this compilation; near may include nodes since deleted. */ public record GraphEvent(Kind kind, long peep, long up, String phase, - int node, int repl, int[] near) { - public enum Kind { BEFORE, RETURN, APPLY, PHASE } + int node, int repl, int[] near, int[] temps, String msg) { + public enum Kind { BEFORE, RETURN, APPLY, PHASE, ERROR } - public GraphEvent { near = near.clone(); } + public GraphEvent(Kind kind, long peep, long up, String phase, int node, int repl, int[] near, int[] temps) { + this(kind, peep, up, phase, node, repl, near, temps, null); + } + + public GraphEvent(Kind kind, long peep, long up, String phase, int node, int repl, int[] near) { + this(kind, peep, up, phase, node, repl, near, new int[0]); + } + + public GraphEvent { near = near.clone(); temps = temps.clone(); } @Override public int[] near() { return near.clone(); } + // Created inside an enclosing peep; not yet returned to the parser. + @Override public int[] temps() { return temps.clone(); } } diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphJson.java b/graph/src/main/java/com/seaofnodes/graph/GraphJson.java index 004f6827..bcdd46cc 100644 --- a/graph/src/main/java/com/seaofnodes/graph/GraphJson.java +++ b/graph/src/main/java/com/seaofnodes/graph/GraphJson.java @@ -29,7 +29,18 @@ public class GraphJson { if( i > 0 ) sb.append(','); sb.append(near[i]); } - sb.append("]}"); + sb.append("],\"temps\":["); + int[] temps = evt.temps(); + for( int i = 0; i < temps.length; i++ ) { + if( i > 0 ) sb.append(','); + sb.append(temps[i]); + } + sb.append(']'); + if( evt.msg() != null ) { + sb.append(",\"msg\":"); + str(sb, evt.msg()); + } + sb.append('}'); return sb.append('}').toString(); } @@ -53,6 +64,7 @@ public class GraphJson { str(sb, node.type()); sb.append(",\"kind\":"); str(sb, node.kind().name()); + if( node.folding() ) sb.append(",\"folding\":true"); sb.append(",\"edges\":["); var edges = node.edges(); for( int j = 0; j < edges.size(); j++ ) { diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphObserver.java b/graph/src/main/java/com/seaofnodes/graph/GraphObserver.java index 24879fe2..4a57c816 100644 --- a/graph/src/main/java/com/seaofnodes/graph/GraphObserver.java +++ b/graph/src/main/java/com/seaofnodes/graph/GraphObserver.java @@ -14,6 +14,9 @@ public abstract class GraphObserver<N> { /** A completed compiler phase. */ public abstract void phase(String phase); + /** A compiler diagnostic and its node, or null for an error without a node. */ + public void error(N node, String msg) {} + /** A rule consulted a dependency, even if already registered or adjacent. */ public void dep(N node, N def) {} } diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java b/graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java index b53f3211..df1e8837 100644 --- a/graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java +++ b/graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java @@ -21,9 +21,12 @@ public record GraphSnapshot(int ver, String comp, long step, /** Header ID, enclosing group (zero outside), and directly owned node IDs. */ public record Group(int id, int par, int[] nodes) { } - /** IDs are stable within one compilation. Labels and types are plain text. */ + /** IDs are stable; labels/types are plain text. folding means pending inline cleanup. */ public record Node(int id, String label, String type, Kind kind, - ArrayList<Edge> edges, Projection proj) { + ArrayList<Edge> edges, Projection proj, boolean folding) { + public Node(int id, String label, String type, Kind kind, ArrayList<Edge> edges, Projection proj) { + this(id,label,type,kind,edges,proj,false); + } public Node { edges = new ArrayList<>(edges); } |
