Skip to content

compat_match: emit null for a non-participating group, not truncation - #16

Merged
InauguralPhysicist merged 2 commits into
mainfrom
fix-compat-unset-group
Jul 25, 2026
Merged

compat_match: emit null for a non-participating group, not truncation#16
InauguralPhysicist merged 2 commits into
mainfrom
fix-compat-unset-group

Conversation

@InauguralPhysicist

Copy link
Copy Markdown
Contributor

EigenScript v0.33.0 fixed the builtin regex_match (upstream #629): a capture
group that did not participate — an unmatched optional (x)?, or the losing
side of an alternation — now emits null and the groups after it still arrive.
Previously the first such group terminated emission, and the list was capped
at 16 by a fixed regmatch_t[16].

Our compat_match shim mirrored both bugs deliberately (the S8 case was
literally titled "shim match truncates at unset group"), which was the right
call while the builtin behaved that way and the wrong one the moment it
didn't. The S8 differential — shim vs live builtin over shared inputs — went
red as soon as the runtime was correct:

regex_match of ["b", "(a)|(b)"]   →  ["b", null, "b"]   (v0.33.0)
regex.compat_match of [...]        →  ["b"]              (before this PR)

The shim's contract is to be drop-in for the builtin, so it follows. Also
drops the 16-element cap — upstream now sizes the array from the compiled
pattern, so a 17-group pattern returns 18 elements instead of silently 16. The
documented "group n sits at index n" invariant only holds if a gap is a hole
rather than a full stop.

The S8 check that asserted truncation is retitled and re-pointed at the new
shape rather than deleted; it is still the test that pins this behavior.

Verification

EIGENSCRIPT=eigenscript bash tests/run.sh against EigenScript main @
v0.33.0: ALL PASSED (359 checks + package smoke).

Found by the v0.33.0 pre-bump consumer sweep. The pin bump to v0.33.0 follows
separately.

🤖 Generated with Claude Code

InauguralPhysicist and others added 2 commits July 24, 2026 23:24
EigenScript v0.33.0 fixed the builtin regex_match (#629): a capture group that
did not participate — an unmatched optional `(x)?`, or the losing side of an
alternation — now emits null and the groups after it still arrive. Before, the
first such group TERMINATED emission and the list was capped at 16.

Our shim mirrored both bugs on purpose, so it was faithful to a builtin that
has since been corrected, and the S8 differential (shim vs live builtin) went
red the moment the runtime was right: `(a)|(b)` on "b" is `["b", null, "b"]`
now, not `["b"]`.

The shim's whole contract is to be drop-in for the builtin, so it follows.
Drops the 16-element cap too — upstream now sizes the array from the compiled
pattern, so a 17-group pattern returns 18 elements rather than silently 16.
The documented invariant (group n at index n) only holds if a gap is a hole
rather than a full stop.

The S8 case that asserted truncation is retitled and re-pointed at the new
shape rather than deleted — it is still the test that pins this behavior.

Suite: ALL PASSED (359 checks + package smoke) against v0.33.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Lands with the compat_match fix in the same PR: the shim's new null-for-
unset-group shape is only correct against the corrected builtin (#629), so on
v0.32.0 the S8 differential would fail in the opposite direction. Fix and pin
are one atomic step.

Verified against the v0.33.0 runtime before the bump: tests/run.sh ALL PASSED
(359 checks + package smoke). CLAUDE.md's two version-prose sites moved with
the pin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@InauguralPhysicist
InauguralPhysicist merged commit ec9ad94 into main Jul 25, 2026
1 check passed
@InauguralPhysicist
InauguralPhysicist deleted the fix-compat-unset-group branch July 25, 2026 04:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant