Repository navigation
det: a numeric-edited item compared with a number is a text comparison (#4665) - #4668
Merged
Merged
Conversation
#4665) A numeric-edited item is not numeric: against a number it is compared as characters (IBM "Comparison of numeric and alphanumeric operands"; GnuCOBOL likewise), not de-edited and compared by value. The generator passes a numeric literal against a nonnumeric item as written (expr.NumLit keeps the spelling: leading zeros, point), the runtime compares a numeric item against an elementary nonnumeric one as its digits (sign dropped). Where IBM and the oracle differ -- a signed literal, a SIGN SEPARATE or P-scaled item, an arithmetic expression -- the comparison is a hole by name (register C13). Fixes #4665 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 8, 2026
Closed
Contributor
This was referenced Oct 8, 2026
…et/layout.py) layout -> expr -> det.cics -> layout: expr's DFHRESP(...) now takes the table from gitgalaxy.standards.cics.resp, the very object det.cics re-exports, so expr no longer imports det.cics. det_port check vs 431ceb7: 68/68 ports unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
Main's #4653 Lit.digits and #4665's NumLit both pass a numeric literal compared with a nonnumeric item as its characters. Measured against cobc 3.1.2 -std=ibm (IF and EVALUATE): unsigned integer literals as written agree on both; a signed literal is compared with its sign character ('12' is not +12/-12, '+12' is +12, '-12' is -12), which main's sign-stripping digits got wrong and IBM differs on (C13: refused); a decimal literal against an alphanumeric item is its digits as written ('012' = 0.12, which main got wrong). Kept NumLit/literal_text as the one path and dropped Lit.digits. New measurement: a numeric-edited item compared for equality with a literal of more decimal places than its own is decided by cobc when it compiles (ZZ9 holding 125: not = 12.5, NOT = 12.5, yet neither < nor >), so that shape is refused by name too (C13); IBM rejects the non-integer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
…rds.cics.resp) det/expr.py imports DFHRESP from the RESP table directly (the CodeQL import-cycle fix, same as #4654); pin it in test_cics_spec.IMPORTERS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
expr.py: keep this PR's NumLit (a numeric literal keeps its spelling) and main's module-level DFHRESP import; #4654's Lit.text (the literal as written, for det/osvs.py's literal identity) becomes a property read from the NumLit's spelling instead of a second copy of it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
…value, text) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
squid-protocol
marked this pull request as ready for review
October 8, 2026 19:44
squid-protocol
added a commit
that referenced
this pull request
Oct 8, 2026
oracle_assumptions.md: both register entries kept, C13 (#4668) then C14 (this PR), in the table and the sections. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
squid-protocol
added a commit
that referenced
this pull request
Oct 8, 2026
…/4681-condition-holes Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
squid-protocol
added a commit
that referenced
this pull request
Oct 8, 2026
…/4675-4676-size-error Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
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.
Fixes #4665 (part of #4270).
Decision
A numeric-edited item belongs to the alphanumeric class: compared with a number it is a nonnumeric (text) comparison, the numeric operand taken as its characters (IBM Enterprise COBOL 6.4 LR, "Comparison of numeric and alphanumeric operands"; GnuCOBOL 3.1.2
-std=ibmmeasured to do the same). The det runtime de-edited it and compared by value. Where IBM and the oracle disagree the comparison is refused by name; recorded as register entry C13 inoracle_assumptions.md.Oracle facts measured (cobc probes, 2026-10-07):
E PIC ZZZ,ZZ9.99= 1500 vs1499.99/1499: LE / LE (issue repro).0012≠12;1499.99→149999;0.12→012.S9(4) COMP-312 →0012); sign dropped.+1234compares its+), a SIGN SEPARATE item (its sign char), a P-scaled item (stored digits), an arithmetic expression vs a nonnumeric item (oracle text of its own making). A non-integer literal or item, which IBM does not allow, is modelled as the oracle's digits.Changes
det/expr.py:NumLit(Decimal)keeps a numeric literal's spelling, including unary+.det/layout.py: 88VALUEnumbers areNumLit(one line).det/gen.py— shared functions touched:cmp(numeric literal vs nonnumeric item emitsCobol.compare(f, "<digits as written>", CS); arithmetic expression vs nonnumeric item refused),vcmp(88 numeric value on a nonnumeric item, same),rel_lifted(a lifted text item vs a numeric item that is not unsigned zoned goes through the bytes path). New helpers:literal_text,digits_as_text.cobolrt/Cobol.java— shared functions touched:compare(Field, Field, Charset, Collating)(new privateoperand/digitsText: a numeric item vs an elementary nonnumeric one compared as its digits) and the comment and condition ofcompare(Field, BigDecimal, …)(NUM_EDITEDgoes to the text branch). Not touched:move,num,edit,nonDigitToBinary,align(see det runtime: truncate arithmetic intermediates as cobc's ARITHMETIC-OSVS does (#4287) #4654 / equivalence: model the oracle's MOVE of a non-digit zoned item to a binary item (#4652) #4663 / det translator: model DECIMAL-POINT IS COMMA; document the refusals #4462 keeps (#4462) #4666).Tests / sweeps
test_det_programs.py::EDCMP, end to end against cobc in bytes / typed / groups modes: the repro plus edited vs literal (incl.0012,1499.99), vs zoned / signed zoned / COMP-3 / COMP /9V9items, edited vs edited,ZERO, EVALUATE subject + THRU, 88s on an edited item, alphanumeric vs literal/item. Fails on origin/main (all 3 modes), passes here.test_a_numeric_operand_compared_as_text_refuses_by_name_…: 7 refusals by name (C13). Fails on main, passes here.tests/cobol_mainframe/test_det_*.pywithEQUIVALENCE_E2E=1: 528 passed, 0 skipped.det_port.py check --base-ref origin/main: all 68 ports change inCobol.java(the runtime is shipped in every port). Service code changes only incarddemo-cotrtlic(alphanumeric vs0:D0→"0", same bytes). A static scan of every port found noCobol.compare(Field, Field)that pairs a signed/packed/binary item with a text item, so the new runtime branch is not reached by any port.proof_sweep.py --det-only --cases carddemo-cotrtlic,carddemo-intcalc: 2/2 proven, "sweep: as expected".pr_gates.py --fast: 5/5 pass.pr_gates.py --ratchets: 7 pass, 0 fail, 0 skipped.Follow-ups (not in this PR)
PIC SVPP99 COMP-3crashes the translator (ValueError: non-hexadecimal numberinlayout.encode_number) instead of refusing by name.MOVE 1200 TOaPIC 99PPitem throws at run time in the det runtime (Cobol.store).🤖 Generated with Claude Code