Repository navigation
det runtime: truncate arithmetic intermediates as cobc's ARITHMETIC-OSVS does (#4287) - #4654
Merged
Merged
Conversation
…SVS does (#4287) The det translator replays cobc -std=ibm's compile-time ARITHMETIC-OSVS decision (det/osvs.py, from GnuCOBOL 3.1.2 typeck.c / tree.c): dmax from receivers and cb_walk_cond, the expr_decp stack with its pushes, pending aligns flushed on the next load, constant folding, conditions built right to left, the state an EVALUATE leaves to its sentence. It emits Cobol.align (libcob's cob_decimal_align, its downward shift included) where cobc emits cob_decimal_align, and a literal on the right of an operation as a Cobol.Dc (libcob's decimal constant, whose scale its uses change). Cobol.divide keeps cob_decimal_div's places and Cobol.power cob_decimal_pow's trimming. Register C2 rewritten: the det runtime matches the oracle; the oracle's departures from IBM's rule are listed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 8, 2026
Merged
Merged
expr imported det.cics (for DFHRESP) and det.cvda lazily, and det.cics imported det.gen, which imports det.osvs, which imports expr. expr now imports DFHRESP from gitgalaxy.standards.cics.resp (its home) and CVDA from det.cvda (no imports) at module level, so expr no longer reaches gen. Also one import form for test_det_programs in test_det_osvs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
# Conflicts: # gitgalaxy/tools/cobol_to_java/det/expr.py
…rds.cics.resp) The CodeQL import-cycle fix made det/expr.py import DFHRESP from the RESP table directly; 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
squid-protocol
added a commit
that referenced
this pull request
Oct 8, 2026
…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
Conflict in Gen's COMPUTE: keep #4685's p_scaled_expr refusal (first) and this PR's ARITHMETIC-OSVS plan around the expression. 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 18:50
squid-protocol
added a commit
that referenced
this pull request
Oct 8, 2026
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
squid-protocol
added a commit
that referenced
this pull request
Oct 8, 2026
#4665) (#4668) * det: a numeric-edited item compared with a number is a text comparison (#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> * chore: clear CodeQL py/cyclic-import (gitgalaxy/tools/cobol_to_java/det/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 * test: det/expr.py is a listed CICS spec consumer (DFHRESP from standards.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 * test_det_osvs: a numeric literal is a NumLit (its spelling), not Lit(value, text) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
squid-protocol
added a commit
that referenced
this pull request
Oct 8, 2026
Conflicts in oracle_assumptions.md, Cobol.java and gen.py came from #4654's pre-squash commits: main's side taken, then this PR's own changes (6e1de82..f6da8e4) re-applied on top. 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) (#4683) * det runtime: truncate arithmetic intermediates as cobc's ARITHMETIC-OSVS does (#4287) The det translator replays cobc -std=ibm's compile-time ARITHMETIC-OSVS decision (det/osvs.py, from GnuCOBOL 3.1.2 typeck.c / tree.c): dmax from receivers and cb_walk_cond, the expr_decp stack with its pushes, pending aligns flushed on the next load, constant folding, conditions built right to left, the state an EVALUATE leaves to its sentence. It emits Cobol.align (libcob's cob_decimal_align, its downward shift included) where cobc emits cob_decimal_align, and a literal on the right of an operation as a Cobol.Dc (libcob's decimal constant, whose scale its uses change). Cobol.divide keeps cob_decimal_div's places and Cobol.power cob_decimal_pow's trimming. Register C2 rewritten: the det runtime matches the oracle; the oracle's departures from IBM's rule are listed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * oracle_assumptions C2: the differential run's size as measured (#4287) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * det runtime: a zero divisor is libcob's NaN, receivers unchanged (#4655) The oracle (GnuCOBOL 3.1.2 -std=ibm) leaves every receiver unchanged on a zero divisor, with or without ON SIZE ERROR; the det port threw ArithmeticException. Cobol.divide now returns libcob's NaN (scale -32768) and raises the statement's size error; add/subtract/multiply/negate/power carry it where the translator sees a division or exponent below; store/storeChecked leave the receiver (lifted receivers guarded with isNan); Cobol.align truncates a NaN to 0 as libcob does. A division in a function argument is 0 (cob_intr_binop); FUNCTION MOD/REM by zero are 0. 0 ** 0 raises the size error; a non-finite exponent is NaN. Statements with ON SIZE ERROR clear and read the size-error state. DIVIDE REMAINDER now uses the quotient truncated to the receiver's places (cob_div_quotient), not the stored quotient. Register entry oracle_assumptions C14 (IBM: undefined / S0CB on z/OS). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * det gen: a distinct name for the lifted DIVIDE INTO quotient (mypy) (#4655) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * det parse: the abbreviated 'OR NOT = x' / 'AND NOT = x' relation parses (#4681) Holes 1 and 2 (D0 + 1 > Q3, S3 NOT < 3 + B0 * - D0) already agree with cobc on this base (#4654/#4677); an end-to-end test pins them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: break det osvs/expr import cycle (CodeQL) expr imported det.cics (for DFHRESP) and det.cvda lazily, and det.cics imported det.gen, which imports det.osvs, which imports expr. expr now imports DFHRESP from gitgalaxy.standards.cics.resp (its home) and CVDA from det.cvda (no imports) at module level, so expr no longer reaches gen. Also one import form for test_det_programs in test_det_osvs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D * chore: one import form for test_det_programs in test_det_size_error (CodeQL) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
squid-protocol
added a commit
that referenced
this pull request
Oct 8, 2026
Takes main's side of #4677 / #4654's pre-squash hunks and keeps #4689's own changes. 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.
Closes #4287. Part of #4270.
What
cobc -std=ibmturns onarithmetic-osvs. cobc then works out at compile time where to truncate an arithmetic intermediate, and to how many decimal places, and emitscob_decimal_alignthere. The det runtime computed every intermediate exactly. It now truncates at the same points:det/osvs.py(new) replays cobc's decision from the GnuCOBOL 3.1.2 sources (typeck.c: build_decimal_assign, cb_build_cond, cb_walk_cond, decimal_expand / decimal_compute / decimal_align;tree.c: constant folding and literal-pair / field-literal relations decided at compile time). It covers:expr_decpstack and what pushes onto it;gen.pyplans COMPUTE, ADD / SUBTRACT / MULTIPLY / DIVIDE with an expression, and the relations of IF, PERFORM UNTIL, SEARCH WHEN and EVALUATE. It emitsCobol.align(v, n). A literal on the right of an operation becomes aCobol.Dc, libcob's decimal constant. Unary minus becomes0 - x.Cobol.java:alignis libcob'scob_decimal_align, including its shift in the wrong direction: with fewer places than the target, the value loses that many low-order digits, so 579 aligned to 2 places becomes 500.Dcreproduces libcob changing a constant's scale in place.dividekeepscob_decimal_div's 38 + max(d1-d2, 0) places. It used to keep 2 fewer when the divisor had more places.powertrims trailing zeros the waycob_decimal_powdoes.Register C2 is rewritten. The det runtime now MATCHES the oracle. The entry lists where GnuCOBOL's ARITHMETIC-OSVS departs from IBM's Appendix A rule:
It also lists what is not replayed.
det_port_design.mdis updated to match.Default chosen (no owner decision needed): the det port models the oracle (cobc 3.1.2
-std=ibm), including its departures from IBM's rule, so a proof can see them. The issue's IBM ARITH(COMPAT) reading matches the oracle on the reproducer. The 30-digit cap is still not modelled on either side, as before.Refused by name (new holes, none in any case): a negative literal exponent (libcob overwrites the constant), and an EVALUATE whose last WHEN leaves dirty state to its own conditions.
Evidence
tests/cobol_mainframe/test_det_osvs.py: 9 planning tests (no Docker) and an end-to-end program run through cobc and the det port in bytes and typed modes. It covers the issue's register-C2 reproducer (COMPUTE R = A / B * C→ 099.00), a literal on the right, a binary sum, unary minus, a product with a literal, an IF, a constant scale change, and the EVALUATE leak. It fails on origin/main (both modes) and passes here.**, ROUNDED, multiple receivers, sentences and compile-time-constant relations. Every output equals the oracle's. The same programs on origin/main differ on about 1 line in 6.EQUIVALENCE_E2E=1 pytest test_det_programs.py test_det_hfp.py test_numproc.py test_cobolrt.py test_det_funcs.py: 464 passed, 0 skipped.det_port.py check --base-ref origin/main: every port changes, becauseCobol.javachanged. 12 services change. The only align emitted in any port is POSTTRAN'sCREDIT - DEBITto 2 places, which does not change the value. The other service changes areCobol.Dcconstants.proof_sweep.py --det-only --caseson those 12): 10/12 proven, matching the baseline ("sweep: as expected"). The 2 not proven are carddemo-intcalc-generated and mortgage-mpmt, both already listed indet_sweep_baseline.json. Coverage numbers equal the ledger (det_coverage_ledger.py check: as expected). CI runs the full sweep.pr_gates.py --fast: 5/5 pass.--ratchets: 7/7 pass (cics-spec, ports, port-surface, estate, fact-crosscheck, completeness, ground-truth; 0 skipped). A first run without the JDK 17 env failedportsfalsely (JDK 21);ports_compile_check.pywith the env: all 45 committed ports compile.Follow-ups filed
🤖 Generated with Claude Code