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.