summaryrefslogtreecommitdiff
path: root/chapter10b
diff options
context:
space:
mode:
Diffstat (limited to 'chapter10b')
-rw-r--r--chapter10b/#README.md#174
-rw-r--r--chapter10b/.#README.md1
-rw-r--r--chapter10b/README.md119
-rw-r--r--chapter10b/docs/Makefile15
-rw-r--r--chapter10b/docs/example1.json31
-rw-r--r--chapter10b/docs/example1.svg248
-rw-r--r--chapter10b/docs/example2a.json20
-rw-r--r--chapter10b/docs/example2a.svg185
-rw-r--r--chapter10b/docs/example2b.json30
-rw-r--r--chapter10b/docs/example2b.svg251
-rw-r--r--chapter10b/docs/example2c.json23
-rw-r--r--chapter10b/docs/example2c.svg177
-rw-r--r--chapter10b/docs/lattice.gv25
-rw-r--r--chapter10b/docs/lattice.svg296
14 files changed, 886 insertions, 709 deletions
diff --git a/chapter10b/#README.md# b/chapter10b/#README.md#
deleted file mode 100644
index 6380b79e..00000000
--- a/chapter10b/#README.md#
+++ /dev/null
@@ -1,174 +0,0 @@
-# Chapter 10b: Splitting Memory
-
-[Previous: Chapter 10a](../chapter10a/README.md) |
-[Next: Chapter 11](../chapter11/README.md)
-
-Chapter 10a made memory effects explicit with one SSA memory value. This
-chapter keeps exactly that parser model and recovers independent memory chains
-through graph rewrites. There is no new language syntax; the
-[grammar](docs/10-grammar.md), pointer types, and null checks are unchanged.
-
-## Why split memory?
-
-```java
-struct Point { int x; int y; }
-Point p = new Point;
-p.x = 42;
-while (arg > 0) {
- p.y = p.y + arg;
- arg = arg - 1;
-}
-return p.x;
-```
-
-The loop changes `y`, so it cannot affect `x`. With one memory chain the load
-of `x` follows the loop's stores. Splitting the fields lets ordinary
-load-after-store forwarding turn the return value into 42.
-
-![Independent field dependencies](docs/example1.svg)
-
-Control, pointer, and value edges are omitted when they do not explain memory.
-
-## Equivalence-class aliasing
-
-Each struct field has an integer alias identity. Two different fields receive
-different identities, even if they have the same spelling in different structs.
-Two instances of the same struct share their field aliases. Thus different
-classes never alias; accesses in the same class **may alias**. Same-class does
-not mean same-address: forwarding still checks pointer identity.
-
-The parser assigns field identities at struct declarations, beginning at 2.
-These identities are independent of Start's output indices. The default slot
-of a memory aggregate is 1; precise slots are greater than 1.
-
-We do not allocate a Start projection, scope binding, or loop Phi for every
-declared field. Start supplies one memory value, Scope holds one `$mem` binding,
-and Return consumes one complete memory value. The optimizer introduces slices
-only where graph operations require them.
-
-## Three memory nodes
-
-| Node | Meaning |
-|---|---|
-| `MemMerge` | A complete memory state: a default plus precise alias overrides |
-| `MemPhi` | One alias selected according to the incoming control path |
-| `BulkMemPhi` | All aliases except an explicit exclusion set, selected by control |
-
-`MemMerge` combines independent pieces of memory at one program point. It is
-not a control-flow merge. For example, after storing to alias `x`:
-
-```text
-prior = current memory
-store = Store_x(prior, pointer, value)
-current memory = MemMerge(default=prior, x=store)
-```
-
-The Store selects its precise input from any incoming MemMerge. Loads and
-precise memory Phis do the same. A missing precise entry falls back to the
-default, provided that default still covers the requested alias.
-
-The explicit entries override the default: the semantic slices are disjoint,
-and their union covers all memory. Flattening stacked aggregates preserves
-entries that the outer aggregate has not replaced. This allows an `x` store
-and a later `y` store to remain visible together at Return.
-
-![An aggregate preserves both updates](docs/example2a.svg)
-
-## Splitting a memory Phi
-
-Scope initially creates a BulkMemPhi wherever the ordinary SSA algorithm needs
-to merge memory. Its empty exclusion set means that it covers every alias.
-After the Region is complete, the Phi inspects its memory inputs and users.
-When they require a precise alias, it splits out that alias:
-
-```text
-BulkPhi(R, left, right)
- becomes
-MemMerge(
- default = BulkPhi_except{x}(R, left, right),
- x = MemPhi_x(R, slice(left,x), slice(right,x)))
-```
-
-The new precise Phi and the remaining bulk Phi share a Region and matching
-control-path indices. A loop uses the same transformation, with the backedge
-among those inputs. Each further split preserves all previously extracted
-slices; replacing a bulk Phi must never drop their parallel precise Phis.
-
-![Precise and bulk Phis share a control merge](docs/example2b.svg)
-
-A bulk Phi can bypass an incoming aggregate only when all of that aggregate's
-explicit slices are already excluded from the Phi. A precise consumer can
-select one entry. A whole-memory consumer cannot just select the default:
-that would lose the explicit updates.
-
-## Types and the worklist
-
-The memory type lattice adds a flat element `MEM#N` for each precise alias.
-Meeting different aliases gives `TypeMem.BOT`. It does not track field values,
-private objects, or escape information. Bulk exclusion sets belong to the
-graph nodes, not to an expanded type lattice.
-
-![The type domains, including precise memory aliases](docs/lattice.svg)
-
-Scalar Phis remain ordinary PhiNodes. The scope's Phi factory chooses a
-BulkMemPhi for whole memory; splitting constructs MemPhis explicitly. Generic
-arithmetic factoring through Phis must not factor a memory aggregate.
-
-Memory splitting can increase node count. Progress comes from extracting an
-alias from a bulk Phi and simplifying its precise chain, rather than from
-requiring every rewrite to shrink the graph. Nodes must have conservative
-initial types before introducing cyclic inputs. New bulk and precise Phis are
-queued, so a recursive peephole cannot start another split halfway through the
-first one.
-
-This also extends the worklist lesson from Chapter 9. A bulk Phi inspects its
-users, so changes to a user's partition must wake the producer. Selecting a
-slice from an aggregate can expose a new bulk-Phi user; that selected definition
-must be queued too. The optimizer's worklist completeness assertion remains
-enabled and checks these dependencies.
-
-## Evaluation and ordering
-
-MemMerge is a dependency node; it emits no heap operation. Its evaluator result
-is a memory token, while Store mutates the object's fields. The scheduler must
-distinguish aggregation from overwriting memory. A MemMerge is not a clobber,
-and stores in different alias classes do not impose load/store anti-dependencies.
-
-![Ordering applies within the affected alias](docs/example2c.svg)
-
-Tests cover independent-field folding, parallel memory Phis, multiple field
-updates surviving at Return, early returns, nested loops with break/continue,
-and reads before subsequent stores through potentially aliased pointers.
-
-## What remains for later chapters?
-
-Chapter 10b knows every access's alias while parsing. What is lazy here is the
-construction of memory partitions. Chapter 25 also allows an existing access's
-alias to become known later, using the same representation. Its private
-constructor memory, escape tracking, incomplete types, and module alias
-remapping are separate extensions and are not needed here.
-
-Chapters 11-24 currently retain their older parser-managed memory chains.
-Forwarding this representation through those snapshots is tracked in the
-[backport queue](../docs/chapter-backports.md). Chapter 11's scheduling lesson
-therefore still shows the older graph construction, with the same language.
-
-## Build and test
-
-With JDK 21 or newer, from this directory:
-
-```sh
-make lib
-make tests
-make release
-make view
-```
-
-Make builds this complete snapshot without Maven. `make release` writes
-`build/release/simple.jar`; `make view` launches the shared graph viewer.
-Both the root Maven reactor and the supplied IDEA module descriptor include
-the chapter. From the repository root, test both halves with:
-
-```sh
-make tests CHAPTERS="chapter10a chapter10b"
-```
diff --git a/chapter10b/.#README.md b/chapter10b/.#README.md
deleted file mode 100644
index c657b199..00000000
--- a/chapter10b/.#README.md
+++ /dev/null
@@ -1 +0,0 @@
-cliffc@DESKTOP-DAD.21980:1790387027 \ No newline at end of file
diff --git a/chapter10b/README.md b/chapter10b/README.md
index 671d53c3..7cb4cc75 100644
--- a/chapter10b/README.md
+++ b/chapter10b/README.md
@@ -5,7 +5,7 @@
Chapter 10a made memory effects explicit with one SSA memory value. This
chapter keeps exactly that parser model and recovers independent memory chains
-through graph rewrites. There is no new language syntax; the
+through graph rewrites. There is no new language syntax; the
[grammar](docs/10-grammar.md), pointer types, and null checks are unchanged.
## Why split memory?
@@ -27,6 +27,15 @@ load-after-store forwarding turn the return value into 42.
![Independent field dependencies](docs/example1.svg)
+The graph shows the split chains before the final Load folds. Its memory input
+goes straight to the Store of 42, bypassing the loop's `y` chain. As in 10a,
+definitions appear above uses, apart from loop backedges, and arrows point
+from use to definition. As in 10a, small, detached True/False projections
+show the source branches gating Loads and Stores. Other control-flow context,
+including Regions and their Phi bindings, is omitted. Chapter 11 chooses
+the actual scheduling inputs; the vertical placement of independent chains
+does not specify their execution order.
+
## Equivalence-class aliasing
Each struct field has an integer alias identity. Two different fields receive
@@ -71,14 +80,21 @@ and their union covers all memory. Flattening stacked aggregates preserves
entries that the outer aggregate has not replaced. This allows an `x` store
and a later `y` store to remain visible together at Return.
+The graph below shows `p.x = arg; p.y = 42; return p;` after redundant
+initialization stores have been removed. MemMerge takes the default memory
+in slot 1 and the `x` and `y` overrides in slots 2 and 3.
+
![An aggregate preserves both updates](docs/example2a.svg)
+
## Splitting a memory Phi
Scope initially creates a BulkMemPhi wherever the ordinary SSA algorithm needs
-to merge memory. Its empty exclusion set means that it covers every alias.
-After the Region is complete, the Phi inspects its memory inputs and users.
-When they require a precise alias, it splits out that alias:
+to merge memory. It starts by covering all aliases and an empty exclusion set
+while the merge point is finalized. Later, peeps will split out precise memory
+slices from the bulk memory, lazily on demand.
+
+Precise single aliases can be split out from the bulk by this transformation:
```text
BulkPhi(R, left, right)
@@ -88,19 +104,47 @@ MemMerge(
x = MemPhi_x(R, slice(left,x), slice(right,x)))
```
-The new precise Phi and the remaining bulk Phi share a Region and matching
-control-path indices. A loop uses the same transformation, with the backedge
-among those inputs. Each further split preserves all previously extracted
-slices; replacing a bulk Phi must never drop their parallel precise Phis.
+The new precise Phi and the remaining bulk Phi share a Region (omitted from
+the illustrations) and matching control-path indices. A loop uses the same
+transformation, with the backedge among those inputs. Each further split preserves all previously extracted
+slices (and peephole optimizations tidy up the stacked splits).
+
+Here the two branches store 3 or 4 into `p.x`, then return `p`. The graph shows
+the partition immediately after extracting `x`, before further simplification
+of the bulk Phi and its incoming aggregates.
![Precise and bulk Phis share a control merge](docs/example2b.svg)
-A bulk Phi can bypass an incoming aggregate only when all of that aggregate's
-explicit slices are already excluded from the Phi. A precise consumer can
-select one entry. A whole-memory consumer cannot just select the default:
-that would lose the explicit updates.
+This transform is invasive, and is disallowed from being called recursively;
+you can end up splitting around a loop (which is good) but then visiting a
+1/2-split loop head (which is bad). The new nodes from the split are put
+on the worklist and visited after the current split completes.
+
+Since bulk Phis merge a bunch of aliases, they have to take care when
+peepholing vs MemMerges: there cannot be any overlap between the MemMerge
+precise merges and the bulk Phi.
-## Types and the worklist
+Phi refactoring can combine matching Loads or Stores as in Chapter 10a (pushing
+up or pulling down). The Phi new memory operands can use precise MemPhis for
+the alias. This peep requires precise aliases, and is otherwise blocked by
+BulkMems - and thus is a trigger for splitting a BulkMem.
+
+This also extends the worklist lesson from Chapter 9. A bulk Phi inspects its
+users, so changes to a user's partition must wake the producer - job for
+`addDep()`. Selecting a slice from an aggregate can expose a new bulk-Phi
+user; that selected definition must be queued too. In short, any time we're
+working with MemMerge, MemPhi or BulkMemPhi we can expect some non-local
+dependencies.
+
+Memory splitting can increase node count - but Phis (Mem, Bulk or otherwise)
+make no code. Progress comes from extracting an alias from a bulk Phi and
+removing some Loads & Stores, rather than from requiring every rewrite
+to shrink the graph. In other words, the total Load/Store count is going down
+even if the MemPhi count is going up.
+
+
+
+## Types
The type lattice retains Chapter 10a's six domains, colors, and notation:
`⊤` means top, `⊥` means bottom, and a suffix names the domain. The other five
@@ -110,45 +154,18 @@ alias between memory top (`TypeMem.TOP`) and memory bottom (`TypeMem.BOT`).
![The type domains, including precise memory aliases](docs/lattice.svg)
The parallel `MEM#2`, `MEM#3`, and further alias elements describe independent
-field slices. For the first `Point` declaration above, these two aliases identify
-`Point.x` and `Point.y`. Meeting different aliases gives memory bottom; joining
-them gives memory top. Each precise alias is its own dual. The ellipsis stands
-for more parallel aliases, not a type representing a set of aliases.
-
-Memory bottom covers all memory. The default aggregate slot numbered 1 is a
-graph input position, not a precise field alias in this diagram. Types do not
-track field values, private objects, or escape information. Bulk exclusion sets
+field slices. For the first `Point` declaration above, these two aliases identify
+`Point.x` and `Point.y`. Meeting different aliases gives memory bottom; joining
+them gives memory top. Each precise alias is its own dual. (And the ellipsis stands
+for more parallel aliases, not a type representing a set of aliases).
+
+Memory bottom covers all memory. The default aggregate slot numbered 1 is a
+graph input position, not a precise field alias in this diagram. Types do not
+track field values, private objects, or escape information. Bulk exclusion sets
and the default-plus-overrides structure of MemMerge belong to graph nodes,
-not to an expanded type lattice. As in Chapter 10a, diagram edges show lattice
+not to an expanded type lattice. As in Chapter 10a, diagram edges show lattice
order, with top above bottom; field and tuple-element type lattices are elided.
-Scalar Phis remain ordinary PhiNodes. The scope's Phi factory chooses a
-BulkMemPhi for whole memory; splitting constructs MemPhis explicitly. Phi
-factoring can combine matching Loads or Stores as in Chapter 10a, but cannot
-factor MemMerge or BulkMemPhi. Its new memory operands use precise MemPhis for
-the operation's alias. Load safety checks only immediate memory users, rejecting
-Stores, Phis, and MemMerges. A Phi or aggregate might lead to a later write;
-we conservatively skip the rewrite instead of searching farther to save one Load.
-
-Factoring waits while a BulkMemPhi remains at the same Region. Bulk splitting
-identifies parallel slices by Region and alias, whereas factoring a Store can
-introduce a memory Phi *before* the Store at that same Region. Waiting avoids
-mistaking that earlier memory for the aggregate's completed slice.
-
-Memory splitting can increase node count. Progress comes from extracting an
-alias from a bulk Phi and simplifying its precise chain, rather than from
-requiring every rewrite to shrink the graph. Nodes must have conservative
-initial types before introducing cyclic inputs. New bulk and precise Phis are
-queued, so a recursive peephole cannot start another split halfway through the
-first one.
-
-This also extends the worklist lesson from Chapter 9. A bulk Phi inspects its
-users, so changes to a user's partition must wake the producer. Selecting a
-slice from an aggregate can expose a new bulk-Phi user; that selected definition
-must be queued too. The optimizer's worklist completeness assertion remains
-enabled and checks these dependencies. Factoring also depends on user counts:
-removing a use wakes recorded dependents even when the definition's type stays
-unchanged.
## Evaluation and ordering
@@ -157,6 +174,10 @@ is a memory token, while Store mutates the object's fields. The scheduler must
distinguish aggregation from overwriting memory. A MemMerge is not a clobber,
and stores in different alias classes do not impose load/store anti-dependencies.
+In `int old = p.x; p.x = arg; p.y = arg; return old;`, the Load must precede
+the later `x` Store; the `y` Store has an independent memory chain. The graph
+retains the Load to show this scheduling requirement before local folding.
+
![Ordering applies within the affected alias](docs/example2c.svg)
Tests cover independent-field folding, parallel memory Phis, multiple field
diff --git a/chapter10b/docs/Makefile b/chapter10b/docs/Makefile
index 055882b2..6fa0f057 100644
--- a/chapter10b/docs/Makefile
+++ b/chapter10b/docs/Makefile
@@ -1,14 +1 @@
-GV := $(wildcard *.gv)
-SVG := $(patsubst %.gv,%.svg,$(GV))
-.DELETE_ON_ERROR:
-
-.PHONY: all
-all: $(SVG)
-
-%.svg: %.gv
- dot -Tsvg $< > $@
- @sed -i 's/\r$$//' $@
-
-.PHONY: clean
-clean:
- @rm -f $(SVG)
+include ../../graph/docs.mk
diff --git a/chapter10b/docs/example1.json b/chapter10b/docs/example1.json
new file mode 100644
index 00000000..67c277e1
--- /dev/null
+++ b/chapter10b/docs/example1.json
@@ -0,0 +1,31 @@
+{
+ "ver": 1,
+ "comp": "chapter10b/docs/example1.svg",
+ "step": 1,
+ "roots": [24],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 3, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 1, "role": "MEM", "label": null}], "proj": {"par": 1, "idx": 1}},
+ {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "DATA", "label": null}], "proj": {"par": 1, "idx": 2}},
+ {"id": 5, "label": "new Point", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 6, "label": "#0", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null},
+ {"id": 7, "label": "#42", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null},
+ {"id": 8, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 7, "role": "DATA", "label": null}], "proj": null},
+ {"id": 9, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null},
+ {"id": 11, "label": "MemPhi y", "type": "MEM#3", "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 9, "role": "MEM", "label": null}, {"idx": 2, "def": 19, "role": "MEM", "label": null}], "proj": null},
+ {"id": 12, "label": "Phi arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 21, "role": "DATA", "label": null}], "proj": null},
+ {"id": 15, "label": "True", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 0}},
+ {"id": 16, "label": "False", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 1}},
+ {"id": 17, "label": "Load p.y", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}, {"idx": 1, "def": 11, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 0, "role": "DATA", "label": null}], "proj": null},
+ {"id": 18, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 17, "role": "DATA", "label": null}, {"idx": 2, "def": 12, "role": "DATA", "label": null}], "proj": null},
+ {"id": 19, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}, {"idx": 1, "def": 11, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 18, "role": "DATA", "label": null}], "proj": null},
+ {"id": 20, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null},
+ {"id": 21, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}, {"idx": 2, "def": 20, "role": "DATA", "label": null}], "proj": null},
+ {"id": 22, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 8, "role": "MEM", "label": null}, {"idx": 3, "def": 11, "role": "MEM", "label": null}], "proj": null},
+ {"id": 23, "label": "Load p.x", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 0, "role": "DATA", "label": null}], "proj": null},
+ {"id": 24, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 23, "role": "DATA", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter10b/docs/example1.svg b/chapter10b/docs/example1.svg
index f0b57612..46faf818 100644
--- a/chapter10b/docs/example1.svg
+++ b/chapter10b/docs/example1.svg
@@ -1,93 +1,155 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Generated by graphviz version 12.2.0 (20241103.1931)
- -->
-<!-- Title: Memory Pages: 1 -->
-<svg width="255pt" height="348pt"
- viewBox="0.00 0.00 254.55 348.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 344)">
-<title>Memory</title>
-<polygon fill="#fafbfc" stroke="none" points="-4,4 -4,-344 250.55,-344 250.55,4 -4,4"/>
-<!-- M -->
-<g id="node1" class="node">
-<title>M</title>
-<polygon fill="#dcecff" stroke="#758191" points="169.68,-314.54 169.68,-329.46 133.28,-340 81.81,-340 45.42,-329.46 45.42,-314.54 81.81,-304 133.28,-304 169.68,-314.54"/>
-<text text-anchor="middle" x="107.55" y="-317.73" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Initial memory</text>
-</g>
-<!-- X -->
-<g id="node2" class="node">
-<title>X</title>
-<polygon fill="#dcecff" stroke="#758191" points="210.45,-238.54 210.45,-253.46 178.29,-264 132.81,-264 100.65,-253.46 100.65,-238.54 132.81,-228 178.29,-228 210.45,-238.54"/>
-<text text-anchor="middle" x="155.55" y="-241.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Store x = 42</text>
-</g>
-<!-- X&#45;&gt;M -->
-<g id="edge2" class="edge">
-<title>X&#45;&gt;M</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M135.16,-264.4C135.16,-264.4 135.16,-294.76 135.16,-294.76"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="132.71,-294.76 135.16,-301.76 137.61,-294.76 132.71,-294.76"/>
-</g>
-<!-- Y -->
-<g id="node3" class="node">
-<title>Y</title>
-<polygon fill="#dcecff" stroke="#758191" points="119.1,-162.54 119.1,-177.46 84.21,-188 34.88,-188 0,-177.46 0,-162.54 34.88,-152 84.21,-152 119.1,-162.54"/>
-<text text-anchor="middle" x="59.55" y="-165.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Loop: Store y</text>
-</g>
-<!-- Y&#45;&gt;M -->
-<g id="edge3" class="edge">
-<title>Y&#45;&gt;M</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M73.03,-188.33C73.03,-188.33 73.03,-297.09 73.03,-297.09"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="70.58,-297.09 73.03,-304.09 75.48,-297.09 70.58,-297.09"/>
-</g>
-<!-- Y&#45;&gt;X -->
-<!-- L -->
-<g id="node4" class="node">
-<title>L</title>
-<path fill="#edf3f7" stroke="#758191" d="M234.55,-112C234.55,-112 182.55,-112 182.55,-112 176.55,-112 170.55,-106 170.55,-100 170.55,-100 170.55,-88 170.55,-88 170.55,-82 176.55,-76 182.55,-76 182.55,-76 234.55,-76 234.55,-76 240.55,-76 246.55,-82 246.55,-88 246.55,-88 246.55,-100 246.55,-100 246.55,-106 240.55,-112 234.55,-112"/>
-<text text-anchor="middle" x="208.55" y="-89.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Load x (42)</text>
-</g>
-<!-- L&#45;&gt;X -->
-<g id="edge1" class="edge">
-<title>L&#45;&gt;X</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M190.5,-112.33C190.5,-112.33 190.5,-222.4 190.5,-222.4"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="188.05,-222.4 190.5,-229.4 192.95,-222.4 188.05,-222.4"/>
-</g>
-<!-- MemMerge -->
-<g id="node5" class="node">
-<title>MemMerge</title>
-<polygon fill="#dcecff" stroke="#758191" points="145.87,-86.54 145.87,-101.46 115.22,-112 71.88,-112 41.23,-101.46 41.23,-86.54 71.88,-76 115.22,-76 145.87,-86.54"/>
-<text text-anchor="middle" x="93.55" y="-89.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">MemMerge</text>
-</g>
-<!-- MemMerge&#45;&gt;X -->
-<g id="edge4" class="edge">
-<title>MemMerge&#45;&gt;X</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M132.48,-106.44C132.48,-106.44 132.48,-218.56 132.48,-218.56"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="130.03,-218.56 132.48,-225.56 134.93,-218.56 130.03,-218.56"/>
-</g>
-<!-- MemMerge&#45;&gt;Y -->
-<g id="edge5" class="edge">
-<title>MemMerge&#45;&gt;Y</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M80.16,-112.4C80.16,-112.4 80.16,-142.24 80.16,-142.24"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="77.71,-142.24 80.16,-149.24 82.61,-142.24 77.71,-142.24"/>
-</g>
-<!-- MemMerge&#45;&gt;L -->
-<!-- Return -->
-<g id="node6" class="node">
-<title>Return</title>
-<polygon fill="#fff1c4" stroke="#758191" points="177.55,-36 123.55,-36 123.55,0 177.55,0 177.55,-36"/>
-<text text-anchor="middle" x="150.55" y="-13.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Return</text>
-</g>
-<!-- Return&#45;&gt;L -->
-<g id="edge7" class="edge">
-<title>Return&#45;&gt;L</title>
-<path fill="none" stroke="#536477" stroke-width="1.5" d="M174.05,-36.4C174.05,-36.4 174.05,-66.24 174.05,-66.24"/>
-<polygon fill="#536477" stroke="#536477" stroke-width="1.5" points="171.6,-66.24 174.05,-73.24 176.5,-66.24 171.6,-66.24"/>
-</g>
-<!-- Return&#45;&gt;MemMerge -->
-<g id="edge6" class="edge">
-<title>Return&#45;&gt;MemMerge</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M134.71,-36.4C134.71,-36.4 134.71,-73.34 134.71,-73.34"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="132.26,-73.34 134.71,-80.34 137.16,-73.34 132.26,-73.34"/>
-</g>
-</g>
-</svg>
+<svg aria-label="Compiler graph" width="929" height="674" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 929 674" 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 ASSOC" id="e6i0" d="M435,46 C435,70 682,41 682,65" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#6[0] → #1 · ASSOC</title></path><path class="edge ASSOC" id="e7i0" d="M435,46 C435,70 100,41 100,65" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#7[0] → #1 · ASSOC</title></path><path class="edge MEM" id="e8i1" d="M252,118 L252,168" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#8[1] → #3 · MEM</title></path><path class="edge DATA" id="e8i2" d="M530,118 L530,140 Q530,148 522,148 L284,148 Q276,148 276,156 L276,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#8[2] → #5 · DATA</title></path><path class="edge DATA" id="e8i3" d="M100,118 L100,150 Q100,158 108,158 L295,158 Q300,158 300,163 L300,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#8[3] → #7 · DATA</title></path><path class="edge MEM" id="e9i1" d="M252,118 L252,130 Q252,138 260,138 L385,138 Q393,138 393,146 L393,168" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#9[1] → #3 · MEM</title></path><path class="edge DATA" id="e9i2" d="M530,118 L530,140 Q530,148 522,148 L425,148 Q417,148 417,156 L417,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#9[2] → #5 · DATA</title></path><path class="edge DATA" id="e9i3" d="M682,118 L682,150 Q682,158 674,158 L446,158 Q441,158 441,163 L441,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#9[3] → #6 · DATA</title></path><path class="edge MEM" id="e11i1" d="M405,224 L405,272" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#11[1] → #9 · MEM</title></path><path class="edge MEM" id="e11i2" d="M777,640 L777,645 Q777,650 772,650 L32,650 Q24,650 24,642 L24,242 Q24,234 32,234 L437,234 Q445,234 445,242 L445,272" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#11[2] → #19 · MEM</title></path><path class="edge DATA" id="e12i1" d="M372,118 L372,123 Q372,128 377,128 L684,128 Q692,128 692,136 L692,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#12[1] → #4 · DATA</title></path><path class="edge DATA" id="e12i2" d="M620,328 L620,333 Q620,338 625,338 L682,338 Q690,338 690,330 L690,252 Q690,244 698,244 L774,244 Q782,244 782,236 L782,166 Q782,158 774,158 L737,158 Q732,158 732,163 L732,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#12[2] → #21 · DATA</title></path><path class="edge CTRL" id="e17i0" d="M741,328 L741,340 Q741,348 749,348 L790,348 Q798,348 798,356 L798,376" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#17[0] → #15 · CTRL</title></path><path class="edge MEM" id="e17i1" d="M425,328 L425,350 Q425,358 433,358 L814,358 Q822,358 822,366 L822,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#17[1] → #11 · MEM</title></path><path class="edge DATA" id="e17i2" d="M530,118 L530,140 Q530,148 538,148 L784,148 Q792,148 792,156 L792,330 Q792,338 800,338 L838,338 Q846,338 846,346 L846,376" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#17[2] → #5 · DATA</title></path><path class="edge DATA" id="e18i1" d="M834,432 L834,480" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#18[1] → #17 · DATA</title></path><path class="edge DATA" id="e18i2" d="M712,224 L712,229 Q712,234 717,234 L896,234 Q904,234 904,242 L904,434 Q904,442 896,442 L872,442 Q864,442 864,450 L864,480" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#18[2] → #12 · DATA</title></path><path class="edge CTRL" id="e19i0" d="M741,328 L741,584" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#19[0] → #15 · CTRL</title></path><path class="edge MEM" id="e19i1" d="M425,328 L425,350 Q425,358 433,358 L744,358 Q752,358 752,366 L752,549.5 Q752,556 758.5,556 L758.5,556 Q765,556 765,562.5 L765,584" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#19[1] → #11 · MEM</title></path><path class="edge DATA" id="e19i2" d="M530,118 L530,140 Q530,148 538,148 L784,148 Q792,148 792,156 L792,330 Q792,338 784,338 L771,338 Q763,338 763,346 L763,538 Q763,546 771,546 L781,546 Q789,546 789,554 L789,584" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#19[2] → #5 · DATA</title></path><path class="edge DATA" id="e19i3" d="M834,536 L834,541 Q834,546 829,546 L821,546 Q813,546 813,554 L813,584" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#19[3] → #18 · DATA</title></path><path class="edge ASSOC" id="e20i0" d="M435,46 C435,70 557,147 557,171" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#20[0] → #1 · ASSOC</title></path><path class="edge DATA" id="e21i1" d="M712,224 L712,229 Q712,234 707,234 L628,234 Q620,234 620,242 L620,272" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[1] → #12 · DATA</title></path><path class="edge DATA" id="e21i2" d="M557,224 L557,236 Q557,244 565,244 L642,244 Q650,244 650,252 L650,272" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#21[2] → #20 · DATA</title></path><path class="edge MEM" id="e22i1" d="M252,118 L252,130 Q252,138 244,138 L82,138 Q74,138 74,146 L74,333.5 Q74,338 78.5,338 L78.5,338 Q83,338 83,342.5 L83,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[1] → #3 · MEM</title></path><path class="edge MEM" id="e22i2" d="M264,224 L264,236 Q264,244 256,244 L102,244 Q94,244 94,252 L94,331.5 Q94,338 100.5,338 L100.5,338 Q107,338 107,344.5 L107,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[2] → #8 · MEM</title></path><path class="edge MEM" id="e22i3" d="M425,328 L425,350 Q425,358 417,358 L139,358 Q131,358 131,366 L131,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[3] → #11 · MEM</title></path><path class="edge CTRL" id="e23i0" d="M129,224 L129,272" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#23[0] → #16 · CTRL</title></path><path class="edge MEM" id="e23i1" d="M264,224 L264,236 Q264,244 256,244 L161,244 Q153,244 153,252 L153,272" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#23[1] → #8 · MEM</title></path><path class="edge DATA" id="e23i2" d="M530,118 L530,140 Q530,148 522,148 L342,148 Q334,148 334,156 L334,246 Q334,254 326,254 L185,254 Q177,254 177,262 L177,272" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#23[2] → #5 · DATA</title></path><path class="edge MEM" id="e24i1" d="M95,432 L95,437 Q95,442 100,442 L127,442 Q135,442 135,450 L135,480" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#24[1] → #22 · MEM</title></path><path class="edge DATA" id="e24i2" d="M165,328 L165,480" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#24[2] → #23 · 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(192,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">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="120"/><title>#1 Start
+Type not computed
+
+</title></g><g class="node" id="n3" data-id="3" transform="translate(192,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">  #3/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#3 $mem
+Projection 1 of #1
+Type not computed
+
+[0] → #1 MEM</title></g><g class="node" id="n4" data-id="4" transform="translate(312,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">  #4/2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 arg
+Projection 2 of #1
+Type not computed
+
+[0] → #1 DATA</title></g><g class="node" id="n5" data-id="5" transform="translate(470,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 Point</tspan><tspan class="node-id">  #5</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#5 new Point
+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="n6" data-id="6" transform="translate(622,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">  #6</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 #0
+Type not computed
+
+[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n7" data-id="7" transform="translate(40,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>#42</tspan><tspan class="node-id">  #7</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#7 #42
+Type not computed
+
+[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n8" data-id="8" transform="translate(204,174)" 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>Store p.x</tspan><tspan class="node-id">  #8</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#2</text><title>#8 Store p.x
+MEM#2
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #5 DATA
+[3] → #7 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="n9" data-id="9" transform="translate(345,174)" 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>Store p.y</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#3</text><title>#9 Store p.y
+MEM#3
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #5 DATA
+[3] → #6 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="n11" data-id="11" transform="translate(365,278)" 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 y</tspan><tspan class="node-id">  #11</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#3</text><title>#11 MemPhi y
+MEM#3
+
+[0] → — ASSOC
+[1] → #9 MEM
+[2] → #19 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="n12" data-id="12" transform="translate(652,174)" 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>Phi arg</tspan><tspan class="node-id">  #12</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#12 Phi arg
+Type not computed
+
+[0] → — ASSOC
+[1] → #4 DATA
+[2] → #21 DATA</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="n15" data-id="15" transform="translate(700,296)" 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="n16" data-id="16" transform="translate(85,192)" style="opacity: 1;"><path class="box" d="M0,0H87V26H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="43.5" y="17"><tspan>False</tspan><tspan class="node-id">  #16/1</tspan></text><text class="type" text-anchor="middle" y="35" x="43.5"/><title>#16 False
+Projection 1 of #0
+Type not computed
+
+</title></g><g class="node" id="n17" data-id="17" transform="translate(774,382)" 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>Load p.y</tspan><tspan class="node-id">  #17</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#17 Load p.y
+Type not computed
+
+[0] → #15 CTRL
+[1] → #11 MEM
+[2] → #5 DATA
+[3] → — 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="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="n18" data-id="18" transform="translate(774,486)" 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">  #18</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#18 +
+Type not computed
+
+[0] → — CTRL
+[1] → #17 DATA
+[2] → #12 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="n19" data-id="19" transform="translate(717,590)" 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>Store p.y</tspan><tspan class="node-id">  #19</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#3</text><title>#19 Store p.y
+MEM#3
+
+[0] → #15 CTRL
+[1] → #11 MEM
+[2] → #5 DATA
+[3] → #18 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="n20" data-id="20" transform="translate(497,174)" 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">  #20</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#20 #1
+Type not computed
+
+[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n21" data-id="21" transform="translate(560,278)" 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] → #12 DATA
+[2] → #20 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(35,382)" 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">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #8 MEM
+[3] → #11 MEM</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="n23" data-id="23" transform="translate(105,278)" 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>Load p.x</tspan><tspan class="node-id">  #23</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#23 Load p.x
+Type not computed
+
+[0] → #16 CTRL
+[1] → #8 MEM
+[2] → #5 DATA
+[3] → — 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="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="n24" data-id="24" transform="translate(75,486)" 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">  #24</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#24 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #22 MEM
+[2] → #23 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><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/chapter10b/docs/example2a.json b/chapter10b/docs/example2a.json
new file mode 100644
index 00000000..2a9461b6
--- /dev/null
+++ b/chapter10b/docs/example2a.json
@@ -0,0 +1,20 @@
+{
+ "ver": 1,
+ "comp": "chapter10b/docs/example2a.svg",
+ "step": 1,
+ "roots": [11],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 3, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 1, "role": "MEM", "label": null}], "proj": {"par": 1, "idx": 1}},
+ {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "DATA", "label": null}], "proj": {"par": 1, "idx": 2}},
+ {"id": 5, "label": "new Point", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 7, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 8, "label": "#42", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null},
+ {"id": 9, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 8, "role": "DATA", "label": null}], "proj": null},
+ {"id": 10, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 7, "role": "MEM", "label": null}, {"idx": 3, "def": 9, "role": "MEM", "label": null}], "proj": null},
+ {"id": 11, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter10b/docs/example2a.svg b/chapter10b/docs/example2a.svg
index 47bc3a8f..b43a55b4 100644
--- a/chapter10b/docs/example2a.svg
+++ b/chapter10b/docs/example2a.svg
@@ -1,82 +1,103 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Generated by graphviz version 12.2.0 (20241103.1931)
- -->
-<!-- Title: Memory Pages: 1 -->
-<svg width="498pt" height="105pt"
- viewBox="0.00 0.00 497.99 105.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 101)">
-<title>Memory</title>
-<polygon fill="#fafbfc" stroke="none" points="-4,4 -4,-101 493.99,-101 493.99,4 -4,4"/>
-<!-- M -->
-<g id="node1" class="node">
-<title>M</title>
-<polygon fill="#dcecff" stroke="#758191" points="137.69,-71.54 137.69,-86.46 97.36,-97 40.33,-97 0,-86.46 0,-71.54 40.33,-61 97.36,-61 137.69,-71.54"/>
-<text text-anchor="middle" x="68.84" y="-74.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Default memory</text>
-</g>
-<!-- X -->
-<g id="node2" class="node">
-<title>X</title>
-<polygon fill="#dcecff" stroke="#758191" points="251.35,-71.54 251.35,-86.46 229.77,-97 199.26,-97 177.69,-86.46 177.69,-71.54 199.26,-61 229.77,-61 251.35,-71.54"/>
-<text text-anchor="middle" x="214.52" y="-74.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Store x</text>
-</g>
-<!-- X&#45;&gt;M -->
-<g id="edge1" class="edge">
-<title>X&#45;&gt;M</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M177.38,-79C177.38,-79 147.2,-79 147.2,-79"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="147.2,-76.55 140.2,-79 147.2,-81.45 147.2,-76.55"/>
-</g>
-<!-- Y -->
-<g id="node3" class="node">
-<title>Y</title>
-<polygon fill="#dcecff" stroke="#758191" points="251.35,-10.54 251.35,-25.46 229.77,-36 199.26,-36 177.69,-25.46 177.69,-10.54 199.26,0 229.77,0 251.35,-10.54"/>
-<text text-anchor="middle" x="214.52" y="-13.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Store y</text>
-</g>
-<!-- Y&#45;&gt;M -->
-<g id="edge2" class="edge">
-<title>Y&#45;&gt;M</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M177.51,-18C127.88,-18 45.9,-18 45.9,-18 45.9,-18 36.62,-18 36.62,-18"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="41.53,-52.16 45.41,-58.48 46.32,-51.12 41.53,-52.16"/>
-</g>
-<!-- MemMerge -->
-<g id="node4" class="node">
-<title>MemMerge</title>
-<polygon fill="#dcecff" stroke="#758191" points="395.99,-71.54 395.99,-86.46 365.34,-97 322,-97 291.35,-86.46 291.35,-71.54 322,-61 365.34,-61 395.99,-71.54"/>
-<text text-anchor="middle" x="343.67" y="-74.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">MemMerge</text>
-</g>
-<!-- MemMerge&#45;&gt;M -->
-<g id="edge3" class="edge">
-<title>MemMerge&#45;&gt;M</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M361.11,-60.55C361.11,-54.13 361.11,-48.5 361.11,-48.5 361.11,-48.5 91.79,-48.5 91.79,-48.5 91.79,-48.5 91.79,-51.28 91.79,-51.28"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="89.34,-51.28 91.79,-58.28 94.24,-51.28 89.34,-51.28"/>
-<text text-anchor="middle" x="244.96" y="-39.95" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#364352">default</text>
-</g>
-<!-- MemMerge&#45;&gt;X -->
-<g id="edge4" class="edge">
-<title>MemMerge&#45;&gt;X</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M291.14,-79C291.14,-79 260.84,-79 260.84,-79"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="260.84,-76.55 253.84,-79 260.84,-81.45 260.84,-76.55"/>
-<text text-anchor="middle" x="278.24" y="-70.45" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#364352">x</text>
-</g>
-<!-- MemMerge&#45;&gt;Y -->
-<g id="edge5" class="edge">
-<title>MemMerge&#45;&gt;Y</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M326.23,-60.7C326.23,-42.73 326.23,-18 326.23,-18 326.23,-18 260.98,-18 260.98,-18"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="260.98,-15.55 253.98,-18 260.98,-20.45 260.98,-15.55"/>
-<text text-anchor="middle" x="317.21" y="-9.45" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#364352">y</text>
-</g>
-<!-- Return -->
-<g id="node5" class="node">
-<title>Return</title>
-<polygon fill="#fff1c4" stroke="#758191" points="489.99,-97 435.99,-97 435.99,-61 489.99,-61 489.99,-97"/>
-<text text-anchor="middle" x="462.99" y="-74.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Return</text>
-</g>
-<!-- Return&#45;&gt;MemMerge -->
-<g id="edge6" class="edge">
-<title>Return&#45;&gt;MemMerge</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M435.61,-79C435.61,-79 405.55,-79 405.55,-79"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="405.55,-76.55 398.55,-79 405.55,-81.45 405.55,-76.55"/>
-</g>
-</g>
-</svg>
+<svg aria-label="Compiler graph" width="598" height="454" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 598 454" 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="e7i1" d="M84,118 L84,140 Q84,148 92,148 L135,148 Q143,148 143,156 L143,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#7[1] → #3 · MEM</title></path><path class="edge DATA" id="e7i2" d="M362,118 L362,123 Q362,128 357,128 L175,128 Q167,128 167,136 L167,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#7[2] → #5 · DATA</title></path><path class="edge DATA" id="e7i3" d="M204,118 L204,131.5 Q204,138 197.5,138 L197.5,138 Q191,138 191,144.5 L191,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#7[3] → #4 · DATA</title></path><path class="edge ASSOC" id="e8i0" d="M267,46 C267,70 514,41 514,65" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#8[0] → #1 · ASSOC</title></path><path class="edge MEM" id="e9i1" d="M84,118 L84,140 Q84,148 92,148 L287,148 Q295,148 295,156 L295,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#9[1] → #3 · MEM</title></path><path class="edge DATA" id="e9i2" d="M362,118 L362,123 Q362,128 357,128 L327,128 Q319,128 319,136 L319,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#9[2] → #5 · DATA</title></path><path class="edge DATA" id="e9i3" d="M514,118 L514,130 Q514,138 506,138 L351,138 Q343,138 343,146 L343,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#9[3] → #8 · DATA</title></path><path class="edge MEM" id="e10i1" d="M84,118 L84,224 Q84,232 92,232 L123,232 Q131,232 131,240 L131,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#10[1] → #3 · MEM</title></path><path class="edge MEM" id="e10i2" d="M155,222 L155,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#10[2] → #7 · MEM</title></path><path class="edge MEM" id="e10i3" d="M307,222 L307,227 Q307,232 302,232 L187,232 Q179,232 179,240 L179,270" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#10[3] → #9 · MEM</title></path><path class="edge MEM" id="e11i1" d="M143,326 L143,331 Q143,336 148,336 L339,336 Q347,336 347,344 L347,374" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#11[1] → #10 · MEM</title></path><path class="edge DATA" id="e11i2" d="M362,118 L362,123 Q362,128 367,128 L369.5,128 Q377,128 377,135.5 L377,374" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#11[2] → #5 · 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(24,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">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="120"/><title>#1 Start
+Type not computed
+
+</title></g><g class="node" id="n3" data-id="3" 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">  #3/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#3 $mem
+Projection 1 of #1
+Type not computed
+
+[0] → #1 MEM</title></g><g class="node" id="n4" data-id="4" transform="translate(144,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">  #4/2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 arg
+Projection 2 of #1
+Type not computed
+
+[0] → #1 DATA</title></g><g class="node" id="n5" data-id="5" transform="translate(302,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 Point</tspan><tspan class="node-id">  #5</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#5 new Point
+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="n7" data-id="7" transform="translate(95,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>Store p.x</tspan><tspan class="node-id">  #7</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#2</text><title>#7 Store p.x
+MEM#2
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #5 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="n8" data-id="8" transform="translate(454,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>#42</tspan><tspan class="node-id">  #8</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#8 #42
+Type not computed
+
+[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n9" data-id="9" transform="translate(247,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>Store p.y</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#3</text><title>#9 Store p.y
+MEM#3
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #5 DATA
+[3] → #8 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="n10" data-id="10" transform="translate(83,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>MemMerge</tspan><tspan class="node-id">  #10</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#10 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #7 MEM
+[3] → #9 MEM</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="n11" data-id="11" transform="translate(287,380)" 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">  #11</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#11 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #10 MEM
+[2] → #5 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><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/chapter10b/docs/example2b.json b/chapter10b/docs/example2b.json
new file mode 100644
index 00000000..3d919618
--- /dev/null
+++ b/chapter10b/docs/example2b.json
@@ -0,0 +1,30 @@
+{
+ "ver": 1,
+ "comp": "chapter10b/docs/example2b.svg",
+ "step": 1,
+ "roots": [23],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 3, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 1, "role": "MEM", "label": null}], "proj": {"par": 1, "idx": 1}},
+ {"id": 5, "label": "new Point", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 6, "label": "#0", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null},
+ {"id": 7, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null},
+ {"id": 8, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null},
+ {"id": 9, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 7, "role": "MEM", "label": null}, {"idx": 3, "def": 8, "role": "MEM", "label": null}], "proj": null},
+ {"id": 11, "label": "True", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 0}},
+ {"id": 12, "label": "False", "type": null, "kind": "CTRL", "edges": [], "proj": {"par": 0, "idx": 1}},
+ {"id": 13, "label": "#3", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null},
+ {"id": 14, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 13, "role": "DATA", "label": null}], "proj": null},
+ {"id": 15, "label": "#4", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null},
+ {"id": 16, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 15, "role": "DATA", "label": null}], "proj": null},
+ {"id": 17, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "MEM", "label": null}, {"idx": 2, "def": 14, "role": "MEM", "label": null}], "proj": null},
+ {"id": 18, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "MEM", "label": null}], "proj": null},
+ {"id": 20, "label": "MemPhi x", "type": "MEM#2", "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "MEM", "label": null}], "proj": null},
+ {"id": 21, "label": "BulkMemPhi except x", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": null}, {"idx": 1, "def": 17, "role": "MEM", "label": null}, {"idx": 2, "def": 18, "role": "MEM", "label": null}], "proj": null},
+ {"id": 22, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 21, "role": "MEM", "label": null}, {"idx": 2, "def": 20, "role": "MEM", "label": null}], "proj": null},
+ {"id": 23, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter10b/docs/example2b.svg b/chapter10b/docs/example2b.svg
index cb10b90b..54ddad9d 100644
--- a/chapter10b/docs/example2b.svg
+++ b/chapter10b/docs/example2b.svg
@@ -1,101 +1,150 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Generated by graphviz version 12.2.0 (20241103.1931)
- -->
-<!-- Title: Memory Pages: 1 -->
-<svg width="517pt" height="166pt"
- viewBox="0.00 0.00 516.68 166.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 162)">
-<title>Memory</title>
-<polygon fill="#fafbfc" stroke="none" points="-4,4 -4,-162 512.68,-162 512.68,4 -4,4"/>
-<!-- P -->
-<g id="node1" class="node">
-<title>P</title>
-<polygon fill="#f5e4fa" stroke="#758191" points="305.65,-109 278.57,-127 224.41,-127 197.33,-109 224.41,-91 278.57,-91 305.65,-109"/>
-<text text-anchor="middle" x="251.49" y="-104.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">MemPhi(x)</text>
-</g>
-<!-- Left -->
-<g id="node3" class="node">
-<title>Left</title>
-<polygon fill="#dcecff" stroke="#758191" points="76.47,-132.54 76.47,-147.46 60.65,-158 38.29,-158 22.47,-147.46 22.47,-132.54 38.29,-122 60.65,-122 76.47,-132.54"/>
-<text text-anchor="middle" x="49.47" y="-135.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Left</text>
-</g>
-<!-- P&#45;&gt;Left -->
-<g id="edge1" class="edge">
-<title>P&#45;&gt;Left</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M206.74,-115.75C144.8,-115.75 40.47,-115.75 40.47,-115.75 40.47,-115.75 35.19,-115.75 35.19,-115.75"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="32.45,-116.37 38.95,-119.93 36.09,-113.09 32.45,-116.37"/>
-<text text-anchor="middle" x="108.21" y="-107.2" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#364352">slice x</text>
-</g>
-<!-- Right -->
-<g id="node4" class="node">
-<title>Right</title>
-<polygon fill="#dcecff" stroke="#758191" points="80.11,-71.54 80.11,-86.46 62.16,-97 36.78,-97 18.84,-86.46 18.84,-71.54 36.78,-61 62.16,-61 80.11,-71.54"/>
-<text text-anchor="middle" x="49.47" y="-74.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Right</text>
-</g>
-<!-- P&#45;&gt;Right -->
-<g id="edge2" class="edge">
-<title>P&#45;&gt;Right</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M197.21,-109.5C140.12,-109.5 58.47,-109.5 58.47,-109.5 58.47,-109.5 67.74,-109.5 67.74,-109.5"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="66.06,-103.3 59.86,-99.25 62.18,-106.29 66.06,-103.3"/>
-<text text-anchor="middle" x="135.96" y="-100.95" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#364352">slice x</text>
-</g>
-<!-- Region -->
-<g id="node5" class="node">
-<title>Region</title>
-<polygon fill="#fff1c4" stroke="#758191" points="78.36,-36 20.58,-36 0,0 98.94,0 78.36,-36"/>
-<text text-anchor="middle" x="49.47" y="-13.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Region</text>
-</g>
-<!-- P&#45;&gt;Region -->
-<g id="edge5" class="edge">
-<title>P&#45;&gt;Region</title>
-<path fill="none" stroke="#9396a3" stroke-width="1.5" stroke-dasharray="5,2" d="M205.5,-103.25C156.65,-103.25 86.38,-103.25 86.38,-103.25 86.38,-103.25 95.66,-103.25 95.66,-103.25"/>
-<polygon fill="#9396a3" stroke="#9396a3" stroke-width="1.5" points="89.88,-31.51 86.64,-24.84 85.01,-32.07 89.88,-31.51"/>
-</g>
-<!-- B -->
-<g id="node2" class="node">
-<title>B</title>
-<polygon fill="#f5e4fa" stroke="#758191" points="364.04,-48 307.77,-66 195.22,-66 138.94,-48 195.22,-30 307.77,-30 364.04,-48"/>
-<text text-anchor="middle" x="251.49" y="-43.73" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">BulkMemPhi(All except x)</text>
-</g>
-<!-- B&#45;&gt;Left -->
-<g id="edge3" class="edge">
-<title>B&#45;&gt;Left</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M177.87,-60.74C177.87,-86.54 177.87,-142.5 177.87,-142.5 177.87,-142.5 85.97,-142.5 85.97,-142.5"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="85.97,-140.05 78.97,-142.5 85.97,-144.95 85.97,-140.05"/>
-</g>
-<!-- B&#45;&gt;Right -->
-<g id="edge4" class="edge">
-<title>B&#45;&gt;Right</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M158.4,-54.74C158.4,-65.35 158.4,-84.75 158.4,-84.75 158.4,-84.75 89.67,-84.75 89.67,-84.75"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="89.67,-82.3 82.67,-84.75 89.67,-87.2 89.67,-82.3"/>
-</g>
-<!-- B&#45;&gt;Region -->
-<g id="edge6" class="edge">
-<title>B&#45;&gt;Region</title>
-<path fill="none" stroke="#9396a3" stroke-width="1.5" stroke-dasharray="5,2" d="M139.03,-48.5C112.95,-48.5 92.66,-48.5 92.66,-48.5 92.66,-48.5 101.93,-48.5 101.93,-48.5"/>
-<polygon fill="#9396a3" stroke="#9396a3" stroke-width="1.5" points="97.71,-26.24 93.33,-20.26 93.02,-27.67 97.71,-26.24"/>
-</g>
-<!-- MemMerge -->
-<g id="node6" class="node">
-<title>MemMerge</title>
-<polygon fill="#dcecff" stroke="#758191" points="508.68,-70.54 508.68,-85.46 478.03,-96 434.69,-96 404.04,-85.46 404.04,-70.54 434.69,-60 478.03,-60 508.68,-70.54"/>
-<text text-anchor="middle" x="456.36" y="-73.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">MemMerge</text>
-</g>
-<!-- MemMerge&#45;&gt;P -->
-<g id="edge7" class="edge">
-<title>MemMerge&#45;&gt;P</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M403.6,-78.5C342.9,-78.5 251.49,-78.5 251.49,-78.5 251.49,-78.5 251.49,-81.28 251.49,-81.28"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="249.04,-81.28 251.49,-88.28 253.94,-81.28 249.04,-81.28"/>
-<text text-anchor="middle" x="328.4" y="-69.95" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#364352">x</text>
-</g>
-<!-- MemMerge&#45;&gt;B -->
-<g id="edge8" class="edge">
-<title>MemMerge&#45;&gt;B</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M403.77,-72.25C370.93,-72.25 334.85,-72.25 334.85,-72.25 334.85,-72.25 334.85,-66.85 334.85,-66.85"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="337.3,-66.85 334.85,-59.85 332.4,-66.85 337.3,-66.85"/>
-<text text-anchor="middle" x="380.49" y="-63.7" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#364352">default</text>
-</g>
-</g>
-</svg>
+<svg aria-label="Compiler graph" width="886" height="768" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 886 768" 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 ASSOC" id="e6i0" d="M147,46 C147,70 279,41 279,65" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#6[0] → #1 · ASSOC</title></path><path class="edge MEM" id="e7i1" d="M84,118 L84,140 Q84,148 92,148 L341,148 Q349,148 349,156 L349,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#7[1] → #3 · MEM</title></path><path class="edge DATA" id="e7i2" d="M431,118 L431,130 Q431,138 423,138 L381,138 Q373,138 373,146 L373,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#7[2] → #5 · DATA</title></path><path class="edge DATA" id="e7i3" d="M279,118 L279,123 Q279,128 284,128 L389,128 Q397,128 397,136 L397,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#7[3] → #6 · DATA</title></path><path class="edge MEM" id="e8i1" d="M84,118 L84,166" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#8[1] → #3 · MEM</title></path><path class="edge DATA" id="e8i2" d="M431,118 L431,130 Q431,138 423,138 L116,138 Q108,138 108,146 L108,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#8[2] → #5 · DATA</title></path><path class="edge DATA" id="e8i3" d="M279,118 L279,123 Q279,128 274,128 L140,128 Q132,128 132,136 L132,166" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#8[3] → #6 · DATA</title></path><path class="edge MEM" id="e9i1" d="M84,118 L84,140 Q84,148 76,148 L33,148 Q25,148 25,156 L25,234 Q25,242 33,242 L93,242 Q101,242 101,250 L101,272" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#9[1] → #3 · MEM</title></path><path class="edge MEM" id="e9i2" d="M361,222 L361,234 Q361,242 353,242 L133,242 Q125,242 125,250 L125,272" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#9[2] → #7 · MEM</title></path><path class="edge MEM" id="e9i3" d="M96,222 L96,227 Q96,232 101,232 L141,232 Q149,232 149,240 L149,272" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#9[3] → #8 · MEM</title></path><path class="edge ASSOC" id="e13i0" d="M147,46 C147,70 502,145 502,169" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#13[0] → #1 · ASSOC</title></path><path class="edge CTRL" id="e14i0" d="M229,222 L229,272" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#14[0] → #11 · CTRL</title></path><path class="edge MEM" id="e14i1" d="M361,222 L361,234 Q361,242 353,242 L261,242 Q253,242 253,250 L253,272" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#14[1] → #7 · MEM</title></path><path class="edge DATA" id="e14i2" d="M431,118 L431,244 Q431,252 423,252 L285,252 Q277,252 277,260 L277,272" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#14[2] → #5 · DATA</title></path><path class="edge DATA" id="e14i3" d="M502,222 L502,254 Q502,262 494,262 L306,262 Q301,262 301,267 L301,272" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#14[3] → #13 · DATA</title></path><path class="edge ASSOC" id="e15i0" d="M147,46 C147,70 762,145 762,169" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#15[0] → #1 · ASSOC</title></path><path class="edge CTRL" id="e16i0" d="M638,222 L638,272" stroke="#b63838" marker-start="url(#arrow-CTRL)" style="opacity: 1;"><title>#16[0] → #12 · CTRL</title></path><path class="edge MEM" id="e16i1" d="M361,222 L361,234 Q361,242 369,242 L654,242 Q662,242 662,250 L662,272" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#16[1] → #7 · MEM</title></path><path class="edge DATA" id="e16i2" d="M431,118 L431,130 Q431,138 439,138 L683,138 Q691,138 691,146 L691,229.5 Q691,232 688.5,232 L688.5,232 Q686,232 686,234.5 L686,272" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#16[2] → #5 · DATA</title></path><path class="edge DATA" id="e16i3" d="M762,222 L762,227 Q762,232 757,232 L718,232 Q710,232 710,240 L710,272" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#16[3] → #15 · DATA</title></path><path class="edge MEM" id="e17i1" d="M113,328 L113,340 Q113,348 121,348 L227,348 Q235,348 235,356 L235,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#17[1] → #9 · MEM</title></path><path class="edge MEM" id="e17i2" d="M265,328 L265,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#17[2] → #14 · MEM</title></path><path class="edge MEM" id="e18i1" d="M113,328 L113,340 Q113,348 121,348 L491,348 Q499,348 499,356 L499,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#18[1] → #9 · MEM</title></path><path class="edge MEM" id="e18i2" d="M674,328 L674,340 Q674,348 666,348 L537,348 Q529,348 529,356 L529,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#18[2] → #16 · MEM</title></path><path class="edge MEM" id="e20i1" d="M265,328 L265,333 Q265,338 270,338 L626,338 Q634,338 634,346 L634,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#20[1] → #14 · MEM</title></path><path class="edge MEM" id="e20i2" d="M674,328 L674,376" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#20[2] → #16 · MEM</title></path><path class="edge MEM" id="e21i1" d="M235,432 L235,437 Q235,442 240,442 L436,442 Q444,442 444,450 L444,480" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#21[1] → #17 · MEM</title></path><path class="edge MEM" id="e21i2" d="M499,432 L499,480" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#21[2] → #18 · MEM</title></path><path class="edge MEM" id="e22i1" d="M472,536 L472,541 Q472,546 477,546 L616,546 Q624,546 624,554 L624,584" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[1] → #21 · MEM</title></path><path class="edge MEM" id="e22i2" d="M654,432 L654,584" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#22[2] → #20 · MEM</title></path><path class="edge MEM" id="e23i1" d="M624,640 L624,645 Q624,650 629,650 L794,650 Q802,650 802,658 L802,688" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#23[1] → #22 · MEM</title></path><path class="edge DATA" id="e23i2" d="M431,118 L431,130 Q431,138 439,138 L824,138 Q832,138 832,146 L832,688" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#23[2] → #5 · 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(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">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#1 Start
+Type not computed
+
+</title></g><g class="node" id="n3" data-id="3" 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">  #3/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#3 $mem
+Projection 1 of #1
+Type not computed
+
+[0] → #1 MEM</title></g><g class="node" id="n5" data-id="5" transform="translate(371,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 Point</tspan><tspan class="node-id">  #5</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#5 new Point
+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="n6" data-id="6" transform="translate(219,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">  #6</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 #0
+Type not computed
+
+[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n7" data-id="7" transform="translate(301,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>Store p.x</tspan><tspan class="node-id">  #7</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#2</text><title>#7 Store p.x
+MEM#2
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #5 DATA
+[3] → #6 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="n8" data-id="8" transform="translate(36,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>Store p.y</tspan><tspan class="node-id">  #8</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#3</text><title>#8 Store p.y
+MEM#3
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #5 DATA
+[3] → #6 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="n9" data-id="9" transform="translate(53,278)" 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">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #7 MEM
+[3] → #8 MEM</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="n11" data-id="11" transform="translate(188,190)" style="opacity: 1;"><path class="box" d="M0,0H81V26H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="40.5" y="17"><tspan>True</tspan><tspan class="node-id">  #11/0</tspan></text><text class="type" text-anchor="middle" y="35" x="40.5"/><title>#11 True
+Projection 0 of #0
+Type not computed
+
+</title></g><g class="node" id="n12" data-id="12" transform="translate(594,190)" style="opacity: 1;"><path class="box" d="M0,0H87V26H0Z" fill="#fff1c4"/><text class="label" text-anchor="middle" x="43.5" y="17"><tspan>False</tspan><tspan class="node-id">  #12/1</tspan></text><text class="type" text-anchor="middle" y="35" x="43.5"/><title>#12 False
+Projection 1 of #0
+Type not computed
+
+</title></g><g class="node" id="n13" data-id="13" transform="translate(442,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>#3</tspan><tspan class="node-id">  #13</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#13 #3
+Type not computed
+
+[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n14" data-id="14" transform="translate(205,278)" 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>Store p.x</tspan><tspan class="node-id">  #14</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#2</text><title>#14 Store p.x
+MEM#2
+
+[0] → #11 CTRL
+[1] → #7 MEM
+[2] → #5 DATA
+[3] → #13 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="n15" data-id="15" transform="translate(702,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>#4</tspan><tspan class="node-id">  #15</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#15 #4
+Type not computed
+
+[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n16" data-id="16" transform="translate(614,278)" 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>Store p.x</tspan><tspan class="node-id">  #16</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#2</text><title>#16 Store p.x
+MEM#2
+
+[0] → #12 CTRL
+[1] → #7 MEM
+[2] → #5 DATA
+[3] → #15 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="n17" data-id="17" transform="translate(175,382)" 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">  #17</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#17 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #9 MEM
+[2] → #14 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="n18" data-id="18" transform="translate(439,382)" 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">  #18</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#18 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #9 MEM
+[2] → #16 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="n20" data-id="20" transform="translate(594,382)" 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 x</tspan><tspan class="node-id">  #20</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#2</text><title>#20 MemPhi x
+MEM#2
+
+[0] → — ASSOC
+[1] → #14 MEM
+[2] → #16 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="n21" data-id="21" transform="translate(390,486)" style="opacity: 1;"><path class="box" d="M12,0H151L163,22L151,44H12L0,22Z" fill="#f5e4fa"/><text class="label" text-anchor="middle" x="81.5" y="18"><tspan>BulkMemPhi except x</tspan><tspan class="node-id">  #21</tspan></text><text class="type" text-anchor="middle" y="35" x="81.5"/><title>#21 BulkMemPhi except x
+Type not computed
+
+[0] → — ASSOC
+[1] → #17 MEM
+[2] → #18 MEM</title><circle class="port" cx="0" cy="-3" r="3" fill="white"/><circle class="port" cx="54" cy="-3" r="3" fill="#536477"/><circle class="port" cx="109" cy="-3" r="3" fill="#536477"/><text class="slot" x="0" y="-10" text-anchor="middle">0</text><text class="slot" x="54" y="-10" text-anchor="middle">1</text><text class="slot" x="109" y="-10" text-anchor="middle">2</text></g><g class="node" id="n22" data-id="22" transform="translate(564,590)" 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">  #22</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#22 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #21 MEM
+[2] → #20 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="n23" data-id="23" transform="translate(742,694)" 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">  #23</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#23 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #22 MEM
+[2] → #5 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><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/chapter10b/docs/example2c.json b/chapter10b/docs/example2c.json
new file mode 100644
index 00000000..380815a2
--- /dev/null
+++ b/chapter10b/docs/example2c.json
@@ -0,0 +1,23 @@
+{
+ "ver": 1,
+ "comp": "chapter10b/docs/example2c.svg",
+ "step": 1,
+ "roots": [13],
+ "scope": 0,
+ "nodes": [
+ {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null},
+ {"id": 3, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 1, "role": "MEM", "label": null}], "proj": {"par": 1, "idx": 1}},
+ {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "DATA", "label": null}], "proj": {"par": 1, "idx": 2}},
+ {"id": 5, "label": "new Point", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}], "proj": null},
+ {"id": 6, "label": "#0", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null},
+ {"id": 7, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null},
+ {"id": 8, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 6, "role": "DATA", "label": null}], "proj": null},
+ {"id": 9, "label": "Load p.x", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 0, "role": "DATA", "label": null}], "proj": null},
+ {"id": 10, "label": "Store p.x", "type": "MEM#2", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 11, "label": "Store p.y", "type": "MEM#3", "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "MEM", "label": null}, {"idx": 2, "def": 5, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null},
+ {"id": 12, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 3, "role": "MEM", "label": null}, {"idx": 2, "def": 10, "role": "MEM", "label": null}, {"idx": 3, "def": 11, "role": "MEM", "label": null}], "proj": null},
+ {"id": 13, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 0, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}
+ ],
+ "groups": [
+ ]
+}
diff --git a/chapter10b/docs/example2c.svg b/chapter10b/docs/example2c.svg
index 531fabfe..01bbe10a 100644
--- a/chapter10b/docs/example2c.svg
+++ b/chapter10b/docs/example2c.svg
@@ -1,56 +1,121 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Generated by graphviz version 12.2.0 (20241103.1931)
- -->
-<!-- Title: Memory Pages: 1 -->
-<svg width="470pt" height="133pt"
- viewBox="0.00 0.00 469.52 133.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 129)">
-<title>Memory</title>
-<polygon fill="#fafbfc" stroke="none" points="-4,4 -4,-129 465.52,-129 465.52,4 -4,4"/>
-<!-- M -->
-<g id="node1" class="node">
-<title>M</title>
-<polygon fill="#dcecff" stroke="#758191" points="132.52,-38.54 132.52,-53.46 93.71,-64 38.81,-64 0,-53.46 0,-38.54 38.81,-28 93.71,-28 132.52,-38.54"/>
-<text text-anchor="middle" x="66.26" y="-41.73" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Prior x memory</text>
-</g>
-<!-- L -->
-<g id="node2" class="node">
-<title>L</title>
-<path fill="#edf3f7" stroke="#758191" d="M222.27,-36C222.27,-36 184.52,-36 184.52,-36 178.52,-36 172.52,-30 172.52,-24 172.52,-24 172.52,-12 172.52,-12 172.52,-6 178.52,0 184.52,0 184.52,0 222.27,0 222.27,0 228.27,0 234.27,-6 234.27,-12 234.27,-12 234.27,-24 234.27,-24 234.27,-30 228.27,-36 222.27,-36"/>
-<text text-anchor="middle" x="203.4" y="-13.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Load p.x</text>
-</g>
-<!-- L&#45;&gt;M -->
-<g id="edge1" class="edge">
-<title>L&#45;&gt;M</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M172.28,-32C172.28,-32 119.52,-32 119.52,-32"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="119.52,-29.55 112.52,-32 119.52,-34.45 119.52,-29.55"/>
-</g>
-<!-- S -->
-<g id="node3" class="node">
-<title>S</title>
-<polygon fill="#dcecff" stroke="#758191" points="411.44,-38.54 411.44,-53.46 385.93,-64 349.86,-64 324.36,-53.46 324.36,-38.54 349.86,-28 385.93,-28 411.44,-38.54"/>
-<text text-anchor="middle" x="367.9" y="-41.73" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Store p.x</text>
-</g>
-<!-- S&#45;&gt;M -->
-<g id="edge2" class="edge">
-<title>S&#45;&gt;M</title>
-<path fill="none" stroke="#2867b2" stroke-width="1.5" d="M324.04,-50C324.04,-50 142.29,-50 142.29,-50"/>
-<polygon fill="#2867b2" stroke="#2867b2" stroke-width="1.5" points="142.29,-47.55 135.29,-50 142.29,-52.45 142.29,-47.55"/>
-</g>
-<!-- S&#45;&gt;L -->
-<g id="edge3" class="edge">
-<title>S&#45;&gt;L</title>
-<path fill="none" stroke="#536477" stroke-width="1.5" stroke-dasharray="5,2" d="M339.24,-32C339.24,-32 243.79,-32 243.79,-32"/>
-<polygon fill="#536477" stroke="#536477" stroke-width="1.5" points="243.79,-29.55 236.79,-32 243.79,-34.45 243.79,-29.55"/>
-<text text-anchor="middle" x="257.02" y="-33.95" font-family="Helvetica,sans-Serif" font-size="9.00" fill="#364352">execute load first</text>
-</g>
-<!-- Y -->
-<g id="node4" class="node">
-<title>Y</title>
-<polygon fill="#dcecff" stroke="#758191" points="461.52,-99.54 461.52,-114.46 406.68,-125 329.12,-125 274.27,-114.46 274.27,-99.54 329.12,-89 406.68,-89 461.52,-99.54"/>
-<text text-anchor="middle" x="367.9" y="-102.72" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#152330">Store p.y: independent</text>
-</g>
-</g>
-</svg>
+<svg aria-label="Compiler graph" width="598" height="572" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 598 572" 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 ASSOC" id="e6i0" d="M267,46 C267,70 514,41 514,65" stroke="#9396a3" marker-start="url(#arrow-ASSOC)" style="opacity: 1;"><title>#6[0] → #1 · ASSOC</title></path><path class="edge MEM" id="e7i1" d="M84,118 L84,150 Q84,158 92,158 L181,158 Q186,158 186,163 L186,168" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#7[1] → #3 · MEM</title></path><path class="edge DATA" id="e7i2" d="M362,118 L362,140 Q362,148 354,148 L218,148 Q210,148 210,156 L210,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#7[2] → #5 · DATA</title></path><path class="edge DATA" id="e7i3" d="M514,118 L514,130 Q514,138 506,138 L242,138 Q234,138 234,146 L234,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#7[3] → #6 · DATA</title></path><path class="edge MEM" id="e8i1" d="M84,118 L84,150 Q84,158 92,158 L333,158 Q338,158 338,163 L338,168" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#8[1] → #3 · MEM</title></path><path class="edge DATA" id="e8i2" d="M362,118 L362,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#8[2] → #5 · DATA</title></path><path class="edge DATA" id="e8i3" d="M514,118 L514,130 Q514,138 506,138 L394,138 Q386,138 386,146 L386,168" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#8[3] → #6 · DATA</title></path><path class="edge MEM" id="e9i1" d="M198,224 L198,256 Q198,264 206,264 L439,264 Q447,264 447,272 L447,284" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#9[1] → #7 · MEM</title></path><path class="edge DATA" id="e9i2" d="M362,118 L362,140 Q362,148 370,148 L463,148 Q471,148 471,156 L471,284" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#9[2] → #5 · DATA</title></path><path class="edge MEM" id="e10i1" d="M198,224 L198,256 Q198,264 190,264 L151,264 Q143,264 143,272 L143,284" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#10[1] → #7 · MEM</title></path><path class="edge DATA" id="e10i2" d="M362,118 L362,140 Q362,148 354,148 L124,148 Q116,148 116,156 L116,266 Q116,274 124,274 L162,274 Q167,274 167,279 L167,284" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#10[2] → #5 · DATA</title></path><path class="edge DATA" id="e10i3" d="M204,118 L204,123 Q204,128 199,128 L135,128 Q127,128 127,136 L127,226 Q127,234 135,234 L183,234 Q191,234 191,242 L191,284" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#10[3] → #4 · DATA</title></path><path class="edge MEM" id="e11i1" d="M350,224 L350,229 Q350,234 345,234 L303,234 Q295,234 295,242 L295,284" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#11[1] → #8 · MEM</title></path><path class="edge DATA" id="e11i2" d="M362,118 L362,140 Q362,148 370,148 L412,148 Q420,148 420,156 L420,236 Q420,244 412,244 L327,244 Q319,244 319,252 L319,284" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#11[2] → #5 · DATA</title></path><path class="edge DATA" id="e11i3" d="M204,118 L204,123 Q204,128 209,128 L423,128 Q431,128 431,136 L431,246 Q431,254 423,254 L351,254 Q343,254 343,262 L343,284" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#11[3] → #4 · DATA</title></path><path class="edge MEM" id="e12i1" d="M84,118 L84,342 Q84,350 92,350 L123,350 Q131,350 131,358 L131,388" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#12[1] → #3 · MEM</title></path><path class="edge MEM" id="e12i2" d="M155,340 L155,388" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#12[2] → #10 · MEM</title></path><path class="edge MEM" id="e12i3" d="M307,340 L307,345 Q307,350 302,350 L187,350 Q179,350 179,358 L179,388" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#12[3] → #11 · MEM</title></path><path class="edge MEM" id="e13i1" d="M143,444 L143,449 Q143,454 148,454 L421,454 Q429,454 429,462 L429,492" stroke="#2867b2" marker-start="url(#arrow-MEM)" style="opacity: 1;"><title>#13[1] → #12 · MEM</title></path><path class="edge DATA" id="e13i2" d="M459,340 L459,492" stroke="#536477" marker-start="url(#arrow-DATA)" style="opacity: 1;"><title>#13[2] → #9 · 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(24,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">  #1</tspan></text><text class="type" text-anchor="middle" y="35" x="120"/><title>#1 Start
+Type not computed
+
+</title></g><g class="node" id="n3" data-id="3" 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">  #3/1</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#3 $mem
+Projection 1 of #1
+Type not computed
+
+[0] → #1 MEM</title></g><g class="node" id="n4" data-id="4" transform="translate(144,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">  #4/2</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#4 arg
+Projection 2 of #1
+Type not computed
+
+[0] → #1 DATA</title></g><g class="node" id="n5" data-id="5" transform="translate(302,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 Point</tspan><tspan class="node-id">  #5</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#5 new Point
+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="n6" data-id="6" transform="translate(454,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">  #6</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#6 #0
+Type not computed
+
+[0] → #1 ASSOC</title><circle class="port" cx="60" cy="-3" r="3" fill="#536477"/><text class="slot" x="60" y="-10" text-anchor="middle">0</text></g><g class="node" id="n7" data-id="7" transform="translate(138,174)" 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>Store p.x</tspan><tspan class="node-id">  #7</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#2</text><title>#7 Store p.x
+MEM#2
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #5 DATA
+[3] → #6 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="n8" data-id="8" transform="translate(290,174)" 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>Store p.y</tspan><tspan class="node-id">  #8</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#3</text><title>#8 Store p.y
+MEM#3
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #5 DATA
+[3] → #6 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="n9" data-id="9" transform="translate(399,290)" 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>Load p.x</tspan><tspan class="node-id">  #9</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#9 Load p.x
+Type not computed
+
+[0] → — CTRL
+[1] → #7 MEM
+[2] → #5 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="#536477"/><circle class="port" cx="72" cy="-3" r="3" fill="#536477"/><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="n10" data-id="10" transform="translate(95,290)" 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>Store p.x</tspan><tspan class="node-id">  #10</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#2</text><title>#10 Store p.x
+MEM#2
+
+[0] → — CTRL
+[1] → #7 MEM
+[2] → #5 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="n11" data-id="11" transform="translate(247,290)" 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>Store p.y</tspan><tspan class="node-id">  #11</tspan></text><text class="type" text-anchor="middle" y="35" x="60">MEM#3</text><title>#11 Store p.y
+MEM#3
+
+[0] → — CTRL
+[1] → #8 MEM
+[2] → #5 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="n12" data-id="12" transform="translate(83,394)" 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">  #12</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#12 MemMerge
+Type not computed
+
+[0] → — CTRL
+[1] → #3 MEM
+[2] → #10 MEM
+[3] → #11 MEM</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(369,498)" 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">  #13</tspan></text><text class="type" text-anchor="middle" y="35" x="60"/><title>#13 Return
+Type not computed
+
+[0] → — CTRL
+[1] → #12 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><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/chapter10b/docs/lattice.gv b/chapter10b/docs/lattice.gv
index a37a1738..93d99dd8 100644
--- a/chapter10b/docs/lattice.gv
+++ b/chapter10b/docs/lattice.gv
@@ -97,9 +97,28 @@ digraph Lattice {
node [fillcolor="#ffc0cb"];
TUPLE_TOP [label="⊤:tuple"];
TUPLE_BOT [label="⊥:tuple"];
- TUPLE1 [label="(type)", shape=box];
- TUPLE2 [label="(type, type)", shape=box];
- TUPLEN [label="(type, …)", shape=box];
+ // Each black element stands for a recursively nested type lattice.
+ TUPLE1 [shape=plain, label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="#ffc0cb">tuple</TD></TR>
+ <TR><TD BGCOLOR="black"><FONT COLOR="white">type</FONT></TD></TR>
+ </TABLE>
+ >];
+ TUPLE2 [shape=plain, label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="#ffc0cb">tuple</TD></TR>
+ <TR><TD BGCOLOR="black"><FONT COLOR="white">type</FONT></TD></TR>
+ <TR><TD BGCOLOR="black"><FONT COLOR="white">type</FONT></TD></TR>
+ </TABLE>
+ >];
+ TUPLEN [shape=plain, label=<
+ <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
+ <TR><TD BGCOLOR="#ffc0cb">tuple</TD></TR>
+ <TR><TD BGCOLOR="black"><FONT COLOR="white">type</FONT></TD></TR>
+ <TR><TD BGCOLOR="black"><FONT COLOR="white">…</FONT></TD></TR>
+ <TR><TD BGCOLOR="black"><FONT COLOR="white">type</FONT></TD></TR>
+ </TABLE>
+ >];
{rank=same; TUPLE1; TUPLE2; TUPLEN;}
TUPLE1 -> TUPLE2 -> TUPLEN [style=invis];
TUPLE_TOP -> {TUPLE1 TUPLE2 TUPLEN};
diff --git a/chapter10b/docs/lattice.svg b/chapter10b/docs/lattice.svg
index ff554601..8d2e2875 100644
--- a/chapter10b/docs/lattice.svg
+++ b/chapter10b/docs/lattice.svg
@@ -4,123 +4,123 @@
<!-- Generated by graphviz version 12.2.0 (20241103.1931)
-->
<!-- Title: Lattice Pages: 1 -->
-<svg width="1823pt" height="533pt"
- viewBox="0.00 0.00 1823.00 533.45" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 529.45)">
+<svg width="1727pt" height="603pt"
+ viewBox="0.00 0.00 1727.00 603.45" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 599.45)">
<title>Lattice</title>
-<polygon fill="white" stroke="none" points="-4,4 -4,-529.45 1819,-529.45 1819,4 -4,4"/>
+<polygon fill="white" stroke="none" points="-4,4 -4,-599.45 1723,-599.45 1723,4 -4,4"/>
<g id="clust1" class="cluster">
<title>cluster_control</title>
-<polygon fill="none" stroke="#cccccc" points="8,-85.99 8,-454.71 98,-454.71 98,-85.99 8,-85.99"/>
-<text text-anchor="middle" x="53" y="-437.41" font-family="Arial" font-size="14.00">Control</text>
+<polygon fill="none" stroke="#cccccc" points="8,-85.99 8,-524.71 98,-524.71 98,-85.99 8,-85.99"/>
+<text text-anchor="middle" x="53" y="-507.41" font-family="Arial" font-size="14.00">Control</text>
</g>
<g id="clust2" class="cluster">
<title>cluster_integer</title>
-<polygon fill="none" stroke="#cccccc" points="106,-85.99 106,-454.71 404,-454.71 404,-85.99 106,-85.99"/>
-<text text-anchor="middle" x="255" y="-437.41" font-family="Arial" font-size="14.00">Integer</text>
+<polygon fill="none" stroke="#cccccc" points="106,-85.99 106,-524.71 404,-524.71 404,-85.99 106,-85.99"/>
+<text text-anchor="middle" x="255" y="-507.41" font-family="Arial" font-size="14.00">Integer</text>
</g>
<g id="clust6" class="cluster">
<title>cluster_pointer</title>
-<polygon fill="none" stroke="#cccccc" points="412,-75 412,-465.7 893,-465.7 893,-75 412,-75"/>
-<text text-anchor="middle" x="652.5" y="-448.4" font-family="Arial" font-size="14.00">Pointer = nullability × struct type</text>
+<polygon fill="none" stroke="#cccccc" points="412,-75 412,-535.7 893,-535.7 893,-75 412,-75"/>
+<text text-anchor="middle" x="652.5" y="-518.4" font-family="Arial" font-size="14.00">Pointer = nullability × struct type</text>
</g>
<g id="clust13" class="cluster">
<title>cluster_struct</title>
-<polygon fill="none" stroke="#cccccc" points="901,-75 901,-481.45 1233,-481.45 1233,-75 901,-75"/>
-<text text-anchor="middle" x="1067" y="-464.15" font-family="Arial" font-size="14.00">Struct</text>
-<text text-anchor="middle" x="1067" y="-448.4" font-family="Arial" font-size="14.00">named collection of named scalar types</text>
+<polygon fill="none" stroke="#cccccc" points="901,-75 901,-551.45 1233,-551.45 1233,-75 901,-75"/>
+<text text-anchor="middle" x="1067" y="-534.15" font-family="Arial" font-size="14.00">Struct</text>
+<text text-anchor="middle" x="1067" y="-518.4" font-family="Arial" font-size="14.00">named collection of named scalar types</text>
</g>
<g id="clust17" class="cluster">
<title>cluster_memory</title>
-<polygon fill="none" stroke="#cccccc" points="1241,-85.99 1241,-470.46 1523,-470.46 1523,-85.99 1241,-85.99"/>
-<text text-anchor="middle" x="1382" y="-453.16" font-family="Arial" font-size="14.00">Memory</text>
-<text text-anchor="middle" x="1382" y="-437.41" font-family="Arial" font-size="14.00">precise alias slices</text>
+<polygon fill="none" stroke="#cccccc" points="1241,-85.99 1241,-540.46 1523,-540.46 1523,-85.99 1241,-85.99"/>
+<text text-anchor="middle" x="1382" y="-523.16" font-family="Arial" font-size="14.00">Memory</text>
+<text text-anchor="middle" x="1382" y="-507.41" font-family="Arial" font-size="14.00">precise alias slices</text>
</g>
<g id="clust21" class="cluster">
<title>cluster_tuple</title>
-<polygon fill="none" stroke="#cccccc" points="1531,-85.99 1531,-470.46 1807,-470.46 1807,-85.99 1531,-85.99"/>
-<text text-anchor="middle" x="1669" y="-453.16" font-family="Arial" font-size="14.00">Tuple</text>
-<text text-anchor="middle" x="1669" y="-437.41" font-family="Arial" font-size="14.00">collection of types</text>
+<polygon fill="none" stroke="#cccccc" points="1531,-85.99 1531,-540.46 1711,-540.46 1711,-85.99 1531,-85.99"/>
+<text text-anchor="middle" x="1621" y="-523.16" font-family="Arial" font-size="14.00">Tuple</text>
+<text text-anchor="middle" x="1621" y="-507.41" font-family="Arial" font-size="14.00">collection of types</text>
</g>
<!-- TOP -->
<g id="node1" class="node">
<title>TOP</title>
-<ellipse fill="black" stroke="black" cx="887" cy="-507.45" rx="27" ry="18"/>
-<text text-anchor="middle" x="887" y="-503.35" font-family="DejaVu Sans" font-size="13.00" fill="white">⊤</text>
+<ellipse fill="black" stroke="black" cx="887" cy="-577.45" rx="27" ry="18"/>
+<text text-anchor="middle" x="887" y="-573.35" font-family="DejaVu Sans" font-size="13.00" fill="white">⊤</text>
</g>
<!-- XCTRL -->
<g id="node3" class="node">
<title>XCTRL</title>
-<ellipse fill="#ffff00" stroke="black" cx="53" cy="-404.96" rx="36.51" ry="18"/>
-<text text-anchor="middle" x="53" y="-400.86" font-family="DejaVu Sans" font-size="13.00">⊤:ctrl</text>
+<ellipse fill="#ffff00" stroke="black" cx="53" cy="-474.96" rx="36.51" ry="18"/>
+<text text-anchor="middle" x="53" y="-470.86" font-family="DejaVu Sans" font-size="13.00">⊤:ctrl</text>
</g>
<!-- TOP&#45;&gt;XCTRL -->
<g id="edge60" class="edge">
<title>TOP&#45;&gt;XCTRL</title>
-<path fill="none" stroke="#555555" d="M859.92,-506.29C725.56,-505.4 135.66,-500.43 102,-481.45 82.17,-470.27 69.05,-447.37 61.41,-429.71"/>
-<polygon fill="#555555" stroke="#555555" points="63.45,-429.15 59.23,-424.39 59.57,-430.74 63.45,-429.15"/>
+<path fill="none" stroke="#555555" d="M859.92,-576.29C725.56,-575.4 135.66,-570.43 102,-551.45 82.17,-540.27 69.05,-517.37 61.41,-499.71"/>
+<polygon fill="#555555" stroke="#555555" points="63.45,-499.15 59.23,-494.39 59.57,-500.74 63.45,-499.15"/>
</g>
<!-- INT_TOP -->
<g id="node5" class="node">
<title>INT_TOP</title>
-<ellipse fill="#add8e6" stroke="black" cx="353" cy="-404.96" rx="33.44" ry="18"/>
-<text text-anchor="middle" x="353" y="-400.86" font-family="DejaVu Sans" font-size="13.00">⊤:int</text>
+<ellipse fill="#add8e6" stroke="black" cx="353" cy="-474.96" rx="33.44" ry="18"/>
+<text text-anchor="middle" x="353" y="-470.86" font-family="DejaVu Sans" font-size="13.00">⊤:int</text>
</g>
<!-- TOP&#45;&gt;INT_TOP -->
<g id="edge61" class="edge">
<title>TOP&#45;&gt;INT_TOP</title>
-<path fill="none" stroke="#555555" d="M859.8,-506.38C764.27,-505.97 447.72,-502.97 408,-481.45 387.23,-470.19 372.29,-447.31 363.27,-429.67"/>
-<polygon fill="#555555" stroke="#555555" points="365.18,-428.79 360.66,-424.32 361.41,-430.63 365.18,-428.79"/>
+<path fill="none" stroke="#555555" d="M859.8,-576.38C764.27,-575.97 447.72,-572.97 408,-551.45 387.23,-540.19 372.29,-517.31 363.27,-499.67"/>
+<polygon fill="#555555" stroke="#555555" points="365.18,-498.79 360.66,-494.32 361.41,-500.63 365.18,-498.79"/>
</g>
<!-- PTR_TOP -->
<g id="node10" class="node">
<title>PTR_TOP</title>
-<ellipse fill="#008000" stroke="black" cx="715" cy="-404.96" rx="61.7" ry="28.99"/>
-<text text-anchor="middle" x="715" y="-409.11" font-family="DejaVu Sans" font-size="13.00" fill="white">⊤:ptr</text>
-<text text-anchor="middle" x="715" y="-392.61" font-family="DejaVu Sans" font-size="13.00" fill="white">[*⊤:struct]</text>
+<ellipse fill="#008000" stroke="black" cx="715" cy="-474.96" rx="61.7" ry="28.99"/>
+<text text-anchor="middle" x="715" y="-479.11" font-family="DejaVu Sans" font-size="13.00" fill="white">⊤:ptr</text>
+<text text-anchor="middle" x="715" y="-462.61" font-family="DejaVu Sans" font-size="13.00" fill="white">[*⊤:struct]</text>
</g>
<!-- TOP&#45;&gt;PTR_TOP -->
<g id="edge62" class="edge">
<title>TOP&#45;&gt;PTR_TOP</title>
-<path fill="none" stroke="#555555" d="M867.27,-494.92C841.1,-479.63 794.17,-452.21 759.3,-431.84"/>
-<polygon fill="#555555" stroke="#555555" points="760.48,-430.1 754.24,-428.88 758.36,-433.72 760.48,-430.1"/>
+<path fill="none" stroke="#555555" d="M867.27,-564.92C841.1,-549.63 794.17,-522.21 759.3,-501.84"/>
+<polygon fill="#555555" stroke="#555555" points="760.48,-500.1 754.24,-498.88 758.36,-503.72 760.48,-500.1"/>
</g>
<!-- STRUCT_TOP -->
<g id="node20" class="node">
<title>STRUCT_TOP</title>
-<ellipse fill="#90ee90" stroke="black" cx="1020" cy="-404.96" rx="64.35" ry="28.99"/>
-<text text-anchor="middle" x="1020" y="-409.11" font-family="DejaVu Sans" font-size="13.00">⊤:struct</text>
-<text text-anchor="middle" x="1020" y="-392.61" font-family="DejaVu Sans" font-size="13.00">[struct top]</text>
+<ellipse fill="#90ee90" stroke="black" cx="1020" cy="-474.96" rx="64.35" ry="28.99"/>
+<text text-anchor="middle" x="1020" y="-479.11" font-family="DejaVu Sans" font-size="13.00">⊤:struct</text>
+<text text-anchor="middle" x="1020" y="-462.61" font-family="DejaVu Sans" font-size="13.00">[struct top]</text>
</g>
<!-- TOP&#45;&gt;STRUCT_TOP -->
<g id="edge63" class="edge">
<title>TOP&#45;&gt;STRUCT_TOP</title>
-<path fill="none" stroke="#555555" d="M904.39,-493.31C923.88,-478.58 956.09,-454.25 981.56,-435"/>
-<polygon fill="#555555" stroke="#555555" points="982.82,-436.68 986.34,-431.39 980.29,-433.33 982.82,-436.68"/>
+<path fill="none" stroke="#555555" d="M904.39,-563.31C923.88,-548.58 956.09,-524.25 981.56,-505"/>
+<polygon fill="#555555" stroke="#555555" points="982.82,-506.68 986.34,-501.39 980.29,-503.33 982.82,-506.68"/>
</g>
<!-- MEM_TOP -->
<g id="node26" class="node">
<title>MEM_TOP</title>
-<ellipse fill="#00008b" stroke="black" cx="1347" cy="-404.96" rx="44.7" ry="18"/>
-<text text-anchor="middle" x="1347" y="-400.86" font-family="DejaVu Sans" font-size="13.00" fill="white">⊤:mem</text>
+<ellipse fill="#00008b" stroke="black" cx="1347" cy="-474.96" rx="44.7" ry="18"/>
+<text text-anchor="middle" x="1347" y="-470.86" font-family="DejaVu Sans" font-size="13.00" fill="white">⊤:mem</text>
</g>
<!-- TOP&#45;&gt;MEM_TOP -->
<g id="edge64" class="edge">
<title>TOP&#45;&gt;MEM_TOP</title>
-<path fill="none" stroke="#555555" d="M914.28,-506.34C985.84,-505.75 1177.55,-502.23 1237,-481.45 1270.57,-469.71 1303.45,-444.89 1324.38,-426.91"/>
-<polygon fill="#555555" stroke="#555555" points="1325.69,-428.56 1328.82,-423.03 1322.92,-425.39 1325.69,-428.56"/>
+<path fill="none" stroke="#555555" d="M914.28,-576.34C985.84,-575.75 1177.55,-572.23 1237,-551.45 1270.57,-539.71 1303.45,-514.89 1324.38,-496.91"/>
+<polygon fill="#555555" stroke="#555555" points="1325.69,-498.56 1328.82,-493.03 1322.92,-495.39 1325.69,-498.56"/>
</g>
<!-- TUPLE_TOP -->
<g id="node31" class="node">
<title>TUPLE_TOP</title>
-<ellipse fill="#ffc0cb" stroke="black" cx="1584" cy="-404.96" rx="44.7" ry="18"/>
-<text text-anchor="middle" x="1584" y="-400.86" font-family="DejaVu Sans" font-size="13.00">⊤:tuple</text>
+<ellipse fill="#ffc0cb" stroke="black" cx="1584" cy="-474.96" rx="44.7" ry="18"/>
+<text text-anchor="middle" x="1584" y="-470.86" font-family="DejaVu Sans" font-size="13.00">⊤:tuple</text>
</g>
<!-- TOP&#45;&gt;TUPLE_TOP -->
<g id="edge65" class="edge">
<title>TOP&#45;&gt;TUPLE_TOP</title>
-<path fill="none" stroke="#555555" d="M914.19,-506.75C1029.19,-507.83 1472.18,-510.1 1527,-481.45 1548.39,-470.27 1564,-447.05 1573.43,-429.3"/>
-<polygon fill="#555555" stroke="#555555" points="1575.08,-430.68 1575.93,-424.38 1571.33,-428.78 1575.08,-430.68"/>
+<path fill="none" stroke="#555555" d="M914.19,-576.75C1029.19,-577.83 1472.18,-580.1 1527,-551.45 1548.39,-540.27 1564,-517.05 1573.43,-499.3"/>
+<polygon fill="#555555" stroke="#555555" points="1575.08,-500.68 1575.93,-494.38 1571.33,-498.78 1575.08,-500.68"/>
</g>
<!-- BOT -->
<g id="node2" class="node">
@@ -137,7 +137,7 @@
<!-- XCTRL&#45;&gt;CTRL -->
<g id="edge1" class="edge">
<title>XCTRL&#45;&gt;CTRL</title>
-<path fill="none" stroke="#555555" d="M53,-386.63C53,-337.1 53,-194.83 53,-137.43"/>
+<path fill="none" stroke="#555555" d="M53,-456.55C53,-397.7 53,-206.04 53,-137.58"/>
<polygon fill="#555555" stroke="#555555" points="55.1,-137.74 53,-131.74 50.9,-137.74 55.1,-137.74"/>
</g>
<!-- XCTRL&#45;&gt;INT_TOP -->
@@ -150,38 +150,38 @@
<!-- INT_NEG -->
<g id="node7" class="node">
<title>INT_NEG</title>
-<ellipse fill="#add8e6" stroke="black" cx="169" cy="-310.97" rx="55.45" ry="18"/>
-<text text-anchor="middle" x="169" y="-306.87" font-family="DejaVu Sans" font-size="13.00">… −2, −1</text>
+<ellipse fill="#add8e6" stroke="black" cx="169" cy="-345.97" rx="55.45" ry="18"/>
+<text text-anchor="middle" x="169" y="-341.87" font-family="DejaVu Sans" font-size="13.00">… −2, −1</text>
</g>
<!-- INT_TOP&#45;&gt;INT_NEG -->
<g id="edge4" class="edge">
<title>INT_TOP&#45;&gt;INT_NEG</title>
-<path fill="none" stroke="#555555" d="M328.95,-391.93C297.31,-376.11 241.45,-348.19 204.83,-329.88"/>
-<polygon fill="#555555" stroke="#555555" points="205.88,-328.06 199.58,-327.25 204,-331.81 205.88,-328.06"/>
+<path fill="none" stroke="#555555" d="M330.56,-461.28C305.82,-447.02 265.13,-422.74 232,-398.97 218.63,-389.37 204.44,-377.8 192.92,-368"/>
+<polygon fill="#555555" stroke="#555555" points="194.57,-366.65 188.64,-364.34 191.83,-369.84 194.57,-366.65"/>
</g>
<!-- INT_ZERO -->
<g id="node8" class="node">
<title>INT_ZERO</title>
-<ellipse fill="#add8e6" stroke="black" cx="267" cy="-310.97" rx="27" ry="18"/>
-<text text-anchor="middle" x="267" y="-306.87" font-family="DejaVu Sans" font-size="13.00">0</text>
+<ellipse fill="#add8e6" stroke="black" cx="267" cy="-345.97" rx="27" ry="18"/>
+<text text-anchor="middle" x="267" y="-341.87" font-family="DejaVu Sans" font-size="13.00">0</text>
</g>
<!-- INT_TOP&#45;&gt;INT_ZERO -->
<g id="edge5" class="edge">
<title>INT_TOP&#45;&gt;INT_ZERO</title>
-<path fill="none" stroke="#555555" d="M338.41,-388.35C323.94,-372.88 301.71,-349.1 285.9,-332.18"/>
-<polygon fill="#555555" stroke="#555555" points="287.47,-330.79 281.84,-327.84 284.4,-333.66 287.47,-330.79"/>
+<path fill="none" stroke="#555555" d="M341.83,-457.59C331.49,-442.41 315.68,-419.18 302,-398.97 295.36,-389.15 288.04,-378.28 281.81,-369.03"/>
+<polygon fill="#555555" stroke="#555555" points="283.64,-367.97 278.55,-364.17 280.15,-370.32 283.64,-367.97"/>
</g>
<!-- INT_POS -->
<g id="node9" class="node">
<title>INT_POS</title>
-<ellipse fill="#add8e6" stroke="black" cx="353" cy="-310.97" rx="43.16" ry="18"/>
-<text text-anchor="middle" x="353" y="-306.87" font-family="DejaVu Sans" font-size="13.00">1, 2, …</text>
+<ellipse fill="#add8e6" stroke="black" cx="353" cy="-345.97" rx="43.16" ry="18"/>
+<text text-anchor="middle" x="353" y="-341.87" font-family="DejaVu Sans" font-size="13.00">1, 2, …</text>
</g>
<!-- INT_TOP&#45;&gt;INT_POS -->
<g id="edge6" class="edge">
<title>INT_TOP&#45;&gt;INT_POS</title>
-<path fill="none" stroke="#555555" d="M353,-386.65C353,-372.52 353,-352.37 353,-336.56"/>
-<polygon fill="#555555" stroke="#555555" points="355.1,-336.7 353,-330.7 350.9,-336.7 355.1,-336.7"/>
+<path fill="none" stroke="#555555" d="M353,-456.57C353,-434.53 353,-396.41 353,-371.44"/>
+<polygon fill="#555555" stroke="#555555" points="355.1,-371.66 353,-365.66 350.9,-371.66 355.1,-371.66"/>
</g>
<!-- INT_TOP&#45;&gt;PTR_TOP -->
<!-- INT_BOT -->
@@ -199,70 +199,70 @@
<!-- INT_NEG&#45;&gt;INT_BOT -->
<g id="edge7" class="edge">
<title>INT_NEG&#45;&gt;INT_BOT</title>
-<path fill="none" stroke="#555555" d="M179.44,-292.83C201.14,-257.2 251.13,-175.15 275.35,-135.4"/>
-<polygon fill="#555555" stroke="#555555" points="276.89,-136.9 278.22,-130.68 273.31,-134.72 276.89,-136.9"/>
+<path fill="none" stroke="#555555" d="M177.82,-327.91C199.03,-286.92 252.87,-182.84 276.99,-136.21"/>
+<polygon fill="#555555" stroke="#555555" points="278.74,-137.4 279.63,-131.11 275.01,-135.47 278.74,-137.4"/>
</g>
<!-- INT_NEG&#45;&gt;INT_ZERO -->
<!-- INT_ZERO&#45;&gt;INT_BOT -->
<g id="edge8" class="edge">
<title>INT_ZERO&#45;&gt;INT_BOT</title>
-<path fill="none" stroke="#555555" d="M268.91,-292.83C272.82,-257.83 281.73,-178.04 286.26,-137.55"/>
-<polygon fill="#555555" stroke="#555555" points="288.33,-137.93 286.91,-131.73 284.15,-137.46 288.33,-137.93"/>
+<path fill="none" stroke="#555555" d="M268.65,-327.53C272.53,-286.71 282.19,-184.82 286.66,-137.66"/>
+<polygon fill="#555555" stroke="#555555" points="288.74,-137.99 287.21,-131.82 284.56,-137.59 288.74,-137.99"/>
</g>
<!-- INT_ZERO&#45;&gt;INT_POS -->
<!-- INT_POS&#45;&gt;INT_BOT -->
<g id="edge9" class="edge">
<title>INT_POS&#45;&gt;INT_BOT</title>
-<path fill="none" stroke="#555555" d="M347.43,-292.83C336.04,-257.76 310.03,-177.71 296.9,-137.29"/>
-<polygon fill="#555555" stroke="#555555" points="298.92,-136.72 295.07,-131.67 294.92,-138.02 298.92,-136.72"/>
+<path fill="none" stroke="#555555" d="M348.29,-327.91C337.06,-287.19 308.65,-184.2 295.66,-137.13"/>
+<polygon fill="#555555" stroke="#555555" points="297.74,-136.76 294.12,-131.53 293.69,-137.88 297.74,-136.76"/>
</g>
<!-- PTR_NULL -->
<g id="node12" class="node">
<title>PTR_NULL</title>
-<ellipse fill="#008000" stroke="black" cx="799" cy="-310.97" rx="27.3" ry="18"/>
-<text text-anchor="middle" x="799" y="-306.87" font-family="DejaVu Sans" font-size="13.00" fill="white">null</text>
+<ellipse fill="#008000" stroke="black" cx="799" cy="-345.97" rx="27.3" ry="18"/>
+<text text-anchor="middle" x="799" y="-341.87" font-family="DejaVu Sans" font-size="13.00" fill="white">null</text>
</g>
<!-- PTR_TOP&#45;&gt;PTR_NULL -->
<g id="edge16" class="edge">
<title>PTR_TOP&#45;&gt;PTR_NULL</title>
-<path fill="none" stroke="#555555" d="M738.85,-377.84C752,-363.43 768.1,-345.8 780.33,-332.41"/>
-<polygon fill="#555555" stroke="#555555" points="781.8,-333.91 784.3,-328.06 778.7,-331.08 781.8,-333.91"/>
+<path fill="none" stroke="#555555" d="M732.81,-447.03C748.16,-423.83 770.03,-390.77 784.37,-369.09"/>
+<polygon fill="#555555" stroke="#555555" points="785.98,-370.45 787.54,-364.29 782.48,-368.13 785.98,-370.45"/>
</g>
<!-- PTR_PERSON -->
<g id="node14" class="node">
<title>PTR_PERSON</title>
-<ellipse fill="#008000" stroke="black" cx="542" cy="-310.97" rx="45.72" ry="18"/>
-<text text-anchor="middle" x="542" y="-306.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*Person</text>
+<ellipse fill="#008000" stroke="black" cx="542" cy="-345.97" rx="45.72" ry="18"/>
+<text text-anchor="middle" x="542" y="-341.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*Person</text>
</g>
<!-- PTR_TOP&#45;&gt;PTR_PERSON -->
<g id="edge17" class="edge">
<title>PTR_TOP&#45;&gt;PTR_PERSON</title>
-<path fill="none" stroke="#555555" d="M674.88,-382.62C644.57,-366.5 603.47,-344.65 575.04,-329.54"/>
-<polygon fill="#555555" stroke="#555555" points="576.08,-327.71 569.8,-326.75 574.11,-331.42 576.08,-327.71"/>
+<path fill="none" stroke="#555555" d="M675.88,-452.05C651.99,-438.01 621.28,-418.77 596,-398.97 584.24,-389.76 572.18,-378.36 562.44,-368.58"/>
+<polygon fill="#555555" stroke="#555555" points="564.05,-367.22 558.35,-364.42 561.06,-370.17 564.05,-367.22"/>
</g>
<!-- PTR_S1 -->
<g id="node15" class="node">
<title>PTR_S1</title>
-<ellipse fill="#008000" stroke="black" cx="631" cy="-310.97" rx="27" ry="18"/>
-<text text-anchor="middle" x="631" y="-306.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*s1</text>
+<ellipse fill="#008000" stroke="black" cx="631" cy="-345.97" rx="27" ry="18"/>
+<text text-anchor="middle" x="631" y="-341.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*s1</text>
</g>
<!-- PTR_TOP&#45;&gt;PTR_S1 -->
<g id="edge18" class="edge">
<title>PTR_TOP&#45;&gt;PTR_S1</title>
-<path fill="none" stroke="#555555" d="M691.15,-377.84C678,-363.43 661.9,-345.8 649.67,-332.41"/>
-<polygon fill="#555555" stroke="#555555" points="651.3,-331.08 645.7,-328.06 648.2,-333.91 651.3,-331.08"/>
+<path fill="none" stroke="#555555" d="M697.19,-447.03C681.84,-423.83 659.97,-390.77 645.63,-369.09"/>
+<polygon fill="#555555" stroke="#555555" points="647.52,-368.13 642.46,-364.29 644.02,-370.45 647.52,-368.13"/>
</g>
<!-- PTR_MORE -->
<g id="node16" class="node">
<title>PTR_MORE</title>
-<ellipse fill="#008000" stroke="black" cx="715" cy="-310.97" rx="40.6" ry="18"/>
-<text text-anchor="middle" x="715" y="-306.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*s2, …</text>
+<ellipse fill="#008000" stroke="black" cx="715" cy="-345.97" rx="40.6" ry="18"/>
+<text text-anchor="middle" x="715" y="-341.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*s2, …</text>
</g>
<!-- PTR_TOP&#45;&gt;PTR_MORE -->
<g id="edge19" class="edge">
<title>PTR_TOP&#45;&gt;PTR_MORE</title>
-<path fill="none" stroke="#555555" d="M715,-375.61C715,-363.22 715,-348.82 715,-336.86"/>
-<polygon fill="#555555" stroke="#555555" points="717.1,-336.91 715,-330.91 712.9,-336.91 717.1,-336.91"/>
+<path fill="none" stroke="#555555" d="M715,-445.77C715,-423.52 715,-392.77 715,-371.51"/>
+<polygon fill="#555555" stroke="#555555" points="717.1,-371.66 715,-365.66 712.9,-371.66 717.1,-371.66"/>
</g>
<!-- PTR_TOP&#45;&gt;STRUCT_TOP -->
<!-- PTR_BOT -->
@@ -287,8 +287,8 @@
<!-- PTR_NULL&#45;&gt;PTR_PERSON_NIL -->
<g id="edge26" class="edge">
<title>PTR_NULL&#45;&gt;PTR_PERSON_NIL</title>
-<path fill="none" stroke="#555555" d="M779.65,-297.94C754.63,-282.39 710.79,-255.14 681.32,-236.82"/>
-<polygon fill="#555555" stroke="#555555" points="682.76,-235.24 676.55,-233.86 680.54,-238.81 682.76,-235.24"/>
+<path fill="none" stroke="#555555" d="M790.34,-328.75C783.99,-317.83 774.65,-303.55 764,-292.97 740.64,-269.76 709.08,-249.53 685.25,-235.95"/>
+<polygon fill="#555555" stroke="#555555" points="686.33,-234.14 680.07,-233.04 684.27,-237.8 686.33,-234.14"/>
</g>
<!-- PTR_S1_NIL -->
<g id="node18" class="node">
@@ -299,8 +299,8 @@
<!-- PTR_NULL&#45;&gt;PTR_S1_NIL -->
<g id="edge27" class="edge">
<title>PTR_NULL&#45;&gt;PTR_S1_NIL</title>
-<path fill="none" stroke="#555555" d="M789.88,-293.52C781.74,-278.83 769.73,-257.16 760.65,-240.8"/>
-<polygon fill="#555555" stroke="#555555" points="762.69,-240.14 757.94,-235.91 759.02,-242.18 762.69,-240.14"/>
+<path fill="none" stroke="#555555" d="M792.23,-328.1C783.31,-305.9 767.59,-266.75 757.49,-241.6"/>
+<polygon fill="#555555" stroke="#555555" points="759.55,-241.1 755.36,-236.31 755.65,-242.66 759.55,-241.1"/>
</g>
<!-- PTR_MORE_NIL -->
<g id="node19" class="node">
@@ -311,8 +311,8 @@
<!-- PTR_NULL&#45;&gt;PTR_MORE_NIL -->
<g id="edge28" class="edge">
<title>PTR_NULL&#45;&gt;PTR_MORE_NIL</title>
-<path fill="none" stroke="#555555" d="M806.33,-293.52C812.78,-279.05 822.24,-257.81 829.5,-241.54"/>
-<polygon fill="#555555" stroke="#555555" points="831.32,-242.62 831.84,-236.28 827.48,-240.91 831.32,-242.62"/>
+<path fill="none" stroke="#555555" d="M804.53,-327.84C811.65,-305.78 824.07,-267.3 832.17,-242.24"/>
+<polygon fill="#555555" stroke="#555555" points="834.12,-243.03 833.96,-236.68 830.12,-241.74 834.12,-243.03"/>
</g>
<!-- PTR_ANY -->
<g id="node13" class="node">
@@ -331,41 +331,41 @@
<!-- PTR_PERSON&#45;&gt;PTR_ANY -->
<g id="edge20" class="edge">
<title>PTR_PERSON&#45;&gt;PTR_ANY</title>
-<path fill="none" stroke="#555555" d="M534.66,-293.09C529.74,-281.77 523.08,-266.45 517.05,-252.6"/>
-<polygon fill="#555555" stroke="#555555" points="519.08,-251.99 514.76,-247.33 515.23,-253.67 519.08,-251.99"/>
+<path fill="none" stroke="#555555" d="M536.61,-327.84C530.59,-308.74 520.69,-277.32 513.02,-252.97"/>
+<polygon fill="#555555" stroke="#555555" points="515.08,-252.52 511.28,-247.43 511.08,-253.78 515.08,-252.52"/>
</g>
<!-- PTR_PERSON&#45;&gt;PTR_S1 -->
<!-- PTR_PERSON&#45;&gt;PTR_PERSON_NIL -->
<g id="edge23" class="edge">
<title>PTR_PERSON&#45;&gt;PTR_PERSON_NIL</title>
-<path fill="none" stroke="#555555" d="M560.49,-294.36C578.62,-279.06 606.38,-255.63 626.38,-238.76"/>
-<polygon fill="#555555" stroke="#555555" points="627.67,-240.42 630.9,-234.94 624.96,-237.21 627.67,-240.42"/>
+<path fill="none" stroke="#555555" d="M556.03,-328.62C575.38,-306.08 610.32,-265.36 632,-240.11"/>
+<polygon fill="#555555" stroke="#555555" points="633.38,-241.73 635.7,-235.81 630.19,-238.99 633.38,-241.73"/>
</g>
<!-- PTR_S1&#45;&gt;PTR_ANY -->
<g id="edge21" class="edge">
<title>PTR_S1&#45;&gt;PTR_ANY</title>
-<path fill="none" stroke="#555555" d="M613.06,-297.17C595.19,-284.43 567.11,-264.41 543.66,-247.68"/>
-<polygon fill="#555555" stroke="#555555" points="545.14,-246.16 539.04,-244.39 542.7,-249.58 545.14,-246.16"/>
+<path fill="none" stroke="#555555" d="M621.75,-328.57C615.28,-317.84 606.03,-303.85 596,-292.97 580.61,-276.28 561.35,-260.24 544.26,-247.31"/>
+<polygon fill="#555555" stroke="#555555" points="545.84,-245.87 539.78,-243.96 543.32,-249.23 545.84,-245.87"/>
</g>
<!-- PTR_S1&#45;&gt;PTR_MORE -->
<!-- PTR_S1&#45;&gt;PTR_S1_NIL -->
<g id="edge24" class="edge">
<title>PTR_S1&#45;&gt;PTR_S1_NIL</title>
-<path fill="none" stroke="#555555" d="M648.01,-296.59C668.14,-280.76 701.78,-254.32 724.41,-236.52"/>
-<polygon fill="#555555" stroke="#555555" points="725.59,-238.26 729.01,-232.91 722.99,-234.96 725.59,-238.26"/>
+<path fill="none" stroke="#555555" d="M640.49,-328.79C647.07,-318.15 656.34,-304.18 666,-292.97 684.1,-271.96 707.73,-250.9 724.97,-236.47"/>
+<polygon fill="#555555" stroke="#555555" points="726.11,-238.25 729.39,-232.8 723.43,-235.02 726.11,-238.25"/>
</g>
<!-- PTR_MORE&#45;&gt;PTR_NULL -->
<!-- PTR_MORE&#45;&gt;PTR_ANY -->
<g id="edge22" class="edge">
<title>PTR_MORE&#45;&gt;PTR_ANY</title>
-<path fill="none" stroke="#555555" d="M686.72,-297.75C654.45,-283.81 600.84,-260.66 559.66,-242.88"/>
-<polygon fill="#555555" stroke="#555555" points="560.63,-241.01 554.29,-240.56 558.97,-244.86 560.63,-241.01"/>
+<path fill="none" stroke="#555555" d="M702.63,-328.84C693.45,-317.69 680.11,-303.08 666,-292.97 635.59,-271.17 597.84,-253.38 566.22,-240.61"/>
+<polygon fill="#555555" stroke="#555555" points="567.33,-238.79 560.98,-238.52 565.78,-242.69 567.33,-238.79"/>
</g>
<!-- PTR_MORE&#45;&gt;PTR_MORE_NIL -->
<g id="edge25" class="edge">
<title>PTR_MORE&#45;&gt;PTR_MORE_NIL</title>
-<path fill="none" stroke="#555555" d="M735.36,-294.98C756.57,-279.37 789.9,-254.84 813.23,-237.67"/>
-<polygon fill="#555555" stroke="#555555" points="814.42,-239.4 818.01,-234.16 811.93,-236.02 814.42,-239.4"/>
+<path fill="none" stroke="#555555" d="M729.86,-328.89C739.5,-318.54 752.38,-304.85 764,-292.97 782,-274.55 802.85,-254.03 818.15,-239.12"/>
+<polygon fill="#555555" stroke="#555555" points="819.6,-240.64 822.44,-234.95 816.67,-237.63 819.6,-240.64"/>
</g>
<!-- PTR_PERSON_NIL&#45;&gt;PTR_BOT -->
<g id="edge30" class="edge">
@@ -397,8 +397,8 @@
<!-- STRUCT_TOP&#45;&gt;STRUCT_PERSON -->
<g id="edge36" class="edge">
<title>STRUCT_TOP&#45;&gt;STRUCT_PERSON</title>
-<path fill="none" stroke="#555555" d="M1008.47,-376.11C993.72,-340.49 968.36,-279.23 953.91,-244.33"/>
-<polygon fill="#555555" stroke="#555555" points="955.99,-243.86 951.75,-239.12 952.11,-245.47 955.99,-243.86"/>
+<path fill="none" stroke="#555555" d="M1011.61,-446.07C996.71,-396.53 965.8,-293.77 951.1,-244.91"/>
+<polygon fill="#555555" stroke="#555555" points="953.15,-244.41 949.41,-239.27 949.12,-245.62 953.15,-244.41"/>
</g>
<!-- STRUCT_S1 -->
<g id="node23" class="node">
@@ -410,8 +410,8 @@
<!-- STRUCT_TOP&#45;&gt;STRUCT_S1 -->
<g id="edge37" class="edge">
<title>STRUCT_TOP&#45;&gt;STRUCT_S1</title>
-<path fill="none" stroke="#555555" d="M1020,-375.71C1020,-340.38 1020,-280.29 1020,-245.36"/>
-<polygon fill="#555555" stroke="#555555" points="1022.1,-245.4 1020,-239.4 1017.9,-245.4 1022.1,-245.4"/>
+<path fill="none" stroke="#555555" d="M1020,-445.58C1020,-395.91 1020,-293.85 1020,-245.08"/>
+<polygon fill="#555555" stroke="#555555" points="1022.1,-245.25 1020,-239.25 1017.9,-245.25 1022.1,-245.25"/>
</g>
<!-- STRUCT_S2 -->
<g id="node24" class="node">
@@ -423,8 +423,8 @@
<!-- STRUCT_TOP&#45;&gt;STRUCT_S2 -->
<g id="edge38" class="edge">
<title>STRUCT_TOP&#45;&gt;STRUCT_S2</title>
-<path fill="none" stroke="#555555" d="M1033.32,-376.11C1050.37,-340.49 1079.69,-279.23 1096.39,-244.33"/>
-<polygon fill="#555555" stroke="#555555" points="1098.2,-245.4 1098.9,-239.09 1094.41,-243.59 1098.2,-245.4"/>
+<path fill="none" stroke="#555555" d="M1029.69,-446.07C1046.92,-396.53 1082.65,-293.77 1099.64,-244.91"/>
+<polygon fill="#555555" stroke="#555555" points="1101.62,-245.61 1101.6,-239.25 1097.65,-244.23 1101.62,-245.61"/>
</g>
<!-- STRUCT_MORE -->
<g id="node25" class="node">
@@ -435,8 +435,8 @@
<!-- STRUCT_TOP&#45;&gt;STRUCT_MORE -->
<g id="edge39" class="edge">
<title>STRUCT_TOP&#45;&gt;STRUCT_MORE</title>
-<path fill="none" stroke="#555555" d="M1044.75,-378.1C1079.75,-341.53 1143.14,-275.3 1176.36,-240.58"/>
-<polygon fill="#555555" stroke="#555555" points="1177.75,-242.17 1180.38,-236.39 1174.71,-239.27 1177.75,-242.17"/>
+<path fill="none" stroke="#555555" d="M1038.71,-447.05C1073.74,-396.68 1148.63,-288.97 1181.71,-241.39"/>
+<polygon fill="#555555" stroke="#555555" points="1183.35,-242.73 1185.05,-236.6 1179.9,-240.33 1183.35,-242.73"/>
</g>
<!-- STRUCT_TOP&#45;&gt;MEM_TOP -->
<!-- STRUCT_BOT -->
@@ -488,8 +488,8 @@
<!-- MEM_TOP&#45;&gt;MEM_ALIAS2 -->
<g id="edge46" class="edge">
<title>MEM_TOP&#45;&gt;MEM_ALIAS2</title>
-<path fill="none" stroke="#555555" d="M1342.11,-386.79C1332.64,-353.58 1311.8,-280.42 1300.92,-242.24"/>
-<polygon fill="#555555" stroke="#555555" points="1302.96,-241.75 1299.29,-236.55 1298.92,-242.9 1302.96,-241.75"/>
+<path fill="none" stroke="#555555" d="M1343.44,-456.76C1334.24,-412.32 1309.64,-293.5 1299.01,-242.16"/>
+<polygon fill="#555555" stroke="#555555" points="1301.12,-242.02 1297.85,-236.57 1297.01,-242.88 1301.12,-242.02"/>
</g>
<!-- MEM_ALIAS3 -->
<g id="node29" class="node">
@@ -500,8 +500,8 @@
<!-- MEM_TOP&#45;&gt;MEM_ALIAS3 -->
<g id="edge47" class="edge">
<title>MEM_TOP&#45;&gt;MEM_ALIAS3</title>
-<path fill="none" stroke="#555555" d="M1351.89,-386.79C1361.36,-353.58 1382.2,-280.42 1393.08,-242.24"/>
-<polygon fill="#555555" stroke="#555555" points="1395.08,-242.9 1394.71,-236.55 1391.04,-241.75 1395.08,-242.9"/>
+<path fill="none" stroke="#555555" d="M1350.56,-456.76C1359.76,-412.32 1384.36,-293.5 1394.99,-242.16"/>
+<polygon fill="#555555" stroke="#555555" points="1396.99,-242.88 1396.15,-236.57 1392.88,-242.02 1396.99,-242.88"/>
</g>
<!-- MEM_MORE -->
<g id="node30" class="node">
@@ -512,8 +512,8 @@
<!-- MEM_TOP&#45;&gt;MEM_MORE -->
<g id="edge48" class="edge">
<title>MEM_TOP&#45;&gt;MEM_MORE</title>
-<path fill="none" stroke="#555555" d="M1359.51,-387.45C1385.1,-353.7 1443.4,-276.8 1471.82,-239.32"/>
-<polygon fill="#555555" stroke="#555555" points="1473.25,-240.91 1475.2,-234.86 1469.9,-238.37 1473.25,-240.91"/>
+<path fill="none" stroke="#555555" d="M1356.25,-457.16C1380.82,-412.56 1447.72,-291.1 1475.57,-240.54"/>
+<polygon fill="#555555" stroke="#555555" points="1477.29,-241.76 1478.35,-235.49 1473.62,-239.74 1477.29,-241.76"/>
</g>
<!-- MEM_TOP&#45;&gt;TUPLE_TOP -->
<!-- MEM_BOT -->
@@ -551,70 +551,94 @@
<!-- TUPLE1 -->
<g id="node33" class="node">
<title>TUPLE1</title>
-<polygon fill="#ffc0cb" stroke="black" points="1594.88,-328.97 1539.12,-328.97 1539.12,-292.97 1594.88,-292.97 1594.88,-328.97"/>
-<text text-anchor="middle" x="1567" y="-306.87" font-family="DejaVu Sans" font-size="13.00">(type)</text>
+<polygon fill="#ffc0cb" stroke="none" points="1582.88,-372.47 1539.12,-372.47 1539.12,-319.47 1582.88,-319.47 1582.88,-372.47"/>
+<polygon fill="#ffc0cb" stroke="none" points="1539.12,-345.97 1539.12,-372.47 1582.88,-372.47 1582.88,-345.97 1539.12,-345.97"/>
+<polygon fill="none" stroke="black" points="1539.12,-345.97 1539.12,-372.47 1582.88,-372.47 1582.88,-345.97 1539.12,-345.97"/>
+<text text-anchor="start" x="1544.12" y="-355.12" font-family="DejaVu Sans" font-size="13.00">tuple</text>
+<polygon fill="black" stroke="none" points="1539.12,-319.47 1539.12,-345.97 1582.88,-345.97 1582.88,-319.47 1539.12,-319.47"/>
+<polygon fill="none" stroke="black" points="1539.12,-319.47 1539.12,-345.97 1582.88,-345.97 1582.88,-319.47 1539.12,-319.47"/>
+<text text-anchor="start" x="1546.38" y="-328.62" font-family="DejaVu Sans" font-size="13.00" fill="white">type</text>
</g>
<!-- TUPLE_TOP&#45;&gt;TUPLE1 -->
<g id="edge54" class="edge">
<title>TUPLE_TOP&#45;&gt;TUPLE1</title>
-<path fill="none" stroke="#555555" d="M1580.8,-386.65C1578.19,-372.52 1574.47,-352.37 1571.54,-336.56"/>
-<polygon fill="#555555" stroke="#555555" points="1573.61,-336.2 1570.46,-330.68 1569.48,-336.96 1573.61,-336.2"/>
+<path fill="none" stroke="#555555" d="M1580.85,-456.57C1577.26,-436.74 1571.31,-403.91 1566.86,-379.34"/>
+<polygon fill="#555555" stroke="#555555" points="1568.94,-379.03 1565.81,-373.5 1564.81,-379.77 1568.94,-379.03"/>
</g>
<!-- TUPLE2 -->
<g id="node34" class="node">
<title>TUPLE2</title>
-<polygon fill="#ffc0cb" stroke="black" points="1705,-328.97 1611,-328.97 1611,-292.97 1705,-292.97 1705,-328.97"/>
-<text text-anchor="middle" x="1658" y="-306.87" font-family="DejaVu Sans" font-size="13.00">(type, type)</text>
+<polygon fill="#ffc0cb" stroke="none" points="1642.88,-385.72 1599.12,-385.72 1599.12,-306.22 1642.88,-306.22 1642.88,-385.72"/>
+<polygon fill="#ffc0cb" stroke="none" points="1599.12,-359.22 1599.12,-385.72 1642.88,-385.72 1642.88,-359.22 1599.12,-359.22"/>
+<polygon fill="none" stroke="black" points="1599.12,-359.22 1599.12,-385.72 1642.88,-385.72 1642.88,-359.22 1599.12,-359.22"/>
+<text text-anchor="start" x="1604.12" y="-368.37" font-family="DejaVu Sans" font-size="13.00">tuple</text>
+<polygon fill="black" stroke="none" points="1599.12,-332.72 1599.12,-359.22 1642.88,-359.22 1642.88,-332.72 1599.12,-332.72"/>
+<polygon fill="none" stroke="black" points="1599.12,-332.72 1599.12,-359.22 1642.88,-359.22 1642.88,-332.72 1599.12,-332.72"/>
+<text text-anchor="start" x="1606.38" y="-341.87" font-family="DejaVu Sans" font-size="13.00" fill="white">type</text>
+<polygon fill="black" stroke="none" points="1599.12,-306.22 1599.12,-332.72 1642.88,-332.72 1642.88,-306.22 1599.12,-306.22"/>
+<polygon fill="none" stroke="black" points="1599.12,-306.22 1599.12,-332.72 1642.88,-332.72 1642.88,-306.22 1599.12,-306.22"/>
+<text text-anchor="start" x="1606.38" y="-315.37" font-family="DejaVu Sans" font-size="13.00" fill="white">type</text>
</g>
<!-- TUPLE_TOP&#45;&gt;TUPLE2 -->
<g id="edge55" class="edge">
<title>TUPLE_TOP&#45;&gt;TUPLE2</title>
-<path fill="none" stroke="#555555" d="M1597.23,-387.51C1609,-372.87 1626.35,-351.31 1639.5,-334.97"/>
-<polygon fill="#555555" stroke="#555555" points="1641.06,-336.38 1643.18,-330.39 1637.79,-333.74 1641.06,-336.38"/>
+<path fill="none" stroke="#555555" d="M1588.99,-456.83C1593.76,-440.46 1601.17,-415.04 1607.65,-392.78"/>
+<polygon fill="#555555" stroke="#555555" points="1609.64,-393.48 1609.3,-387.13 1605.6,-392.3 1609.64,-393.48"/>
</g>
<!-- TUPLEN -->
<g id="node35" class="node">
<title>TUPLEN</title>
-<polygon fill="#ffc0cb" stroke="black" points="1798.75,-328.97 1721.25,-328.97 1721.25,-292.97 1798.75,-292.97 1798.75,-328.97"/>
-<text text-anchor="middle" x="1760" y="-306.87" font-family="DejaVu Sans" font-size="13.00">(type, …)</text>
+<polygon fill="#ffc0cb" stroke="none" points="1702.88,-398.97 1659.12,-398.97 1659.12,-292.97 1702.88,-292.97 1702.88,-398.97"/>
+<polygon fill="#ffc0cb" stroke="none" points="1659.12,-372.47 1659.12,-398.97 1702.88,-398.97 1702.88,-372.47 1659.12,-372.47"/>
+<polygon fill="none" stroke="black" points="1659.12,-372.47 1659.12,-398.97 1702.88,-398.97 1702.88,-372.47 1659.12,-372.47"/>
+<text text-anchor="start" x="1664.12" y="-381.62" font-family="DejaVu Sans" font-size="13.00">tuple</text>
+<polygon fill="black" stroke="none" points="1659.12,-345.97 1659.12,-372.47 1702.88,-372.47 1702.88,-345.97 1659.12,-345.97"/>
+<polygon fill="none" stroke="black" points="1659.12,-345.97 1659.12,-372.47 1702.88,-372.47 1702.88,-345.97 1659.12,-345.97"/>
+<text text-anchor="start" x="1666.38" y="-355.12" font-family="DejaVu Sans" font-size="13.00" fill="white">type</text>
+<polygon fill="black" stroke="none" points="1659.12,-319.47 1659.12,-345.97 1702.88,-345.97 1702.88,-319.47 1659.12,-319.47"/>
+<polygon fill="none" stroke="black" points="1659.12,-319.47 1659.12,-345.97 1702.88,-345.97 1702.88,-319.47 1659.12,-319.47"/>
+<text text-anchor="start" x="1674.62" y="-328.62" font-family="DejaVu Sans" font-size="13.00" fill="white">…</text>
+<polygon fill="black" stroke="none" points="1659.12,-292.97 1659.12,-319.47 1702.88,-319.47 1702.88,-292.97 1659.12,-292.97"/>
+<polygon fill="none" stroke="black" points="1659.12,-292.97 1659.12,-319.47 1702.88,-319.47 1702.88,-292.97 1659.12,-292.97"/>
+<text text-anchor="start" x="1666.38" y="-302.12" font-family="DejaVu Sans" font-size="13.00" fill="white">type</text>
</g>
<!-- TUPLE_TOP&#45;&gt;TUPLEN -->
<g id="edge56" class="edge">
<title>TUPLE_TOP&#45;&gt;TUPLEN</title>
-<path fill="none" stroke="#555555" d="M1610.35,-390.18C1639.39,-375.01 1686.42,-350.42 1720.01,-332.87"/>
-<polygon fill="#555555" stroke="#555555" points="1720.85,-334.8 1725.2,-330.16 1718.91,-331.07 1720.85,-334.8"/>
+<path fill="none" stroke="#555555" d="M1600.21,-457.82C1614.47,-443.17 1635.34,-420.61 1651,-398.97 1652.4,-397.02 1653.8,-395.01 1655.17,-392.95"/>
+<polygon fill="#555555" stroke="#555555" points="1656.91,-394.14 1658.41,-387.96 1653.38,-391.86 1656.91,-394.14"/>
</g>
<!-- TUPLE_BOT -->
<g id="node32" class="node">
<title>TUPLE_BOT</title>
-<ellipse fill="#ffc0cb" stroke="black" cx="1621" cy="-111.99" rx="44.7" ry="18"/>
-<text text-anchor="middle" x="1621" y="-107.89" font-family="DejaVu Sans" font-size="13.00">⊥:tuple</text>
+<ellipse fill="#ffc0cb" stroke="black" cx="1602" cy="-111.99" rx="44.7" ry="18"/>
+<text text-anchor="middle" x="1602" y="-107.89" font-family="DejaVu Sans" font-size="13.00">⊥:tuple</text>
</g>
<!-- TUPLE_BOT&#45;&gt;BOT -->
<g id="edge71" class="edge">
<title>TUPLE_BOT&#45;&gt;BOT</title>
-<path fill="none" stroke="#555555" d="M1592.44,-97.66C1574.14,-89.72 1549.65,-80.21 1527,-75 1299.48,-22.62 1016.37,-18.41 918.88,-18.65"/>
-<polygon fill="#555555" stroke="#555555" points="918.88,-16.55 912.89,-18.68 918.89,-20.75 918.88,-16.55"/>
+<path fill="none" stroke="#555555" d="M1577.54,-96.47C1563.29,-88.74 1544.69,-79.84 1527,-75 1410.53,-43.12 1034.45,-25.23 918.41,-20.37"/>
+<polygon fill="#555555" stroke="#555555" points="918.75,-18.28 912.67,-20.13 918.57,-22.48 918.75,-18.28"/>
</g>
<!-- TUPLE1&#45;&gt;TUPLE_BOT -->
<g id="edge57" class="edge">
<title>TUPLE1&#45;&gt;TUPLE_BOT</title>
-<path fill="none" stroke="#555555" d="M1571.79,-292.49C1581.46,-257.21 1603.33,-177.44 1614.37,-137.19"/>
-<polygon fill="#555555" stroke="#555555" points="1616.33,-137.95 1615.9,-131.61 1612.28,-136.84 1616.33,-137.95"/>
+<path fill="none" stroke="#555555" d="M1565.47,-319.7C1573.39,-274.85 1589.82,-181.9 1597.66,-137.56"/>
+<polygon fill="#555555" stroke="#555555" points="1599.69,-138.14 1598.66,-131.86 1595.55,-137.4 1599.69,-138.14"/>
</g>
<!-- TUPLE1&#45;&gt;TUPLE2 -->
<!-- TUPLE2&#45;&gt;TUPLE_BOT -->
<g id="edge58" class="edge">
<title>TUPLE2&#45;&gt;TUPLE_BOT</title>
-<path fill="none" stroke="#555555" d="M1654.72,-292.49C1648.12,-257.37 1633.24,-178.17 1625.65,-137.74"/>
-<polygon fill="#555555" stroke="#555555" points="1627.73,-137.43 1624.56,-131.92 1623.6,-138.2 1627.73,-137.43"/>
+<path fill="none" stroke="#555555" d="M1617.84,-306.4C1613.91,-258.37 1607.3,-177.75 1604,-137.46"/>
+<polygon fill="#555555" stroke="#555555" points="1606.13,-137.74 1603.55,-131.93 1601.95,-138.08 1606.13,-137.74"/>
</g>
<!-- TUPLE2&#45;&gt;TUPLEN -->
<!-- TUPLEN&#45;&gt;TUPLE_BOT -->
<g id="edge59" class="edge">
<title>TUPLEN&#45;&gt;TUPLE_BOT</title>
-<path fill="none" stroke="#555555" d="M1747.66,-292.49C1722.44,-256.74 1664.97,-175.3 1636.95,-135.59"/>
-<polygon fill="#555555" stroke="#555555" points="1638.76,-134.52 1633.59,-130.83 1635.33,-136.94 1638.76,-134.52"/>
+<path fill="none" stroke="#555555" d="M1663.37,-293.19C1646.79,-244.5 1622.69,-173.75 1610.2,-137.07"/>
+<polygon fill="#555555" stroke="#555555" points="1612.27,-136.64 1608.35,-131.63 1608.3,-137.99 1612.27,-136.64"/>
</g>
</g>
</svg>