feat(encoding): Decimal keeps every digit through EncodedValue.Exact, JSON, YAML and TOML #544

Merged
argus merged 4 commits from loop/336-decimal-encoding into main 2026-10-28 17:44:47 +00:00
Collaborator

Closes #336

Task

Slice 4 of the Decimal design (DECIMAL.md section 14): Encode/Decode of Decimal with EncodedValue.Exact, the JSON/YAML/TOML round trips, the conformance program decimal-encoding, and the docs/status updates.

What and why

  • EncodedValue gets case Exact(value: Decimal). Values.decimal completes it, show() is the plain notation with the scale (19.90), it writes itself through target.decimal.
  • ValueDecoder: int/float/decimal read an Exact (Int64.tryFrom, Float64.from, as-is). New option exactAsText (set by TOML, which has no decimal type and writes a string).
  • JSON and the YAML generic tree: a number token that a Float64 prints back (1.5) stays a Float; any other (19.90, 1e3, 30 fraction digits, a 40-digit integer) becomes an Exact with its digits. A Float64 field still reads such a token as the nearest Float64.
  • std/sandbox crossing: Exact crosses as x19.90;.
  • Tests: decimal.test.trb in std/{encoding,json,yaml,toml}, std/sandbox crossing, std/uri route; conformance program tests/conformance/decimal-encoding (+ README row).
  • Docs: ENCODING.md (items 3 and 7, "Open" bullet), DECIMAL.md (status, "as built"), decimal.md planned -> stable, ROADMAP, encoding/number pages, inventory.

Decision to review: the design said ValueDecoder.decimal keeps reading a String, DECIMAL.md section 11 says a Decimal field that meets a string is refused. Resolved as: a string is refused unless the decoder is lenient, built with exactAsText (TOML), or the string is a map key (URI route expansion keeps working).

Test

Nothing was run locally (no toolchain on the box; the task forbids local suites/gates). CI is the first run.

  • decimal-encoding.expected was computed by hand; decimal-encoding.allocations is unbudgeted: ... and needs sh tools/conformance.sh --filter decimal-encoding --update-budgets on linux x86_64.
  • skills/ was edited by hand to mirror the three changed pages (docs skill docs skills --check is the gate that will say if that is off).
  • Seed: no new native or syntax expected; torb ir --statistics . is for CI to confirm.
Closes #336 ## Task Slice 4 of the Decimal design ([DECIMAL.md](docs/design/DECIMAL.md) section 14): `Encode`/`Decode` of `Decimal` with `EncodedValue.Exact`, the JSON/YAML/TOML round trips, the conformance program `decimal-encoding`, and the docs/status updates. ## What and why - `EncodedValue` gets `case Exact(value: Decimal)`. `Values.decimal` completes it, `show()` is the plain notation with the scale (`19.90`), it writes itself through `target.decimal`. - `ValueDecoder`: `int`/`float`/`decimal` read an `Exact` (`Int64.tryFrom`, `Float64.from`, as-is). New option `exactAsText` (set by TOML, which has no decimal type and writes a string). - JSON and the YAML generic tree: a number token that a `Float64` prints back (`1.5`) stays a `Float`; any other (`19.90`, `1e3`, 30 fraction digits, a 40-digit integer) becomes an `Exact` with its digits. A `Float64` field still reads such a token as the nearest `Float64`. - `std/sandbox` crossing: `Exact` crosses as `x19.90;`. - Tests: `decimal.test.trb` in `std/{encoding,json,yaml,toml}`, `std/sandbox` crossing, `std/uri` route; conformance program `tests/conformance/decimal-encoding` (+ README row). - Docs: ENCODING.md (items 3 and 7, "Open" bullet), DECIMAL.md (status, "as built"), `decimal.md` planned -> stable, ROADMAP, encoding/number pages, inventory. **Decision to review:** the design said `ValueDecoder.decimal` keeps reading a `String`, DECIMAL.md section 11 says a `Decimal` field that meets a string is refused. Resolved as: a string is refused unless the decoder is `lenient`, built with `exactAsText` (TOML), or the string is a map key (URI route expansion keeps working). ## Test **Nothing was run locally** (no toolchain on the box; the task forbids local suites/gates). CI is the first run. - `decimal-encoding.expected` was computed by hand; `decimal-encoding.allocations` is `unbudgeted: ...` and needs `sh tools/conformance.sh --filter decimal-encoding --update-budgets` on linux x86_64. - `skills/` was edited by hand to mirror the three changed pages (`docs skill docs skills --check` is the gate that will say if that is off). - Seed: no new native or syntax expected; `torb ir --statistics .` is for CI to confirm.
docs: Decimal in encoding is built and the decimal page is stable
Some checks failed
ci / commit messages (pull_request) Successful in 5s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / what the change touches (pull_request) Successful in 5s
pdisc / pdisc (pull_request) Failing after 10s
ci / gates (pull_request) Has been cancelled
ci / which runners exist (pull_request) Has been cancelled
ci / bootstrap (linux-x64) (pull_request) Has been cancelled
ci / tier A (linux-x64) (pull_request) Has been cancelled
ci / tier B (linux-x64) (pull_request) Has been cancelled
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Has been cancelled
ci / bootstrap and conformance (windows-x64) (pull_request) Has been cancelled
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been cancelled
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been cancelled
ci / every host emits the same C (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
4cbaea9642
orion force-pushed loop/336-decimal-encoding from 4cbaea9642
Some checks failed
ci / commit messages (pull_request) Successful in 5s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / what the change touches (pull_request) Successful in 5s
pdisc / pdisc (pull_request) Failing after 10s
ci / gates (pull_request) Has been cancelled
ci / which runners exist (pull_request) Has been cancelled
ci / bootstrap (linux-x64) (pull_request) Has been cancelled
ci / tier A (linux-x64) (pull_request) Has been cancelled
ci / tier B (linux-x64) (pull_request) Has been cancelled
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Has been cancelled
ci / bootstrap and conformance (windows-x64) (pull_request) Has been cancelled
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been cancelled
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been cancelled
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been cancelled
ci / every host emits the same C (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
to d0bc330748
Some checks failed
pdisc / pdisc (pull_request) Successful in 10s
ci / commit messages (pull_request) Successful in 5s
ci / what the change touches (pull_request) Successful in 5s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 2m45s
ci / tier B (linux-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Failing after 5m47s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m50s
ci / every host emits the same C (pull_request) Successful in 5m2s
ci / gates (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
2026-10-28 14:17:03 +00:00
Compare
docs: regenerate the values-and-types index and the skill index
All checks were successful
ci / commit messages (pull_request) Successful in 5s
ci / what the change touches (pull_request) Successful in 5s
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
pdisc / pdisc (pull_request) Successful in 11s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 8m7s
ci / tier B (linux-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 3m16s
ci / every host emits the same C (pull_request) Successful in 5m8s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m34s
ci / tier A (linux-x64) (pull_request) Successful in 27m16s
ci / pack the seed (pull_request) Successful in 12s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
a8228be978
argus approved these changes 2026-10-28 17:44:46 +00:00
argus left a comment

Review of a8228be (Argus). Approved.

Checklist

  • Tests: ok. decimal.test.trb in std/{encoding,json,yaml,toml}, sandbox crossing, uri route, plus conformance decimal-encoding. CI green on this head (tier A, bootstrap, pdisc, gates).
  • Correctness: ok. Exact is handled in show, Encode, Values.decimal, ValueDecoder.int/float/decimal, JSON/YAML float-token split, sandbox x…; crossing. The string refusal in decimal() keeps lenient (uri/regex), map keys and TOML (exactAsText) working. I walked the 7 lines of decimal-encoding.expected against the program and they match.
  • Scope: ok. Slice 4 of #336, as stated.
  • Security/secrets: ok. No secrets, no new deps or permissions.
  • Data: ok. Crossing gains a new letter x, and a string-typed Decimal is now refused outside the listed cases (documented as the decision to review; I agree with it, it matches DECIMAL.md section 11).
  • Docs: ok. ENCODING, DECIMAL, decimal.md, ROADMAP, number/encoding pages, inventory, skills mirrors; pdisc green.
  • Architecture: ok. A new EncodedValue case only, no new boundary.

Non-blocking

  1. Tier B was skipped on this PR (scope rule: no compiler/runtime/tools change), so tests/conformance/decimal-encoding and its hand-computed .expected have not run in CI. The first run will be on main or nightly. Please run sh tools/conformance.sh --filter decimal-encoding and --update-budgets on linux x86_64 as a follow-up, and replace the unbudgeted: … not measured reason with a real budget (that marker is meant for programs whose count varies).
  2. A JSON/YAML token such as 1e2000000000 now becomes an Exact (scale fits Int32), and its show() or encoding is a ~2 GB string, where it used to be a Float. Float64.from is native and safe, so typed Float64 fields are unaffected, but Json().decode<EncodedValue> followed by show() or encode on untrusted input can blow up memory. Consider a digit or scale cap in Exact creation from parsed text, or a note in DECIMAL.md section 11.
Review of a8228be (Argus). Approved. **Checklist** - Tests: ok. `decimal.test.trb` in std/{encoding,json,yaml,toml}, sandbox crossing, uri route, plus conformance `decimal-encoding`. CI green on this head (tier A, bootstrap, pdisc, gates). - Correctness: ok. `Exact` is handled in `show`, `Encode`, `Values.decimal`, `ValueDecoder.int/float/decimal`, JSON/YAML float-token split, sandbox `x…;` crossing. The string refusal in `decimal()` keeps `lenient` (uri/regex), map keys and TOML (`exactAsText`) working. I walked the 7 lines of `decimal-encoding.expected` against the program and they match. - Scope: ok. Slice 4 of #336, as stated. - Security/secrets: ok. No secrets, no new deps or permissions. - Data: ok. Crossing gains a new letter `x`, and a string-typed `Decimal` is now refused outside the listed cases (documented as the decision to review; I agree with it, it matches DECIMAL.md section 11). - Docs: ok. ENCODING, DECIMAL, decimal.md, ROADMAP, number/encoding pages, inventory, skills mirrors; pdisc green. - Architecture: ok. A new `EncodedValue` case only, no new boundary. **Non-blocking** 1. Tier B was skipped on this PR (scope rule: no compiler/runtime/tools change), so `tests/conformance/decimal-encoding` and its hand-computed `.expected` have not run in CI. The first run will be on main or nightly. Please run `sh tools/conformance.sh --filter decimal-encoding` and `--update-budgets` on linux x86_64 as a follow-up, and replace the `unbudgeted: … not measured` reason with a real budget (that marker is meant for programs whose count varies). 2. A JSON/YAML token such as `1e2000000000` now becomes an `Exact` (scale fits `Int32`), and its `show()` or encoding is a ~2 GB string, where it used to be a `Float`. `Float64.from` is native and safe, so typed `Float64` fields are unaffected, but `Json().decode<EncodedValue>` followed by `show()` or `encode` on untrusted input can blow up memory. Consider a digit or scale cap in `Exact` creation from parsed text, or a note in DECIMAL.md section 11.
argus merged commit 9e77466362 into main 2026-10-28 17:44:47 +00:00
argus deleted branch loop/336-decimal-encoding 2026-10-28 17:44:47 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!544
No description provided.