Rakugrid

The behavioural grid of the Raku language — every recorded test, on every engine on record.

Roast asks whether an implementation is Raku. Rakugrid asks whether it survives real programs: small constructs (atoms) and their combinations (molecules), each crossed against a ladder of awkward values, each cell recording what every engine on record actually printed. The suite is its own dataset — this site is that dataset, browsable.

172,211testsevery one a single recorded behaviour
797atomsone construct probed across a ladder of values
2enginesRakudo as the reference · rakupp across 6 build snapshots
125,966agreenewest observations, both engines
41,860differ107 of them crash an engine
3,489ruledsigned verdicts — the oracle is not the arbiter

The whole suite, one pixel per test

Every test in the suite, grouped by family — a gap separates atoms. Hover names the atom; click opens it. The colored streaks are divergence clusters: one root cause is usually one streak.

operators112,415 tests · 147 atoms

methods29,142 tests · 103 atoms

regexes11,776 tests · 92 atoms

signatures13,923 tests · 15 atoms

syntax434 tests · 13 atoms

spelling952 tests · 119 atoms

laws3,051 tests · 33 atoms

types44 tests · 8 atoms

molecules204 tests · 3 atoms

regression260 tests · 260 atoms

numeric4 tests · 1 atom

unicode3 tests · 1 atom

io2 tests · 1 atom

hangs1 tests · 1 atom

How to read a cell

A test is one record in a .grid file: the code, the asserted behaviour, and one oracle line per engine that ever ran it — newest observation last:

- id     0005
  from   ladder:mixed×mixed
  cell   0 | NaN
  code   (0) cmp (NaN)
  is     Order::Less
  type   Order
  oracle rakudo-2026.07 → Order::Less
  oracle rakupp-v3.14.0-77-gf431f48-dirty → Order::Less

The colors compare each record’s newest rakupp observation with the reference: agree and differs mean what they say; crash means the engine went down rather than answering; ruled means the divergence was adjudicated by hand; no data means one side was never recorded. An observation is a snapshot, not a verdict on today’s binary: a differing cell says the engines disagreed when that cell was last probed, and the drawer names the exact build that said it. The rakupp snapshots accumulate on purpose — a sweep re-probes only what changed, so an untouched cell keeps the build that last ran it instead of costing a fresh run of the whole grid.

The oracle is not the arbiter

Where the engines disagree, Rakudo’s answer is the default, not the law. A divergence must either be fixed or receive a signed verdict naming which behaviour is right and why — otherwise the build fails. Sometimes the verdict goes against the reference:

(1).asinh

reference0.8813735870195429e0
rakupp0.881373587019543e0
rulingimpl-bug asinh(1) = ln(1+sqrt 2); the correctly-rounded double is 0.881373587019543, and the reference is one ULP below it

All 3,489 signed rulings are on the rulings page; the 367 recorded crash observations have their own.

The sweep, over time

Each point is one measured run of the whole suite against a rakupp build. The failing count only means something while the suite holds still, so its line breaks wherever the suite grew.

The newest point predates the suite's growth: that sweep ran 41,412 of the 42,402 tests the suite held then, and the suite holds 172,211 today — a full-grid sweep has not been recorded since. Only these charts wait for one: the colors above come from the observations each record already carries, so they cover the whole grid.

020k40k08-1608-17
suite size (tests run) latest: 41,412
05k10k08-1608-17
failing on the engine under test latest: 7,842
the measured points
dateranfailednote
2026-08-1624,1449,518baseline: the sweep starts here
2026-08-1624,1446,874batch 1+2: `$!` from a returned Failure; take/emit; Cool numerics; .raku itemisation
2026-08-1624,1446,195batch 3: strict numification, Any.join/Mu.bless/Cool.chrs
2026-08-1624,1445,490batch 4: argument shapes (uniprop, same-*, join, roots, unpolar)
2026-08-1624,1445,166batch 5: chomp needle, Any.Capture, roots(1), Code.Str
2026-08-1624,1445,011batch 6: min/max ties, NaN ordering, Cool.Failure — 3 Roast regressions, fixed in 7
2026-08-1624,1444,930batch 7: scalar-numeric strictness + the batch-6 repairs
2026-08-1741,41210,153SUITE GREW to 42,402 records (operator inventory matrix): not comparable to the rows above
2026-08-1741,4129,015operator spellings: !== is negated ==, plus the unicode equality and negated-set forms
2026-08-1741,4128,469empty Set/Bag/Mix .raku is the sub form; ~< and ~> are no-such-operator, not NYI
2026-08-1741,4128,078≼/≽ removed-in-6.d diagnostic; bitwise ops reject a non-finite operand
2026-08-1741,4127,950exact numification of Hash/type-object operands; `.` as infix is X::Obsolete
2026-08-1741,4127,842Any.nl-out (documented); the rest of the "internals" cluster triaged against the docs
2026-08-1741,4127,842constants immutable + ++/-- honour readonly — grid flat, Roast 600 (misc.t 11→15, advent2009-day09 full)

Run it yourself

The suite is engine-neutral and lives at github.com/ash/rakugrid. The harness runs unchanged under any implementation:

raku bin/rakugrid fire --engine=/path/to/rakupp   # run everything, emit TAP
raku bin/rakugrid matrix operators/infix-cmp      # one atom as a matrix
raku bin/rakugrid isolate 'grid:operators/infix-cmp#0005'   # one test, standalone
raku bin/rakugrid check                           # the build rule: no unsigned divergences

Every test on this site has a “run in the playground” button — the code runs in your browser on the same engine that powers the playground.