Skip to content

Read a format sample's bare commodity symbol - #5

Merged
jwiegley merged 2 commits into
mainfrom
johnw/format-bare-symbol
Nov 4, 2026
Merged

jwiegley merged 2 commits into
mainfrom
johnw/format-bare-symbol

Conversation

@jwiegley

@jwiegley jwiegley commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

Summary

  • A commodity block's format sample may now spell the block's symbol bare, as the commodity header does, although an amount must quote it: commodity N1 with format 1,000.00 N1 declares the display precision of N1. Before parseAmount reads the sample, quoteBareSymbol quotes a bare occurrence of the block's symbol at either end of it.
  • This follows the C++ fix for commodity directive: can't agree if quoted commodity needs to be quoted ledger#3312, which C++ rejected before (unexpected characters '1' after commodity symbol in format directive). This reader took the bare N1 for a malformed commodity and skipped the line, so N1 kept the precision its postings had taught it.
  • The conditions are those of C++ (textual_directives.cc quote_bare_symbol). The symbol must need quotes by the C++ table (commodity.cc invalid_chars, which is not this reader's validCommodity). The sample must quote nothing itself. The symbol must not run into the number between two characters of a number, as in N11,000.00, where nothing marks where it ends.
  • Witness: test/regress/3312.test in ledger/ledger, whose N1 balance rounds to the format's two places only under this rule. The rule's comment cites it.

ledger/ledger#3316, which fixes C++ for ledger/ledger#3312, moves both pins (the flake input and the lean/ submodule) to this branch's commit, 1f4d113. Please merge this with a merge commit, as #1 and #2 were, so that the commit stays reachable from main. ledger-semantics#3, #4 and #6 also start from f5d891e. The four rules touch separate definitions, and a trial merge of #6 (the commodity header and alias comment rules, for ledger/ledger#3313) into this branch applies cleanly.

Test plan

  • nix build .#oracle -L exits 0, so every proof checks
  • Bisimulation of the fixed C++ build against this oracle over the whole C++ suite (test/semantic/check_all.py): 3800 PASS, 0 FAIL, 0 out-of-scope, 0 cpp-parse (491 negative, 77 no-journal, 2 python)
  • With the pinned oracle f5d891e, the same run fails on exactly 3312.test (only_oracle: N1|1234.567|Assets:N1, only_cpp: N1|1234.57|Assets:N1)

🤖 Generated with Claude Code

https://claude.ai/code/session_01CBCCbSZ9jNESexSR5iwBDC

jwiegley and others added 2 commits November 4, 2026 10:45
C++ Ledger now reads the string in an expression such as
`commodity == '"NAME"'` the way a journal reads a quoted symbol, so
the predicate names the commodity NAME, as `commodity == 'NAME'`
does (ledger/ledger#3241).  The quoted form is the one the C++
manual documents and the only one 3.3 accepted; since 3.4 the
comparison had looked the string up with its quotes and named
nothing.  This reader kept the quotes too, so it agreed with C++ on
the defect.

After unquoteAny removes the expression's own string quotes, remove
one layer of journal quotes with unquote, as the account and
commodity directives already do for their names.  The witness is
regress/3241, whose automated transaction applies to a posting in
"Amundi_NASDAQ-100_II_UCITS_ETF_Acc" only under this rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WjmMXZJwtkLbpNoEJ9HoYt
C++ Ledger now lets a commodity block's format sub-directive spell
the block's symbol bare, as the commodity header does, although an
amount must quote it (ledger/ledger#3312): `commodity N1` with
`format 1,000.00 N1` declares the display precision of N1.  This
reader took the bare N1 for a malformed commodity and skipped the
format line, so N1 kept the precision its postings had taught it.

Before parseAmount reads the sample, quote a bare occurrence of the
block's symbol at either end of it, under the C++ conditions: the
symbol needs quotes by the C++ table (commodity.cc invalid_chars,
which is not this reader's validCommodity), the sample quotes
nothing itself, and the symbol does not run into the number between
two characters of a number.  The witness is regress/3312, whose N1
balance rounds to the format's two places only under this rule.

Verified as follows.  `nix build .#oracle` exits 0, so every proof
checks.  test/semantic/check_all.py, run with the fixed C++ build
against this oracle over the whole C++ suite, reports 3800 PASS and
0 FAIL (491 negative, 77 without a journal, 2 with Python).  The
same run against f5d891e fails on exactly regress/3312, where the
oracle keeps 1234.567 N1 and C++ rounds to 1234.57.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CBCCbSZ9jNESexSR5iwBDC
@jwiegley
jwiegley force-pushed the johnw/format-bare-symbol branch from 1f4d113 to 1115499 Compare November 4, 2026 20:28
@jwiegley
jwiegley merged commit 1115499 into main Nov 4, 2026
3 checks passed
@jwiegley
jwiegley deleted the johnw/format-bare-symbol branch November 5, 2026 06:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant