From e587a11049129866bf3fd6db0a0f72d44ad6b39f Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 21 Sep 2026 21:26:03 -0700 Subject: Change protocol between compiler and browser --- .../java/com/seaofnodes/simple/print/JSViewer.java | 24 +++++++++++++---- .../seaofnodes/simple/print/SimpleWebSocket.java | 30 +++++++++++----------- 2 files changed, 34 insertions(+), 20 deletions(-) (limited to 'chapter25/src/main/java') diff --git a/chapter25/src/main/java/com/seaofnodes/simple/print/JSViewer.java b/chapter25/src/main/java/com/seaofnodes/simple/print/JSViewer.java index 156f1fe9..a9f6bfd4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/print/JSViewer.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/print/JSViewer.java @@ -1,5 +1,6 @@ package com.seaofnodes.simple.print; +import com.seaofnodes.graph.GraphJson; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.node.*; import com.seaofnodes.simple.type.*; @@ -11,8 +12,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.net.URI; import java.util.Collection; +import java.util.ArrayList; import java.util.Arrays; import java.util.Stack; +import java.util.UUID; import static com.seaofnodes.simple.codegen.CodeGen.CODE; public class JSViewer implements AutoCloseable { @@ -28,7 +31,9 @@ public class JSViewer implements AutoCloseable { // WebSocket to the browser for display static SimpleWebSocket SERVER; - static int N; // Dot frames + static long N; // Snapshot step within this compilation + static String COMP; + static final SimpleGraphAdapter GRAPH = new SimpleGraphAdapter(); JSViewer() throws Exception { // Launch server; handshake @@ -60,6 +65,7 @@ public class JSViewer implements AutoCloseable { System.out.println(src); try { N=0; + COMP = UUID.randomUUID().toString(); // Use parser scope, xscope when building views CodeGen code = new CodeGen(src); SHOW = true; @@ -93,10 +99,19 @@ public class JSViewer implements AutoCloseable { return; boolean midParse = CODE._phase == CodeGen.Phase.Parse; Stack xScopes = midParse ? CODE.P._xScopes : null; + var roots = new ArrayList(); + roots.add(CODE._stop); + if( midParse ) { + roots.add(CODE.P._scope); + roots.addAll(xScopes); + } + long step = N++; + var snap = GRAPH.snap(COMP, step, roots.toArray(Node[]::new)); + int pos = midParse ? CODE.P.pos() : -1; Collection all = GraphVisualizer.findAll(xScopes, CODE._stop, midParse ? CODE.P._scope: null); SB sb = new SB(); - sb.p("digraph view_").p(N++).p(" {\n").ii(); + sb.p("digraph view_").p(step).p(" {\n").ii(); if( midParse ) sb.i().p("// POS: ").p(CODE.P.pos()).nl(); @@ -139,11 +154,10 @@ public class JSViewer implements AutoCloseable { sb.p("}\n").di(); - // Tell client another DOT frame + // Send the model and its current DOT rendering as one playback frame. String dot = sb.toString(); - System.out.println(dot); try { - SERVER.put(dot); + SERVER.put(GraphJson.frame(snap, pos, dot)); } catch( IOException ioe ) { try { SERVER.close();} catch( IOException ignored ){} } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/print/SimpleWebSocket.java b/chapter25/src/main/java/com/seaofnodes/simple/print/SimpleWebSocket.java index d7fa8bf2..ae500879 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/print/SimpleWebSocket.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/print/SimpleWebSocket.java @@ -139,7 +139,7 @@ class SimpleWebSocket extends ServerSocket { for( int i=0; i>>8); + _out.write(len&255); + } else { + _out.write(127); + for( int shift = 56; shift >= 0; shift -= 8 ) + _out.write((int)((long)len >>> shift) & 255); } - if( len > 65535 ) - throw Utils.TODO("MOAR LENGTH"); - _out.write(129); // FIN, opcode 1 - whole text message - _out.write(126); // Length is 16b - _out.write(len>>>8); - _out.write(len&255); - for( int i=0; i