Diagram Vocabulary
8 diagram types · Fundamentals of CS · each specimen is interactive
STATUS exploration DATE 2026-04-25 FIDELITY wireframe
keys 0–9
Goal: limit the total number of visualization tools to precisely the number needed — where removing one hurts the ability to express a unique concept, and adding more is only marginally helpful. Three categories, each with one tool.
EEvaluation
how does an expression reduce to a value?
Any function that returns (including operators), switch conditions, recursive calls. The bar-stacking Reduction notation handles all of these in one shape.
"What does this expression equal, and why?"
FFlow
in what order do statements run?
Branching, loops, function call sequences. The question is always which line runs next and how many times. One tool with two modes: branch (fork + merge) and trace (iteration table).
"Which path did execution take?"
MMemory
what does memory look like right now?
Variables, objects, arrays, linked-list nodes, call-stack frames. All one diagram: stack + heap snapshot. Different heap shapes (indexed strip, node chain, object fields) are rendering variations, not separate tools.
"Where does this value live, and who else can see it?"
New tool
Absorbs
What it no longer needs
What would break if removed?
Reduction
bar-stacking
Eval TreeSwitch / MatchReduction strip
All are "how does X evaluate to Y?" — one notation with numbered ticks handles arithmetic, function calls, pattern matching, and recursion.
Eval Tree's static tree view (structure of sub-expressions). Covered by the order of the bars — the structure is implicit in which bar sits above which.
Can't show how expressions simplify step by step.
Flow
branch + trace
if / elseLoop Trace
Both are "which line runs?" — branching is a one-shot fork; trace is repeated iteration. Two modes, one concept.
Nothing — the two modes cover every control-flow shape in the book.
Can't show which path code takes or how loops iterate.
Memory
stack + heap
Value MemoryRef TypesArraysLinked ListsCall Stack
All are "what does memory look like right now?" — stack slots, heap objects, indexed strips, node chains, and call frames are all shapes drawn in the same stack+heap view.
Separate "Array diagram" and "Linked List diagram" as standalone types. An array is just a heap object with an indexed strip; a linked list is heap objects with next pointers. Same memory view, different shapes.
Can't show where values live, aliasing, or heap structure.
10 old diagrams → 3 tools. Each tool is irreplaceable — removing any one of the three loses the ability to express a concept no other tool can cover.
Every topic covered by 3 tools
Each row is a topic. The columns show which tool(s) you reach for. Nearly every topic needs exactly 1 or 2 — no topic needs all 3.
Topic
Reduction
Flow
Memory
Notes
Variables & assignment
ch. intro
Memory only — stack slots, copy semantics
Arithmetic & operators
expressions
Reduction — bar-stacking for operator precedence
Boolean logic
expressions
Reduction — same notation, boolean operators
if / else
control flow
Flow (branch mode) — condition forks to arms
switch / match
control flow
Reduction — input reduces through arm matching
for / while loops
iteration
Flow (trace mode) — iteration table + Memory for accumulators
Memory (node chain on heap) + Reduction for operations like len()
Sorting / searching
algorithms
Flow (trace) + Memory (array with swaps highlighted)
Exceptions / early return
control flow
Flow (branch — which path exits) + Memory (stack unwinding)
The rule
If you're explaining what something evaluates to → draw a Reduction.
If you're explaining which code runs and in what order → draw a Flow (branch or trace).
If you're explaining what memory looks like → draw a Memory snapshot.
Most topics need 1 tool. Some need 2 side-by-side. None needs all 3.
what we cut
7 diagrams removed, 0 concepts lost
Eval Tree → absorbed by Reduction (bars show structure implicitly). Switch / Match → absorbed by Reduction (arm matching is evaluation). Call Stack → absorbed by Memory (frames are stack state). Value Memory → absorbed by Memory (it's the simple case). Ref Types → absorbed by Memory (add heap pane). Arrays → absorbed by Memory (indexed-strip heap shape). Linked Lists → absorbed by Memory (node-chain heap shape).
what we keep
3 tools, each irreplaceable
Reduction — the only tool that shows step-by-step evaluation. Remove it and you can't explain operator precedence, recursion unwinding, or pattern matching. Flow — the only tool that shows execution order. Remove it and you can't explain which branch runs, how a loop iterates, or when code exits early. Memory — the only tool that shows state. Remove it and you can't explain where values live, aliasing, or heap structure.
Already prototyped in v3. Shown here as the reference baseline for the vocabulary.
Value-type memory stack only
Each variable is a named slot on the stack. Value types store their data directly in the slot — no indirection.
intx = 5;inty = x;y = y + 1;
0x1005x
0x1046y
0x108—
0x10c—
hover a code line ↔ cell highlights together.
Authoring ::: diagram type=memory
::: diagram id="vm" type="memory"
code:
int x = 5; # group-1, tok: xlhs=x, xrhs=5
int y = x; # group-2, tok: ylhs=y, yrhs=x
y = y + 1; # group-3variables:
x: { type: int, addr: 0x100, group: 1 }
y: { type: int, addr: 0x104, group: 2 }
:::
Use when: introducing a new variable, assignment, or copy semantics
Hover link: code line ↔ cell(s) in the same group
Quiz mode: blank the val or name fields; student fills them
Extends to: reference type memory (tab 7) with heap split
Bar-stacking reduction — the way you'd actually work it on paper. Start at the bottom with the original expression. Then draw a bar above any sub-expression you want to reduce, and write the reduced form on that bar. Bars stack upward as you simplify; once a bar resolves to a value, the layer below it can take that value and reduce further. Numbers ¹ ² ³ … trace the order in which each piece was written.
Value-type evaluation arithmetic, operators
From the sketch: (x + 3) * 5 with x = 2. Read it bottom-up — the original expression is at the bottom; each bar above shows the reduced form of the bit underneath. Numbers trace the order each piece was written.
read bottom → top · numbers = write-order1 first · 7 last
25⁶*⁷
5⁴+⁵
2²mem³
¹( x + 3 ) * 5simplifies to→25
Order: 1 write the bottom expression · 2 draw a bar over x labeled "mem" · 3 write 2 on it · 4 draw a bar over (2+3) labeled "+" · 5 write 5 on it · 6 draw a bar over the whole thing labeled "*" · 7 write 25 on it. The "→ simplifies to" at the bottom is the final value of the whole expression — visually the same as the topmost bar, just pulled out for emphasis.
Reference-type evaluation len(list) · same notation
Same bar-stacking, applied to len(a→b→c→∅). Each bar above peels one node, leaving 1 + len(rest). Recursion bottoms out at len(∅)=0; then the +'s collapse upward.
each bar reduces the layer beneath itread bottom → top
3⁶+
1 + 1 + 1 + 0⁵base
1 + 1 + 1 + len ( )⁴
1 + 1 + len (
c→→
)³
1 + len (
b→→c→→
)²
¹len (
a→→b→→c→→
)simplifies to→3
Same notation as the arithmetic. The bars are literally the working — drawn over what's being reduced, with the result written on top. Linked-list nodes inside the expression aren't a separate diagram; they're just structured tokens in the same line of work.
The two rules students need value vs reference
Within this notation, every "look up" or argument-pass step follows one of two rules. Naming them once means we don't re-explain at every chapter.
rule 1 · value types
Look up = copy the value
When the notation reduces a variable name like x, replace it with a copy of the bits stored at that slot. Two slots can hold equal values without being "the same."
Applies to: int, double, bool, char, structs.
rule 2 · reference types
Look up = follow the arrow
For a reference like list, the slot holds an address. Reducing the variable doesn't copy the object — it gives you a handle. Recursing into rest means stepping one node along the chain.
Applies to: classes, arrays, lists, strings (in C#), any new'd thing.
Why add this and not extend Eval Tree?
The Eval Tree shows structure (which sub-expression feeds which operator). The Reduction notation shows order + state — what's happening to memory at each step. They answer different questions, but Reduction subsumes the existing "reduction strip" already living inside Eval Tree.
Proposal: promote Reduction to a first-class diagram, demote Eval Tree's reduction strip to just the static tree, and route every value/reference teaching moment through the same numbered-tick notation. That keeps the vocabulary at 9 diagrams with no overlap.
Evaluation tree — shows how a compound expression reduces to a value. Each internal node is an operator or function; leaves are literals or variable lookups. Hover a node to see what it evaluates to and which sub-tree feeds it.
Expression tree reduce bottom-up
For (3 + 4) * (x - 1) where x = 5. Hover a node to see its value and highlight its sub-expression in the code.
int x = 5;int result = (3 + 4) * (x - 1);
*
= 28
+
= 7
−
= 4
3
= 3
4
= 4
x
= 5
1
= 1
hover any node → see its value + highlight its span in the code above.
Reduction strip step-by-step
Same expression, shown as sequential reduction steps — closer to how a student reads it left to right.
(3 + 4) * (x - 1)→start
(3 + 4) * (5 - 1)→evaluate x
7 * (5 - 1)→evaluate 3+4
7 * 4→evaluate 5−1
28→evaluate 7*4
hover a step to highlight it. For nested method calls, each frame gets a step.
Use when: operator precedence, nested calls, compound expressions
Tree vs strip: tree shows structure; strip shows order of evaluation
Hover link: node/step ↔ sub-expression span in code ↔ variable cell if a lookup
Quiz mode: blank result fields; student fills in the value at each node
Call stack — when a method is called, a new frame is pushed. Each frame shows its local variables. Hover a frame to highlight the corresponding call site in the code.
Call stack frames push/pop
Active frame at top. Older frames below. Each frame shows its locals. Returning pops the top frame.
static intMain() {int a = 3;int result = Square(a);}static intSquare(int n) {returnn * n;}
Square( ) ← active
3
n
Main( )
3
a
?
result
hover a frame → its call site in the code highlights.
Use when: introducing functions, recursion, parameter passing
Hover link: frame ↔ function definition + call site in code
Animation: push frame (call), pop frame (return) — can be stepped
Quiz mode: blank a param or local value; student fills in what's passed
Extends to: recursion (many frames of same function), closures
Loop trace table — each row is one iteration. Columns are the loop variable, condition, body effect, and any accumulator. Hover a row to highlight the corresponding loop body state.
Loop trace state × iteration
For a for loop accumulating a sum. Each row shows the state at the top of that iteration.
int sum = 0;for (inti = 0; i < 4; i++) { sum = sum + i;}// sum is now 6
iter
i
i < 4 ?
sum + i
sum after
0
0
true
0 + 0 = 0
0
1
1
true
0 + 1 = 1
1
2
2
true
1 + 2 = 3
3
3
3
true
3 + 3 = 6
6
—
4
false
loop exits
6
loop body at this iteration
hover a row → see what the loop body does that iteration.
Use when: for/while loops, accumulation, array traversal
Hover link: row ↔ loop body code lines for that iteration
Columns adapt: array-traversal loop adds an index + element column
Quiz mode: blank selected cells (e.g. the "sum after" column); student fills in
Extends to: while loops, nested loops (two index columns)
if / else branching — shows the condition as a decision diamond, with two labelled paths. Hover the condition to see both arms; hover an arm to highlight its code block.
if / else fork + merge
For a simple grade check. The diamond evaluates the condition; the arms show what each branch does; they merge back at the end.
::: diagram id="br1" type="branch"
condition: "score >= 60"
then:
label: "Pass"
code-lines: [3]
else:
label: "Fail"
code-lines: [5]
active-arm: then # optional: shade the live branch:::
Use when: if/else, early returns, guard clauses
Hover link: arm ↔ its code block; condition ↔ the boolean expression
Active arm: shades the branch taken for a given example value
Quiz mode: blank active-arm; student selects which branch runs
Note: distinct from switch — no "result value," just control flow
Switch expression — more like evaluation than control flow. The expression produces a value by matching an arm. Layout mirrors the eval tree: input → matched arm → output value.
Switch expression match → value
C# switch expression: each arm is a pattern → result. The matched arm lights up; others fade.
Use when: switch expressions, pattern matching, any arms-to-value form
Hover link: arm ↔ its pattern + result tokens in code
Differs from if/else: produces a value — closer to the eval tree than the branch diagram
Quiz mode: blank which arm matches, or blank the result; student selects
Reference-type memory — the stack holds a reference (address); the object lives on the heap. Two variables can reference the same object — mutation through one is visible through the other.
Heap + stack ref on stack, object on heap
A Point class. p holds a reference; the fields live on the heap. Assigning q = p copies the reference, not the object.
Point p = new Point(3, 4);Point q = p;q.X = 99;// p.X is also 99 — same object!
Stack
0x100→ 0x500p
0x108→ 0x500q
Heap
Point @ 0x500
X:99
Y:4
Both p and q point here → mutation visible through either reference.
hover a code line → the relevant stack cell + heap object highlight.
Use when: introducing classes, null, aliasing, mutation through refs
Key teaching moment: assigning a reference copies the address, not the object
Hover link: stack cell → heap object it points to; code line → involved cells/objects
Extends to: arrays (tab 8) and linked lists (tab 9), both of which use heap objects
Array diagram — a reference type whose heap object is a contiguous indexed strip. The stack holds the reference; the heap holds the cells. Index-out-of-bounds shows grayed ghost cells beyond the end.
Array ref → indexed strip
An int[] of length 5. Stack holds a reference; heap holds the cells. Hover a cell to highlight the corresponding indexing expression in code.
int[] nums = { 10, 20, 30, 40, 50 };nums[2] = 99;// nums[2] is now 99
nums
→heap array @ 0x200
[0]10
[1]20
[2]99
[3]40
[4]50
[5]?
[6]?
Ghost cells (dashed) show out-of-bounds territory.
hover a cell → highlights the corresponding index expression in code.
Quiz mode: blank element values; student fills after tracing a loop
Combine with: loop trace (tab 4) for traversal; ref memory (tab 7) for aliasing
Linked list diagram — each node is a heap object with a value field and a next pointer. The head variable on the stack points to the first node. Null terminates the chain.
Linked list node chain with pointers
A singly-linked list of three nodes. Each box shows val | next. Hover a node to highlight the traversal step that visits it.
Node head = new Node(10);head.Next = new Node(20);head.Next.Next = new Node(30);Node curr = head;while (curr != null) {print(curr.Value); curr = curr.Next;}
stack→ 0x300head
→
10
next→
→
20
next→
→
30
null
→
null
traversal state (curr pointer)
10
curr
20
next
30
next
print(10) · curr = curr.Next
hover a node → shows what the traversal body does at that node.