Repository navigation
det: an unsigned binary ADD / SUBTRACT wraps as cobc's native arithmetic does; lifted COMP-5 under TRUNC(STD) (#4684) - #4689
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>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
…4655) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… arithmetic does (#4684) cobc 3.1.2 compiles ADD / SUBTRACT ... TO / FROM an unsigned binary item of no decimal places, with one operand that fits a C int and no ROUNDED or store option, to native integer arithmetic: a result below zero wraps modulo 2 ** bits (1 - 3 is 65534) where libcob's decimal store keeps the absolute value. COMP-5 always, COMP / COMP-4 / BINARY under TRUNC(BIN) only. gen.native_add picks the statements as cb_build_add / cb_fits_int do; Cobol.storeNative / binaryNative store them. An unsigned doubleword is no longer lifted to a long (it holds up to 2 ** 64 - 1). Every other binary store measured (about 4,000: COMP / COMP-4 / BINARY / COMP-5, signed and unsigned, halfword to doubleword, scaled, COMPUTE / ADD / SUBTRACT / MULTIPLY / DIVIDE / GIVING / MOVE, both TRUNC settings) already matched on this base; the issue's own case was fixed by ARITHMETIC-OSVS (#4287). oracle_assumptions C4 records the measurement, IBM's absolute value, and the one MOVE cobc stores unlike IBM under TRUNC(STD). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…4684) Cobol.binary built its scratch item as COMP, so a typed (lifted) COMP-5 receiver lost its high-order digits under TRUNC(STD): COMPUTE N = 12345 into S9(4) COMP-5 gave 2345, cobc -fbinary-truncate 12345. The store of a lifted COMP-5 item now names it (Cobol.binary's comp5 overload). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Owner decision (2026-10-08): follow IBM, not GnuCOBOL. Unsigned binary ADD/SUBTRACT stores the absolute value as IBM documents (1 - 3 = 2), not libcob's native wrap (65534). Make the ORACLE side z/OS-like too: first look for a cobc option/config that disables the native binary add/subtract path (so cobc yields IBM's result); if none exists, record it in oracle_assumptions C4 as a declared oracle-vs-IBM difference the comparator expects (IBM value on the port side), never by loosening the proof. Policy: the oracle should be as z/OS-like as possible so it's a better comparator. 🤖 Generated with Claude Code |
|
Owner decision, final (2026-10-08; supersedes my previous comment's wording). Policy: IBM is the reference; GnuCOBOL is the instrument. IBM documents the absolute value for an unsigned binary receiver, so the det port stores |result| (1 - 3 = 2) under the estate's TRUNC option. On the oracle side, first look for a cobc option or config that turns off the native binary add/subtract wrap. If none exists, record it in oracle_assumptions C4 as a declared oracle-vs-IBM difference the comparator expects. Never loosen the proof. To be calibrated later against real Enterprise COBOL (#4702). 🤖 Generated with Claude Code |
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
…value; cobc's native wrap is declared (#4684) Owner policy (2026-10-08, #4702): IBM is the reference, GnuCOBOL the instrument. IBM stores the absolute value in an unsigned receiver (6.4 Language Reference, "Elementary moves"; the arithmetic store: confirm), truncated per TRUNC (6.4 Programming Guide, "TRUNC"). Cobol.storeNative / binaryNative now store that (1 - 3 = 2); gen.native_add still marks where cobc compiles native arithmetic, and a COMP-5 statement with a lone NOT ON SIZE ERROR keeps IBM's size check. No cobc 3.1.2 option or config entry turns cobc's native wrap off, so oracle_assumptions C4 declares it as an oracle-vs-IBM difference: test_det_binary_store expects cobc's wrap on the oracle and IBM's value on the port on exactly the named lines (DECLARED_C4), equality on every other line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D
Fixes #4684
Reworked per the owner decision on this PR (2026-10-08) and the policy in #4702: IBM is the reference; GnuCOBOL is the instrument. Merged origin/main (#4654 and #4677 are in; main's side taken for their pre-squash hunks).
The decision: an unsigned binary ADD / SUBTRACT stores IBM's absolute value
Cobol.storeNative/binaryNativenow store IBM's value: 1 − 3 into an unsignedPIC 9(4) COMPis 2, not libcob's native wrap of 65534. They arestore/binary.gen.native_add/fits_intstill mark the statements cobc compiles to native integer arithmetic (cb_build_optim_add/_sub), so the generated Java names where the oracle departs.storeChecked), as before det: an unsigned binary ADD / SUBTRACT wraps as cobc's native arithmetic does; lifted COMP-5 under TRUNC(STD) (#4684) #4689.long. Under TRUNC(BIN) it holds up to 2 ** 64 − 1, per IBM's doubleword boundary.Oracle side: no cobc option, so the wrap is a declared difference
gitgalaxy-gnucobol:3image (cobc 3.1.2-std=ibm):-O0,-O2,-fbinary-size=1-2-4-8/1--8,-fbinary-byteorder=native,-fnotrunc,-fno-constant-folding,-fno-arithmetic-osvs,-std=ibm-strict,-std=mvs,-debug,-fec=EC-SIZE/-TRUNCATION/-OVERFLOW. None turns the native path off. No/etc/gnucobol/*.confkey does either.-fbinary-truncatekeeps COMP / COMP-4 / BINARY off the native path, but that flag is TRUNC(STD) itself. Soequivalence_common.COBC_OPTIONSis unchanged.docs/language_status/oracle_assumptions.md) is rewritten with the policy wording and the IBM references. It records the native wrap as a declared oracle-vs-IBM difference: MATCHED (det runtime = IBM), DIFFERS (oracle vs IBM, declared). No proven case reaches it.test_det_binary_store.py's end-to-end test (TRUNC(BIN) and TRUNC(STD), bytes and typed) asserts the oracle's measured values, cobc's wrap included.DECLARED_C4lines, where the port shows IBM's value and the oracle does not.test_det_programs._cobolkeeps main'srawand gainsflags._java_runkeepsrawand gainstrunc_std.Verification
test_det_binary_store.py+test_det_programs.py+test_det_osvs.py+test_det_size_error.pywith EQUIVALENCE_E2E=1 (JDK 17): 171 passed, no skips.det_port.py checkvs origin/main: all 79 ports change inCobol.java, which has new methods. Three services change fromstore/binarytostoreNative/binaryNative, the same semantics: cbsa-delacc, cbsa-inqacc and mortgage-nbrvl.proof_sweep.py --det-only(all 79 cases, Db2 local, before the second main merge): 75 PROVED, "sweep: as expected". After merging main again (equivalence: non-digit zoned data as MOVE sender, operand, comparand; the oracle's sign rewrite (#4662) #4693, det runtime: browse/DELETE RESP2 as IBM states it; signon model port LOW-VALUES (#4657, #4659) #4661, test: batch Sysout DISPLAY of high bytes vs cobc, latin-1 and non-latin-1 (#4697) #4699, ci: evidence report refreshed by bot on main, advisory in PRs, release-gated (#4703) #4705): the same three services change; cbsa-delacc, cbsa-inqacc, mortgage-nbrvl, carddemo-signon, carddemo-billpay and genapp-lgicdb01 re-proven: PROVED. The 4 det e2e files plus test_det_nondigit_zoned: 193 passed.evidence_report.py --checkclean; evidence pytests 71 passed.pr_gates.py --fast5/5;--ratchets7/7.Part A / Part B (unchanged from the first version)
SUBTRACT 3 D0 P0 FROM Q8) was det runtime: truncate arithmetic intermediates as cobc's ARITHMETIC-OSVS does (#4287) #4654's OSVS intermediate: it matches.🤖 Generated with Claude Code
https://claude.ai/code/session_01MQNoe4wPJgr7dbUvs3DG6D