picture language

SICP §2.2.4's picture language: a painter is not a value, it is a procedure from a frame – a parallelogram given by an origin and two edge vectors – to a drawing. Every combinator (beside, below, the flips and rotations, the recursive splits, square-limit) is built entirely out of transform-painter: pick a triple of points in the unit square, map each through the frame's own frame-coord-map, and hand the sub-painter the resulting frame. Drag the frame's three handles (origin, edge1, edge2) below and step through the trace to watch each combinator construct its sub-frame and recurse.

The frame-coord-map toggle includes two deliberately wrong variants (swap, which exchanges the two edge vectors, and noorigin, which drops the origin term) – pick one and watch every combinator and primitive downstream get it wrong identically, since they all go through the same function. The reference-comparison table runs the current expression twice, once with whichever variant is selected and once forced to the correct implementation, and checks five things against each other: something was drawn, the segment count matches, every endpoint lands inside the outer frame, the bounding box matches, and every segment's coordinates match exactly. The first few tests pass even for the buggy variants – a bug that still produces some plausible-looking picture with the same segment count and bounding box looks fine by those measures. Only the exact-coordinate test reliably catches it.

The pure trace model lives in wal-sh.tools.picture-language.core (host-neutral .cljc, tested on the JVM with test.check: the correct frame-coord-map is affine and origin-preserving, the two bug variants provably differ from it, the recursive splits' n = 0 base case is a true no-op wrapper, and the five-test comparison logic is exercised directly against identical and deliberately-differing traces). The browser adapter is wal-sh.tools.picture-language.browser. Build: gmake tools-cljs; debug in isolation: gmake dev-tool TOOL=picture-language.