This is a refactoring change with no output changes.
The chunk logic already separates the concepts of "nodes with children"
and "nodes with content" in practice, but it's not obvious in the API.
This rewrites the logic to make the separation clearer.
This also subtly takes advantage of the API to avoid creating lots of
empty chunks... Right now, there's always an empty chunk between two
tentative chunks. With this change, it lazily creates a chunk only when
`out()` is used (which it often isn't), which should substantially
reduce the number of chunks created.
This shifts logic a little so that empty top-level scopes are printed
less often. This affects imports mainly for now, but should be expected
to affect the soon-to-be-added generated scope more significantly.
Assisted-by: Google Antigravity with Gemini 3 Flash
I'm looking at making `constants { ... }` etc omitted when empty,
because in turn I'm looking at adding a third section, and seeing more
boilerplate empty sections just seems awkward to me. This PR starts down
the path by factoring out the chunk logic, which I may want to refactor
further.
This changes the `size_t` chunk id into a wrapped type for type safety.
This PR is just a refactoring, and doesn't make any behavior changes.
Assisted-by: Google Antigravity with Gemini 3 Flash