Add REXX (rexx), resolving the .cmd collision with batch (#2504) - #3107
Merged
Merged
Conversation
- 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>
Contributor
This was referenced Sep 17, 2026
Detection hardening: EQU-only .asm copybooks misclassify as assembly (hlasm discriminator gap)
#3110
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds REXX (
rexx) end to end perhow_to_add_a_language.md, resolving the.cmdcollision withbatch. 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.ymlchecks the engine out atmain— a green dispatched run againstpull/<this-PR>/headis linked there).The profile (
languages/rexx.py)z/OS TSO/E REXX (SAA) plus the ooRexx directive surface (
::requires/::routine/::class/::method/::constant—.rexxfiles in the wild host ooRexx code). 35/53 baseline keys wired, 18 explicitNones (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 —\bcannot police them (pli's discipline).Issue-text deviations, both #2856/#2878-style contract-over-issue rulings, pinned in the strict suite:
ADDRESSisipc_rpc_bridges, notio(the issue's y-clause grouped it under io): the ADDRESS statement is the host-command bridge; io's data movers areEXECIO/LINEIN(/OUTTRAP(/PULL/PUSH/QUEUE.SIGNALsplits three ways:SIGNAL ON→ safety (handler install),SIGNAL OFF→ safety_bypasses (removal), bareSIGNAL label→ safety_bypasses (the GO TO unstructured-jump ruling).EXITis the high_risk_execution has no stated contract: agc reads the plant while 45 languages read plant+decoy, and the rules disagree on identifiers, references, goto and deletion #2878 termination dual (high_risk_execution + panics_and_aborts), guarded againstSIGNAL EXIT/CALL EXIT/EXIT:label lines.PARSEform:ARG→ args,PULL→ io,VAR|VALUE→ state_mutation.invocation_modelstays default (by_name):CALL name/name()/SIGNAL namereach labels by name, so the #2866 census applies — noPOSITIONAL_LANGUAGESpin.New prism dialect family:
recursive_block_rexxREXX block comments genuinely nest (
/* /* */ */— TSO/E REXX Reference), so the language needs the recursive peel — but the sharedrecursive_blockfamily 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):["--", "/*", "*/"]—--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;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
.cmdcollision (and whybatchgained an internal_discriminator).cmdjoinsCOLLISION_FREQUENCIES(batch + rexx both claim it; the hlasm.asmmechanism). rexx's discriminator: first token/*(OS/2's and z/OS's actual .cmd dispatch rule), or line-anchoredPARSE ARG/PULL/SOURCE/VAR,ADDRESS <env>,SIGNAL/CALL ON|OFF,EXECIO,::directives.batch's
rulesdict 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,.batbehavior too) resolve to rexx. batch's new discriminator uses batch-only line shapes (@echo off/on,SETLOCAL/ENDLOCAL,goto :label, no-spaceset NAME=,if exist/defined,%~dp0modifiers,%ERRORLEVEL%); bareremand spacedset = 1are 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 namedrem.Golden-master diff (both environments, identical)
Exactly 6 diffs, all on-target for the collision machinery, zero language flips: three cpython
.batfiles upgrade Identity Proof fromSingle Indicator (Ext)toAbsolute Consensuswith Lock Tier 2→0, because batch's discriminator now corroborates the extension with content evidence. The corpus's two real.cmdfiles (powertoys batch wrappers) are byte-identical in the report — they must and do staybatch. 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 itslabel:toRETURN/EXIT(both already inassembly_returns) or the next label; routines don't nest.rexxjoins_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-splitgroup(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.ruff_audit --ci/mypy_audit --cibaseline-clean.data/rexx/— 97 gate assertions PASS; bias report unexplained cells 5→1 after landing (the survivor is the pre-existingbms/classes_found).(False, False, True, False); ecosysteminfra(host-command automation is the language's purpose, shell's profile).Post-merge: rosetta PR's PR-triggered check re-run;
fidelity_table.pyFIDELITY_PROVENANCE re-pin owed (audit--langwarning; also owed for the prior landings).🤖 Generated with Claude Code