summaryrefslogtreecommitdiff
path: root/docs/chapter10a
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-09-29 12:34:58 -0700
committerCliff Click <cliffc@acm.org>2026-09-29 12:34:58 -0700
commit502e7e752f3efdb069a36b23ab51ac22f9d74e9e (patch)
treed2b3c84357be365b5a6cc674285d1d2778c0072c /docs/chapter10a
parentfdfc4e4b824e97952110069558de70cd16c725a1 (diff)
downloadSimple-502e7e752f3efdb069a36b23ab51ac22f9d74e9e.tar.gz
Simple-502e7e752f3efdb069a36b23ab51ac22f9d74e9e.zip
Chapter 10a: Structs and Memorylinear-chapter10a
Diffstat (limited to 'docs/chapter10a')
-rw-r--r--docs/chapter10a/10-grammar.md125
-rw-r--r--docs/chapter10a/Makefile14
-rw-r--r--docs/chapter10a/README.md290
-rw-r--r--docs/chapter10a/example1.gv10
-rw-r--r--docs/chapter10a/example1.svg73
-rw-r--r--docs/chapter10a/example2a.gv10
-rw-r--r--docs/chapter10a/example2a.svg85
-rw-r--r--docs/chapter10a/example2b.gv11
-rw-r--r--docs/chapter10a/example2b.svg74
-rw-r--r--docs/chapter10a/example2c.gv9
-rw-r--r--docs/chapter10a/example2c.svg50
-rw-r--r--docs/chapter10a/lattice.gv108
-rw-r--r--docs/chapter10a/lattice.svg570
-rw-r--r--docs/chapter10a/type-control.svg5
-rw-r--r--docs/chapter10a/type-integer.svg5
-rw-r--r--docs/chapter10a/type-memory.svg5
-rw-r--r--docs/chapter10a/type-pointer.svg5
-rw-r--r--docs/chapter10a/type-struct.svg5
-rw-r--r--docs/chapter10a/type-tuple.svg5
19 files changed, 1459 insertions, 0 deletions
diff --git a/docs/chapter10a/10-grammar.md b/docs/chapter10a/10-grammar.md
new file mode 100644
index 00000000..5b9b680e
--- /dev/null
+++ b/docs/chapter10a/10-grammar.md
@@ -0,0 +1,125 @@
+# Grammar for Chapter 10a
+
+```antlrv4
+grammar SimpleLanguage;
+
+program
+ : statement+ EOF
+ ;
+
+statement
+ : returnStatement
+ | structDeclaration
+ | declStatement
+ | blockStatment
+ | expressionStatement
+ | ifStatement
+ | whileStatement
+ | breakStatement
+ | continueStatment
+ ;
+
+field
+ : 'int' IDENTIFIER ';'
+ ;
+
+fields
+ : field+
+ ;
+
+structDeclaration
+ : 'struct' IDENTIFIER '{' fields '}'
+ ;
+
+whileStatement
+ : 'while' '(' expression ')' statement
+ ;
+
+breakStatement
+ : 'break' ';'
+ ;
+
+continueStatement
+ : 'continue' ';'
+ ;
+
+ifStatement
+ : 'if' '(' expression ')' statement ('else' statement)?
+ ;
+
+
+expressionStatement
+ : IDENTIFIER '=' expression ';'
+ | fieldExpression '=' expression ';'
+ ;
+
+blockStatement
+ : '{' statement+ '}'
+ ;
+
+structName
+ : IDENTIFIER
+ ;
+
+declStatement
+ : 'int' IDENTIFIER '=' expression ';'
+ | structName ('?')? IDENTIFIER '=' expression ';'
+ ;
+
+returnStatement
+ : 'return' expression ';'
+ ;
+
+expression
+ : comparisonExpression
+ ;
+
+comparisonExpression
+ : additiveExpression (('==' | '!='| '>'| '<'| '>='| '<=') additiveExpression)*
+ ;
+
+additiveExpression
+ : multiplicativeExpression (('+' | '-') multiplicativeExpression)*
+ ;
+
+multiplicativeExpression
+ : unaryExpression (('*' | '/') unaryExpression)*
+ ;
+
+unaryExpression
+ : ('-') unaryExpression
+ | '!' unaryExpression
+ | primaryExpression
+ ;
+
+newExpression
+ : 'new' IDENTIFIER
+ ;
+
+fieldExpression
+ : primaryExpresson '.' IDENTIFIER
+ ;
+
+primaryExpression
+ : IDENTIFIER
+ | INTEGER_LITERAL
+ | 'true'
+ | 'false'
+ | 'null'
+ | newExpression
+ | '(' expression ')'
+ | fieldExpression
+ ;
+
+INTEGER_LITERAL
+ : [1-9][0-9]*
+ | [0]
+ ;
+
+IDENTIFIER
+ : NON_DIGIT (NON_DIGIT | DIGIT)*
+ ;
+
+NON_DIGIT: [a-zA-Z_];
+DEC_DIGIT: [0-9];
+```
diff --git a/docs/chapter10a/Makefile b/docs/chapter10a/Makefile
new file mode 100644
index 00000000..055882b2
--- /dev/null
+++ b/docs/chapter10a/Makefile
@@ -0,0 +1,14 @@
+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)
diff --git a/docs/chapter10a/README.md b/docs/chapter10a/README.md
new file mode 100644
index 00000000..8aaf779c
--- /dev/null
+++ b/docs/chapter10a/README.md
@@ -0,0 +1,290 @@
+# Chapter 10a: Structs and Memory
+
+[Previous: Chapter 9](../chapter09/README.md) |
+[Next: Chapter 10b](../chapter10b/README.md)
+
+This chapter adds user-defined structs, pointers, allocation, field loads and
+stores, and null checking. It also introduces an evaluator that executes the
+graph, including its memory effects. The [grammar](10-grammar.md) is the
+same in 10a and 10b; the next chapter improves the memory representation.
+
+## One memory value
+
+Arithmetic nodes depend on the values they use, similarly a load also depends
+on when it observes memory. In this chapter every store consumes the preceding
+memory state and produces the next one, and a load consumes memory without
+changing it. This makes the source program's memory ordering explicit in the
+graph.
+
+```java
+struct Point { int x; int y; }
+Point p = new Point;
+p.x = 3;
+p.y = arg;
+return p.x;
+```
+
+`NewNode` produces the pointer. The parser emits stores of zero for both fields,
+then stores 3 into `x` and `arg` into `y`. The final load observes the memory
+after the `y` store. We deliberately keep that dependency here, even though
+different fields are independent. Chapter 10b will remove it.
+
+![One chain orders stores and loads](example1.svg)
+
+| Node | Inputs | Result |
+|----------|---|---|
+| `New` | Control and a struct type | A fresh, non-null object pointer |
+| `Store` | Memory, pointer, field name, value | The updated whole-memory state |
+| `Load` | Memory, pointer, field name | The value of the field |
+| `Start` | External entry | Control, initial memory, and `arg` |
+| `Return` | Control, result, memory | Completion with all preceding effects retained |
+
+The memory edge is a dependency, not a copy of the heap. The graph determines
+the legal execution order. In hardware, a Store updates physical memory
+directly. In the evaluator, a Store updates an objects' attached memory array.
+
+## Memory is an SSA variable
+
+The parser keeps one hidden binding named `$mem`. Source identifiers cannot
+contain `$`, so user code cannot name it. Reading and updating memory uses the
+same `ScopeNode` lookup and update operations as a local variable.
+
+For an `if`, the two branches can finish with different memory values. An
+ordinary Phi selects the memory from the branch that executed:
+
+![Whole memory across a branch](example2a.svg)
+
+Loops reuse Chapter 8's lazy Phi construction. Reading or updating `$mem` in a
+loop creates an initially incomplete memory Phi. Closing the loop supplies its
+backedge. `break`, `continue`, nested loops, and early returns use the same scope
+mechanics as scalar variables.
+
+![Whole memory around a loop](example2b.svg)
+
+Every Return consumes the current whole-memory value. This keeps stores alive
+even when the returned scalar does not depend on them, or when the program
+returns the modified object itself.
+
+## Local memory optimizations
+
+A load immediately following a store to the **same pointer and field** can use
+the stored value. A store immediately following another store to the same
+address can discard the earlier store when no other user needs it. Both the
+pointer and field checks matter: two different fields of one object are
+different addresses, as are the same fields of two different objects.
+
+A load can also move through a memory Phi when doing so exposes a useful
+load-after-store fold. On a loop, the backedge must fold, preventing this rewrite
+from repeatedly moving the load around the cycle.
+
+The single chain is conservative. A store to `y` can prevent forwarding an
+earlier store to `x`, even when the objects are identical. This is a missed
+optimization, not a correctness problem; it motivates the next chapter.
+
+## Enhanced Type Lattice
+
+The Type Lattice for Simple has a major revision in this chapter.
+
+![Type lattice with six domains and parallel named struct alternatives](./lattice.svg)
+
+The diagram uses `⊤` for **top** and `⊥` for **bottom**. A suffix names the
+domain: `⊤:struct` is *struct top*, while the bare `⊤` is global top. In the
+prose we use those words; in code examples we use the actual Java constants.
+The implementation's `$TOP` and `$BOT` names need not appear in the diagram:
+
+| Diagram | Prose | Java constant | Internal struct name |
+|---|---|---|---|
+| `⊤:struct` | struct top | `TypeStruct.TOP` | `$TOP` |
+| `⊥:struct` | struct bottom | `TypeStruct.BOT` | `$BOT` |
+
+Edges in this diagram show lattice order, with top above bottom. They are not
+the use-to-definition edges of the program graphs elsewhere in the chapter.
+Boxes containing an ellipsis abbreviate further parallel alternatives; they
+are not extra union types. Field and tuple-element type lattices are elided.
+
+Within the type lattice, we now have the following domains:
+
+* ![Control](type-control.svg) represents control flow: unreachable control
+ at control top, and reachable control at control bottom.
+* ![Integer](type-integer.svg) has integer top, integer bottom, and parallel
+ constants between them. The ellipses stand for the other integer constants.
+* ![Pointer](type-pointer.svg) (new) combines a struct type with nullability.
+ * The prefix `*` means pointer-to: `*Person` is a non-null pointer to a Person.
+ The suffix `?` includes null, so `*Person?` permits a Person pointer or null.
+ * The pointer domain contains the whole struct lattice twice, once without
+ null and once with it. The diagram expands named alternatives in both
+ copies. It is not just two individual pointer types.
+ * `null` combines struct top with the nullable flag: it has no non-null
+ object alternative. The diagram labels it `*⊤:struct?` as well as `null`.
+ * A pointer to struct bottom can point to any struct. The diagram shows the
+ non-null form as `*⊥:struct` and the nullable form as `*⊥:struct?`.
+ The latter is pointer bottom; pointer top is `*⊤:struct`.
+ * Null evaluates to false; non-null pointers evaluate to true.
+
+ > C analogy: the non-null pointer to struct bottom is akin to `void *`, except
+ > that C's `void *` may also be null. Simple names this constant
+ > `TypeMemPtr.VOIDPTR` and prints it as `*void`. Struct bottom itself is the
+ > common lower bound of struct types, not C's `void` type.
+
+* ![Struct](type-struct.svg) (new) represents user-defined named structs.
+ Fields have integer types in this chapter.
+ * Struct top lies above every named struct; struct bottom lies below every
+ named struct. Top is the high/empty struct alternative, while bottom
+ conservatively includes any struct name.
+ * `Person`, `s1`, `s2`, and further names are parallel alternatives. There is
+ no inheritance, so different named structs do not nest beneath one another,
+ even if they have identical fields.
+ * There is no fixed bound on the names a program can declare. The diagram's
+ ellipsis stands for more named alternatives, not a distinguished unnamed
+ struct. Each named box abbreviates its own field-type lattice.
+* ![Memory](type-memory.svg) (new) represents the whole-memory token.
+ Memory top and memory bottom are `TypeMem.TOP` and `TypeMem.BOT`. Neither
+ records the values stored in individual fields.
+* ![Tuple](type-tuple.svg) represents a collection of results from one node,
+ such as Start's control, memory, and argument. The displayed shapes abbreviate
+ tuples of different lengths and their element-type lattices.
+
+We use the following operations on the lattice:
+
+* **Meet** computes the greatest lower bound. For these examples, think of
+ combining the alternatives represented by its inputs.
+ * The meet of `Person` and `s1` is struct bottom. There is no separate type
+ representing exactly those two names.
+ * The meet of `*Person` and `*s1` is the non-null pointer to struct bottom.
+ * The meet of `*Person` and `null` is `*Person?`.
+ * The meet of the non-null pointer to struct bottom and `null` is pointer bottom.
+ * The meet of `1` and `2` is integer bottom.
+* **Dual** reflects the lattice about its centerline: top and bottom exchange
+ places, and applying dual twice returns the original type.
+ * Struct top and struct bottom are duals.
+ * `null` and the non-null pointer to struct bottom are duals.
+ * A pointer's dual also duals its struct's fields and flips nullability. Thus
+ the dual of `*Person` is not generally the original `*Person?`: the field
+ types must be dualed too. Those field details are omitted in the diagram.
+* **Join** computes the least upper bound. It is defined through meet and dual:
+ `JOIN(x,y) = MEET(x.dual(),y.dual()).dual()`.
+ * The join of `Person` and `s1` is struct top.
+ * The join of `*Person` and `*s1` is pointer top.
+ * The join of the non-null pointer to struct bottom and `null` is pointer top.
+ * The join of `1` and `2` is integer top.
+
+As we construct the Sea of Nodes graph, we ensure that values stay inside the
+domain they are created in - that is ptr fields will never contain ints
+(obviously)... nor even the generic `TOP` and `BOT`. There are a couple of
+nuances worth highlighting.
+
+* When Phis are created, the initial type of the Phi is based on the declared
+ type of its first input. This is a pessimistic type assignment because we do
+ not yet know what other types will be met.
+
+* When all the inputs of the Phi are known, we start with the local Top of the
+ declared type, and then compute a meet of all the input types. This
+ computation results in a more refined type for the Phi.
+
+## Parser Enhancements
+
+In previous chapters the only available type was Integer. Now, variables can
+be of Integer type or pointer to Struct types. To support this, the Parser now
+tracks the declared type of a variable (used to only be Integer!). The
+declared type of a variable defines the set of values that can be legitimately
+assigned to the variable. The Sea of Nodes graph also tracks the actual type
+of values assigned to variables, these type transitions are defined by the Type
+lattice described in the previous section.
+
+## Null Pointer Analysis
+
+The Simple language syntax allows a pointer variable to be specified as
+null-able - and it prevents ever throwing a Null Pointer Exception. The
+compiler decides if a null check is needed, and if needed and missing
+the compiler rejects the program (asking the user to insert a null check).
+
+When the Parser encounters conditions that test the truthiness of a pointer variable, it uses this knowledge to refine the type information in the branches that follow.
+
+Here are two motivating examples:
+
+```java
+struct Bar { int a; }
+Bar? bar = new Bar;
+if (arg) bar = null;
+if( bar ) bar.a = 1;
+```
+
+If `bar` is not `null` above, then we would like to allow the assignment to
+`bar.a`. If the final line lacked the null check, e.g. a plain `bar.a = 1;`,
+then `Java` would compile this program but throw a NPE, and Simple rejects the
+program pointing out a null check is required.
+
+
+```java
+struct Bar { int a; }
+Bar? bar = new Bar;
+if (arg) bar = null;
+int rez = 3;
+if( !bar ) rez=4;
+else bar.a = 1;
+```
+
+If `bar` is `null` then we would like `!bar` to evaluate to `true`. In the else
+branch we know `bar` is not null, hence the assignment to `bar.a` should be
+allowed.
+
+To enable this behaviour, we make following enhancements.
+
+* We track the null-ness of a pointer in the Type system, and hence in every
+ Node that ptr type flows through.
+
+* We "wrap" the predicate of an `If` node with an up-cast when we see that the
+ predicate is a ptr value. The up-cast removes the null possibility on the
+ true branch making it legal to use the pointer.
+
+* The up-cast uses a `Cast` with the non-null pointer to struct bottom
+ (`TypeMemPtr.VOIDPTR`). It joins the original pointer type with that type,
+ corresponding to `*⊥:struct` in the diagram. This JOIN operation preserves
+ everything we already know about ptr, and also adds the new knowledge that
+ the ptr is not-null.
+
+* The up-cast is represented by the `CastNode` op, and if applicable, we
+ replace all occurrences of the original predicate with the up-cast in the
+ current scope. The change is local to each branch of the `If`; occuring
+ separately for the true and the false branches of the `If` (and the false
+ branch inverts the predicate).
+
+* The up-cast peepholes normally; if its input's type is a super type of the
+ up-cast, then the `CastNode` can be removed. See `ScopeNode.upcast()` method,
+ and `CastNode`.
+
+* When computing a type for Not, we produce an Integer type when its input is a
+ ptr. When the input is a `null` we convert to `1` and when is a not `null`
+ ptr value, we convert to `0`. See `NotNode.compute()`.
+
+
+## Executing the graph
+
+The evaluator includes a small late scheduler. A load must execute before a
+later store that consumes the same memory definition, even though there is no
+ordinary data edge from the load to that store. These load/store
+anti-dependencies supplement the explicit graph edges.
+
+![A load must precede a clobbering store](example2c.svg)
+
+The scheduler is sufficient to execute this chapter. Chapter 11 develops
+global code motion and scheduling as a separate topic.
+
+## Build and test
+
+From this directory, with JDK 21 or newer, Make, and a shell:
+
+```sh
+make lib
+make tests
+make release
+make view
+```
+
+Make builds this snapshot directly, without Maven. `make release` produces
+`build/release/simple.jar`; `make view` launches the shared interactive graph
+viewer. Maven and IDEA module descriptions are also supplied. Tests include all
+earlier chapters, memory ordering, returned object contents, and nested loops.
+
+Next, [Chapter 10b](../chapter10b/README.md) keeps this one parser binding while
+splitting the graph into independent memory slices.
diff --git a/docs/chapter10a/example1.gv b/docs/chapter10a/example1.gv
new file mode 100644
index 00000000..d399b562
--- /dev/null
+++ b/docs/chapter10a/example1.gv
@@ -0,0 +1,10 @@
+digraph Memory {
+ rankdir=RL;
+ node [shape=box];
+ M0 [label="Initial memory"];
+ X [label="Store p.x = 3"];
+ Y [label="Store p.y = arg"];
+ L [label="Load p.x"];
+ L -> Y -> X -> M0 [color=blue];
+ Return -> Y [color=blue]; Return -> L;
+}
diff --git a/docs/chapter10a/example1.svg b/docs/chapter10a/example1.svg
new file mode 100644
index 00000000..d1c5e3bd
--- /dev/null
+++ b/docs/chapter10a/example1.svg
@@ -0,0 +1,73 @@
+<?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="556pt" height="67pt"
+ viewBox="0.00 0.00 555.75 67.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 63)">
+<title>Memory</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-63 551.75,-63 551.75,4 -4,4"/>
+<!-- M0 -->
+<g id="node1" class="node">
+<title>M0</title>
+<polygon fill="none" stroke="black" points="98.5,-59 0,-59 0,-23 98.5,-23 98.5,-59"/>
+<text text-anchor="middle" x="49.25" y="-35.95" font-family="Times New Roman,serif" font-size="14.00">Initial memory</text>
+</g>
+<!-- X -->
+<g id="node2" class="node">
+<title>X</title>
+<polygon fill="none" stroke="black" points="222.5,-59 134.5,-59 134.5,-23 222.5,-23 222.5,-59"/>
+<text text-anchor="middle" x="178.5" y="-35.95" font-family="Times New Roman,serif" font-size="14.00">Store p.x = 3</text>
+</g>
+<!-- X&#45;&gt;M0 -->
+<g id="edge3" class="edge">
+<title>X&#45;&gt;M0</title>
+<path fill="none" stroke="blue" d="M134.06,-41C126.33,-41 118.16,-41 110.06,-41"/>
+<polygon fill="blue" stroke="blue" points="110.24,-37.5 100.24,-41 110.24,-44.5 110.24,-37.5"/>
+</g>
+<!-- Y -->
+<g id="node3" class="node">
+<title>Y</title>
+<polygon fill="none" stroke="black" points="357,-59 258.5,-59 258.5,-23 357,-23 357,-59"/>
+<text text-anchor="middle" x="307.75" y="-35.95" font-family="Times New Roman,serif" font-size="14.00">Store p.y = arg</text>
+</g>
+<!-- Y&#45;&gt;X -->
+<g id="edge2" class="edge">
+<title>Y&#45;&gt;X</title>
+<path fill="none" stroke="blue" d="M258.28,-41C250.45,-41 242.29,-41 234.32,-41"/>
+<polygon fill="blue" stroke="blue" points="234.35,-37.5 224.35,-41 234.35,-44.5 234.35,-37.5"/>
+</g>
+<!-- L -->
+<g id="node4" class="node">
+<title>L</title>
+<polygon fill="none" stroke="black" points="457.75,-36 393,-36 393,0 457.75,0 457.75,-36"/>
+<text text-anchor="middle" x="425.38" y="-12.95" font-family="Times New Roman,serif" font-size="14.00">Load p.x</text>
+</g>
+<!-- L&#45;&gt;Y -->
+<g id="edge1" class="edge">
+<title>L&#45;&gt;Y</title>
+<path fill="none" stroke="blue" d="M392.78,-24.28C385.16,-25.8 376.76,-27.47 368.31,-29.15"/>
+<polygon fill="blue" stroke="blue" points="367.85,-25.68 358.73,-31.06 369.22,-32.54 367.85,-25.68"/>
+</g>
+<!-- Return -->
+<g id="node5" class="node">
+<title>Return</title>
+<polygon fill="none" stroke="black" points="547.75,-59 493.75,-59 493.75,-23 547.75,-23 547.75,-59"/>
+<text text-anchor="middle" x="520.75" y="-35.95" font-family="Times New Roman,serif" font-size="14.00">Return</text>
+</g>
+<!-- Return&#45;&gt;Y -->
+<g id="edge4" class="edge">
+<title>Return&#45;&gt;Y</title>
+<path fill="none" stroke="blue" d="M493.52,-43.07C482.49,-43.84 469.5,-44.62 457.75,-45 428.99,-45.93 421.77,-45.68 393,-45 385.14,-44.81 376.87,-44.53 368.71,-44.2"/>
+<polygon fill="blue" stroke="blue" points="368.95,-40.7 358.81,-43.76 368.65,-47.7 368.95,-40.7"/>
+</g>
+<!-- Return&#45;&gt;L -->
+<g id="edge5" class="edge">
+<title>Return&#45;&gt;L</title>
+<path fill="none" stroke="black" d="M493.74,-34.59C486.17,-32.73 477.69,-30.64 469.38,-28.59"/>
+<polygon fill="black" stroke="black" points="470.24,-25.2 459.7,-26.21 468.57,-32 470.24,-25.2"/>
+</g>
+</g>
+</svg>
diff --git a/docs/chapter10a/example2a.gv b/docs/chapter10a/example2a.gv
new file mode 100644
index 00000000..ec5afbdc
--- /dev/null
+++ b/docs/chapter10a/example2a.gv
@@ -0,0 +1,10 @@
+digraph Memory {
+ rankdir=RL;
+ node [shape=box];
+ M [label="Incoming memory"];
+ A [label="True: Store x"];
+ B [label="False: Store y"];
+ P [label="Phi(memory)"];
+ P -> A -> M [color=blue]; P -> B -> M [color=blue];
+ P -> Region [style=dashed]; Return -> P [color=blue];
+}
diff --git a/docs/chapter10a/example2a.svg b/docs/chapter10a/example2a.svg
new file mode 100644
index 00000000..f9a9b4fd
--- /dev/null
+++ b/docs/chapter10a/example2a.svg
@@ -0,0 +1,85 @@
+<?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="469pt" height="152pt"
+ viewBox="0.00 0.00 469.25 152.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 148)">
+<title>Memory</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-148 465.25,-148 465.25,4 -4,4"/>
+<!-- M -->
+<g id="node1" class="node">
+<title>M</title>
+<polygon fill="none" stroke="black" points="118.75,-117 0,-117 0,-81 118.75,-81 118.75,-117"/>
+<text text-anchor="middle" x="59.38" y="-93.95" font-family="Times New Roman,serif" font-size="14.00">Incoming memory</text>
+</g>
+<!-- A -->
+<g id="node2" class="node">
+<title>A</title>
+<polygon fill="none" stroke="black" points="244.25,-144 156.25,-144 156.25,-108 244.25,-108 244.25,-144"/>
+<text text-anchor="middle" x="200.25" y="-120.95" font-family="Times New Roman,serif" font-size="14.00">True: Store x</text>
+</g>
+<!-- A&#45;&gt;M -->
+<g id="edge2" class="edge">
+<title>A&#45;&gt;M</title>
+<path fill="none" stroke="blue" d="M156.07,-117.61C147.84,-116.01 139.03,-114.29 130.22,-112.58"/>
+<polygon fill="blue" stroke="blue" points="131.06,-109.18 120.58,-110.7 129.72,-116.05 131.06,-109.18"/>
+</g>
+<!-- B -->
+<g id="node3" class="node">
+<title>B</title>
+<polygon fill="none" stroke="black" points="245.75,-90 154.75,-90 154.75,-54 245.75,-54 245.75,-90"/>
+<text text-anchor="middle" x="200.25" y="-66.95" font-family="Times New Roman,serif" font-size="14.00">False: Store y</text>
+</g>
+<!-- B&#45;&gt;M -->
+<g id="edge4" class="edge">
+<title>B&#45;&gt;M</title>
+<path fill="none" stroke="blue" d="M154.54,-80.69C146.8,-82.2 138.59,-83.79 130.37,-85.39"/>
+<polygon fill="blue" stroke="blue" points="129.83,-81.93 120.68,-87.28 131.16,-88.8 129.83,-81.93"/>
+</g>
+<!-- P -->
+<g id="node4" class="node">
+<title>P</title>
+<polygon fill="none" stroke="black" points="371.25,-90 281.75,-90 281.75,-54 371.25,-54 371.25,-90"/>
+<text text-anchor="middle" x="326.5" y="-66.95" font-family="Times New Roman,serif" font-size="14.00">Phi(memory)</text>
+</g>
+<!-- P&#45;&gt;A -->
+<g id="edge1" class="edge">
+<title>P&#45;&gt;A</title>
+<path fill="none" stroke="blue" d="M283.09,-90.43C273.69,-94.52 263.62,-98.89 253.88,-103.13"/>
+<polygon fill="blue" stroke="blue" points="252.64,-99.85 244.86,-107.05 255.43,-106.27 252.64,-99.85"/>
+</g>
+<!-- P&#45;&gt;B -->
+<g id="edge3" class="edge">
+<title>P&#45;&gt;B</title>
+<path fill="none" stroke="blue" d="M281.34,-72C273.66,-72 265.57,-72 257.61,-72"/>
+<polygon fill="blue" stroke="blue" points="257.62,-68.5 247.62,-72 257.62,-75.5 257.62,-68.5"/>
+</g>
+<!-- Region -->
+<g id="node5" class="node">
+<title>Region</title>
+<polygon fill="none" stroke="black" points="227.75,-36 172.75,-36 172.75,0 227.75,0 227.75,-36"/>
+<text text-anchor="middle" x="200.25" y="-12.95" font-family="Times New Roman,serif" font-size="14.00">Region</text>
+</g>
+<!-- P&#45;&gt;Region -->
+<g id="edge5" class="edge">
+<title>P&#45;&gt;Region</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M283.09,-53.57C268.52,-47.24 252.34,-40.21 238.24,-34.08"/>
+<polygon fill="black" stroke="black" points="239.88,-30.97 229.31,-30.2 237.09,-37.39 239.88,-30.97"/>
+</g>
+<!-- Return -->
+<g id="node6" class="node">
+<title>Return</title>
+<polygon fill="none" stroke="black" points="461.25,-90 407.25,-90 407.25,-54 461.25,-54 461.25,-90"/>
+<text text-anchor="middle" x="434.25" y="-66.95" font-family="Times New Roman,serif" font-size="14.00">Return</text>
+</g>
+<!-- Return&#45;&gt;P -->
+<g id="edge6" class="edge">
+<title>Return&#45;&gt;P</title>
+<path fill="none" stroke="blue" d="M406.84,-72C399.52,-72 391.29,-72 382.97,-72"/>
+<polygon fill="blue" stroke="blue" points="383.17,-68.5 373.17,-72 383.17,-75.5 383.17,-68.5"/>
+</g>
+</g>
+</svg>
diff --git a/docs/chapter10a/example2b.gv b/docs/chapter10a/example2b.gv
new file mode 100644
index 00000000..3f3309e5
--- /dev/null
+++ b/docs/chapter10a/example2b.gv
@@ -0,0 +1,11 @@
+digraph Memory {
+ rankdir=RL;
+ node [shape=box];
+ P [label="Phi(memory)"];
+ S [label="Loop-body Store"];
+ P -> Entry [color=blue];
+ P -> S [color=blue,constraint=false]; // Backedge must not place Store before Phi.
+ S -> P [color=blue];
+ P -> Loop [style=dashed]; Return -> P [color=blue];
+ Return -> S [style=invis]; // Layout only: Phi, Store, Return from left to right.
+}
diff --git a/docs/chapter10a/example2b.svg b/docs/chapter10a/example2b.svg
new file mode 100644
index 00000000..8fff33d4
--- /dev/null
+++ b/docs/chapter10a/example2b.svg
@@ -0,0 +1,74 @@
+<?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="422pt" height="98pt"
+ viewBox="0.00 0.00 421.75 98.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 94)">
+<title>Memory</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-94 417.75,-94 417.75,4 -4,4"/>
+<!-- P -->
+<g id="node1" class="node">
+<title>P</title>
+<polygon fill="none" stroke="black" points="179.5,-63 90,-63 90,-27 179.5,-27 179.5,-63"/>
+<text text-anchor="middle" x="134.75" y="-39.95" font-family="Times New Roman,serif" font-size="14.00">Phi(memory)</text>
+</g>
+<!-- S -->
+<g id="node2" class="node">
+<title>S</title>
+<polygon fill="none" stroke="black" points="323.75,-40 215.5,-40 215.5,-4 323.75,-4 323.75,-40"/>
+<text text-anchor="middle" x="269.62" y="-16.95" font-family="Times New Roman,serif" font-size="14.00">Loop&#45;body Store</text>
+</g>
+<!-- P&#45;&gt;S -->
+<g id="edge2" class="edge">
+<title>P&#45;&gt;S</title>
+<path fill="none" stroke="blue" d="M179.67,-43.79C187.52,-42.69 195.84,-41.37 204.12,-39.91"/>
+<polygon fill="blue" stroke="blue" points="204.65,-43.37 213.86,-38.13 203.39,-36.49 204.65,-43.37"/>
+</g>
+<!-- Entry -->
+<g id="node3" class="node">
+<title>Entry</title>
+<polygon fill="none" stroke="black" points="54,-90 0,-90 0,-54 54,-54 54,-90"/>
+<text text-anchor="middle" x="27" y="-66.95" font-family="Times New Roman,serif" font-size="14.00">Entry</text>
+</g>
+<!-- P&#45;&gt;Entry -->
+<g id="edge1" class="edge">
+<title>P&#45;&gt;Entry</title>
+<path fill="none" stroke="blue" d="M89.52,-56.29C81.45,-58.35 73.12,-60.48 65.28,-62.48"/>
+<polygon fill="blue" stroke="blue" points="64.54,-59.06 55.72,-64.92 66.27,-65.84 64.54,-59.06"/>
+</g>
+<!-- Loop -->
+<g id="node4" class="node">
+<title>Loop</title>
+<polygon fill="none" stroke="black" points="54,-36 0,-36 0,0 54,0 54,-36"/>
+<text text-anchor="middle" x="27" y="-12.95" font-family="Times New Roman,serif" font-size="14.00">Loop</text>
+</g>
+<!-- P&#45;&gt;Loop -->
+<g id="edge4" class="edge">
+<title>P&#45;&gt;Loop</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M89.52,-33.71C81.45,-31.65 73.12,-29.52 65.28,-27.52"/>
+<polygon fill="black" stroke="black" points="66.27,-24.16 55.72,-25.08 64.54,-30.94 66.27,-24.16"/>
+</g>
+<!-- S&#45;&gt;P -->
+<g id="edge3" class="edge">
+<title>S&#45;&gt;P</title>
+<path fill="none" stroke="blue" d="M215.35,-24.59C207.3,-25.84 198.98,-27.27 190.89,-28.79"/>
+<polygon fill="blue" stroke="blue" points="190.29,-25.34 181.15,-30.71 191.64,-32.21 190.29,-25.34"/>
+</g>
+<!-- Return -->
+<g id="node5" class="node">
+<title>Return</title>
+<polygon fill="none" stroke="black" points="413.75,-63 359.75,-63 359.75,-27 413.75,-27 413.75,-63"/>
+<text text-anchor="middle" x="386.75" y="-39.95" font-family="Times New Roman,serif" font-size="14.00">Return</text>
+</g>
+<!-- Return&#45;&gt;P -->
+<g id="edge5" class="edge">
+<title>Return&#45;&gt;P</title>
+<path fill="none" stroke="blue" d="M359.52,-47.07C348.49,-47.84 335.5,-48.62 323.75,-49 275.66,-50.55 263.6,-50.21 215.5,-49 207.59,-48.8 199.24,-48.49 191.04,-48.13"/>
+<polygon fill="blue" stroke="blue" points="191.28,-44.64 181.12,-47.67 190.95,-51.63 191.28,-44.64"/>
+</g>
+<!-- Return&#45;&gt;S -->
+</g>
+</svg>
diff --git a/docs/chapter10a/example2c.gv b/docs/chapter10a/example2c.gv
new file mode 100644
index 00000000..ef8a5fc8
--- /dev/null
+++ b/docs/chapter10a/example2c.gv
@@ -0,0 +1,9 @@
+digraph Memory {
+ rankdir=RL;
+ node [shape=box];
+ M [label="Prior memory"];
+ L [label="Load p.x"];
+ S [label="Store p.x"];
+ L -> M [color=blue]; S -> M [color=blue];
+ S -> L [style=dashed,label="execute load first"];
+}
diff --git a/docs/chapter10a/example2c.svg b/docs/chapter10a/example2c.svg
new file mode 100644
index 00000000..c7b37912
--- /dev/null
+++ b/docs/chapter10a/example2c.svg
@@ -0,0 +1,50 @@
+<?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="398pt" height="67pt"
+ viewBox="0.00 0.00 398.25 67.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 63)">
+<title>Memory</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-63 394.25,-63 394.25,4 -4,4"/>
+<!-- M -->
+<g id="node1" class="node">
+<title>M</title>
+<polygon fill="none" stroke="black" points="93.25,-59 0,-59 0,-23 93.25,-23 93.25,-59"/>
+<text text-anchor="middle" x="46.62" y="-35.95" font-family="Times New Roman,serif" font-size="14.00">Prior memory</text>
+</g>
+<!-- L -->
+<g id="node2" class="node">
+<title>L</title>
+<polygon fill="none" stroke="black" points="195,-36 130.25,-36 130.25,0 195,0 195,-36"/>
+<text text-anchor="middle" x="162.62" y="-12.95" font-family="Times New Roman,serif" font-size="14.00">Load p.x</text>
+</g>
+<!-- L&#45;&gt;M -->
+<g id="edge1" class="edge">
+<title>L&#45;&gt;M</title>
+<path fill="none" stroke="blue" d="M129.87,-24.41C122.08,-25.98 113.51,-27.71 104.92,-29.44"/>
+<polygon fill="blue" stroke="blue" points="104.29,-26 95.18,-31.41 105.68,-32.86 104.29,-26"/>
+</g>
+<!-- S -->
+<g id="node3" class="node">
+<title>S</title>
+<polygon fill="none" stroke="black" points="390.25,-59 324.75,-59 324.75,-23 390.25,-23 390.25,-59"/>
+<text text-anchor="middle" x="357.5" y="-35.95" font-family="Times New Roman,serif" font-size="14.00">Store p.x</text>
+</g>
+<!-- S&#45;&gt;M -->
+<g id="edge2" class="edge">
+<title>S&#45;&gt;M</title>
+<path fill="none" stroke="blue" d="M324.5,-47.66C318.62,-48.63 312.52,-49.48 306.75,-50 237.56,-56.21 157.62,-51.66 105.04,-47.07"/>
+<polygon fill="blue" stroke="blue" points="105.37,-43.59 95.1,-46.17 104.74,-50.56 105.37,-43.59"/>
+</g>
+<!-- S&#45;&gt;L -->
+<g id="edge3" class="edge">
+<title>S&#45;&gt;L</title>
+<path fill="none" stroke="black" stroke-dasharray="5,2" d="M324.41,-35.96C318.54,-35.1 312.47,-34.24 306.75,-33.5 273.09,-29.14 234.87,-25.05 206.4,-22.16"/>
+<polygon fill="black" stroke="black" points="207.03,-18.71 196.73,-21.19 206.33,-25.67 207.03,-18.71"/>
+<text text-anchor="middle" x="259.88" y="-36.7" font-family="Times New Roman,serif" font-size="14.00">execute load first</text>
+</g>
+</g>
+</svg>
diff --git a/docs/chapter10a/lattice.gv b/docs/chapter10a/lattice.gv
new file mode 100644
index 00000000..733a5287
--- /dev/null
+++ b/docs/chapter10a/lattice.gv
@@ -0,0 +1,108 @@
+digraph Lattice {
+ rankdir=TB;
+ newrank=true;
+ // Preserve the same-rank ordering edges through cluster layout.
+ remincross=false;
+ nodesep=0.22;
+ ranksep=0.65;
+ node [shape=ellipse, style=filled, fontname="DejaVu Sans", fontsize=13];
+ edge [color="#555555", arrowsize=0.6];
+
+ // These arrows are lattice-order edges, not use/definition edges.
+ TOP [label="⊤", fillcolor=black, fontcolor=white];
+ BOT [label="⊥", fillcolor=black, fontcolor=white];
+
+ subgraph cluster_control {
+ label="Control"; fontname="Arial"; color="#cccccc";
+ node [fillcolor="#ffff00"];
+ XCTRL [label="⊤:ctrl"];
+ CTRL [label="⊥:ctrl"];
+ XCTRL -> CTRL;
+ }
+
+ subgraph cluster_integer {
+ label="Integer"; fontname="Arial"; color="#cccccc";
+ node [fillcolor="#add8e6"];
+ INT_TOP [label="⊤:int"];
+ INT_BOT [label="⊥:int"];
+ INT_NEG [label="… −2, −1"];
+ INT_ZERO [label="0"];
+ INT_POS [label="1, 2, …"];
+ {rank=same; INT_NEG; INT_ZERO; INT_POS;}
+ INT_NEG -> INT_ZERO -> INT_POS [style=invis];
+ INT_TOP -> {INT_NEG INT_ZERO INT_POS};
+ {INT_NEG INT_ZERO INT_POS} -> INT_BOT;
+ }
+
+ subgraph cluster_pointer {
+ label="Pointer = nullability × struct type";
+ fontname="Arial"; color="#cccccc";
+ node [fillcolor="#008000", fontcolor=white];
+ PTR_TOP [label="⊤:ptr\n[*⊤:struct]"];
+ PTR_BOT [label="⊥:ptr\n[*⊥:struct?]"];
+ PTR_NULL [label="null"];
+ PTR_ANY [label="*⊥:struct\n[ptr any struct]"];
+ PTR_PERSON [label="*Person"];
+ PTR_S1 [label="*s1"];
+ PTR_MORE [label="*s2, …"];
+ PTR_PERSON_NIL [label="*Person?"];
+ PTR_S1_NIL [label="*s1?"];
+ PTR_MORE_NIL [label="*s2?, …"];
+ {rank=same; PTR_PERSON; PTR_S1; PTR_MORE; PTR_NULL;}
+ {rank=same; PTR_ANY; PTR_PERSON_NIL; PTR_S1_NIL; PTR_MORE_NIL;}
+ PTR_PERSON -> PTR_S1 -> PTR_MORE -> PTR_NULL [style=invis];
+ PTR_ANY -> PTR_PERSON_NIL -> PTR_S1_NIL -> PTR_MORE_NIL [style=invis];
+ PTR_TOP -> {PTR_PERSON PTR_S1 PTR_MORE PTR_NULL};
+ {PTR_PERSON PTR_S1 PTR_MORE} -> PTR_ANY;
+ PTR_PERSON -> PTR_PERSON_NIL;
+ PTR_S1 -> PTR_S1_NIL;
+ PTR_MORE -> PTR_MORE_NIL;
+ PTR_NULL -> {PTR_PERSON_NIL PTR_S1_NIL PTR_MORE_NIL};
+ {PTR_ANY PTR_PERSON_NIL PTR_S1_NIL PTR_MORE_NIL} -> PTR_BOT;
+ }
+
+ subgraph cluster_struct {
+ label="Struct\nnamed collection of named scalar types";
+ fontname="Arial"; color="#cccccc";
+ node [fillcolor="#90ee90"];
+ STRUCT_TOP [label="⊤:struct\n[struct top]"];
+ STRUCT_BOT [label="⊥:struct\n[struct bottom]"];
+ STRUCT_PERSON [label="Person\nage: int", shape=box];
+ STRUCT_S1 [label="s1\nx: int", shape=box];
+ STRUCT_S2 [label="s2\nx: int, y: *s1", shape=box];
+ STRUCT_MORE [label="…", shape=box];
+ {rank=same; STRUCT_PERSON; STRUCT_S1; STRUCT_S2; STRUCT_MORE;}
+ STRUCT_PERSON -> STRUCT_S1 -> STRUCT_S2 -> STRUCT_MORE [style=invis];
+ STRUCT_TOP -> {STRUCT_PERSON STRUCT_S1 STRUCT_S2 STRUCT_MORE};
+ {STRUCT_PERSON STRUCT_S1 STRUCT_S2 STRUCT_MORE} -> STRUCT_BOT;
+ }
+
+ subgraph cluster_memory {
+ label="Memory"; fontname="Arial"; color="#cccccc";
+ node [fillcolor="#00008b", fontcolor=white];
+ MEM_TOP [label="⊤:mem"];
+ MEM_BOT [label="⊥:mem"];
+ MEM_TOP -> MEM_BOT;
+ }
+
+ subgraph cluster_tuple {
+ label="Tuple\ncollection of types";
+ fontname="Arial"; color="#cccccc";
+ 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];
+ {rank=same; TUPLE1; TUPLE2; TUPLEN;}
+ TUPLE1 -> TUPLE2 -> TUPLEN [style=invis];
+ TUPLE_TOP -> {TUPLE1 TUPLE2 TUPLEN};
+ {TUPLE1 TUPLE2 TUPLEN} -> TUPLE_BOT;
+ }
+
+ TOP -> {XCTRL INT_TOP PTR_TOP STRUCT_TOP MEM_TOP TUPLE_TOP};
+ {CTRL INT_BOT PTR_BOT STRUCT_BOT MEM_BOT TUPLE_BOT} -> BOT;
+ {rank=same; XCTRL; INT_TOP; PTR_TOP; STRUCT_TOP; MEM_TOP; TUPLE_TOP;}
+ {rank=same; CTRL; INT_BOT; PTR_BOT; STRUCT_BOT; MEM_BOT; TUPLE_BOT;}
+ XCTRL -> INT_TOP -> PTR_TOP -> STRUCT_TOP -> MEM_TOP -> TUPLE_TOP [style=invis];
+}
diff --git a/docs/chapter10a/lattice.svg b/docs/chapter10a/lattice.svg
new file mode 100644
index 00000000..24c0de8c
--- /dev/null
+++ b/docs/chapter10a/lattice.svg
@@ -0,0 +1,570 @@
+<?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: Lattice Pages: 1 -->
+<svg width="1647pt" height="555pt"
+ viewBox="0.00 0.00 1647.00 555.43" 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 551.43)">
+<title>Lattice</title>
+<polygon fill="white" stroke="none" points="-4,4 -4,-551.43 1643,-551.43 1643,4 -4,4"/>
+<g id="clust1" class="cluster">
+<title>cluster_control</title>
+<polygon fill="none" stroke="#cccccc" points="8,-85.99 8,-476.69 98,-476.69 98,-85.99 8,-85.99"/>
+<text text-anchor="middle" x="53" y="-459.39" 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,-476.69 404,-476.69 404,-85.99 106,-85.99"/>
+<text text-anchor="middle" x="255" y="-459.39" 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,-487.68 893,-487.68 893,-75 412,-75"/>
+<text text-anchor="middle" x="652.5" y="-470.38" 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,-503.43 1233,-503.43 1233,-75 901,-75"/>
+<text text-anchor="middle" x="1067" y="-486.13" font-family="Arial" font-size="14.00">Struct</text>
+<text text-anchor="middle" x="1067" y="-470.38" 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,-476.69 1347,-476.69 1347,-85.99 1241,-85.99"/>
+<text text-anchor="middle" x="1294" y="-459.39" font-family="Arial" font-size="14.00">Memory</text>
+</g>
+<g id="clust18" class="cluster">
+<title>cluster_tuple</title>
+<polygon fill="none" stroke="#cccccc" points="1355,-85.99 1355,-492.44 1631,-492.44 1631,-85.99 1355,-85.99"/>
+<text text-anchor="middle" x="1493" y="-475.14" font-family="Arial" font-size="14.00">Tuple</text>
+<text text-anchor="middle" x="1493" y="-459.39" 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="845" cy="-529.43" rx="27" ry="18"/>
+<text text-anchor="middle" x="845" y="-525.33" 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="-426.94" rx="36.51" ry="18"/>
+<text text-anchor="middle" x="53" y="-422.84" font-family="DejaVu Sans" font-size="13.00">⊤:ctrl</text>
+</g>
+<!-- TOP&#45;&gt;XCTRL -->
+<g id="edge53" class="edge">
+<title>TOP&#45;&gt;XCTRL</title>
+<path fill="none" stroke="#555555" d="M817.66,-528.22C687.28,-527.11 133.71,-521.35 102,-503.43 82.18,-492.23 69.06,-469.34 61.42,-451.68"/>
+<polygon fill="#555555" stroke="#555555" points="63.46,-451.12 59.24,-446.37 59.57,-452.72 63.46,-451.12"/>
+</g>
+<!-- INT_TOP -->
+<g id="node5" class="node">
+<title>INT_TOP</title>
+<ellipse fill="#add8e6" stroke="black" cx="353" cy="-426.94" rx="33.44" ry="18"/>
+<text text-anchor="middle" x="353" y="-422.84" font-family="DejaVu Sans" font-size="13.00">⊤:int</text>
+</g>
+<!-- TOP&#45;&gt;INT_TOP -->
+<g id="edge54" class="edge">
+<title>TOP&#45;&gt;INT_TOP</title>
+<path fill="none" stroke="#555555" d="M817.72,-528.22C727.72,-527.33 443.86,-522.98 408,-503.43 387.26,-492.12 372.32,-469.24 363.29,-451.62"/>
+<polygon fill="#555555" stroke="#555555" points="365.2,-450.74 360.67,-446.28 361.42,-452.59 365.2,-450.74"/>
+</g>
+<!-- PTR_TOP -->
+<g id="node10" class="node">
+<title>PTR_TOP</title>
+<ellipse fill="#008000" stroke="black" cx="685" cy="-426.94" rx="61.7" ry="28.99"/>
+<text text-anchor="middle" x="685" y="-431.09" font-family="DejaVu Sans" font-size="13.00" fill="white">⊤:ptr</text>
+<text text-anchor="middle" x="685" y="-414.59" font-family="DejaVu Sans" font-size="13.00" fill="white">[*⊤:struct]</text>
+</g>
+<!-- TOP&#45;&gt;PTR_TOP -->
+<g id="edge55" class="edge">
+<title>TOP&#45;&gt;PTR_TOP</title>
+<path fill="none" stroke="#555555" d="M825.7,-516.31C801.54,-501.14 759.48,-474.72 727.62,-454.71"/>
+<polygon fill="#555555" stroke="#555555" points="728.87,-453.01 722.67,-451.6 726.64,-456.57 728.87,-453.01"/>
+</g>
+<!-- STRUCT_TOP -->
+<g id="node20" class="node">
+<title>STRUCT_TOP</title>
+<ellipse fill="#90ee90" stroke="black" cx="996" cy="-426.94" rx="64.35" ry="28.99"/>
+<text text-anchor="middle" x="996" y="-431.09" font-family="DejaVu Sans" font-size="13.00">⊤:struct</text>
+<text text-anchor="middle" x="996" y="-414.59" font-family="DejaVu Sans" font-size="13.00">[struct top]</text>
+</g>
+<!-- TOP&#45;&gt;STRUCT_TOP -->
+<g id="edge56" class="edge">
+<title>TOP&#45;&gt;STRUCT_TOP</title>
+<path fill="none" stroke="#555555" d="M867.28,-518.93C876.68,-514.61 887.61,-509.19 897,-503.43 919.21,-489.82 942.45,-472.29 960.83,-457.55"/>
+<polygon fill="#555555" stroke="#555555" points="961.85,-459.43 965.2,-454.02 959.21,-456.16 961.85,-459.43"/>
+</g>
+<!-- MEM_TOP -->
+<g id="node26" class="node">
+<title>MEM_TOP</title>
+<ellipse fill="#00008b" stroke="black" cx="1294" cy="-426.94" rx="44.7" ry="18"/>
+<text text-anchor="middle" x="1294" y="-422.84" font-family="DejaVu Sans" font-size="13.00" fill="white">⊤:mem</text>
+</g>
+<!-- TOP&#45;&gt;MEM_TOP -->
+<g id="edge57" class="edge">
+<title>TOP&#45;&gt;MEM_TOP</title>
+<path fill="none" stroke="#555555" d="M872.35,-528C956.06,-526.49 1205.1,-520.6 1237,-503.43 1258.25,-491.99 1273.89,-468.81 1283.35,-451.14"/>
+<polygon fill="#555555" stroke="#555555" points="1284.99,-452.55 1285.86,-446.25 1281.25,-450.62 1284.99,-452.55"/>
+</g>
+<!-- TUPLE_TOP -->
+<g id="node28" class="node">
+<title>TUPLE_TOP</title>
+<ellipse fill="#ffc0cb" stroke="black" cx="1408" cy="-426.94" rx="44.7" ry="18"/>
+<text text-anchor="middle" x="1408" y="-422.84" font-family="DejaVu Sans" font-size="13.00">⊤:tuple</text>
+</g>
+<!-- TOP&#45;&gt;TUPLE_TOP -->
+<g id="edge58" class="edge">
+<title>TOP&#45;&gt;TUPLE_TOP</title>
+<path fill="none" stroke="#555555" d="M872.34,-528.42C971.49,-528.22 1308.63,-525.85 1351,-503.43 1372.33,-492.14 1387.95,-468.94 1397.39,-451.22"/>
+<polygon fill="#555555" stroke="#555555" points="1399.04,-452.62 1399.9,-446.32 1395.3,-450.7 1399.04,-452.62"/>
+</g>
+<!-- BOT -->
+<g id="node2" class="node">
+<title>BOT</title>
+<ellipse fill="black" stroke="black" cx="884" cy="-18" rx="27" ry="18"/>
+<text text-anchor="middle" x="884" y="-13.9" font-family="DejaVu Sans" font-size="13.00" fill="white">⊥</text>
+</g>
+<!-- CTRL -->
+<g id="node4" class="node">
+<title>CTRL</title>
+<ellipse fill="#ffff00" stroke="black" cx="53" cy="-111.99" rx="36.51" ry="18"/>
+<text text-anchor="middle" x="53" y="-107.89" font-family="DejaVu Sans" font-size="13.00">⊥:ctrl</text>
+</g>
+<!-- XCTRL&#45;&gt;CTRL -->
+<g id="edge1" class="edge">
+<title>XCTRL&#45;&gt;CTRL</title>
+<path fill="none" stroke="#555555" d="M53,-408.67C53,-356.2 53,-198.53 53,-137.49"/>
+<polygon fill="#555555" stroke="#555555" points="55.1,-137.72 53,-131.72 50.9,-137.72 55.1,-137.72"/>
+</g>
+<!-- XCTRL&#45;&gt;INT_TOP -->
+<!-- CTRL&#45;&gt;BOT -->
+<g id="edge59" class="edge">
+<title>CTRL&#45;&gt;BOT</title>
+<path fill="none" stroke="#555555" d="M69.29,-95.39C78.22,-87.83 89.91,-79.45 102,-75 242.26,-23.4 717.31,-19.12 849.57,-18.95"/>
+<polygon fill="#555555" stroke="#555555" points="849.19,-21.05 855.19,-18.94 849.18,-16.85 849.19,-21.05"/>
+</g>
+<!-- INT_NEG -->
+<g id="node7" class="node">
+<title>INT_NEG</title>
+<ellipse fill="#add8e6" stroke="black" cx="169" cy="-216.97" rx="55.45" ry="18"/>
+<text text-anchor="middle" x="169" y="-212.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="M339.17,-410.31C306.78,-373.7 225.91,-282.29 188.52,-240.04"/>
+<polygon fill="#555555" stroke="#555555" points="190.31,-238.89 184.76,-235.78 187.16,-241.67 190.31,-238.89"/>
+</g>
+<!-- INT_ZERO -->
+<g id="node8" class="node">
+<title>INT_ZERO</title>
+<ellipse fill="#add8e6" stroke="black" cx="267" cy="-216.97" rx="27" ry="18"/>
+<text text-anchor="middle" x="267" y="-212.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="M345.96,-408.92C330.64,-371.87 294.24,-283.85 276.74,-241.52"/>
+<polygon fill="#555555" stroke="#555555" points="278.71,-240.79 274.47,-236.05 274.83,-242.39 278.71,-240.79"/>
+</g>
+<!-- INT_POS -->
+<g id="node9" class="node">
+<title>INT_POS</title>
+<ellipse fill="#add8e6" stroke="black" cx="353" cy="-216.97" rx="43.16" ry="18"/>
+<text text-anchor="middle" x="353" y="-212.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,-408.57C353,-371.71 353,-285.59 353,-242.89"/>
+<polygon fill="#555555" stroke="#555555" points="355.1,-242.96 353,-236.96 350.9,-242.96 355.1,-242.96"/>
+</g>
+<!-- INT_TOP&#45;&gt;PTR_TOP -->
+<!-- INT_BOT -->
+<g id="node6" class="node">
+<title>INT_BOT</title>
+<ellipse fill="#add8e6" stroke="black" cx="310" cy="-111.99" rx="33.44" ry="18"/>
+<text text-anchor="middle" x="310" y="-107.89" font-family="DejaVu Sans" font-size="13.00">⊥:int</text>
+</g>
+<!-- INT_BOT&#45;&gt;BOT -->
+<g id="edge60" class="edge">
+<title>INT_BOT&#45;&gt;BOT</title>
+<path fill="none" stroke="#555555" d="M335.28,-99.84C354.78,-91.7 382.61,-81.07 408,-75 570.29,-36.22 770.4,-23.83 849.5,-20.29"/>
+<polygon fill="#555555" stroke="#555555" points="849.36,-22.39 855.26,-20.04 849.17,-18.2 849.36,-22.39"/>
+</g>
+<!-- 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="M190.72,-200.11C216.15,-181.54 258.17,-150.85 284.95,-131.29"/>
+<polygon fill="#555555" stroke="#555555" points="285.92,-133.18 289.52,-127.95 283.44,-129.79 285.92,-133.18"/>
+</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="M273.91,-199.43C281.01,-182.41 292.14,-155.76 300.16,-136.55"/>
+<polygon fill="#555555" stroke="#555555" points="302.01,-137.58 302.38,-131.24 298.13,-135.96 302.01,-137.58"/>
+</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="M345.9,-198.97C338.83,-182.05 327.93,-155.94 319.99,-136.93"/>
+<polygon fill="#555555" stroke="#555555" points="321.94,-136.15 317.69,-131.42 318.07,-137.76 321.94,-136.15"/>
+</g>
+<!-- PTR_NULL -->
+<g id="node12" class="node">
+<title>PTR_NULL</title>
+<ellipse fill="#008000" stroke="black" cx="808" cy="-321.96" rx="66.47" ry="28.99"/>
+<text text-anchor="middle" x="808" y="-326.11" font-family="DejaVu Sans" font-size="13.00" fill="white">null</text>
+<text text-anchor="middle" x="808" y="-309.61" font-family="DejaVu Sans" font-size="13.00" fill="white">[*⊤:struct?]</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="M714.46,-401.27C731.85,-386.71 753.98,-368.18 772.35,-352.8"/>
+<polygon fill="#555555" stroke="#555555" points="773.51,-354.57 776.76,-349.11 770.82,-351.35 773.51,-354.57"/>
+</g>
+<!-- PTR_PERSON -->
+<g id="node14" class="node">
+<title>PTR_PERSON</title>
+<ellipse fill="#008000" stroke="black" cx="512" cy="-321.96" rx="45.72" ry="18"/>
+<text text-anchor="middle" x="512" y="-317.86" 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="M647.46,-403.59C616.14,-384.95 572.05,-358.7 542.78,-341.28"/>
+<polygon fill="#555555" stroke="#555555" points="543.94,-339.52 537.71,-338.26 541.79,-343.13 543.94,-339.52"/>
+</g>
+<!-- PTR_S1 -->
+<g id="node15" class="node">
+<title>PTR_S1</title>
+<ellipse fill="#008000" stroke="black" cx="601" cy="-321.96" rx="27" ry="18"/>
+<text text-anchor="middle" x="601" y="-317.86" 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="M663.37,-399.42C649.25,-382.12 631.09,-359.85 618.01,-343.81"/>
+<polygon fill="#555555" stroke="#555555" points="619.81,-342.7 614.39,-339.38 616.56,-345.36 619.81,-342.7"/>
+</g>
+<!-- PTR_MORE -->
+<g id="node16" class="node">
+<title>PTR_MORE</title>
+<ellipse fill="#008000" stroke="black" cx="685" cy="-321.96" rx="40.6" ry="18"/>
+<text text-anchor="middle" x="685" y="-317.86" 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="M685,-397.53C685,-381.91 685,-362.73 685,-347.73"/>
+<polygon fill="#555555" stroke="#555555" points="687.1,-347.82 685,-341.82 682.9,-347.82 687.1,-347.82"/>
+</g>
+<!-- PTR_TOP&#45;&gt;STRUCT_TOP -->
+<!-- PTR_BOT -->
+<g id="node11" class="node">
+<title>PTR_BOT</title>
+<ellipse fill="#008000" stroke="black" cx="748" cy="-111.99" rx="66.47" ry="28.99"/>
+<text text-anchor="middle" x="748" y="-116.14" font-family="DejaVu Sans" font-size="13.00" fill="white">⊥:ptr</text>
+<text text-anchor="middle" x="748" y="-99.64" font-family="DejaVu Sans" font-size="13.00" fill="white">[*⊥:struct?]</text>
+</g>
+<!-- PTR_BOT&#45;&gt;BOT -->
+<g id="edge61" class="edge">
+<title>PTR_BOT&#45;&gt;BOT</title>
+<path fill="none" stroke="#555555" d="M783.38,-87.06C807.3,-70.88 838.29,-49.92 859.52,-35.56"/>
+<polygon fill="#555555" stroke="#555555" points="860.46,-37.46 864.25,-32.36 858.1,-33.98 860.46,-37.46"/>
+</g>
+<!-- PTR_PERSON_NIL -->
+<g id="node17" class="node">
+<title>PTR_PERSON_NIL</title>
+<ellipse fill="#008000" stroke="black" cx="651" cy="-216.97" rx="50.33" ry="18"/>
+<text text-anchor="middle" x="651" y="-212.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*Person?</text>
+</g>
+<!-- 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="M771.98,-297.33C744.16,-279.08 706.14,-254.14 680.2,-237.12"/>
+<polygon fill="#555555" stroke="#555555" points="681.63,-235.56 675.47,-234.02 679.33,-239.07 681.63,-235.56"/>
+</g>
+<!-- PTR_S1_NIL -->
+<g id="node18" class="node">
+<title>PTR_S1_NIL</title>
+<ellipse fill="#008000" stroke="black" cx="748" cy="-216.97" rx="30.37" ry="18"/>
+<text text-anchor="middle" x="748" y="-212.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*s1?</text>
+</g>
+<!-- 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="M791.92,-293.36C782.32,-276.89 770.28,-256.22 761.24,-240.69"/>
+<polygon fill="#555555" stroke="#555555" points="763.16,-239.82 758.32,-235.69 759.53,-241.93 763.16,-239.82"/>
+</g>
+<!-- PTR_MORE_NIL -->
+<g id="node19" class="node">
+<title>PTR_MORE_NIL</title>
+<ellipse fill="#008000" stroke="black" cx="840" cy="-216.97" rx="45.21" ry="18"/>
+<text text-anchor="middle" x="840" y="-212.87" font-family="DejaVu Sans" font-size="13.00" fill="white">*s2?, …</text>
+</g>
+<!-- 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="M816.74,-292.82C821.67,-276.95 827.77,-257.33 832.48,-242.16"/>
+<polygon fill="#555555" stroke="#555555" points="834.45,-242.91 834.23,-236.56 830.44,-241.66 834.45,-242.91"/>
+</g>
+<!-- PTR_ANY -->
+<g id="node13" class="node">
+<title>PTR_ANY</title>
+<ellipse fill="#008000" stroke="black" cx="502" cy="-216.97" rx="82.38" ry="28.99"/>
+<text text-anchor="middle" x="502" y="-221.12" font-family="DejaVu Sans" font-size="13.00" fill="white">*⊥:struct</text>
+<text text-anchor="middle" x="502" y="-204.62" font-family="DejaVu Sans" font-size="13.00" fill="white">[ptr any struct]</text>
+</g>
+<!-- PTR_ANY&#45;&gt;PTR_BOT -->
+<g id="edge29" class="edge">
+<title>PTR_ANY&#45;&gt;PTR_BOT</title>
+<path fill="none" stroke="#555555" d="M554.17,-194.13C595.32,-176.91 652.51,-152.97 694.1,-135.56"/>
+<polygon fill="#555555" stroke="#555555" points="694.78,-137.55 699.5,-133.29 693.15,-133.67 694.78,-137.55"/>
+</g>
+<!-- PTR_ANY&#45;&gt;PTR_PERSON_NIL -->
+<!-- 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="M510.3,-303.49C508.98,-289.83 507.09,-270.39 505.45,-253.5"/>
+<polygon fill="#555555" stroke="#555555" points="507.58,-253.71 504.91,-247.94 503.4,-254.12 507.58,-253.71"/>
+</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="M532.81,-305.54C557.17,-287.49 597.57,-257.56 624.25,-237.8"/>
+<polygon fill="#555555" stroke="#555555" points="625.26,-239.66 628.83,-234.4 622.76,-236.28 625.26,-239.66"/>
+</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="M586.82,-306.2C572.74,-291.56 550.72,-268.65 532.64,-249.85"/>
+<polygon fill="#555555" stroke="#555555" points="534.38,-248.62 528.7,-245.75 531.35,-251.53 534.38,-248.62"/>
+</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="M617.46,-307.22C623.23,-302.56 629.81,-297.42 636,-292.97 667.33,-270.44 677.09,-267.67 709,-245.97 713.75,-242.74 718.77,-239.22 723.56,-235.8"/>
+<polygon fill="#555555" stroke="#555555" points="724.61,-237.64 728.26,-232.43 722.16,-234.22 724.61,-237.64"/>
+</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="M660.85,-307.1C652.94,-302.58 644.1,-297.55 636,-292.97 608.08,-277.18 576.81,-259.67 551.5,-245.54"/>
+<polygon fill="#555555" stroke="#555555" points="552.79,-243.85 546.52,-242.76 550.74,-247.52 552.79,-243.85"/>
+</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="M706.88,-306.42C734.22,-288.25 781.1,-257.11 811.3,-237.04"/>
+<polygon fill="#555555" stroke="#555555" points="812.38,-238.85 816.22,-233.78 810.06,-235.35 812.38,-238.85"/>
+</g>
+<!-- PTR_PERSON_NIL&#45;&gt;PTR_BOT -->
+<g id="edge30" class="edge">
+<title>PTR_PERSON_NIL&#45;&gt;PTR_BOT</title>
+<path fill="none" stroke="#555555" d="M666.58,-199.43C680.58,-184.56 701.51,-162.35 718.65,-144.16"/>
+<polygon fill="#555555" stroke="#555555" points="719.75,-146.05 722.33,-140.24 716.69,-143.17 719.75,-146.05"/>
+</g>
+<!-- PTR_PERSON_NIL&#45;&gt;PTR_S1_NIL -->
+<!-- PTR_S1_NIL&#45;&gt;PTR_BOT -->
+<g id="edge31" class="edge">
+<title>PTR_S1_NIL&#45;&gt;PTR_BOT</title>
+<path fill="none" stroke="#555555" d="M748,-198.5C748,-184.97 748,-165.76 748,-148.97"/>
+<polygon fill="#555555" stroke="#555555" points="750.1,-148.97 748,-142.97 745.9,-148.97 750.1,-148.97"/>
+</g>
+<!-- PTR_S1_NIL&#45;&gt;PTR_MORE_NIL -->
+<!-- PTR_MORE_NIL&#45;&gt;PTR_BOT -->
+<g id="edge32" class="edge">
+<title>PTR_MORE_NIL&#45;&gt;PTR_BOT</title>
+<path fill="none" stroke="#555555" d="M825.62,-199.88C812.53,-185.22 792.8,-163.14 776.51,-144.9"/>
+<polygon fill="#555555" stroke="#555555" points="778.14,-143.58 772.58,-140.51 775.01,-146.38 778.14,-143.58"/>
+</g>
+<!-- STRUCT_PERSON -->
+<g id="node22" class="node">
+<title>STRUCT_PERSON</title>
+<polygon fill="#90ee90" stroke="black" points="976.5,-237.47 909.5,-237.47 909.5,-196.47 976.5,-196.47 976.5,-237.47"/>
+<text text-anchor="middle" x="943" y="-221.12" font-family="DejaVu Sans" font-size="13.00">Person</text>
+<text text-anchor="middle" x="943" y="-204.62" font-family="DejaVu Sans" font-size="13.00">age: int</text>
+</g>
+<!-- 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="M988.85,-397.89C978.61,-357.71 959.89,-284.26 949.83,-244.77"/>
+<polygon fill="#555555" stroke="#555555" points="951.95,-244.58 948.43,-239.28 947.88,-245.61 951.95,-244.58"/>
+</g>
+<!-- STRUCT_S1 -->
+<g id="node23" class="node">
+<title>STRUCT_S1</title>
+<polygon fill="#90ee90" stroke="black" points="1047,-237.47 993,-237.47 993,-196.47 1047,-196.47 1047,-237.47"/>
+<text text-anchor="middle" x="1020" y="-221.12" font-family="DejaVu Sans" font-size="13.00">s1</text>
+<text text-anchor="middle" x="1020" y="-204.62" font-family="DejaVu Sans" font-size="13.00">x: int</text>
+</g>
+<!-- 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="M999.24,-397.89C1003.85,-357.88 1012.28,-284.87 1016.85,-245.27"/>
+<polygon fill="#555555" stroke="#555555" points="1018.94,-245.52 1017.54,-239.32 1014.76,-245.04 1018.94,-245.52"/>
+</g>
+<!-- STRUCT_S2 -->
+<g id="node24" class="node">
+<title>STRUCT_S2</title>
+<polygon fill="#90ee90" stroke="black" points="1154.88,-237.47 1063.12,-237.47 1063.12,-196.47 1154.88,-196.47 1154.88,-237.47"/>
+<text text-anchor="middle" x="1109" y="-221.12" font-family="DejaVu Sans" font-size="13.00">s2</text>
+<text text-anchor="middle" x="1109" y="-204.62" font-family="DejaVu Sans" font-size="13.00">x: int, y: int</text>
+</g>
+<!-- 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="M1011.01,-398.32C1032.86,-358.11 1073.16,-283.94 1094.64,-244.41"/>
+<polygon fill="#555555" stroke="#555555" points="1096.43,-245.51 1097.45,-239.24 1092.74,-243.51 1096.43,-245.51"/>
+</g>
+<!-- STRUCT_MORE -->
+<g id="node25" class="node">
+<title>STRUCT_MORE</title>
+<polygon fill="#90ee90" stroke="black" points="1225,-234.97 1171,-234.97 1171,-198.97 1225,-198.97 1225,-234.97"/>
+<text text-anchor="middle" x="1198" y="-212.87" font-family="DejaVu Sans" font-size="13.00">…</text>
+</g>
+<!-- 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="M1021.18,-400.02C1061.16,-358.86 1138.49,-279.24 1176.23,-240.39"/>
+<polygon fill="#555555" stroke="#555555" points="1177.33,-242.26 1180.01,-236.5 1174.32,-239.34 1177.33,-242.26"/>
+</g>
+<!-- STRUCT_TOP&#45;&gt;MEM_TOP -->
+<!-- STRUCT_BOT -->
+<g id="node21" class="node">
+<title>STRUCT_BOT</title>
+<ellipse fill="#90ee90" stroke="black" cx="1020" cy="-111.99" rx="82.91" ry="28.99"/>
+<text text-anchor="middle" x="1020" y="-116.14" font-family="DejaVu Sans" font-size="13.00">⊥:struct</text>
+<text text-anchor="middle" x="1020" y="-99.64" font-family="DejaVu Sans" font-size="13.00">[struct bottom]</text>
+</g>
+<!-- STRUCT_BOT&#45;&gt;BOT -->
+<g id="edge62" class="edge">
+<title>STRUCT_BOT&#45;&gt;BOT</title>
+<path fill="none" stroke="#555555" d="M982.84,-85.85C959.17,-69.85 929.19,-49.57 908.49,-35.56"/>
+<polygon fill="#555555" stroke="#555555" points="909.78,-33.9 903.63,-32.28 907.42,-37.38 909.78,-33.9"/>
+</g>
+<!-- STRUCT_PERSON&#45;&gt;STRUCT_BOT -->
+<g id="edge40" class="edge">
+<title>STRUCT_PERSON&#45;&gt;STRUCT_BOT</title>
+<path fill="none" stroke="#555555" d="M957.85,-196.12C968.43,-181.96 982.92,-162.59 995.24,-146.11"/>
+<polygon fill="#555555" stroke="#555555" points="996.85,-147.46 998.76,-141.4 993.49,-144.94 996.85,-147.46"/>
+</g>
+<!-- STRUCT_PERSON&#45;&gt;STRUCT_S1 -->
+<!-- STRUCT_S1&#45;&gt;STRUCT_BOT -->
+<g id="edge41" class="edge">
+<title>STRUCT_S1&#45;&gt;STRUCT_BOT</title>
+<path fill="none" stroke="#555555" d="M1020,-196.12C1020,-182.64 1020,-164.43 1020,-148.49"/>
+<polygon fill="#555555" stroke="#555555" points="1022.1,-148.87 1020,-142.87 1017.9,-148.87 1022.1,-148.87"/>
+</g>
+<!-- STRUCT_S1&#45;&gt;STRUCT_S2 -->
+<!-- STRUCT_S2&#45;&gt;STRUCT_BOT -->
+<g id="edge42" class="edge">
+<title>STRUCT_S2&#45;&gt;STRUCT_BOT</title>
+<path fill="none" stroke="#555555" d="M1091.84,-196.12C1079.5,-181.83 1062.57,-162.25 1048.25,-145.68"/>
+<polygon fill="#555555" stroke="#555555" points="1050,-144.5 1044.49,-141.33 1046.82,-147.24 1050,-144.5"/>
+</g>
+<!-- STRUCT_S2&#45;&gt;STRUCT_MORE -->
+<!-- STRUCT_MORE&#45;&gt;STRUCT_BOT -->
+<g id="edge43" class="edge">
+<title>STRUCT_MORE&#45;&gt;STRUCT_BOT</title>
+<path fill="none" stroke="#555555" d="M1177.76,-198.72C1173.05,-195 1167.95,-191.22 1163,-187.98 1135.19,-169.81 1102.49,-152.39 1075.38,-138.93"/>
+<polygon fill="#555555" stroke="#555555" points="1076.64,-137.21 1070.33,-136.44 1074.78,-140.97 1076.64,-137.21"/>
+</g>
+<!-- MEM_BOT -->
+<g id="node27" class="node">
+<title>MEM_BOT</title>
+<ellipse fill="#00008b" stroke="black" cx="1294" cy="-111.99" rx="44.7" ry="18"/>
+<text text-anchor="middle" x="1294" y="-107.89" font-family="DejaVu Sans" font-size="13.00" fill="white">⊥:mem</text>
+</g>
+<!-- MEM_TOP&#45;&gt;MEM_BOT -->
+<g id="edge44" class="edge">
+<title>MEM_TOP&#45;&gt;MEM_BOT</title>
+<path fill="none" stroke="#555555" d="M1294,-408.67C1294,-356.2 1294,-198.53 1294,-137.49"/>
+<polygon fill="#555555" stroke="#555555" points="1296.1,-137.72 1294,-131.72 1291.9,-137.72 1296.1,-137.72"/>
+</g>
+<!-- MEM_TOP&#45;&gt;TUPLE_TOP -->
+<!-- MEM_BOT&#45;&gt;BOT -->
+<g id="edge63" class="edge">
+<title>MEM_BOT&#45;&gt;BOT</title>
+<path fill="none" stroke="#555555" d="M1273.96,-95.5C1263.49,-88.17 1250.14,-79.95 1237,-75 1125.68,-33.06 983.13,-22.53 918.55,-19.89"/>
+<polygon fill="#555555" stroke="#555555" points="918.65,-17.79 912.58,-19.66 918.49,-21.99 918.65,-17.79"/>
+</g>
+<!-- TUPLE1 -->
+<g id="node30" class="node">
+<title>TUPLE1</title>
+<polygon fill="#ffc0cb" stroke="black" points="1418.88,-339.96 1363.12,-339.96 1363.12,-303.96 1418.88,-303.96 1418.88,-339.96"/>
+<text text-anchor="middle" x="1391" y="-317.86" font-family="DejaVu Sans" font-size="13.00">(type)</text>
+</g>
+<!-- TUPLE_TOP&#45;&gt;TUPLE1 -->
+<g id="edge47" class="edge">
+<title>TUPLE_TOP&#45;&gt;TUPLE1</title>
+<path fill="none" stroke="#555555" d="M1405.19,-408.93C1402.44,-392.26 1398.22,-366.67 1395.09,-347.74"/>
+<polygon fill="#555555" stroke="#555555" points="1397.16,-347.4 1394.11,-341.83 1393.02,-348.09 1397.16,-347.4"/>
+</g>
+<!-- TUPLE2 -->
+<g id="node31" class="node">
+<title>TUPLE2</title>
+<polygon fill="#ffc0cb" stroke="black" points="1529,-339.96 1435,-339.96 1435,-303.96 1529,-303.96 1529,-339.96"/>
+<text text-anchor="middle" x="1482" y="-317.86" font-family="DejaVu Sans" font-size="13.00">(type, type)</text>
+</g>
+<!-- TUPLE_TOP&#45;&gt;TUPLE2 -->
+<g id="edge48" class="edge">
+<title>TUPLE_TOP&#45;&gt;TUPLE2</title>
+<path fill="none" stroke="#555555" d="M1419.89,-409.39C1432.2,-392.26 1451.54,-365.35 1465.37,-346.1"/>
+<polygon fill="#555555" stroke="#555555" points="1466.97,-347.48 1468.76,-341.38 1463.56,-345.02 1466.97,-347.48"/>
+</g>
+<!-- TUPLEN -->
+<g id="node32" class="node">
+<title>TUPLEN</title>
+<polygon fill="#ffc0cb" stroke="black" points="1622.75,-339.96 1545.25,-339.96 1545.25,-303.96 1622.75,-303.96 1622.75,-339.96"/>
+<text text-anchor="middle" x="1584" y="-317.86" font-family="DejaVu Sans" font-size="13.00">(type, …)</text>
+</g>
+<!-- TUPLE_TOP&#45;&gt;TUPLEN -->
+<g id="edge49" class="edge">
+<title>TUPLE_TOP&#45;&gt;TUPLEN</title>
+<path fill="none" stroke="#555555" d="M1432.78,-411.64C1458.78,-396.61 1500.83,-372.23 1537,-350.95 1540.81,-348.7 1544.8,-346.35 1548.76,-344"/>
+<polygon fill="#555555" stroke="#555555" points="1549.56,-345.97 1553.64,-341.1 1547.41,-342.36 1549.56,-345.97"/>
+</g>
+<!-- TUPLE_BOT -->
+<g id="node29" class="node">
+<title>TUPLE_BOT</title>
+<ellipse fill="#ffc0cb" stroke="black" cx="1445" cy="-111.99" rx="44.7" ry="18"/>
+<text text-anchor="middle" x="1445" y="-107.89" font-family="DejaVu Sans" font-size="13.00">⊥:tuple</text>
+</g>
+<!-- TUPLE_BOT&#45;&gt;BOT -->
+<g id="edge64" class="edge">
+<title>TUPLE_BOT&#45;&gt;BOT</title>
+<path fill="none" stroke="#555555" d="M1416.38,-97.91C1398.05,-90.08 1373.56,-80.58 1351,-75 1192.43,-35.77 996.51,-23.66 918.45,-20.23"/>
+<polygon fill="#555555" stroke="#555555" points="918.86,-18.15 912.78,-19.99 918.69,-22.35 918.86,-18.15"/>
+</g>
+<!-- TUPLE1&#45;&gt;TUPLE_BOT -->
+<g id="edge50" class="edge">
+<title>TUPLE1&#45;&gt;TUPLE_BOT</title>
+<path fill="none" stroke="#555555" d="M1395.51,-303.58C1405.12,-266.56 1427.65,-179.82 1438.68,-137.32"/>
+<polygon fill="#555555" stroke="#555555" points="1440.68,-137.97 1440.16,-131.63 1436.62,-136.91 1440.68,-137.97"/>
+</g>
+<!-- TUPLE1&#45;&gt;TUPLE2 -->
+<!-- TUPLE2&#45;&gt;TUPLE_BOT -->
+<g id="edge51" class="edge">
+<title>TUPLE2&#45;&gt;TUPLE_BOT</title>
+<path fill="none" stroke="#555555" d="M1478.91,-303.58C1472.32,-266.56 1456.89,-179.82 1449.33,-137.32"/>
+<polygon fill="#555555" stroke="#555555" points="1451.44,-137.2 1448.32,-131.66 1447.3,-137.93 1451.44,-137.2"/>
+</g>
+<!-- TUPLE2&#45;&gt;TUPLEN -->
+<!-- TUPLEN&#45;&gt;TUPLE_BOT -->
+<g id="edge52" class="edge">
+<title>TUPLEN&#45;&gt;TUPLE_BOT</title>
+<path fill="none" stroke="#555555" d="M1572.39,-303.58C1547.38,-266.16 1488.41,-177.94 1460.36,-135.96"/>
+<polygon fill="#555555" stroke="#555555" points="1462.21,-134.96 1457.13,-131.14 1458.72,-137.29 1462.21,-134.96"/>
+</g>
+</g>
+</svg>
diff --git a/docs/chapter10a/type-control.svg b/docs/chapter10a/type-control.svg
new file mode 100644
index 00000000..d4b79c53
--- /dev/null
+++ b/docs/chapter10a/type-control.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="61" height="20" viewBox="0 0 61 20" role="img" aria-labelledby="title">
+ <title id="title">Control</title>
+ <rect width="61" height="20" rx="2" fill="#ffff00"/>
+ <text x="30.5" y="14" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" fill="#000000">Control</text>
+</svg>
diff --git a/docs/chapter10a/type-integer.svg b/docs/chapter10a/type-integer.svg
new file mode 100644
index 00000000..97d03372
--- /dev/null
+++ b/docs/chapter10a/type-integer.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="60" height="20" viewBox="0 0 60 20" role="img" aria-labelledby="title">
+ <title id="title">Integer</title>
+ <rect width="60" height="20" rx="2" fill="#add8e6"/>
+ <text x="30.0" y="14" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" fill="#000000">Integer</text>
+</svg>
diff --git a/docs/chapter10a/type-memory.svg b/docs/chapter10a/type-memory.svg
new file mode 100644
index 00000000..16b5121f
--- /dev/null
+++ b/docs/chapter10a/type-memory.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="67" height="20" viewBox="0 0 67 20" role="img" aria-labelledby="title">
+ <title id="title">Memory</title>
+ <rect width="67" height="20" rx="2" fill="#00008b"/>
+ <text x="33.5" y="14" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" fill="#ffffff">Memory</text>
+</svg>
diff --git a/docs/chapter10a/type-pointer.svg b/docs/chapter10a/type-pointer.svg
new file mode 100644
index 00000000..7604492e
--- /dev/null
+++ b/docs/chapter10a/type-pointer.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="62" height="20" viewBox="0 0 62 20" role="img" aria-labelledby="title">
+ <title id="title">Pointer</title>
+ <rect width="62" height="20" rx="2" fill="#008000"/>
+ <text x="31.0" y="14" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" fill="#ffffff">Pointer</text>
+</svg>
diff --git a/docs/chapter10a/type-struct.svg b/docs/chapter10a/type-struct.svg
new file mode 100644
index 00000000..97a16562
--- /dev/null
+++ b/docs/chapter10a/type-struct.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="52" height="20" viewBox="0 0 52 20" role="img" aria-labelledby="title">
+ <title id="title">Struct</title>
+ <rect width="52" height="20" rx="2" fill="#90ee90"/>
+ <text x="26.0" y="14" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" fill="#000000">Struct</text>
+</svg>
diff --git a/docs/chapter10a/type-tuple.svg b/docs/chapter10a/type-tuple.svg
new file mode 100644
index 00000000..691478ac
--- /dev/null
+++ b/docs/chapter10a/type-tuple.svg
@@ -0,0 +1,5 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="47" height="20" viewBox="0 0 47 20" role="img" aria-labelledby="title">
+ <title id="title">Tuple</title>
+ <rect width="47" height="20" rx="2" fill="#ffc0cb"/>
+ <text x="23.5" y="14" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" fill="#000000">Tuple</text>
+</svg>