summaryrefslogtreecommitdiff
path: root/chapter13/docs
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-03 14:03:48 -0700
committerCliff Click <cliffc@acm.org>2026-10-03 14:03:48 -0700
commit22df891893d30e9906d0b14fc3ae5d8e67d500b2 (patch)
tree2bda142f92febc8b26f1cabd4bb0c46d1864f34b /chapter13/docs
parentc3958e34c0de21df52e57e47e4f47ffe6464f138 (diff)
downloadSimple-22df891893d30e9906d0b14fc3ae5d8e67d500b2.tar.gz
Simple-22df891893d30e9906d0b14fc3ae5d8e67d500b2.zip
Chapter renumber, and split ch 17
Renumber chapters 10a, 10b, 11, 12, 13, 14 -> 10, 11, 13, 12, [11,14]. Split ch 17 into a 17a and 17b; shuffle around im/mutable syntax to be consistent, and present it more slowly. THe new immutable syntax is pushed through all later chapters
Diffstat (limited to 'chapter13/docs')
-rw-r--r--chapter13/docs/13-grammar.md11
-rw-r--r--chapter13/docs/Makefile13
-rw-r--r--chapter13/docs/graph1.gv79
-rw-r--r--chapter13/docs/graph1.json25
-rw-r--r--chapter13/docs/graph1.svg123
-rw-r--r--chapter13/docs/graph2.gv84
-rw-r--r--chapter13/docs/graph2.json25
-rw-r--r--chapter13/docs/graph2.svg123
-rw-r--r--chapter13/docs/graph3-snip.jpgbin0 -> 19681 bytes
-rw-r--r--chapter13/docs/graph3-snip.json17
-rw-r--r--chapter13/docs/graph3-snip.svg91
-rw-r--r--chapter13/docs/graph3.gv85
-rw-r--r--chapter13/docs/graph3.json26
-rw-r--r--chapter13/docs/graph3.svg128
-rw-r--r--chapter13/docs/graph4.gv110
-rw-r--r--chapter13/docs/graph4.json24
-rw-r--r--chapter13/docs/graph4.svg120
-rw-r--r--chapter13/docs/graph5.gv117
-rw-r--r--chapter13/docs/graph5.json24
-rw-r--r--chapter13/docs/graph5.svg120
-rw-r--r--chapter13/docs/graph6.gv117
-rw-r--r--chapter13/docs/graph6.json25
-rw-r--r--chapter13/docs/graph6.svg124
-rw-r--r--chapter13/docs/graph7.gv23
-rw-r--r--chapter13/docs/graph7.json16
-rw-r--r--chapter13/docs/graph7.svg78
-rw-r--r--chapter13/docs/graph8.gv45
-rw-r--r--chapter13/docs/graph8.json21
-rw-r--r--chapter13/docs/graph8.svg98
29 files changed, 1874 insertions, 18 deletions
diff --git a/chapter13/docs/13-grammar.md b/chapter13/docs/13-grammar.md
index 6cbbf388..4e7ae5b4 100644
--- a/chapter13/docs/13-grammar.md
+++ b/chapter13/docs/13-grammar.md
@@ -11,22 +11,21 @@ statement
: returnStatement
| structDeclaration
| declStatement
- | blockStatment
+ | blockStatement
| expressionStatement
| ifStatement
| whileStatement
| breakStatement
- | continueStatment
+ | continueStatement
;
PRIMTYPE
: 'int'
- | 'flt'
;
field
: PRIMTYPE IDENTIFIER ';'
- | structName IDENTIFIER ('?')? ';'
+ | structName ('?')? IDENTIFIER ';'
;
fields
@@ -103,7 +102,7 @@ newExpression
;
fieldExpression
- : primaryExpresson '.' IDENTIFIER
+ : primaryExpression '.' IDENTIFIER
;
primaryExpression
@@ -123,7 +122,7 @@ INTEGER_LITERAL
;
IDENTIFIER
- : NON_DIGIT (NON_DIGIT | DIGIT)*
+ : NON_DIGIT (NON_DIGIT | DEC_DIGIT)*
;
NON_DIGIT: [a-zA-Z_];
diff --git a/chapter13/docs/Makefile b/chapter13/docs/Makefile
index 12659b8f..6fa0f057 100644
--- a/chapter13/docs/Makefile
+++ b/chapter13/docs/Makefile
@@ -1,12 +1 @@
-GV := $(wildcard *.gv)
-SVG := $(patsubst %.gv,%.svg,$(GV))
-
-.PHONY: all
-all: $(SVG)
-
-%.svg: %.gv
- dot -Tsvg $< > $@
-
-.PHONY: clean
-clean:
- @rm -f $(SVG)
+include ../../graph/docs.mk
diff --git a/chapter13/docs/graph1.gv b/chapter13/docs/graph1.gv
new file mode 100644
index 00000000..4d6ee1fe
--- /dev/null
+++ b/chapter13/docs/graph1.gv
@@ -0,0 +1,79 @@
+digraph chapter13 {
+/*
+struct S { int f; }
+S v=new S;
+v.f = 2;
+int i=new S.f;
+i=v.f;
+if (arg) v.f=1;
+return i;
+
+*/
+ rankdir=BT;
+ concentrate="true";
+ compound="true";
+ subgraph cluster_Nodes {
+ Start2 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Start</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">$ctrl</TD><TD PORT="p1">$mem</TD><TD PORT="p2">arg</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ MemMerge [ shape=box label="MemMerge" ];
+ Stop3 [ shape=box style=filled fillcolor=yellow label="Stop" ];
+ Con_4 [ label="#0" ];
+ new9 [ label="new S" ];
+ Con_11 [ label="#2" ];
+ Store12 [ label=".f =" ];
+ new13 [ label="new S" ];
+ Store14 [ label=".f =" ];
+ Load16 [ label=".f" ];
+ If17 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Con_21 [ label="#1" ];
+ Store22 [ label=".f =" ];
+ Region23 [ shape=box style=filled fillcolor=yellow label="Region" ];
+ Phi_224 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Return25 [ shape=box style=filled fillcolor=yellow label="Return" ];
+ { rank=same; Region23;Phi_224;}
+ }
+ edge [ fontname=Helvetica, fontsize=8 ];
+ Stop3 -> Return25[taillabel=0 color=red];
+ new9 -> Start2:p0[taillabel=0 color=green];
+ Store12 -> Start2:p1[taillabel=1 color=blue];
+ Store12 -> new9[taillabel=2];
+ Store12 -> Con_11[taillabel=3];
+ new13 -> Start2:p0[taillabel=0 color=green];
+ Store14 -> Store12[taillabel=1 color=blue];
+ Store14 -> new13[taillabel=2];
+ Store14 -> Con_4[taillabel=3];
+ Load16 -> Store14[taillabel=1 color=blue];
+ Load16 -> new9[taillabel=2];
+ If17 -> Start2:p0[taillabel=0 color=red];
+ If17 -> Start2:p2[taillabel=1];
+ Store22 -> Store14[taillabel=1 color=blue];
+ Store22 -> new9[taillabel=2];
+ Store22 -> Con_21[taillabel=3];
+ Region23 -> If17:p0[taillabel=1 color=red];
+ Region23 -> If17:p1[taillabel=2 color=red];
+ Phi_224 -> Region23 [style=dotted taillabel=0];
+ Phi_224 -> Store22[taillabel=1 color=blue];
+ Phi_224 -> Store14[taillabel=2 color=blue constraint=false];
+ Return25 -> Region23[taillabel=0 color=red];
+ Return25 -> Load16[taillabel=2];
+ Return25 -> MemMerge[taillabel=1 color=blue];
+ MemMerge -> Start2:p1[taillabel=1 color=blue];
+ MemMerge -> Phi_224[taillabel=2 color=blue];
+}
diff --git a/chapter13/docs/graph1.json b/chapter13/docs/graph1.json
new file mode 100644
index 00000000..aac69ce2
--- /dev/null
+++ b/chapter13/docs/graph1.json
@@ -0,0 +1,25 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph1.svg",
+ "step": 1,
+ "roots": [25],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 224, "role": "MEM", "label": null}], "proj": null},
+ {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}},
+ {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 11, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 12, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 11, "role": "DATA", "label": null}], "proj": null},
+ {"id": 13, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 14, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 12, "role": "MEM", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 16, "label": ".f", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null},
+ {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 22, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null},
+ {"id": 25, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null},
+ {"id": 224, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 14, "role": "MEM", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter13/docs/graph1.svg b/chapter13/docs/graph1.svg
new file mode 100644
index 00000000..93a2a03f
--- /dev/null
+++ b/chapter13/docs/graph1.svg
@@ -0,0 +1,123 @@
+<svg aria-label="Compiler graph" width="565" height="766" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 565 766" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge MEM" id="e1i1" d="M84,118 L84,536 Q84,544 92,544 L137,544 Q145,544 145,552 L145,582" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[1] → #6 · MEM</title></path><path class="edge MEM" id="e1i2" d="M175,534 L175,582" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[2] → #224 · MEM</title></path><path class="edge MEM" id="e12i1" d="M84,118 L84,130 Q84,138 92,138 L146,138 Q154,138 154,146 L154,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#12[1] → #6 · MEM</title></path><path class="edge DATA" id="e12i2" d="M242,118 L242,123 Q242,128 237,128 L186,128 Q178,128 178,136 L178,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#12[2] → #9 · DATA</title></path><path class="edge DATA" id="e12i3" d="M394,118 L394,130 Q394,138 386,138 L210,138 Q202,138 202,146 L202,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#12[3] → #11 · DATA</title></path><path class="edge MEM" id="e14i1" d="M166,222 L166,227 Q166,232 171,232 L298,232 Q306,232 306,240 L306,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#14[1] → #12 · MEM</title></path><path class="edge DATA" id="e14i2" d="M318,222 L318,227 Q318,232 323,232 L324,232 Q330,232 330,238 L330,270" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#14[2] → #13 · DATA</title></path><path class="edge DATA" id="e14i3" d="M470,222 L470,227 Q470,232 465,232 L362,232 Q354,232 354,240 L354,270" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#14[3] → #4 · DATA</title></path><path class="edge MEM" id="e16i1" d="M318,326 L318,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#16[1] → #14 · MEM</title></path><path class="edge DATA" id="e16i2" d="M242,118 L242,123 Q242,128 247,128 L532,128 Q540,128 540,136 L540,328 Q540,336 532,336 L356,336 Q348,336 348,344 L348,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#16[2] → #9 · DATA</title></path><path class="edge MEM" id="e22i1" d="M318,326 L318,338 Q318,346 310,346 L151,346 Q143,346 143,354 L143,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[1] → #14 · MEM</title></path><path class="edge DATA" id="e22i2" d="M242,118 L242,123 Q242,128 237,128 L103,128 Q95,128 95,136 L95,348 Q95,356 103,356 L159,356 Q167,356 167,364 L167,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[2] → #9 · DATA</title></path><path class="edge DATA" id="e22i3" d="M166,326 L166,331 Q166,336 171,336 L183,336 Q191,336 191,344 L191,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[3] → #21 · DATA</title></path><path class="edge MEM" id="e25i1" d="M145,638 L145,643 Q145,648 150,648 L280,648 Q288,648 288,656 L288,686" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#25[1] → #1 · MEM</title></path><path class="edge DATA" id="e25i2" d="M318,430 L318,686" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#25[2] → #16 · DATA</title></path><path class="edge MEM" id="e224i1" d="M155,430 L155,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#224[1] → #22 · MEM</title></path><path class="edge MEM" id="e224i2" d="M318,326 L318,338 Q318,346 310,346 L233,346 Q225,346 225,354 L225,432 Q225,440 217,440 L203,440 Q195,440 195,448 L195,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#224[2] → #14 · MEM</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(85,588)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemMerge</tspan><tspan class="node-id">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 MemMerge
+Type not computed
+
+[0] → — DATA
+[1] → #6 MEM
+[2] → #224 MEM</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n2" data-id="2" transform="translate(24,24)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Start</tspan><tspan class="node-id">  #2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#2 Start
+Type not computed
+
+</title></g><g class="node" id="n4" data-id="4" transform="translate(410,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#0</tspan><tspan class="node-id">  #4</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 #0
+Type not computed
+
+</title></g><g class="node" id="n6" data-id="6" transform="translate(24,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>$mem</tspan><tspan class="node-id">  #6/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 $mem
+Projection 1 of #2
+Type not computed
+
+[0] → #2 MEM</title></g><g class="node" id="n9" data-id="9" transform="translate(182,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n11" data-id="11" transform="translate(334,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#2</tspan><tspan class="node-id">  #11</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#11 #2
+Type not computed
+
+</title></g><g class="node" id="n12" data-id="12" transform="translate(106,172)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #12</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#12 .f =
+Type not computed
+
+[0] → — DATA
+[1] → #6 MEM
+[2] → #9 DATA
+[3] → #11 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n13" data-id="13" transform="translate(258,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #13</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#13 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n14" data-id="14" transform="translate(258,276)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #14</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#14 .f =
+Type not computed
+
+[0] → — DATA
+[1] → #12 MEM
+[2] → #13 DATA
+[3] → #4 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n16" data-id="16" transform="translate(258,380)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f</tspan><tspan class="node-id">  #16</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#16 .f
+Type not computed
+
+[0] → — DATA
+[1] → #14 MEM
+[2] → #9 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n21" data-id="21" transform="translate(106,276)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#1</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#21 #1
+Type not computed
+
+</title></g><g class="node" id="n22" data-id="22" transform="translate(95,380)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 .f =
+Type not computed
+
+[0] → — DATA
+[1] → #14 MEM
+[2] → #9 DATA
+[3] → #21 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n25" data-id="25" transform="translate(228,692)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Return</tspan><tspan class="node-id">  #25</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#25 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #1 MEM
+[2] → #16 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n224" data-id="224" transform="translate(115,484)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #224</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#224 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #22 MEM
+[2] → #14 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>
diff --git a/chapter13/docs/graph2.gv b/chapter13/docs/graph2.gv
new file mode 100644
index 00000000..94d94dae
--- /dev/null
+++ b/chapter13/docs/graph2.gv
@@ -0,0 +1,84 @@
+digraph chapter13 {
+/*
+struct S { int f; }
+S v=new S;
+v.f = 2;
+int i=new S.f;
+i=v.f;
+if (arg) v.f=1;
+return i;
+
+*/
+ rankdir=BT;
+ concentrate="true";
+ compound="true";
+ subgraph cluster_Nodes {
+ Start2 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Start</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">$ctrl</TD><TD PORT="p1">$mem</TD><TD PORT="p2">arg</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ MemMerge [ shape=box label="MemMerge" ];
+ Stop3 [ shape=box style=filled fillcolor=yellow label="Stop" ];
+ Con_4 [ label="#0" ];
+ new9 [ label="new S" ];
+ Con_11 [ label="#2" ];
+ Store12 [ label=".f =" ];
+ new13 [ label="new S" ];
+ Store14 [ label=".f =" ];
+ Load16 [ label=".f" ];
+ If17 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Con_21 [ label="#1" ];
+ Store22 [ label=".f =" ];
+ Region23 [ shape=box style=filled fillcolor=yellow label="Region" ];
+ Phi_224 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Return25 [ shape=box style=filled fillcolor=yellow label="Return" ];
+ { rank=same; Region23;Phi_224;}
+ }
+ edge [ fontname=Helvetica, fontsize=8 ];
+ Stop3 -> Return25[taillabel=0 color=red];
+ new9 -> Start2:p0[taillabel=0 color=green];
+ Store12 -> Start2:p0[taillabel=0 color=red];
+ Store12 -> Start2:p1[taillabel=1 color=blue];
+ Store12 -> new9[taillabel=2];
+ Store12 -> Con_11[taillabel=3];
+ new13 -> Start2:p0[taillabel=0 color=green];
+ Store14 -> Start2:p0[taillabel=0 color=red];
+ Store14 -> Store12[taillabel=1 color=blue];
+ Store14 -> new13[taillabel=2];
+ Store14 -> Con_4[taillabel=3];
+ Load16 -> Start2:p0[taillabel=0 color=red];
+ Load16 -> Store14[taillabel=1 color=blue];
+ Load16 -> new9[taillabel=2];
+ If17 -> Start2:p0[taillabel=0 color=red];
+ If17 -> Start2:p2[taillabel=1];
+ Store22 -> Start2:p0[taillabel=0 color=red];
+ Store22 -> Store14[taillabel=1 color=blue];
+ Store22 -> new9[taillabel=2];
+ Store22 -> Con_21[taillabel=3];
+ Region23 -> If17:p0[taillabel=1 color=red];
+ Region23 -> If17:p1[taillabel=2 color=red];
+ Phi_224 -> Region23 [style=dotted taillabel=0];
+ Phi_224 -> Store22[taillabel=1 color=blue];
+ Phi_224 -> Store14[taillabel=2 color=blue constraint=false];
+ Return25 -> Region23[taillabel=0 color=red];
+ Return25 -> Load16[taillabel=2];
+ Return25 -> MemMerge[taillabel=1 color=blue];
+ MemMerge -> Start2:p1[taillabel=1 color=blue];
+ MemMerge -> Phi_224[taillabel=2 color=blue];
+ MemMerge -> Region23[taillabel=0 color=green];
+}
diff --git a/chapter13/docs/graph2.json b/chapter13/docs/graph2.json
new file mode 100644
index 00000000..47689c72
--- /dev/null
+++ b/chapter13/docs/graph2.json
@@ -0,0 +1,25 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph2.svg",
+ "step": 1,
+ "roots": [25],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 224, "role": "MEM", "label": null}], "proj": null},
+ {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}},
+ {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 11, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 12, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 11, "role": "DATA", "label": null}], "proj": null},
+ {"id": 13, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 14, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "MEM", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 16, "label": ".f", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null},
+ {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 22, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null},
+ {"id": 25, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null},
+ {"id": 224, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 14, "role": "MEM", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter13/docs/graph2.svg b/chapter13/docs/graph2.svg
new file mode 100644
index 00000000..05210749
--- /dev/null
+++ b/chapter13/docs/graph2.svg
@@ -0,0 +1,123 @@
+<svg aria-label="Compiler graph" width="565" height="766" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 565 766" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge MEM" id="e1i1" d="M84,118 L84,536 Q84,544 92,544 L137,544 Q145,544 145,552 L145,582" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[1] → #6 · MEM</title></path><path class="edge MEM" id="e1i2" d="M175,534 L175,582" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[2] → #224 · MEM</title></path><path class="edge MEM" id="e12i1" d="M84,118 L84,130 Q84,138 92,138 L146,138 Q154,138 154,146 L154,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#12[1] → #6 · MEM</title></path><path class="edge DATA" id="e12i2" d="M242,118 L242,123 Q242,128 237,128 L186,128 Q178,128 178,136 L178,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#12[2] → #9 · DATA</title></path><path class="edge DATA" id="e12i3" d="M394,118 L394,130 Q394,138 386,138 L210,138 Q202,138 202,146 L202,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#12[3] → #11 · DATA</title></path><path class="edge MEM" id="e14i1" d="M166,222 L166,227 Q166,232 171,232 L298,232 Q306,232 306,240 L306,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#14[1] → #12 · MEM</title></path><path class="edge DATA" id="e14i2" d="M318,222 L318,227 Q318,232 323,232 L324,232 Q330,232 330,238 L330,270" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#14[2] → #13 · DATA</title></path><path class="edge DATA" id="e14i3" d="M470,222 L470,227 Q470,232 465,232 L362,232 Q354,232 354,240 L354,270" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#14[3] → #4 · DATA</title></path><path class="edge MEM" id="e16i1" d="M318,326 L318,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#16[1] → #14 · MEM</title></path><path class="edge DATA" id="e16i2" d="M242,118 L242,123 Q242,128 247,128 L532,128 Q540,128 540,136 L540,328 Q540,336 532,336 L356,336 Q348,336 348,344 L348,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#16[2] → #9 · DATA</title></path><path class="edge MEM" id="e22i1" d="M318,326 L318,338 Q318,346 310,346 L151,346 Q143,346 143,354 L143,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[1] → #14 · MEM</title></path><path class="edge DATA" id="e22i2" d="M242,118 L242,123 Q242,128 237,128 L103,128 Q95,128 95,136 L95,348 Q95,356 103,356 L159,356 Q167,356 167,364 L167,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[2] → #9 · DATA</title></path><path class="edge DATA" id="e22i3" d="M166,326 L166,331 Q166,336 171,336 L183,336 Q191,336 191,344 L191,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[3] → #21 · DATA</title></path><path class="edge MEM" id="e25i1" d="M145,638 L145,643 Q145,648 150,648 L280,648 Q288,648 288,656 L288,686" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#25[1] → #1 · MEM</title></path><path class="edge DATA" id="e25i2" d="M318,430 L318,686" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#25[2] → #16 · DATA</title></path><path class="edge MEM" id="e224i1" d="M155,430 L155,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#224[1] → #22 · MEM</title></path><path class="edge MEM" id="e224i2" d="M318,326 L318,338 Q318,346 310,346 L233,346 Q225,346 225,354 L225,432 Q225,440 217,440 L203,440 Q195,440 195,448 L195,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#224[2] → #14 · MEM</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(85,588)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemMerge</tspan><tspan class="node-id">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #6 MEM
+[2] → #224 MEM</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n2" data-id="2" transform="translate(24,24)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Start</tspan><tspan class="node-id">  #2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#2 Start
+Type not computed
+
+</title></g><g class="node" id="n4" data-id="4" transform="translate(410,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#0</tspan><tspan class="node-id">  #4</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 #0
+Type not computed
+
+</title></g><g class="node" id="n6" data-id="6" transform="translate(24,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>$mem</tspan><tspan class="node-id">  #6/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 $mem
+Projection 1 of #2
+Type not computed
+
+[0] → #2 MEM</title></g><g class="node" id="n9" data-id="9" transform="translate(182,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n11" data-id="11" transform="translate(334,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#2</tspan><tspan class="node-id">  #11</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#11 #2
+Type not computed
+
+</title></g><g class="node" id="n12" data-id="12" transform="translate(106,172)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #12</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#12 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → #6 MEM
+[2] → #9 DATA
+[3] → #11 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n13" data-id="13" transform="translate(258,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #13</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#13 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n14" data-id="14" transform="translate(258,276)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #14</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#14 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → #12 MEM
+[2] → #13 DATA
+[3] → #4 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n16" data-id="16" transform="translate(258,380)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f</tspan><tspan class="node-id">  #16</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#16 .f
+Type not computed
+
+[0] → — CTRL
+[1] → #14 MEM
+[2] → #9 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n21" data-id="21" transform="translate(106,276)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#1</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#21 #1
+Type not computed
+
+</title></g><g class="node" id="n22" data-id="22" transform="translate(95,380)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → #14 MEM
+[2] → #9 DATA
+[3] → #21 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n25" data-id="25" transform="translate(228,692)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Return</tspan><tspan class="node-id">  #25</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#25 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #1 MEM
+[2] → #16 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n224" data-id="224" transform="translate(115,484)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #224</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#224 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #22 MEM
+[2] → #14 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>
diff --git a/chapter13/docs/graph3-snip.jpg b/chapter13/docs/graph3-snip.jpg
new file mode 100644
index 00000000..804a32c4
--- /dev/null
+++ b/chapter13/docs/graph3-snip.jpg
Binary files differ
diff --git a/chapter13/docs/graph3-snip.json b/chapter13/docs/graph3-snip.json
new file mode 100644
index 00000000..548dbdf3
--- /dev/null
+++ b/chapter13/docs/graph3-snip.json
@@ -0,0 +1,17 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph3-snip.svg",
+ "step": 1,
+ "roots": [22],
+ "scope": 0,
+ "nodes": [
+ {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 0}},
+ {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 14, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 0, "role": "MEM", "label": null}, {"idx": 2, "def": 0, "role": "DATA", "label": null}, {"idx": 3, "def": 0, "role": "DATA", "label": null}], "proj": null},
+ {"id": 16, "label": ".f", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null},
+ {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 22, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}, {"idx": 4, "def": 16, "role": "DATA", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter13/docs/graph3-snip.svg b/chapter13/docs/graph3-snip.svg
new file mode 100644
index 00000000..9f5218af
--- /dev/null
+++ b/chapter13/docs/graph3-snip.svg
@@ -0,0 +1,91 @@
+<svg aria-label="Compiler graph" width="427" height="314" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 427 314" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge MEM" id="e16i1" d="M109,80 L109,92 Q109,100 117,100 L335,100 Q343,100 343,108 L343,128" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#16[1] → #14 · MEM</title></path><path class="edge DATA" id="e16i2" d="M261,80 L261,85 Q261,90 266,90 L365,90 Q373,90 373,98 L373,128" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#16[2] → #9 · DATA</title></path><path class="edge CTRL" id="e22i0" d="M62,184 L62,234" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#22[0] → #8 · CTRL</title></path><path class="edge MEM" id="e22i1" d="M109,80 L109,186 Q109,194 101,194 L90,194 Q82,194 82,202 L82,234" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[1] → #14 · MEM</title></path><path class="edge DATA" id="e22i2" d="M261,80 L261,85 Q261,90 256,90 L128,90 Q120,90 120,98 L120,196 Q120,204 112,204 L110,204 Q102,204 102,212 L102,234" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[2] → #9 · DATA</title></path><path class="edge DATA" id="e22i3" d="M191,184 L191,206 Q191,214 183,214 L130,214 Q122,214 122,222 L122,234" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[3] → #21 · DATA</title></path><path class="edge DATA" id="e22i4" d="M343,184 L343,216 Q343,224 335,224 L147,224 Q142,224 142,229 L142,234" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[4] → #16 · DATA</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n8" data-id="8" transform="translate(24,152)" style="opacity: 1;"><path class="box" d="M0,0H75V26H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="37.5" y="17"><tspan>True</tspan><tspan class="node-id">  #8/0</tspan></text><text class="type" text-anchor="middle" y="35" x="37.5"/><title>#8 True
+Projection 0 of #0
+Type not computed
+
+</title></g><g class="node" id="n9" data-id="9" transform="translate(201,30)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n14" data-id="14" transform="translate(49,30)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #14</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#14 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → — MEM
+[2] → — DATA
+[3] → — DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="white"/><circle class="port" cx="72" cy="-3" r="3" fill="white"/><circle class="port" cx="96" cy="-3" r="3" fill="white"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n16" data-id="16" transform="translate(283,134)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f</tspan><tspan class="node-id">  #16</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#16 .f
+Type not computed
+
+[0] → — CTRL
+[1] → #14 MEM
+[2] → #9 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n21" data-id="21" transform="translate(131,134)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#1</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#21 #1
+Type not computed
+
+</title></g><g class="node" id="n22" data-id="22" transform="translate(42,240)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 .f =
+Type not computed
+
+[0] → #8 CTRL
+[1] → #14 MEM
+[2] → #9 DATA
+[3] → #21 DATA
+[4] → #16 DATA</title><circle class="port" cx="20" cy="-3" r="3" fill="#536477"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><circle class="port" cx="100" cy="-3" r="3" fill="#536477"/><text class="slot" x="20" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="60" y="-10" text-anchor="middle">2</text><text class="slot" x="80" y="-10" text-anchor="middle">3</text><text class="slot" x="100" y="-10" text-anchor="middle">4</text></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>
diff --git a/chapter13/docs/graph3.gv b/chapter13/docs/graph3.gv
new file mode 100644
index 00000000..53c9aafe
--- /dev/null
+++ b/chapter13/docs/graph3.gv
@@ -0,0 +1,85 @@
+digraph chapter13 {
+/*
+struct S { int f; }
+S v=new S;
+v.f = 2;
+int i=new S.f;
+i=v.f;
+if (arg) v.f=1;
+return i;
+
+*/
+ rankdir=BT;
+ concentrate="true";
+ compound="true";
+ subgraph cluster_Nodes {
+ Start2 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Start</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">$ctrl</TD><TD PORT="p1">$mem</TD><TD PORT="p2">arg</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ MemMerge [ shape=box label="MemMerge" ];
+ Stop3 [ shape=box style=filled fillcolor=yellow label="Stop" ];
+ Con_4 [ label="#0" ];
+ new9 [ label="new S" ];
+ Con_11 [ label="#2" ];
+ Store12 [ label=".f =" ];
+ new13 [ label="new S" ];
+ Store14 [ label=".f =" ];
+ Load16 [ label=".f" ];
+ If17 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Con_21 [ label="#1" ];
+ Store22 [ label=".f =" ];
+ Region23 [ shape=box style=filled fillcolor=yellow label="Region" ];
+ Phi_224 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Return25 [ shape=box style=filled fillcolor=yellow label="Return" ];
+ { rank=same; Region23;Phi_224;}
+ }
+ edge [ fontname=Helvetica, fontsize=8 ];
+ Stop3 -> Return25[taillabel=0 color=red];
+ new9 -> Start2:p0[taillabel=0 color=green];
+ Store12 -> Start2:p0[taillabel=0 color=red];
+ Store12 -> Start2:p1[taillabel=1 color=blue];
+ Store12 -> new9[taillabel=2];
+ Store12 -> Con_11[taillabel=3];
+ new13 -> Start2:p0[taillabel=0 color=green];
+ Store14 -> Start2:p0[taillabel=0 color=red];
+ Store14 -> Store12[taillabel=1 color=blue];
+ Store14 -> new13[taillabel=2];
+ Store14 -> Con_4[taillabel=3];
+ Load16 -> Start2:p0[taillabel=0 color=red];
+ Load16 -> Store14[taillabel=1 color=blue];
+ Load16 -> new9[taillabel=2];
+ If17 -> Start2:p0[taillabel=0 color=red];
+ If17 -> Start2:p2[taillabel=1];
+ Store22 -> If17:p0[taillabel=0 color=red];
+ Store22 -> Store14[taillabel=1 color=blue];
+ Store22 -> new9[taillabel=2];
+ Store22 -> Con_21[taillabel=3];
+ Store22 -> Load16[taillabel=4];
+ Region23 -> If17:p0[taillabel=1 color=red];
+ Region23 -> If17:p1[taillabel=2 color=red];
+ Phi_224 -> Region23 [style=dotted taillabel=0];
+ Phi_224 -> Store22[taillabel=1 color=blue];
+ Phi_224 -> Store14[taillabel=2 color=blue constraint=false];
+ Return25 -> Region23[taillabel=0 color=red];
+ Return25 -> Load16[taillabel=2];
+ Return25 -> MemMerge[taillabel=1 color=blue];
+ MemMerge -> Start2:p1[taillabel=1 color=blue];
+ MemMerge -> Phi_224[taillabel=2 color=blue];
+ MemMerge -> Region23[taillabel=0 color=green];
+}
diff --git a/chapter13/docs/graph3.json b/chapter13/docs/graph3.json
new file mode 100644
index 00000000..e44eb1b1
--- /dev/null
+++ b/chapter13/docs/graph3.json
@@ -0,0 +1,26 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph3.svg",
+ "step": 1,
+ "roots": [25],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 224, "role": "MEM", "label": null}], "proj": null},
+ {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}},
+ {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 0}},
+ {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 11, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 12, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 11, "role": "DATA", "label": null}], "proj": null},
+ {"id": 13, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 14, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "MEM", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 16, "label": ".f", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null},
+ {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 22, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}, {"idx": 4, "def": 16, "role": "DATA", "label": null}], "proj": null},
+ {"id": 25, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null},
+ {"id": 224, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 14, "role": "MEM", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter13/docs/graph3.svg b/chapter13/docs/graph3.svg
new file mode 100644
index 00000000..0247b5c6
--- /dev/null
+++ b/chapter13/docs/graph3.svg
@@ -0,0 +1,128 @@
+<svg aria-label="Compiler graph" width="661" height="872" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 661 872" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge MEM" id="e1i1" d="M84,118 L84,642 Q84,650 92,650 L387,650 Q395,650 395,658 L395,688" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[1] → #6 · MEM</title></path><path class="edge MEM" id="e1i2" d="M425,640 L425,688" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[2] → #224 · MEM</title></path><path class="edge MEM" id="e12i1" d="M84,118 L84,140 Q84,148 92,148 L242,148 Q250,148 250,156 L250,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#12[1] → #6 · MEM</title></path><path class="edge DATA" id="e12i2" d="M274,118 L274,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#12[2] → #9 · DATA</title></path><path class="edge DATA" id="e12i3" d="M426,118 L426,123 Q426,128 421,128 L306,128 Q298,128 298,136 L298,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#12[3] → #11 · DATA</title></path><path class="edge MEM" id="e14i1" d="M262,222 L262,227 Q262,232 267,232 L382,232 Q390,232 390,240 L390,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#14[1] → #12 · MEM</title></path><path class="edge DATA" id="e14i2" d="M414,222 L414,270" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#14[2] → #13 · DATA</title></path><path class="edge DATA" id="e14i3" d="M566,222 L566,227 Q566,232 561,232 L446,232 Q438,232 438,240 L438,270" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#14[3] → #4 · DATA</title></path><path class="edge MEM" id="e16i1" d="M402,326 L402,340 Q402,346 408,346 L408,346 Q414,346 414,352 L414,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#16[1] → #14 · MEM</title></path><path class="edge DATA" id="e16i2" d="M274,118 L274,130 Q274,138 282,138 L628,138 Q636,138 636,146 L636,328 Q636,336 628,336 L452,336 Q444,336 444,344 L444,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#16[2] → #9 · DATA</title></path><path class="edge CTRL" id="e22i0" d="M133,430 L133,480" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#22[0] → #8 · CTRL</title></path><path class="edge MEM" id="e22i1" d="M402,326 L402,338 Q402,346 394,346 L188,346 Q180,346 180,354 L180,432 Q180,440 172,440 L161,440 Q153,440 153,448 L153,480" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[1] → #14 · MEM</title></path><path class="edge DATA" id="e22i2" d="M274,118 L274,130 Q274,138 266,138 L199,138 Q191,138 191,146 L191,442 Q191,450 183,450 L181,450 Q173,450 173,458 L173,480" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[2] → #9 · DATA</title></path><path class="edge DATA" id="e22i3" d="M262,430 L262,452 Q262,460 254,460 L201,460 Q193,460 193,468 L193,480" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[3] → #21 · DATA</title></path><path class="edge DATA" id="e22i4" d="M414,430 L414,462 Q414,470 406,470 L218,470 Q213,470 213,475 L213,480" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#22[4] → #16 · DATA</title></path><path class="edge MEM" id="e25i1" d="M395,744 L395,749 Q395,754 400,754 L457,754 Q465,754 465,762 L465,792" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#25[1] → #1 · MEM</title></path><path class="edge DATA" id="e25i2" d="M414,430 L414,462 Q414,470 422,470 L487,470 Q495,470 495,478 L495,792" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#25[2] → #16 · DATA</title></path><path class="edge MEM" id="e224i1" d="M173,536 L173,541 Q173,546 178,546 L397,546 Q405,546 405,554 L405,584" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#224[1] → #22 · MEM</title></path><path class="edge MEM" id="e224i2" d="M402,326 L402,338 Q402,346 410,346 L476,346 Q484,346 484,354 L484,432 Q484,440 476,440 L453,440 Q445,440 445,448 L445,584" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#224[2] → #14 · MEM</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(335,694)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemMerge</tspan><tspan class="node-id">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #6 MEM
+[2] → #224 MEM</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n2" data-id="2" transform="translate(24,24)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Start</tspan><tspan class="node-id">  #2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#2 Start
+Type not computed
+
+</title></g><g class="node" id="n4" data-id="4" transform="translate(506,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#0</tspan><tspan class="node-id">  #4</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 #0
+Type not computed
+
+</title></g><g class="node" id="n6" data-id="6" transform="translate(24,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>$mem</tspan><tspan class="node-id">  #6/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 $mem
+Projection 1 of #2
+Type not computed
+
+[0] → #2 MEM</title></g><g class="node" id="n8" data-id="8" transform="translate(95,398)" style="opacity: 1;"><path class="box" d="M0,0H75V26H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="37.5" y="17"><tspan>True</tspan><tspan class="node-id">  #8/0</tspan></text><text class="type" text-anchor="middle" y="35" x="37.5"/><title>#8 True
+Projection 0 of #0
+Type not computed
+
+</title></g><g class="node" id="n9" data-id="9" transform="translate(214,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n11" data-id="11" transform="translate(366,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#2</tspan><tspan class="node-id">  #11</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#11 #2
+Type not computed
+
+</title></g><g class="node" id="n12" data-id="12" transform="translate(202,172)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #12</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#12 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → #6 MEM
+[2] → #9 DATA
+[3] → #11 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n13" data-id="13" transform="translate(354,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #13</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#13 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n14" data-id="14" transform="translate(342,276)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #14</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#14 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → #12 MEM
+[2] → #13 DATA
+[3] → #4 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n16" data-id="16" transform="translate(354,380)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f</tspan><tspan class="node-id">  #16</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#16 .f
+Type not computed
+
+[0] → — CTRL
+[1] → #14 MEM
+[2] → #9 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n21" data-id="21" transform="translate(202,380)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#1</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#21 #1
+Type not computed
+
+</title></g><g class="node" id="n22" data-id="22" transform="translate(113,486)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 .f =
+Type not computed
+
+[0] → #8 CTRL
+[1] → #14 MEM
+[2] → #9 DATA
+[3] → #21 DATA
+[4] → #16 DATA</title><circle class="port" cx="20" cy="-3" r="3" fill="#536477"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><circle class="port" cx="100" cy="-3" r="3" fill="#536477"/><text class="slot" x="20" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="60" y="-10" text-anchor="middle">2</text><text class="slot" x="80" y="-10" text-anchor="middle">3</text><text class="slot" x="100" y="-10" text-anchor="middle">4</text></g><g class="node" id="n25" data-id="25" transform="translate(405,798)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Return</tspan><tspan class="node-id">  #25</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#25 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #1 MEM
+[2] → #16 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n224" data-id="224" transform="translate(365,590)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #224</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#224 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #22 MEM
+[2] → #14 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>
diff --git a/chapter13/docs/graph4.gv b/chapter13/docs/graph4.gv
new file mode 100644
index 00000000..d7082072
--- /dev/null
+++ b/chapter13/docs/graph4.gv
@@ -0,0 +1,110 @@
+digraph chapter13 {
+/*
+struct S { int f; }
+S v = new S;
+int i = arg;
+while (arg > 0) {
+ int j = i/3;
+ if (arg == 5)
+ v.f = j;
+ arg = arg - 1;
+}
+return v;
+
+*/
+ rankdir=BT;
+ concentrate="true";
+ compound="true";
+ subgraph cluster_Nodes {
+ Start2 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Start</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">$ctrl</TD><TD PORT="p1">$mem</TD><TD PORT="p2">arg</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ MemMerge [ shape=box label="MemMerge" ];
+ Stop3 [ shape=box style=filled fillcolor=yellow label="Stop" ];
+ Con_4 [ label="#0" ];
+ new9 [ label="new S" ];
+ Store10 [ label=".f =" ];
+ Loop11 [ shape=box style=filled fillcolor=yellow label="Loop" ];
+ Phi_arg13 [ style=filled fillcolor=lightyellow label="&phi;_arg" ];
+ LT14 [ label="<" ];
+ If16 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Div21 [ label="//" ];
+ Con_22 [ label="#3" ];
+ EQ23 [ label="==" ];
+ Con_24 [ label="#5" ];
+ If25 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Phi_230 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Store31 [ label=".f =" ];
+ Region32 [ shape=box style=filled fillcolor=yellow label="Region" ];
+ Phi_233 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Sub35 [ label="-" ];
+ Con_36 [ label="#1" ];
+ Return37 [ shape=box style=filled fillcolor=yellow label="Return" ];
+ { rank=same; Loop11;Phi_230;Phi_arg13;}
+ { rank=same; Region32;Phi_233;}
+ }
+ edge [ fontname=Helvetica, fontsize=8 ];
+ Stop3 -> Return37[taillabel=0 color=red];
+ new9 -> Start2:p0[taillabel=0 color=green];
+ Store10 -> Start2:p1[taillabel=1 color=blue];
+ Store10 -> new9[taillabel=2];
+ Store10 -> Con_4[taillabel=3];
+ Loop11 -> Start2:p0[taillabel=1 color=red];
+ Loop11 -> Region32[taillabel=2 color=red constraint=false];
+ Phi_arg13 -> Loop11 [style=dotted taillabel=0];
+ Phi_arg13 -> Start2:p2[taillabel=1];
+ Phi_arg13 -> Sub35[taillabel=2 constraint=false];
+ LT14 -> Con_4[taillabel=1];
+ LT14 -> Phi_arg13[taillabel=2];
+ If16 -> Loop11[taillabel=0 color=red];
+ If16 -> LT14[taillabel=1];
+ Div21 -> Start2:p2[taillabel=1];
+ Div21 -> Con_22[taillabel=2];
+ EQ23 -> Phi_arg13[taillabel=1];
+ EQ23 -> Con_24[taillabel=2];
+ If25 -> If16:p0[taillabel=0 color=red];
+ If25 -> EQ23[taillabel=1];
+ Phi_230 -> Loop11 [style=dotted taillabel=0];
+ Phi_230 -> Store10[taillabel=1 color=blue];
+ Phi_230 -> Phi_233[taillabel=2 color=blue constraint=false];
+ Store31 -> Phi_230[taillabel=1 color=blue];
+ Store31 -> new9[taillabel=2];
+ Store31 -> Div21[taillabel=3];
+ Region32 -> If25:p0[taillabel=1 color=red];
+ Region32 -> If25:p1[taillabel=2 color=red];
+ Phi_233 -> Region32 [style=dotted taillabel=0];
+ Phi_233 -> Store31[taillabel=1 color=blue];
+ Phi_233 -> Phi_230[taillabel=2 color=blue constraint=false];
+ Sub35 -> Phi_arg13[taillabel=1];
+ Sub35 -> Con_36[taillabel=2];
+ Return37 -> If16:p1[taillabel=0 color=red];
+ Return37 -> new9[taillabel=2];
+ Return37 -> MemMerge[taillabel=1 color=blue];
+ MemMerge -> Start2:p1[taillabel=1 color=blue];
+ MemMerge -> Phi_230[taillabel=2 color=blue];
+}
diff --git a/chapter13/docs/graph4.json b/chapter13/docs/graph4.json
new file mode 100644
index 00000000..add08b6b
--- /dev/null
+++ b/chapter13/docs/graph4.json
@@ -0,0 +1,24 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph4.svg",
+ "step": 1,
+ "roots": [37],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null},
+ {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}},
+ {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}},
+ {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 10, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 21, "label": "//", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 22, "role": "DATA", "label": null}], "proj": null},
+ {"id": 22, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 31, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 230, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null},
+ {"id": 37, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null},
+ {"id": 230, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 10, "role": "MEM", "label": null}, {"idx": 2, "def": 233, "role": "MEM", "label": null}], "proj": null},
+ {"id": 233, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 31, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter13/docs/graph4.svg b/chapter13/docs/graph4.svg
new file mode 100644
index 00000000..9ca92879
--- /dev/null
+++ b/chapter13/docs/graph4.svg
@@ -0,0 +1,120 @@
+<svg aria-label="Compiler graph" width="780" height="568" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 780 568" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge MEM" id="e1i1" d="M266,118 L266,123 Q266,128 261,128 L193,128 Q185,128 185,136 L185,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[1] → #6 · MEM</title></path><path class="edge MEM" id="e1i2" d="M259,326 L259,338 Q259,346 251,346 L223,346 Q215,346 215,354 L215,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[2] → #230 · MEM</title></path><path class="edge MEM" id="e10i1" d="M266,118 L266,123 Q266,128 261,128 L252,128 Q244,128 244,136 L244,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#10[1] → #6 · MEM</title></path><path class="edge DATA" id="e10i2" d="M114,118 L114,130 Q114,138 122,138 L260,138 Q268,138 268,146 L268,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#10[2] → #9 · DATA</title></path><path class="edge DATA" id="e10i3" d="M544,118 L544,123 Q544,128 539,128 L300,128 Q292,128 292,136 L292,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#10[3] → #4 · DATA</title></path><path class="edge DATA" id="e21i1" d="M386,118 L386,130 Q386,138 394,138 L400,138 Q408,138 408,146 L408,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[1] → #7 · DATA</title></path><path class="edge DATA" id="e21i2" d="M696,118 L696,130 Q696,138 688,138 L446,138 Q438,138 438,146 L438,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[2] → #22 · DATA</title></path><path class="edge MEM" id="e31i1" d="M259,326 L259,338 Q259,346 267,346 L306,346 Q314,346 314,354 L314,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#31[1] → #230 · MEM</title></path><path class="edge DATA" id="e31i2" d="M114,118 L114,328 Q114,336 122,336 L330,336 Q338,336 338,344 L338,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#31[2] → #9 · DATA</title></path><path class="edge DATA" id="e31i3" d="M408,222 L408,328 Q408,336 400,336 L370,336 Q362,336 362,344 L362,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#31[3] → #21 · DATA</title></path><path class="edge MEM" id="e37i1" d="M185,430 L185,435 Q185,440 180,440 L92,440 Q84,440 84,448 L84,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#37[1] → #1 · MEM</title></path><path class="edge DATA" id="e37i2" d="M114,118 L114,478" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#37[2] → #9 · DATA</title></path><path class="edge MEM" id="e230i1" d="M256,222 L256,227 Q256,232 251,232 L247,232 Q239,232 239,240 L239,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#230[1] → #10 · MEM</title></path><path class="edge MEM" id="e230i2" d="M326,534 L326,539 Q326,544 331,544 L388,544 Q396,544 396,536 L396,240 Q396,232 388,232 L287,232 Q279,232 279,240 L279,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#230[2] → #233 · MEM</title></path><path class="edge MEM" id="e233i1" d="M326,430 L326,435 Q326,440 321,440 L314,440 Q306,440 306,448 L306,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#233[1] → #31 · MEM</title></path><path class="edge MEM" id="e233i2" d="M259,326 L259,344 Q259,346 257,346 L257,346 Q255,346 255,348 L255,442 Q255,450 263,450 L338,450 Q346,450 346,458 L346,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#233[2] → #230 · MEM</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(125,380)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemMerge</tspan><tspan class="node-id">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 MemMerge
+Type not computed
+
+[0] → — DATA
+[1] → #6 MEM
+[2] → #230 MEM</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n2" data-id="2" transform="translate(206,24)" style="opacity: 1;"><path class="box" d="M0,0H240V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="120" y="18"><tspan>Start</tspan><tspan class="node-id">  #2</tspan></text><text class="type" text-anchor="middle" y="35" x="120"/><title>#2 Start
+Type not computed
+
+</title></g><g class="node" id="n4" data-id="4" transform="translate(484,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#0</tspan><tspan class="node-id">  #4</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 #0
+Type not computed
+
+</title></g><g class="node" id="n6" data-id="6" transform="translate(206,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>$mem</tspan><tspan class="node-id">  #6/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 $mem
+Projection 1 of #2
+Type not computed
+
+[0] → #2 MEM</title></g><g class="node" id="n7" data-id="7" transform="translate(326,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>arg</tspan><tspan class="node-id">  #7/2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#7 arg
+Projection 2 of #2
+Type not computed
+
+[0] → #2 DATA</title></g><g class="node" id="n9" data-id="9" transform="translate(54,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n10" data-id="10" transform="translate(196,172)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #10</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#10 .f =
+Type not computed
+
+[0] → — DATA
+[1] → #6 MEM
+[2] → #9 DATA
+[3] → #4 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n21" data-id="21" transform="translate(348,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>//</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#21 //
+Type not computed
+
+[0] → — DATA
+[1] → #7 DATA
+[2] → #22 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n22" data-id="22" transform="translate(636,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#3</tspan><tspan class="node-id">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 #3
+Type not computed
+
+</title></g><g class="node" id="n31" data-id="31" transform="translate(266,380)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #31</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#31 .f =
+Type not computed
+
+[0] → — DATA
+[1] → #230 MEM
+[2] → #9 DATA
+[3] → #21 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n37" data-id="37" transform="translate(24,484)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Return</tspan><tspan class="node-id">  #37</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#37 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #1 MEM
+[2] → #9 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n230" data-id="230" transform="translate(199,276)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #230</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#230 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #10 MEM
+[2] → #233 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g><g class="node" id="n233" data-id="233" transform="translate(266,484)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #233</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#233 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #31 MEM
+[2] → #230 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>
diff --git a/chapter13/docs/graph5.gv b/chapter13/docs/graph5.gv
new file mode 100644
index 00000000..8189f6dd
--- /dev/null
+++ b/chapter13/docs/graph5.gv
@@ -0,0 +1,117 @@
+digraph chapter13 {
+/*
+struct S { int f; }
+S v = new S;
+int i = arg;
+while (arg > 0) {
+ int j = i/3;
+ if (arg == 5)
+ v.f = j;
+ arg = arg - 1;
+}
+return v;
+
+*/
+ rankdir=BT;
+ concentrate="true";
+ compound="true";
+ subgraph cluster_Nodes {
+ Start2 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Start</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">$ctrl</TD><TD PORT="p1">$mem</TD><TD PORT="p2">arg</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ MemMerge [ shape=box label="MemMerge" ];
+ Stop3 [ shape=box style=filled fillcolor=yellow label="Stop" ];
+ Con_4 [ label="#0" ];
+ new9 [ label="new S" ];
+ Store10 [ label=".f =" ];
+ Loop11 [ shape=box style=filled fillcolor=yellow label="Loop" ];
+ Phi_arg13 [ style=filled fillcolor=lightyellow label="&phi;_arg" ];
+ LT14 [ label="<" ];
+ If16 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Div21 [ label="//" ];
+ Con_22 [ label="#3" ];
+ EQ23 [ label="==" ];
+ Con_24 [ label="#5" ];
+ If25 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Phi_230 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Store31 [ label=".f =" ];
+ Region32 [ shape=box style=filled fillcolor=yellow label="Region" ];
+ Phi_233 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Sub35 [ label="-" ];
+ Con_36 [ label="#1" ];
+ Return37 [ shape=box style=filled fillcolor=yellow label="Return" ];
+ { rank=same; Loop11;Phi_230;Phi_arg13;}
+ { rank=same; Region32;Phi_233;}
+ }
+ edge [ fontname=Helvetica, fontsize=8 ];
+ Stop3 -> Return37[taillabel=0 color=red];
+ new9 -> Start2:p0[taillabel=0 color=green];
+ Store10 -> Start2:p0[taillabel=0 color=red];
+ Store10 -> Start2:p1[taillabel=1 color=blue];
+ Store10 -> new9[taillabel=2];
+ Store10 -> Con_4[taillabel=3];
+ Loop11 -> Start2:p0[taillabel=1 color=red];
+ Loop11 -> Region32[taillabel=2 color=red constraint=false];
+ Phi_arg13 -> Loop11 [style=dotted taillabel=0];
+ Phi_arg13 -> Start2:p2[taillabel=1];
+ Phi_arg13 -> Sub35[taillabel=2 constraint=false];
+ LT14 -> Loop11[taillabel=0 color=red];
+ LT14 -> Con_4[taillabel=1];
+ LT14 -> Phi_arg13[taillabel=2];
+ If16 -> Loop11[taillabel=0 color=red];
+ If16 -> LT14[taillabel=1];
+ Div21 -> Start2[taillabel=0 color=red];
+ Div21 -> Start2:p2[taillabel=1];
+ Div21 -> Con_22[taillabel=2];
+ EQ23 -> Loop11[taillabel=0 color=red];
+ EQ23 -> Phi_arg13[taillabel=1];
+ EQ23 -> Con_24[taillabel=2];
+ If25 -> If16:p0[taillabel=0 color=red];
+ If25 -> EQ23[taillabel=1];
+ Phi_230 -> Loop11 [style=dotted taillabel=0];
+ Phi_230 -> Store10[taillabel=1 color=blue];
+ Phi_230 -> Phi_233[taillabel=2 color=blue constraint=false];
+ Store31 -> Loop11[taillabel=0 color=red];
+ Store31 -> Phi_230[taillabel=1 color=blue];
+ Store31 -> new9[taillabel=2];
+ Store31 -> Div21[taillabel=3];
+ Region32 -> If25:p0[taillabel=1 color=red];
+ Region32 -> If25:p1[taillabel=2 color=red];
+ Phi_233 -> Region32 [style=dotted taillabel=0];
+ Phi_233 -> Store31[taillabel=1 color=blue];
+ Phi_233 -> Phi_230[taillabel=2 color=blue constraint=false];
+ Sub35 -> Loop11[taillabel=0 color=red];
+ Sub35 -> Phi_arg13[taillabel=1];
+ Sub35 -> Con_36[taillabel=2];
+ Return37 -> If16:p1[taillabel=0 color=red];
+ Return37 -> new9[taillabel=2];
+ Return37 -> MemMerge[taillabel=1 color=blue];
+ MemMerge -> Start2:p1[taillabel=1 color=blue];
+ MemMerge -> Phi_230[taillabel=2 color=blue];
+ MemMerge -> Loop11[taillabel=0 color=green];
+}
diff --git a/chapter13/docs/graph5.json b/chapter13/docs/graph5.json
new file mode 100644
index 00000000..6b1722f6
--- /dev/null
+++ b/chapter13/docs/graph5.json
@@ -0,0 +1,24 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph5.svg",
+ "step": 1,
+ "roots": [37],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null},
+ {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}},
+ {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}},
+ {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 10, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 21, "label": "//", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 22, "role": "DATA", "label": null}], "proj": null},
+ {"id": 22, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 31, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 230, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null},
+ {"id": 37, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null},
+ {"id": 230, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 10, "role": "MEM", "label": null}, {"idx": 2, "def": 233, "role": "MEM", "label": null}], "proj": null},
+ {"id": 233, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 31, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter13/docs/graph5.svg b/chapter13/docs/graph5.svg
new file mode 100644
index 00000000..c120550f
--- /dev/null
+++ b/chapter13/docs/graph5.svg
@@ -0,0 +1,120 @@
+<svg aria-label="Compiler graph" width="780" height="568" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 780 568" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge MEM" id="e1i1" d="M266,118 L266,123 Q266,128 261,128 L193,128 Q185,128 185,136 L185,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[1] → #6 · MEM</title></path><path class="edge MEM" id="e1i2" d="M259,326 L259,338 Q259,346 251,346 L223,346 Q215,346 215,354 L215,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[2] → #230 · MEM</title></path><path class="edge MEM" id="e10i1" d="M266,118 L266,123 Q266,128 261,128 L252,128 Q244,128 244,136 L244,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#10[1] → #6 · MEM</title></path><path class="edge DATA" id="e10i2" d="M114,118 L114,130 Q114,138 122,138 L260,138 Q268,138 268,146 L268,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#10[2] → #9 · DATA</title></path><path class="edge DATA" id="e10i3" d="M544,118 L544,123 Q544,128 539,128 L300,128 Q292,128 292,136 L292,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#10[3] → #4 · DATA</title></path><path class="edge DATA" id="e21i1" d="M386,118 L386,130 Q386,138 394,138 L400,138 Q408,138 408,146 L408,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[1] → #7 · DATA</title></path><path class="edge DATA" id="e21i2" d="M696,118 L696,130 Q696,138 688,138 L446,138 Q438,138 438,146 L438,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[2] → #22 · DATA</title></path><path class="edge MEM" id="e31i1" d="M259,326 L259,338 Q259,346 267,346 L306,346 Q314,346 314,354 L314,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#31[1] → #230 · MEM</title></path><path class="edge DATA" id="e31i2" d="M114,118 L114,328 Q114,336 122,336 L330,336 Q338,336 338,344 L338,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#31[2] → #9 · DATA</title></path><path class="edge DATA" id="e31i3" d="M408,222 L408,328 Q408,336 400,336 L370,336 Q362,336 362,344 L362,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#31[3] → #21 · DATA</title></path><path class="edge MEM" id="e37i1" d="M185,430 L185,435 Q185,440 180,440 L92,440 Q84,440 84,448 L84,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#37[1] → #1 · MEM</title></path><path class="edge DATA" id="e37i2" d="M114,118 L114,478" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#37[2] → #9 · DATA</title></path><path class="edge MEM" id="e230i1" d="M256,222 L256,227 Q256,232 251,232 L247,232 Q239,232 239,240 L239,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#230[1] → #10 · MEM</title></path><path class="edge MEM" id="e230i2" d="M326,534 L326,539 Q326,544 331,544 L388,544 Q396,544 396,536 L396,240 Q396,232 388,232 L287,232 Q279,232 279,240 L279,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#230[2] → #233 · MEM</title></path><path class="edge MEM" id="e233i1" d="M326,430 L326,435 Q326,440 321,440 L314,440 Q306,440 306,448 L306,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#233[1] → #31 · MEM</title></path><path class="edge MEM" id="e233i2" d="M259,326 L259,344 Q259,346 257,346 L257,346 Q255,346 255,348 L255,442 Q255,450 263,450 L338,450 Q346,450 346,458 L346,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#233[2] → #230 · MEM</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(125,380)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemMerge</tspan><tspan class="node-id">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #6 MEM
+[2] → #230 MEM</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n2" data-id="2" transform="translate(206,24)" style="opacity: 1;"><path class="box" d="M0,0H240V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="120" y="18"><tspan>Start</tspan><tspan class="node-id">  #2</tspan></text><text class="type" text-anchor="middle" y="35" x="120"/><title>#2 Start
+Type not computed
+
+</title></g><g class="node" id="n4" data-id="4" transform="translate(484,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#0</tspan><tspan class="node-id">  #4</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 #0
+Type not computed
+
+</title></g><g class="node" id="n6" data-id="6" transform="translate(206,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>$mem</tspan><tspan class="node-id">  #6/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 $mem
+Projection 1 of #2
+Type not computed
+
+[0] → #2 MEM</title></g><g class="node" id="n7" data-id="7" transform="translate(326,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>arg</tspan><tspan class="node-id">  #7/2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#7 arg
+Projection 2 of #2
+Type not computed
+
+[0] → #2 DATA</title></g><g class="node" id="n9" data-id="9" transform="translate(54,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n10" data-id="10" transform="translate(196,172)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #10</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#10 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → #6 MEM
+[2] → #9 DATA
+[3] → #4 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n21" data-id="21" transform="translate(348,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>//</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#21 //
+Type not computed
+
+[0] → — CTRL
+[1] → #7 DATA
+[2] → #22 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n22" data-id="22" transform="translate(636,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#3</tspan><tspan class="node-id">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 #3
+Type not computed
+
+</title></g><g class="node" id="n31" data-id="31" transform="translate(266,380)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #31</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#31 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → #230 MEM
+[2] → #9 DATA
+[3] → #21 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n37" data-id="37" transform="translate(24,484)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Return</tspan><tspan class="node-id">  #37</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#37 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #1 MEM
+[2] → #9 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n230" data-id="230" transform="translate(199,276)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #230</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#230 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #10 MEM
+[2] → #233 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g><g class="node" id="n233" data-id="233" transform="translate(266,484)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #233</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#233 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #31 MEM
+[2] → #230 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>
diff --git a/chapter13/docs/graph6.gv b/chapter13/docs/graph6.gv
new file mode 100644
index 00000000..47165fdb
--- /dev/null
+++ b/chapter13/docs/graph6.gv
@@ -0,0 +1,117 @@
+digraph chapter13 {
+/*
+struct S { int f; }
+S v = new S;
+int i = arg;
+while (arg > 0) {
+ int j = i/3;
+ if (arg == 5)
+ v.f = j;
+ arg = arg - 1;
+}
+return v;
+
+*/
+ rankdir=BT;
+ concentrate="true";
+ compound="true";
+ subgraph cluster_Nodes {
+ Start2 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Start</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">$ctrl</TD><TD PORT="p1">$mem</TD><TD PORT="p2">arg</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ MemMerge [ shape=box label="MemMerge" ];
+ Stop3 [ shape=box style=filled fillcolor=yellow label="Stop" ];
+ Con_4 [ label="#0" ];
+ new9 [ label="new S" ];
+ Store10 [ label=".f =" ];
+ Loop11 [ shape=box style=filled fillcolor=yellow label="Loop" ];
+ Phi_arg13 [ style=filled fillcolor=lightyellow label="&phi;_arg" ];
+ LT14 [ label="<" ];
+ If16 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Div21 [ label="//" ];
+ Con_22 [ label="#3" ];
+ EQ23 [ label="==" ];
+ Con_24 [ label="#5" ];
+ If25 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">If</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Phi_230 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Store31 [ label=".f =" ];
+ Region32 [ shape=box style=filled fillcolor=yellow label="Region" ];
+ Phi_233 [ style=filled fillcolor=lightyellow label="MemPhi_2" ];
+ Sub35 [ label="-" ];
+ Con_36 [ label="#1" ];
+ Return37 [ shape=box style=filled fillcolor=yellow label="Return" ];
+ { rank=same; Loop11;Phi_230;Phi_arg13;}
+ { rank=same; Region32;Phi_233;}
+ }
+ edge [ fontname=Helvetica, fontsize=8 ];
+ Stop3 -> Return37[taillabel=0 color=red];
+ new9 -> Start2:p0[taillabel=0 color=green];
+ Store10 -> Start2:p0[taillabel=0 color=red];
+ Store10 -> Start2:p1[taillabel=1 color=blue];
+ Store10 -> new9[taillabel=2];
+ Store10 -> Con_4[taillabel=3];
+ Loop11 -> Start2:p0[taillabel=1 color=red];
+ Loop11 -> Region32[taillabel=2 color=red constraint=false];
+ Phi_arg13 -> Loop11 [style=dotted taillabel=0];
+ Phi_arg13 -> Start2:p2[taillabel=1];
+ Phi_arg13 -> Sub35[taillabel=2 constraint=false];
+ LT14 -> Loop11[taillabel=0 color=red];
+ LT14 -> Con_4[taillabel=1];
+ LT14 -> Phi_arg13[taillabel=2];
+ If16 -> Loop11[taillabel=0 color=red];
+ If16 -> LT14[taillabel=1];
+ Div21 -> Start2:p0[taillabel=0 color=red];
+ Div21 -> Start2:p2[taillabel=1];
+ Div21 -> Con_22[taillabel=2];
+ EQ23 -> If16:p0[taillabel=0 color=red];
+ EQ23 -> Phi_arg13[taillabel=1];
+ EQ23 -> Con_24[taillabel=2];
+ If25 -> If16:p0[taillabel=0 color=red];
+ If25 -> EQ23[taillabel=1];
+ Phi_230 -> Loop11 [style=dotted taillabel=0];
+ Phi_230 -> Store10[taillabel=1 color=blue];
+ Phi_230 -> Phi_233[taillabel=2 color=blue constraint=false];
+ Store31 -> If25:p0[taillabel=0 color=red];
+ Store31 -> Phi_230[taillabel=1 color=blue];
+ Store31 -> new9[taillabel=2];
+ Store31 -> Div21[taillabel=3];
+ Region32 -> If25:p0[taillabel=1 color=red];
+ Region32 -> If25:p1[taillabel=2 color=red];
+ Phi_233 -> Region32 [style=dotted taillabel=0];
+ Phi_233 -> Store31[taillabel=1 color=blue];
+ Phi_233 -> Phi_230[taillabel=2 color=blue constraint=false];
+ Sub35 -> Region32[taillabel=0 color=red];
+ Sub35 -> Phi_arg13[taillabel=1];
+ Sub35 -> Con_36[taillabel=2];
+ Return37 -> If16:p1[taillabel=0 color=red];
+ Return37 -> new9[taillabel=2];
+ Return37 -> MemMerge[taillabel=1 color=blue];
+ MemMerge -> Start2:p1[taillabel=1 color=blue];
+ MemMerge -> Phi_230[taillabel=2 color=blue];
+ MemMerge -> If16:p1[taillabel=0 color=green];
+}
diff --git a/chapter13/docs/graph6.json b/chapter13/docs/graph6.json
new file mode 100644
index 00000000..c63c717f
--- /dev/null
+++ b/chapter13/docs/graph6.json
@@ -0,0 +1,25 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph6.svg",
+ "step": 1,
+ "roots": [37],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null},
+ {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}},
+ {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}},
+ {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 10, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 15, "label": "True", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 0}},
+ {"id": 21, "label": "//", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 22, "role": "DATA", "label": null}], "proj": null},
+ {"id": 22, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 31, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}, {"idx": 1, "def": 230, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null},
+ {"id": 37, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null},
+ {"id": 230, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 10, "role": "MEM", "label": null}, {"idx": 2, "def": 233, "role": "MEM", "label": null}], "proj": null},
+ {"id": 233, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 31, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter13/docs/graph6.svg b/chapter13/docs/graph6.svg
new file mode 100644
index 00000000..d6dec88f
--- /dev/null
+++ b/chapter13/docs/graph6.svg
@@ -0,0 +1,124 @@
+<svg aria-label="Compiler graph" width="820" height="568" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 820 568" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"/><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge MEM" id="e1i1" d="M306,118 L306,123 Q306,128 301,128 L151,128 Q143,128 143,136 L143,328 Q143,336 135,336 L92,336 Q84,336 84,344 L84,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[1] → #6 · MEM</title></path><path class="edge MEM" id="e1i2" d="M331,326 L331,338 Q331,346 323,346 L122,346 Q114,346 114,354 L114,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#1[2] → #230 · MEM</title></path><path class="edge MEM" id="e10i1" d="M306,118 L306,123 Q306,128 301,128 L270,128 Q262,128 262,136 L262,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#10[1] → #6 · MEM</title></path><path class="edge DATA" id="e10i2" d="M154,118 L154,130 Q154,138 162,138 L278,138 Q286,138 286,146 L286,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#10[2] → #9 · DATA</title></path><path class="edge DATA" id="e10i3" d="M584,118 L584,130 Q584,138 576,138 L318,138 Q310,138 310,146 L310,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#10[3] → #4 · DATA</title></path><path class="edge DATA" id="e21i1" d="M426,118 L426,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[1] → #7 · DATA</title></path><path class="edge DATA" id="e21i2" d="M736,118 L736,140 Q736,148 728,148 L464,148 Q456,148 456,156 L456,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[2] → #22 · DATA</title></path><path class="edge CTRL" id="e31i0" d="M206,326 L206,374" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#31[0] → #15 · CTRL</title></path><path class="edge MEM" id="e31i1" d="M331,326 L331,338 Q331,346 323,346 L238,346 Q230,346 230,354 L230,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#31[1] → #230 · MEM</title></path><path class="edge DATA" id="e31i2" d="M154,118 L154,224 Q154,232 162,232 L249,232 Q257,232 257,240 L257,354.5 Q257,356 255.5,356 L255.5,356 Q254,356 254,357.5 L254,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#31[2] → #9 · DATA</title></path><path class="edge DATA" id="e31i3" d="M426,222 L426,234 Q426,242 418,242 L409,242 Q401,242 401,250 L401,348 Q401,356 393,356 L286,356 Q278,356 278,364 L278,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#31[3] → #21 · DATA</title></path><path class="edge MEM" id="e37i1" d="M84,430 L84,435 Q84,440 89,440 L116,440 Q124,440 124,448 L124,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#37[1] → #1 · MEM</title></path><path class="edge DATA" id="e37i2" d="M154,118 L154,478" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#37[2] → #9 · DATA</title></path><path class="edge MEM" id="e230i1" d="M274,222 L274,227 Q274,232 279,232 L303,232 Q311,232 311,240 L311,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#230[1] → #10 · MEM</title></path><path class="edge MEM" id="e230i2" d="M311,534 L311,539 Q311,544 316,544 L404,544 Q412,544 412,536 L412,240 Q412,232 404,232 L359,232 Q351,232 351,240 L351,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#230[2] → #233 · MEM</title></path><path class="edge MEM" id="e233i1" d="M242,430 L242,435 Q242,440 247,440 L283,440 Q291,440 291,448 L291,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#233[1] → #31 · MEM</title></path><path class="edge MEM" id="e233i2" d="M331,326 L331,478" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#233[2] → #230 · MEM</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(24,380)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemMerge</tspan><tspan class="node-id">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #6 MEM
+[2] → #230 MEM</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n2" data-id="2" transform="translate(246,24)" style="opacity: 1;"><path class="box" d="M0,0H240V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="120" y="18"><tspan>Start</tspan><tspan class="node-id">  #2</tspan></text><text class="type" text-anchor="middle" y="35" x="120"/><title>#2 Start
+Type not computed
+
+</title></g><g class="node" id="n4" data-id="4" transform="translate(524,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#0</tspan><tspan class="node-id">  #4</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 #0
+Type not computed
+
+</title></g><g class="node" id="n6" data-id="6" transform="translate(246,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>$mem</tspan><tspan class="node-id">  #6/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 $mem
+Projection 1 of #2
+Type not computed
+
+[0] → #2 MEM</title></g><g class="node" id="n7" data-id="7" transform="translate(366,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>arg</tspan><tspan class="node-id">  #7/2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#7 arg
+Projection 2 of #2
+Type not computed
+
+[0] → #2 DATA</title></g><g class="node" id="n9" data-id="9" transform="translate(94,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>new S</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 new S
+Type not computed
+
+[0] → — CTRL</title><circle class="port" cx="60" cy="-3" r="3" fill="white"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n10" data-id="10" transform="translate(214,172)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #10</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#10 .f =
+Type not computed
+
+[0] → — CTRL
+[1] → #6 MEM
+[2] → #9 DATA
+[3] → #4 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="white"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n15" data-id="15" transform="translate(165,294)" style="opacity: 1;"><path class="box" d="M0,0H82V26H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="41" y="17"><tspan>True</tspan><tspan class="node-id">  #15/0</tspan></text><text class="type" text-anchor="middle" y="35" x="41"/><title>#15 True
+Projection 0 of #0
+Type not computed
+
+</title></g><g class="node" id="n21" data-id="21" transform="translate(366,172)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>//</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#21 //
+Type not computed
+
+[0] → — CTRL
+[1] → #7 DATA
+[2] → #22 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n22" data-id="22" transform="translate(676,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#3</tspan><tspan class="node-id">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 #3
+Type not computed
+
+</title></g><g class="node" id="n31" data-id="31" transform="translate(182,380)" style="opacity: 1;"><path class="box" d="M10,0H110L120,10V34L110,44H10L0,34V10Z" fill="#dcecff"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>.f =</tspan><tspan class="node-id">  #31</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#31 .f =
+Type not computed
+
+[0] → #15 CTRL
+[1] → #230 MEM
+[2] → #9 DATA
+[3] → #21 DATA</title><circle class="port" cx="24" cy="-3" r="3" fill="#536477"/><circle class="port" cx="48" cy="-3" r="3" fill="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><circle class="port" cx="96" cy="-3" r="3" fill="#536477"/><text class="slot" x="24" y="-10" text-anchor="middle">0</text><text class="slot" x="48" y="-10" text-anchor="middle">1</text><text class="slot" x="72" y="-10" text-anchor="middle">2</text><text class="slot" x="96" y="-10" text-anchor="middle">3</text></g><g class="node" id="n37" data-id="37" transform="translate(64,484)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Return</tspan><tspan class="node-id">  #37</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#37 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #1 MEM
+[2] → #9 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n230" data-id="230" transform="translate(271,276)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #230</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#230 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #10 MEM
+[2] → #233 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g><g class="node" id="n233" data-id="233" transform="translate(251,484)" style="opacity: 1;"><path class="box" d="M12,0H108L120,22L108,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>MemPhi_2</tspan><tspan class="node-id">  #233</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#233 MemPhi_2
+Type not computed
+
+[0] → — ASSOC
+[1] → #31 MEM
+[2] → #230 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="40" cy="-3" r="3" fill="#536477"/><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="40" y="-10" text-anchor="middle">1</text><text class="slot" x="80" y="-10" text-anchor="middle">2</text></g></g><g class="region-heads" style="opacity: 1;"/><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>
diff --git a/chapter13/docs/graph7.gv b/chapter13/docs/graph7.gv
new file mode 100644
index 00000000..b6507e53
--- /dev/null
+++ b/chapter13/docs/graph7.gv
@@ -0,0 +1,23 @@
+digraph chapter13 {
+ rankdir=BT;
+ concentrate="true";
+ compound="true";
+ subgraph cluster_Nodes {
+ Start2 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Start</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">$ctrl</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Con_4 [ label="#0" ];
+ Loop8 [ shape=box style=filled fillcolor=yellow label="Loop" ];
+ { rank=same; Loop8;}
+ }
+ edge [ fontname=Helvetica, fontsize=8 ];
+ Loop8 -> Start2:p0[taillabel=1 color=red];
+ Loop8 -> Loop8[taillabel=2 color=red constraint=false];
+}
diff --git a/chapter13/docs/graph7.json b/chapter13/docs/graph7.json
new file mode 100644
index 00000000..0e3efb9f
--- /dev/null
+++ b/chapter13/docs/graph7.json
@@ -0,0 +1,16 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph7.svg",
+ "step": 1,
+ "roots": [],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}},
+ {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 8, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 8, "role": "CTRL", "label": null}], "proj": null}
+ ],
+ "groups": [
+ {"id": 8, "par": 0, "nodes": [8]}
+ ]
+}
diff --git a/chapter13/docs/graph7.svg b/chapter13/docs/graph7.svg
new file mode 100644
index 00000000..15d886dc
--- /dev/null
+++ b/chapter13/docs/graph7.svg
@@ -0,0 +1,78 @@
+<svg aria-label="Compiler graph" width="364" height="325" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 364 325" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"><g class="region" transform="translate(164,171)"><rect class="region-box" rx="8" width="176" height="130" fill="#f1f6fc"/></g></g><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge CTRL" id="e8i1" d="M236,118 L236,223" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#8[1] → #1 · CTRL</title></path><path class="edge CTRL" id="e8i2" d="M236,276 L236,281 Q236,286 241,286 L320,286 Q328,286 328,278 L328,222 Q328,214 320,214 L272,214 Q266,214 266,220 L266,226" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#8[2] → #8 · CTRL</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(176,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>$ctrl</tspan><tspan class="node-id">  #1/0</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 $ctrl
+Projection 0 of #2
+Type not computed
+
+[0] → #2 CTRL</title></g><g class="node" id="n2" data-id="2" transform="translate(176,24)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Start</tspan><tspan class="node-id">  #2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#2 Start
+Type not computed
+
+</title></g><g class="node" id="n4" data-id="4" transform="translate(24,49)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#0</tspan><tspan class="node-id">  #4</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 #0
+Type not computed
+
+</title></g><g class="node" id="n8" data-id="8" transform="translate(176,229)" style="opacity: 1;"><path class="box" d="M20,0H100Q120,0 120,20V24Q120,44 100,44H20Q0,44 0,24V20Q0,0 20,0Z" fill="#ffe0ab"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Loop</tspan><tspan class="node-id">  #8</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#8 Loop
+Type not computed
+
+[0] → — DATA
+[1] → #1 CTRL
+[2] → #8 CTRL</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g></g><g class="region-heads" style="opacity: 1;"><g class="region-head" transform="translate(164,171)"><text class="label" x="26" y="17"><tspan>Loop</tspan><tspan class="node-id">  #8</tspan></text><title>Loop · 1 nodes</title><g class="fold-btn" role="button" tabindex="0" transform="translate(4,4)" aria-label="Fold region #8"><rect width="16" height="16" rx="2"/><text x="8" y="12" text-anchor="middle">−</text><title>Fold region</title></g></g></g><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>
diff --git a/chapter13/docs/graph8.gv b/chapter13/docs/graph8.gv
new file mode 100644
index 00000000..442b6843
--- /dev/null
+++ b/chapter13/docs/graph8.gv
@@ -0,0 +1,45 @@
+digraph chapter13 {
+/*
+while (1) {}
+return 0;
+
+*/
+ rankdir=BT;
+ concentrate="true";
+ compound="true";
+ subgraph cluster_Nodes {
+ Never18 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Never</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">True</TD><TD PORT="p1" BGCOLOR="yellow">False</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Start2 [ shape=plaintext label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="yellow">Start</TD></TR>
+ <TR><TD>
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
+ <TR><TD PORT="p0" BGCOLOR="yellow">$ctrl</TD></TR>
+ </TABLE>
+ </TD></TR>
+ </TABLE>>
+ ];
+ Stop3 [ shape=box style=filled fillcolor=yellow label="Stop" ];
+ Con_4 [ label="#0" ];
+ Return21 [ shape=box style=filled fillcolor=yellow label="Return" ];
+ Loop8 [ shape=box style=filled fillcolor=yellow label="Loop" ];
+ { rank=same; Loop8;}
+ }
+ edge [ fontname=Helvetica, fontsize=8 ];
+ Never18 -> Loop8[taillabel=0 color=red];
+ Never18 -> Con_4[taillabel=1];
+ Stop3 -> Return21[taillabel=0 color=red];
+ Return21 -> Never18:p0[taillabel=0 color=red];
+ Return21 -> Con_4[taillabel=2];
+ Loop8 -> Start2:p0[taillabel=1 color=red];
+ Loop8 -> Never18:p1[taillabel=2 color=red constraint=false];
+}
diff --git a/chapter13/docs/graph8.json b/chapter13/docs/graph8.json
new file mode 100644
index 00000000..b7d4f41c
--- /dev/null
+++ b/chapter13/docs/graph8.json
@@ -0,0 +1,21 @@
+{
+ "ver": 1,
+ "comp": "chapter13/docs/graph8.svg",
+ "step": 1,
+ "roots": [],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 18, "role": "CTRL", "label": null}], "proj": {"par": 18, "idx": 0}},
+ {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null},
+ {"id": 5, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 18, "role": "CTRL", "label": null}], "proj": {"par": 18, "idx": 1}},
+ {"id": 6, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}},
+ {"id": 8, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "CTRL", "label": null}, {"idx": 2, "def": 5, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 18, "label": "Never", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 21, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 0, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null}
+ ],
+ "groups": [
+ {"id": 8, "par": 0, "nodes": [1, 5, 8, 18]}
+ ]
+}
diff --git a/chapter13/docs/graph8.svg b/chapter13/docs/graph8.svg
new file mode 100644
index 00000000..d96a9a7d
--- /dev/null
+++ b/chapter13/docs/graph8.svg
@@ -0,0 +1,98 @@
+<svg aria-label="Compiler graph" width="431" height="676" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 431 676" style="font-family: sans-serif;"><style>
+ html, body { height:100%; margin:0; font-family:sans-serif; }
+ .viewer { height:100%; display:grid; grid-template-rows:auto minmax(0,1fr) auto; }
+ .source { padding:8px; border-bottom:1px solid #ccc; }
+ #program { width:min(600px,80vw); vertical-align:middle; }
+ #status { margin-top:4px; }
+ #graph { min-height:0; overflow:hidden; position:relative; background:#fafbfc; }
+ #elk { width:100%; height:100%; }
+ #graph svg { display:block; }
+ .tools { display:flex; flex-wrap:wrap; align-items:center; gap:14px; margin-top:8px; font-size:12px; }
+ .hint { color:#616c78; }
+ .ctrl { color:#b63838; } .mem { color:#2867b2; } .data { color:#536477; }
+ .edge { fill:none; stroke-width:1.5; }
+ .edge.CTRL { stroke-width:2; }
+ .edge.ASSOC { stroke-dasharray:4 4; }
+ .edge.PARSER { stroke-dasharray:5 4; }
+ .parser rect { fill:#f6f0ff; stroke:#7956a5; stroke-width:1.5; stroke-dasharray:5 4; }
+ .edge.selected { stroke-width:3.5; }
+ .edge.bundle { stroke-width:4; }
+ .edge.bundle.selected { stroke-width:6; }
+ .edge-hit { fill:none; stroke:transparent; stroke-width:12; vector-effect:non-scaling-stroke; pointer-events:stroke; cursor:pointer; }
+ .edge-jump { fill:transparent; pointer-events:all; cursor:pointer; }
+ .node { cursor:pointer; }
+ .box { stroke:#758191; stroke-width:1; }
+ .node.held .box { stroke-dasharray:5 3; }
+ .node.near .box { stroke:#c18221; stroke-width:2; }
+ .node.focus .box { stroke:#9c4900; stroke-width:3; }
+ .node.selected .box { stroke:#1569b9; stroke-width:3; }
+ .node.folded .box { stroke-width:4; }
+ .node.folding .box { fill:#f4ccd7; }
+ .fold-tag { font-size:9px; font-weight:700; fill:#963751; }
+ .peep-area { fill:#fff3d9; fill-opacity:.8; stroke:#c18221; stroke-width:2; pointer-events:none; }
+ .node.peep-edit .box { stroke:#9c4900; stroke-width:3; }
+ .node.error .box { stroke:#b42318; stroke-width:4; }
+ #event.error { color:#b42318; font-weight:600; white-space:pre-wrap; overflow-wrap:anywhere; }
+ .peep-ghosts { pointer-events:none; }
+ .region-box { stroke:#9da9b8; stroke-width:1.5; }
+ .fold-btn { cursor:pointer; }
+ .fold-btn rect { fill:white; stroke:#596674; }
+ .fold-btn text { font-size:14px; fill:#152330; }
+ .fold-btn:focus rect { stroke:#1569b9; stroke-width:2; }
+ .shortcut { cursor:pointer; }
+ .shortcut path { fill:none; stroke-width:1.5; }
+ .shortcut rect { fill:#fff8ec; stroke:#b63838; stroke-dasharray:3 2; }
+ .shortcut text { font-size:11px; fill:#783030; }
+ .shortcut.selected rect, .shortcut:focus rect { stroke-width:2.5; }
+ .label { font-size:12px; fill:#152330; font-weight:600; }
+ .node-id { font-size:10px; fill:#596674; font-weight:400; }
+ .type { font-size:11px; fill:#455768; }
+ .port { stroke:#536477; stroke-width:1; }
+ .row { stroke:#b6afcf; stroke-width:1; }
+ .bind { font-size:12px; fill:#152330; }
+ .slot { font-size:10px; fill:#364352; paint-order:stroke; stroke:#fafbfc; stroke-width:3; }
+ #detail { position:absolute; top:8px; right:8px; margin:0; padding:12px; max-width:320px;
+ max-height:45%; overflow:auto; white-space:pre-wrap; overflow-wrap:anywhere;
+ background:#fffffff2; border:1px solid #bac5d0; border-radius:4px; font-size:12px; }
+ .controls { display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap:6px; padding:6px; }
+ .button { color:white; background:black; font-size:20px; min-width:30px; }
+ .button:disabled { background:grey; }
+ .count { font-size:20px; min-width:35px; text-align:center; }
+ #N { width:6ch; }
+ #scrub { width:clamp(120px,35vw,600px); }
+ </style><defs><marker id="arrow-CTRL" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#b63838"/></marker><marker id="arrow-DATA" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#536477"/></marker><marker id="arrow-MEM" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#2867b2"/></marker><marker id="arrow-ASSOC" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#9396a3"/></marker><marker id="arrow-PARSER" viewBox="0 -4 8 8" refX="8" refY="0" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,-4L8,0L0,4Z" fill="#7956a5"/></marker></defs><rect width="100%" height="100%" fill="rgb(250, 251, 252)"/><g><g class="regions" style="opacity: 1;"><g class="region" transform="translate(24,171)"><rect class="region-box" rx="8" width="313" height="298" fill="#f1f6fc"/></g></g><rect class="peep-area" rx="36" style="opacity: 0;"/><g class="edges"><path class="edge CTRL" id="e3i0" d="M126,575 C126,599 215.5,602 215.5,626" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#3[0] → #21 · CTRL</title></path><path class="edge CTRL" id="e8i1" d="M116,118 L116,233" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#8[1] → #6 · CTRL</title></path><path class="edge CTRL" id="e8i2" d="M216,434 L216,439 Q216,444 221,444 L317,444 Q325,444 325,436 L325,232 Q325,224 317,224 L152,224 Q146,224 146,230 L146,236" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#8[2] → #5 · CTRL</title></path><path class="edge CTRL" id="e18i0" d="M116,289 L116,337" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#18[0] → #8 · CTRL</title></path><path class="edge DATA" id="e18i1" d="M347,118 L347,123 Q347,128 342,128 L310,128 Q302,128 302,136 L302,291 Q302,299 294,299 L204,299 Q196,299 196,307 L196,337" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#18[1] → #4 · DATA</title></path><path class="edge CTRL" id="e21i0" d="M96,437 L96,522" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#21[0] → #1 · CTRL</title></path><path class="edge DATA" id="e21i2" d="M347,118 L347,476 Q347,484 339,484 L164,484 Q156,484 156,492 L156,522" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[2] → #4 · DATA</title></path></g><g class="edge-hits"/><g class="parser" style="opacity: 1;"/><g class="nodes"><g class="node" id="n1" data-id="1" transform="translate(36,387)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>True</tspan><tspan class="node-id">  #1/0</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 True
+Projection 0 of #18
+Type not computed
+
+[0] → #18 CTRL</title></g><g class="node" id="n2" data-id="2" transform="translate(56,24)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Start</tspan><tspan class="node-id">  #2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#2 Start
+Type not computed
+
+</title></g><g class="node" id="n3" data-id="3" transform="translate(179.5,626)" style="opacity: 1;"><path class="box" d="M0,0H72V26H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="36" y="17"><tspan>Stop</tspan><tspan class="node-id">  #3</tspan></text><text class="type" text-anchor="middle" y="35" x="36"/><title>#3 Stop
+Type not computed
+
+[0] → #21 CTRL</title><circle class="port" cx="36" cy="0" r="3" fill="#536477"/><text class="slot" x="36" y="-7" text-anchor="middle">0</text></g><g class="node" id="n4" data-id="4" transform="translate(287,68)" style="opacity: 1;"><path class="box" d="M14,0H106Q120,0 120,14V30Q120,44 106,44H14Q0,44 0,30V14Q0,0 14,0Z" fill="#edf3f7"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>#0</tspan><tspan class="node-id">  #4</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 #0
+Type not computed
+
+</title></g><g class="node" id="n5" data-id="5" transform="translate(156,387)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>False</tspan><tspan class="node-id">  #5/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#5 False
+Projection 1 of #18
+Type not computed
+
+[0] → #18 CTRL</title></g><g class="node" id="n6" data-id="6" transform="translate(56,68)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>$ctrl</tspan><tspan class="node-id">  #6/0</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 $ctrl
+Projection 0 of #2
+Type not computed
+
+[0] → #2 CTRL</title></g><g class="node" id="n8" data-id="8" transform="translate(56,239)" style="opacity: 1;"><path class="box" d="M20,0H100Q120,0 120,20V24Q120,44 100,44H20Q0,44 0,24V20Q0,0 20,0Z" fill="#ffe0ab"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Loop</tspan><tspan class="node-id">  #8</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#8 Loop
+Type not computed
+
+[0] → — DATA
+[1] → #6 CTRL
+[2] → #5 CTRL</title><circle class="port" cx="30" cy="-3" r="3" fill="white"/><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g><g class="node" id="n18" data-id="18" transform="translate(36,343)" style="opacity: 1;"><path class="box" d="M0,0H240V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="120" y="18"><tspan>Never</tspan><tspan class="node-id">  #18</tspan></text><text class="type" text-anchor="middle" y="35" x="120"/><title>#18 Never
+Type not computed
+
+[0] → #8 CTRL
+[1] → #4 DATA</title><circle class="port" cx="80" cy="-3" r="3" fill="#536477"/><circle class="port" cx="160" cy="-3" r="3" fill="#536477"/><text class="slot" x="80" y="-10" text-anchor="middle">0</text><text class="slot" x="160" y="-10" text-anchor="middle">1</text></g><g class="node" id="n21" data-id="21" transform="translate(66,528)" style="opacity: 1;"><path class="box" d="M0,0H120V44H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="60" y="18"><tspan>Return</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#21 Return
+Type not computed
+
+[0] → #1 CTRL
+[1] → — DATA
+[2] → #4 DATA</title><circle class="port" cx="30" cy="-3" r="3" fill="#536477"/><circle class="port" cx="60" cy="-3" r="3" fill="white"/><circle class="port" cx="90" cy="-3" r="3" fill="#536477"/><text class="slot" x="30" y="-10" text-anchor="middle">0</text><text class="slot" x="60" y="-10" text-anchor="middle">1</text><text class="slot" x="90" y="-10" text-anchor="middle">2</text></g></g><g class="region-heads" style="opacity: 1;"><g class="region-head" transform="translate(24,171)"><text class="label" x="26" y="17"><tspan>Loop</tspan><tspan class="node-id">  #8</tspan></text><title>Loop · 4 nodes</title><g class="fold-btn" role="button" tabindex="0" transform="translate(4,4)" aria-label="Fold region #8"><rect width="16" height="16" rx="2"/><text x="8" y="12" text-anchor="middle">−</text><title>Fold region</title></g></g></g><g class="shortcuts" style="opacity: 1;"/><g class="peep-ghosts" pointer-events="none"/></g></svg>