nanvm: format bigint string coercion as decimal - #1709
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
functionalscript | 0d9e478 | Commit Preview URL Branch Preview URL |
Aug 29 2026, 08:46 PM |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fb01c968f4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| fn bigint(self, v: BigInt<A>) -> Self::Result { | ||
| // TODO: we should use different algorithm for large numbers. | ||
| to_result(&format!("{v:?}")) | ||
| to_result(&v.to_string()) |
There was a problem hiding this comment.
Add the required unreleased changelog entry
This changes the user-visible behavior of bigint string coercion, but the commit adds no changelog/unreleased/<PR>.md, so the fix will be absent from the next published changelog. Add a short entry for the behavior change once the PR number is available.
AGENTS.md reference: AGENTS.md:L89-L93
Useful? React with 👍 / 👎.
| { name: 'bigint', args: [123n], expected: '123' }, | ||
| { name: 'negativeBigint', args: [-456n], expected: '-456' }, |
There was a problem hiding this comment.
Remove the obsolete known-divergence documentation
With bigint coercion now enabled, fjs/nanvm/README.md lines 84–91 still claims that NaNVM returns hexadecimal text and that these cases carry a rust exclusion; it also links to the todo file deleted by this commit. A repo-wide search finds no replacement target, so readers now see both incorrect behavior documentation and a broken link; remove or update that section in this change.
Useful? React with 👍 / 👎.
o2alexanderfedin
left a comment
There was a problem hiding this comment.
The formatting is correct: 2,044 cases, 0 mismatches, against two independent oracles — Node BigInt(...).toString() and Python int, both reconstructed from the raw hex limb dump so neither shares code with the implementation. 1,316 fit u128, 728 exceed it (up to 8 limbs). Corpus included non-normalized all-zero limb vectors, the 10^19 group boundary, 2^k ± 1 for k=0..127, 10^n ± 1 for n=0..38, and ~500 random vectors with interior zero limbs, each in both signs. No leading zeros, no lone -, digits only. -0 renders "0", matching JS.
generated.rs is genuine regeneration output, not hand-edited — I ran the generator (no diff), then appended a tamper line and re-ran; it was overwritten and git went clean. All three todo tasks are genuinely done.
Rust gates clean (fmt, test 110+1+5, clippy), npm test 3378/0, tsc clean. The --all-targets clippy failure is pre-existing — confirmed at the merge-base, same single eq_op error.
Two things to fix:
changelog/unreleased/1709.md is missing. The body's Changelog: section is correctly shaped and its bullet is right, but CONTRIBUTING is explicit that the file and the section are duplicated on purpose — "the file is what today's release process reads, the section is what a generator reading Git history would read. Neither is derived from the other, so keep them identical." The bullet can be copied verbatim.
fjs/nanvm/README.md:87 still carries a "Known divergence" section whose link points at the file this PR deletes, and whose every claim is now false — the divergence is gone and neither case carries a rust reason any more. That README's own text says the per-case arrangement exists because "a table of them goes stale the moment someone fixes one"; this is that. No link checker in CI will catch it. It was the only remaining reference.
Not verified: only the generator half of npm run ci-update was run (deno/bun unavailable here, same limitation you reported); the tamper test covers the one file this change regenerates.
o2alexanderfedin
left a comment
There was a problem hiding this comment.
Delta is merges of main only — git log --oneline --no-merges fb01c968f..da2e90863 --not origin/main is empty, so nothing branch-authored landed. Main moved a lot underneath (#1699, #1708, #1710-#1715, #1718), so I re-ran the gates at the merged head: npm test 3400/0, tsc --noEmit exit 0, cargo fmt -- --check exit 0, cargo test 110 + 1 + 5 doctests all passing, plain cargo clippy clean. The --all-targets eq_op failure at nanvm-lib/src/vm/mod.rs:40 is still pre-existing — identical on origin/main, and this PR doesn't touch that file.
Both of my findings are still open.
changelog/unreleased/1709.md is still missing. The body's section is correctly shaped and last before the Codex trailer, and its bullet is right — this is a behaviour change, so an entry is owed. CONTRIBUTING is explicit that the file and the section duplicate each other on purpose and must be kept identical; creating the file with that exact bullet closes it.
fjs/nanvm/README.md's "Known divergence" section is still there, now at lines 84-91, and it is still the only remaining reference to the file this PR deletes. All three of its claims are false at head: the link target nanvm-lib/todo/bigint-decimal-string-coercion.md no longer exists (dead link — grep across fjs, nanvm-lib, todo and changelog finds only this line); the "0x7Bn" divergence is what the PR fixes; and "the two affected cases carry a rust reason" is false because the PR deletes both — fjs/nanvm/module.f.mjs drops hexadecimalBigint and both rust: fields, and generated.rs:188-193 uncomments both check::<A> calls. The section should go with the file it documents.
o2alexanderfedin
left a comment
There was a problem hiding this comment.
Measured at 975745950. The delta since my last review is a merge of main only — git log --oneline --no-merges 975745950 --not origin/main is still just fb01c968f — so nothing branch-authored landed and both earlier findings stand.
Gates are green and match main: cargo build 0, cargo test 0 (110 + 1 + 5 doctests, 0 failed), cargo fmt --check 0, cargo clippy 0, npm test 3447/0. The behaviour is right: I ran the new Display on 14 bigints via BigInt::<Naive>::normalize_new and diffed against node's String(BigInt(...)) for the same limb values — 14/14 exact, including 0, -0 → "0", 2^64, 2^128 and 2^128+1 (internal zero limb), -2^128-1, 10^19, 10^19+1 and a 4-limb negative. generated.rs matches a fresh npm run ci-update with an empty git diff, so no hand edits. Deleting nanvm-lib/todo/bigint-decimal-string-coercion.md is right — it described exactly this work.
New finding: the zero-padding of non-leading decimal groups is not pinned. Mutating {group:019} → {group} leaves cargo test at exit 0, 110/1/5 all passing — SURVIVED. It is a genuine defect, not a harmless one: under that mutant 10^19 prints "10". The control mutant, deleting f.write_char('-')?, is KILLED (exit 101, 1 failed), so the harness does bite — the gap is that every value in bigint_display_format (2^64, u128::MAX) happens to have full 19-digit non-leading groups. One case whose second group has leading zeros closes it, e.g. normalize_new(Positive, [10_000_000_000_000_000_000]) → "10000000000000000000".
Still open from before:
changelog/unreleased/1709.mdis missing. The body'sChangelog:section is present and correctly shaped, so only the file is owed.fjs/nanvm/README.md:84-91"Known divergence" outlives what it documents: its link target is the todo file this PR deletes (dead link), the"0x7Bn"claim is what the PR fixes, and "the two affected cases carry arustreason" is now false — bothrust:fields are gone frommodule.f.mjsand bothcheck::<A>calls are uncommented ingenerated.rs. Delete the section.
Not ready to leave draft yet: behaviour is correct, but the padding is untested and the two chores above have not moved.
o2alexanderfedin
left a comment
There was a problem hiding this comment.
Re-measured at 61bddaab5. The delta since 975745950 is a merge of main and nothing else — git log --oneline --no-merges 61bddaab5 --not origin/main is still the single commit fb01c968f, and git diff --stat 975745950 61bddaab5 -- fjs/nanvm nanvm-lib changelog/unreleased/1709.md is empty. So all three findings stand unchanged; I re-ran the padding mutant rather than assuming, and {group:019} → {group} at nanvm-lib/src/vm/bigint/display.rs:37 still leaves cargo test at exit 0 with 110 + 1 + 5 passing — SURVIVED.
One new data point: dropping .rev() from for group in groups.iter().rev() is KILLED (exit 101, bigint_display_format panics at main.rs:126). Group ordering is pinned; only the padding is not.
Gates remain green on both sides — cargo test 110+1+5, build, fmt --check, clippy all exit 0, npm test 3465/0.
Still not ready to leave draft: the padding case, changelog/unreleased/1709.md, and the fjs/nanvm/README.md:84-91 removal.
|
You have reached your Codex usage limits for security reviews. Please try again later. |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Motivation
Debugrepresentation for bigints when coercing to strings, which diverges from JavaScript's decimalToStringbehavior.fjs/nanvm/module.f.mjscommented out bigint string cases because the VM output did not match the JS expectation.String(...)coercion and enable the shared positive/negative bigint test cases.Description
Displayimplementation forBigInt<A>that formats decimal text by repeatedly dividing limb words by10^19groups (nanvm-lib/src/vm/bigint/display.rs).DisplayinStringcoercion by replacing theDebugformatting withto_string()inStringCoercion::bigint(nanvm-lib/src/vm/string_coercion.rs).fjs/nanvm/module.f.mjsand regenerate the Rust test corpus (nanvm-lib/tests/test/generated.rs).to_string()across limb and sign boundaries innanvm-lib/tests/test/main.rs, and delete the resolved issue filenanvm-lib/todo/bigint-decimal-string-coercion.md.Testing
cargo testand all Rust unit, integration and doctests passed (110 unit tests + 1 integration test + 5 doctests; full suite passed).npx tscandnode ./fjs/module.mjs test, which completed successfully (3,378 JS/FunctionalScript tests passed).cargo clippyandcargo fmt -- --checkwith no issues.npm run ci-update/npm run update; generation succeeded, but the fulldenoinstall step could not run in this environment (deno: not found) — this does not affect the compiled/tested outcomes shown above.Changelog:
nanvm: bigint string coercion now produces JavaScript-compatible decimal textCodex Task