◄ WORLD V · SONNY 5DART 231 · a helldive at the net

THE CONTROL FLOW GRAPH blocks are nodes, jumps are edges — the shape of all paths

Wire the basic blocks together: a directed edge from block A to block B whenever control can pass A→B. The result is the control-flow graph, and its shape is the program's shape — a straight line, a diamond (if/else), a cycle (loop). One number reads the branching: cyclomatic complexity M = E − N + 2 (edges minus nodes plus two) counts the independent paths, the minimum tests to cover every branch. A back-edge in the graph is a loop; no back-edge means the graph is acyclic.

THE TECHNIQUE M = E − N + 2 : independent paths through the graph

Pick a shape; the demo builds its CFG and computes cyclomatic complexity M = E − N + 2 — the number of independent paths: live demo


HISTORY & CREDIT Allen 1970 · McCabe 1976

“Read the code top to bottom.” — control does not flow top to bottom; it flows along edges. The CFG is the only honest picture of “what can run next,” and its cyclomatic number is how tangled that picture is — a straight line scores 1, every branch adds one. cited

1970 · Frances E. Allen — the control-flow graph as the frame for global analysis.
1976 · Thomas J. McCabe — “A Complexity Measure”: cyclomatic complexity M = E − N + 2, the independent-path count, borrowed from graph theory (the cycle rank).
now · every CFG-based pass and every code-complexity linter computes it.

The graph is acyclic exactly when there is no back-edge — no loop. A language without loops has a CFG that is a DAG per function, and its complexity is just one-plus-the-branches. McCabe 1976

RECOMMEND FOR I-13 cyclomatic complexity of a diamond, computed

On the canonical compiler, a diamond CFG (N=4 blocks, E=4 edges) has complexity M = 4 − 4 + 2 = 2 — two independent paths:

$ i13 run cfg.i13 # M = edges - nodes + 2, diamond CFG m = 2 -- two independent paths (then-branch, else-branch)
Recommend: report cyclomatic complexity as a “waste” metric — i13's check ledger already lists waste under NOT COVERED. Since i13 has no loops (recursion only), every function's intraprocedural CFG is a DAG — no back-edges — so M is exactly one-plus-the-if-guards, a cheap single-pass count. It would turn an empty ledger slot into a real number without changing what i13 is.