Skip to content

Add REXX (rexx), resolving the .cmd collision with batch (#2504) - #3107

Merged
squid-protocol merged 6 commits into
mainfrom
lang/rexx-2504
Sep 17, 2026
Merged

squid-protocol merged 6 commits into
mainfrom
lang/rexx-2504

Conversation

@squid-protocol

@squid-protocol squid-protocol commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Adds REXX (rexx) end to end per how_to_add_a_language.md, resolving the .cmd collision with batch. Closes #2504 (parent #2516). Corpus half: squid-protocol/keyword-rosetta#138 (opened together; its own PR-triggered CI stays red until this PR merges — verify.yml checks the engine out at main — a green dispatched run against pull/<this-PR>/head is linked there).

The profile (languages/rexx.py)

z/OS TSO/E REXX (SAA) plus the ooRexx directive surface (::requires/::routine/::class/::method/::constant.rexx files in the wild host ooRexx code). 35/53 baseline keys wired, 18 explicit Nones (every gated absence carries a validated rosetta deviation-ledger entry, rexx-stated-absences). Bare keywords use explicit guard classes ((?<![\w.!?@#$])) because REXX symbols carry ! ? @ # $ and compound-variable dots — \b cannot police them (pli's discipline).

Issue-text deviations, both #2856/#2878-style contract-over-issue rulings, pinned in the strict suite:

invocation_model stays default (by_name): CALL name / name() / SIGNAL name reach labels by name, so the #2866 census applies — no POSITIONAL_LANGUAGES pin.

New prism dialect family: recursive_block_rexx

REXX block comments genuinely nest (/* /* */ */ — TSO/E REXX Reference), so the language needs the recursive peel — but the shared recursive_block family also strips // line comments, and // is REXX's integer-remainder operator: the stock family would truncate real arithmetic. Following the haskell/lisp dialect precedent (#621/#770):

  • delimiters ["--", "/*", "*/"]-- is ooRexx/Regina/NetRexx's line comment; classic z/OS REXX has no line comment and adjacent -- double-negation (5--3) is vanishingly rare — the truncation trade is documented in the profile and pinned by a strict test so any future change is deliberate;
  • REXX quote morphology in both nested-comment strippers' combined literal pass (gated like recursive_block_lisp's char literal): quotes double to escape, never backslash, strings can't span lines — the default single-quote branch is char-literal-shaped and would leave a /* inside 'ISPEXEC ...' un-masked for the peel loop to tear apart. Line-bounded branches keep an English apostrophe's worst-case cascade to its own line (the prism.py: _strip_nested_comments' unbounded single-quote shield swallows huge code spans (scala/rust/swift/haskell/scheme) #1302 discipline).

The .cmd collision (and why batch gained an internal_discriminator)

.cmd joins COLLISION_FREQUENCIES (batch + rexx both claim it; the hlasm .asm mechanism). rexx's discriminator: first token /* (OS/2's and z/OS's actual .cmd dispatch rule), or line-anchored PARSE ARG/PULL/SOURCE/VAR, ADDRESS <env>, SIGNAL/CALL ON|OFF, EXECIO, :: directives.

batch's rules dict is empty — it scores 0 in every Tier 3 lexical scan — so registering the collision without giving batch its own Tier 2 anchor made every real batch .cmd (and, by identity-proof weakening, .bat behavior too) resolve to rexx. batch's new discriminator uses batch-only line shapes (@echo off/on, SETLOCAL/ENDLOCAL, goto :label, no-space set NAME=, if exist/defined, %~dp0 modifiers, %ERRORLEVEL%); bare rem and spaced set = 1 are deliberately excluded — both are legal REXX assignments, and registry order checks batch's discriminator first, so a false batch hit on real REXX would lock the wrong language. Both directions are strict-suite-pinned, including a REXX file assigning to a variable named rem.

Golden-master diff (both environments, identical)

Exactly 6 diffs, all on-target for the collision machinery, zero language flips: three cpython .bat files upgrade Identity Proof from Single Indicator (Ext) to Absolute Consensus with Lock Tier 2→0, because batch's discriminator now corroborates the extension with content evidence. The corpus's two real .cmd files (powertoys batch wrappers) are byte-identical in the report — they must and do stay batch. The corpus contains no REXX sources (verified by extension sweep), so the rexx profile itself produces no crucible diff — the rosetta control shell is the semantic evidence instead.

Extraction routing

Mode A label slicing (_slice_by_labels, COBOL's paragraph slot): a routine runs from its label: to RETURN/EXIT (both already in assembly_returns) or the next label; routines don't nest. rexx joins _CLASS_START_NAMED_EXTRACTION_LANGS (::CLASS name, group 1). The args rule captures the PARSE ARG template so the per-function args counter reads the real parameter list — the groupless first draft whitespace-split group(0) to a constant 2 (the ada #6169-shape artifact the rosetta bias report caught; avg_func_args now reads 1, in-band).

Evidence

  • tests/extraction/languages/test_rexx_strict.py — 97 cases; the ReDoS detonation caught a real Rule-14 adjacent-quantifier defect in the drafted compound-lvalue tails (dot inside the segment class overlapping the \. separator) — fixed before landing.
  • tests/tools/language_addition_audit.py --lang rexx — all 5 invariants green.
  • Full extraction suite 8311 passed; ruff_audit --ci / mypy_audit --ci baseline-clean.
  • keyword-rosetta data/rexx/ — 97 gate assertions PASS; bias report unexplained cells 5→1 after landing (the survivor is the pre-existing bms/classes_found).
  • Strictness row (False, False, True, False); ecosystem infra (host-command automation is the language's purpose, shell's profile).

Post-merge: rosetta PR's PR-triggered check re-run; fidelity_table.py FIDELITY_PROVENANCE re-pin owed (audit --lang warning; also owed for the prior landings).

🤖 Generated with Claude Code

squid-protocol and others added 5 commits September 16, 2026 20:57
- languages/rexx.py: full baseline schema; z/OS TSO/E + SAA + ooRexx directives
- recursive_block_rexx prism dialect: nested /* */ peel without recursive_block's
  // line token (// is REXX's remainder operator); REXX quote morphology
  (doubled-quote escape, line-bounded) in both nested-comment strippers
- .cmd registered as a batch/rexx collision; batch gains an internal_discriminator
  (its empty rules dict scores 0 in Tier 3, so without one every batch .cmd
  would lose the lexical scan to rexx)
- detector: rexx in Mode A label slicing + _CLASS_START_NAMED_EXTRACTION_LANGS
- analysis_lens: strictness row (False,False,True,False) + infra ecosystem

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ision both ways, SIGNAL/EXIT/PARSE ownership pins, ReDoS detonation (caught+fixed a Rule-14 dot-run in state_mutation/branch compound tails)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Only diffs, identical in both environments: three cpython .bat files upgrade
Identity Proof from Single Indicator (Ext) to Absolute Consensus with Lock
Tier 2 -> 0, because batch's new internal_discriminator (required by the
.cmd batch/rexx collision) now corroborates the extension with content
evidence. Zero language flips; the corpus's two .cmd files (powertoys, real
batch) are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… are real (#2504)

The groupless first draft fell into detector.py's whitespace-split fallback
on group(0) ('parse arg' = 2 forever, the ada #6169 shape) -- surfaced by the
rosetta bias report as an unexplained avg_func_args cell; now reads the
comma/whitespace-split of the actual template (1 for 'parse arg n').

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

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.

Language Addition: REXX (rexx)

1 participant