diff options
| author | Cliff Click <cliffc@acm.org> | 2026-10-02 13:04:34 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2026-10-02 13:04:34 -0700 |
| commit | e4dc3273f201ae741637b626998637cce973546b (patch) | |
| tree | 7607c1da4378da42549e8142371d95bdca4e06e0 /graph | |
| parent | 6cd01a8d646750748a0af221073de8a7787472ad (diff) | |
| download | Simple-e4dc3273f201ae741637b626998637cce973546b.tar.gz Simple-e4dc3273f201ae741637b626998637cce973546b.zip | |
First pass README updates
Diffstat (limited to 'graph')
| -rw-r--r-- | graph/README.md | 34 | ||||
| -rw-r--r-- | graph/docs.mk | 24 | ||||
| -rw-r--r-- | graph/render_docs.py | 71 |
3 files changed, 125 insertions, 4 deletions
diff --git a/graph/README.md b/graph/README.md index a459898f..915746e9 100644 --- a/graph/README.md +++ b/graph/README.md @@ -120,8 +120,34 @@ visibility, neighborhood highlighting and selection. Clear selection with Escape and uncheck **Peep neighborhood** for an unmarked diagram. The SVG includes its styles and arrow markers and needs no JavaScript or viewer assets; check it into the chapter's docs and embed it like the existing static figures. -Existing `.gv` sources and their generated SVGs remain another way to maintain -documentation figures. +The chapter IR figures also have detached `.json` snapshots. These preserve the +illustrated topology, including schematic pre-optimization states that the +parser does not retain. Node IDs in these illustrations are illustrative; +omitted type annotations are not inferred. Their SVGs use this viewer's actual +layout, node shapes, colors, projection boxes, Region/Phi rows, and group routing. +The old `.gv` files beside these snapshots retain the original figure topology; +when both exist, the JSON is the maintained source for the SVG. + +To regenerate a snapshot, install Python Playwright and its Chromium browser, +then run from the repository root: + +```sh +python graph/render_docs.py chapter01/docs/01-graph.json +``` + +Use `--browser msedge` or `--browser chrome` for an installed Chromium browser, +or `--browser firefox`. The command serves viewer assets on an ephemeral local +port and renders headlessly, without connecting to a compiler or a live viewer. +This optional documentation tool is not needed to build or test the chapters. +The chapter `docs/Makefile` rules select JSON before a same-named legacy DOT +file. They accept `PYTHON` and `DOC_BROWSER` overrides, for example +`make -C chapter01/docs PYTHON=python DOC_BROWSER=msedge` from the repository root. + +The compact memory-dependency schematics in 10a/10b retain `.gv` sources to +preserve their deliberate horizontal layouts. They use the viewer palette and +node shapes; definitions are left of uses horizontally and above uses vertically, +with arrows from use to definition. Type lattices use their own domain colors +and top-to-bottom lattice order, rather than IR edge conventions. The launcher prints the viewer URL before opening the browser. If the desktop only raises an existing browser window, paste that URL into a new tab. Use @@ -509,8 +535,8 @@ defs/uses for its neighborhoods and no worklist or dependency lists. It retains The compiler DOT dump flag, parser graph directive, Java DOT generators and old viewer/transport classes have been removed from all chapters. Use **Save SVG** -for new documentation figures. Existing `.gv` sources, their checked-in SVGs -and the documentation Make rules for regenerating those SVGs remain. +for new documentation figures. The documentation Make rules render maintained +JSON snapshots with the shared viewer and the remaining `.gv` figures with DOT. Chapter 1 has no peepholes and supplies one completed parse snapshot. Chapter 2 shows constant folding; chapters 3 and 4 add variables and algebraic rewrites. diff --git a/graph/docs.mk b/graph/docs.mk new file mode 100644 index 00000000..ad792ff5 --- /dev/null +++ b/graph/docs.mk @@ -0,0 +1,24 @@ +# Included from a chapter's docs/Makefile. +# A viewer snapshot takes precedence over a legacy DOT source of the same name. +GRAPH_DOCS := ../../graph +PYTHON ?= python3 +DOC_BROWSER ?= chromium +JSON := $(wildcard *.json) +VIEW_SVG := $(JSON:.json=.svg) +GV := $(filter-out $(JSON:.json=.gv),$(wildcard *.gv)) +SVG := $(VIEW_SVG) $(GV:.gv=.svg) +.DELETE_ON_ERROR: + +.PHONY: all +all: $(SVG) + +$(VIEW_SVG): %.svg: %.json $(GRAPH_DOCS)/render_docs.py $(wildcard $(GRAPH_DOCS)/web/*.js) $(wildcard $(GRAPH_DOCS)/web/*.css) + $(PYTHON) $(GRAPH_DOCS)/render_docs.py --browser $(DOC_BROWSER) $< + +$(GV:.gv=.svg): %.svg: %.gv + dot -Tsvg $< > $@ + @sed -i 's/\r$$//' $@ + +.PHONY: clean +clean: + @rm -f $(SVG) diff --git a/graph/render_docs.py b/graph/render_docs.py new file mode 100644 index 00000000..a0c5ec26 --- /dev/null +++ b/graph/render_docs.py @@ -0,0 +1,71 @@ +"""Render documentation snapshots with the same layout and SVG export as make view. + +Requires Python Playwright and an installed browser; not needed to build chapters. +Example: python graph/render_docs.py --browser msedge chapter01/docs/01-graph.json +""" +import argparse +from functools import partial +from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer +import json +from pathlib import Path +from threading import Thread +from playwright.sync_api import sync_playwright + + +class QuietHandler(SimpleHTTPRequestHandler): + def log_message(self, *args): + pass + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--browser', default='chromium', choices=['chromium', 'msedge', 'chrome', 'firefox']) + parser.add_argument('snapshots', nargs='+', type=Path) + args = parser.parse_args() + web = Path(__file__).resolve().parent / 'web' + server = ThreadingHTTPServer(('127.0.0.1', 0), partial(QuietHandler, directory=str(web))) + Thread(target=server.serve_forever, daemon=True).start() + try: + with sync_playwright() as pw: + engine = pw.firefox if args.browser == 'firefox' else pw.chromium + options = {'channel': args.browser} if args.browser in ('msedge', 'chrome') else {} + browser = engine.launch(headless=True, **options) + page = browser.new_page(reduced_motion='reduce') + # No connection to a compiler or to the user's live viewer session. + page.route_web_socket('**', lambda ws: ws.on_message(lambda message: None)) + page.goto(f'http://127.0.0.1:{server.server_port}/index.html') + page.wait_for_function('rendererReady') + page.evaluate('''() => { + layout = new GraphLayout(); + document.getElementById("assocs").checked = true; + document.getElementById("near").checked = false; + }''') + for source in args.snapshots: + snap = json.loads(source.read_text(encoding='utf-8')) + page.evaluate('''async snap => { + const evt = {kind: "PHASE", phase: "Documentation", near: [], temps: []}; + const scene = await layout.run(snap, evt); + renderer.show(snap, scene, evt); + renderer.select(0); + }''', snap) + # Capture the normal export's Blob without bulk browser downloads. + svg = page.evaluate('''async () => { + const create = URL.createObjectURL, click = HTMLAnchorElement.prototype.click; + let blob; + URL.createObjectURL = value => { blob = value; return create(value); }; + HTMLAnchorElement.prototype.click = () => {}; + try { renderer.save(1); } + finally { URL.createObjectURL = create; HTMLAnchorElement.prototype.click = click; } + return await blob.text(); + }''') + target = source.with_suffix('.svg') + target.write_text(svg + '\n', encoding='utf-8', newline='\n') + print(target) + browser.close() + finally: + server.shutdown() + server.server_close() + + +if __name__ == '__main__': + main() |
