blaise/stdlib
Graeme Geldenhuys 008cc12785 feat(stdlib): configurable rounding for TMoney
TMoney previously hard-wired banker's rounding (rmHalfEven) at its single
normalisation point.  The underlying TDecimal already supports all eight
TRoundingMode values plus custom IRoundingStrategy, so expose that through
TMoney: every constructor and rounding-sensitive operation gains overloads
taking an explicit TRoundingMode or an IRoundingStrategy.

  MoneyFromStr('1.005','USD')            -> 1.00  (banker's, unchanged default)
  MoneyFromStr('1.005','USD', rmHalfUp)  -> 1.01
  C := A.Add(B, rmCeiling);
  M := MoneyFromStr('9.999','USD', myCashRoundingStrategy);

Overloaded: MoneyFromStr, MoneyFromDecimal, Add, Subtract, Multiply (each
gains a TRoundingMode form and an IRoundingStrategy form).  MoneyFromInt,
MoneyZero, MultiplyInt and Negate are exact (no fraction introduced) and
need no mode.  The existing no-mode calls are unchanged and keep banker's
rounding, so this is fully backward-compatible.

Internally a single MakeMoneyS(strategy) core does the normalisation; the
mode form delegates via StandardRounding(Mode) and the default via
rmHalfEven — one rounding code path.

Tests: 5 IR/semantic tests and 8 dual-backend e2e tests covering the mode
overloads (HalfUp/Down/Ceiling), the custom-strategy overload, the
default-stays-banker's guarantee, and rounding on Add/Multiply/constructors.

Docs: language-rationale.adoc updated to record that rounding is swappable
per call (default banker's), not hard-wired.

Verified: FIXPOINT_OK, NATIVE_FIXPOINT_OK, NATIVE_INTERNAL_OK; full suite
green on both the QBE-built and native-built runners (3686 tests).
2026-06-20 13:38:40 +01:00
..
src/main/pascal feat(stdlib): configurable rounding for TMoney 2026-06-20 13:38:40 +01:00
project.xml refactor: split rtl/ into runtime/ + stdlib/, rename bcl.testing to blaise.testing 2026-05-16 00:51:18 +01:00