summaryrefslogtreecommitdiff
path: root/graph/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'graph/src/main/java')
-rw-r--r--graph/src/main/java/com/seaofnodes/graph/GraphAdapter.java7
-rw-r--r--graph/src/main/java/com/seaofnodes/graph/GraphCapture.java18
-rw-r--r--graph/src/main/java/com/seaofnodes/graph/GraphJson.java2
-rw-r--r--graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java4
4 files changed, 21 insertions, 10 deletions
diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphAdapter.java b/graph/src/main/java/com/seaofnodes/graph/GraphAdapter.java
index 3e840b54..47bf3444 100644
--- a/graph/src/main/java/com/seaofnodes/graph/GraphAdapter.java
+++ b/graph/src/main/java/com/seaofnodes/graph/GraphAdapter.java
@@ -37,6 +37,11 @@ public abstract class GraphAdapter<N> {
}
public final GraphSnapshot snap(String comp, long step, ArrayList<N> roots) {
+ return snap(comp, step, roots, 0);
+ }
+
+ /** scope names the active parser scope, which the caller includes in roots. */
+ public final GraphSnapshot snap(String comp, long step, ArrayList<N> roots, int scope) {
// Node IDs are dense; index directly without boxed keys or map entries.
var seen = new ArrayList<N>();
var todo = new ArrayDeque<N>();
@@ -55,7 +60,7 @@ public abstract class GraphAdapter<N> {
// Determinism without reordering the compiler's use lists.
nodes.sort(Comparator.comparingInt(GraphSnapshot.Node::id));
return new GraphSnapshot(GraphSnapshot.VER, comp, step,
- Arrays.copyOf(rids, len), nodes);
+ Arrays.copyOf(rids, len), scope, nodes);
}
private boolean enq(N node, ArrayList<N> seen, ArrayDeque<N> todo) {
diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphCapture.java b/graph/src/main/java/com/seaofnodes/graph/GraphCapture.java
index 6fc40b5f..4be65392 100644
--- a/graph/src/main/java/com/seaofnodes/graph/GraphCapture.java
+++ b/graph/src/main/java/com/seaofnodes/graph/GraphCapture.java
@@ -23,6 +23,8 @@ public abstract class GraphCapture<N> extends GraphObserver<N> {
protected abstract String phase();
protected abstract int pos();
protected abstract void roots(ArrayList<N> roots);
+ // Called only during parsing; the shared capture adds this root too.
+ protected N scope() { return null; }
protected abstract void detach();
final void run(String src, GraphSocket server) {
@@ -65,7 +67,7 @@ public abstract class GraphCapture<N> extends GraphObserver<N> {
near(p, 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);
+ p.pre = snap(n, true);
}
@Override public void after(N n, N repl, boolean applied) {
@@ -85,7 +87,7 @@ public abstract class GraphCapture<N> extends GraphObserver<N> {
up.sent = true;
}
N rez = repl == null ? n : repl;
- emit(snap(_graph.dead(rez) ? null : rez), pos(),
+ emit(snap(_graph.dead(rez) ? null : rez, true), pos(),
evt(p, applied ? GraphEvent.Kind.APPLY : GraphEvent.Kind.RETURN,
_graph.dead(rez) ? 0 : _graph.id(rez)));
}
@@ -101,7 +103,7 @@ public abstract class GraphCapture<N> extends GraphObserver<N> {
@Override public void phase(String phase) {
if( _off ) return;
- emit(snap(null), pos(), new GraphEvent(GraphEvent.Kind.PHASE, 0, 0, phase, 0, 0, new int[0]));
+ emit(snap(null, false), pos(), new GraphEvent(GraphEvent.Kind.PHASE, 0, 0, phase, 0, 0, new int[0]));
}
private GraphEvent evt(Peep p, GraphEvent.Kind kind, int repl) {
@@ -121,18 +123,22 @@ public abstract class GraphCapture<N> extends GraphObserver<N> {
}
- private GraphSnapshot snap(N extra) {
+ private GraphSnapshot snap(N extra, boolean parsing) {
var roots = new ArrayList<N>();
roots(roots);
+ // Early parsers retain their emptied scope after returning. A completed
+ // phase no longer owns that scope, even while phase() still says Parse.
+ N scope = parsing && "Parse".equals(phase()) ? scope() : null;
+ roots.add(scope);
for( Peep p : _peeps ) if( !_graph.dead(p.node) ) roots.add(p.node);
roots.add(extra);
- return _graph.snap(_comp, 0, roots);
+ return _graph.snap(_comp, 0, roots, _graph.ref(scope));
}
private void emit(GraphSnapshot snap, int pos, GraphEvent evt) {
if( _off ) return;
// Assign steps on emission; attempts without progress do not consume frames.
- snap = new GraphSnapshot(snap.ver(), _comp, _step++, snap.roots(), snap.nodes());
+ snap = new GraphSnapshot(snap.ver(), _comp, _step++, snap.roots(), snap.scope(), snap.nodes());
try {
_server.put(GraphJson.frame(snap, pos, evt));
} catch( IOException e ) {
diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphJson.java b/graph/src/main/java/com/seaofnodes/graph/GraphJson.java
index 8726d81b..c920763a 100644
--- a/graph/src/main/java/com/seaofnodes/graph/GraphJson.java
+++ b/graph/src/main/java/com/seaofnodes/graph/GraphJson.java
@@ -42,7 +42,7 @@ public class GraphJson {
if( i > 0 ) sb.append(',');
sb.append(roots[i]);
}
- sb.append("],\"nodes\":[");
+ sb.append("],\"scope\":").append(snap.scope()).append(",\"nodes\":[");
var nodes = snap.nodes();
for( int i = 0; i < nodes.size(); i++ ) {
if( i > 0 ) sb.append(',');
diff --git a/graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java b/graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java
index 18926726..6836693e 100644
--- a/graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java
+++ b/graph/src/main/java/com/seaofnodes/graph/GraphSnapshot.java
@@ -2,9 +2,9 @@ package com.seaofnodes.graph;
import java.util.ArrayList;
-/** A detached graph. Treat its lists as read-only after capture. */
+/** A detached graph. Lists are read-only; scope is the active parser scope ID, or zero. */
public record GraphSnapshot(int ver, String comp, long step,
- int[] roots, ArrayList<Node> nodes) {
+ int[] roots, int scope, ArrayList<Node> nodes) {
public static final int VER = 1;
public GraphSnapshot {