No Node-equivalent type: anchors, aliases, and per-node style don't round-trip #9

Closed
opened 2026-07-10 12:57:49 +00:00 by Mihaela · 0 comments
Mihaela commented 2026-07-10 12:57:49 +00:00 (Migrated from codeberg.org)

Status (2026-07-10)

Open. Found by a public-API feature-parity audit against Yams
(NodetteHQ/PureYAMLYamsComparison, Reports/macos-2026-07-10-apisguru-sample-504/FEATURE-PARITY.md),
not by a corpus parse-success run: this is a capability gap, not a
correctness bug, and every existing test suite passes around it because
nothing currently exercises it.

Yams's Node enum has 4 cases (scalar, mapping, sequence, alias),
and every case carries tag, anchor, mark, and style (flow/block for
collections, quoting for scalars). A consumer can construct or walk a Node
tree directly, re-emit it with anchors and aliases intact, or force a
specific node's style on output.

PureYAML has no equivalent:

  • Model.Value (the primary parse result) has no tag, no anchor, no style
    field, and no alias case at all — aliases are resolved/expanded during
    parsing, not preserved. A document with &a foo / *a parses to two
    identical Values with no trace that one was an alias of the other.
  • Tagged.Node (parseTagged(_:), a separate parser entry point) carries
    tags but still has no anchor preservation, no style, and is read-only —
    there is no dump-side use of it, so even the tag information it does
    capture cannot be re-emitted.
  • Emitting.Options has no way to re-introduce an alias into output, or to
    force a specific node's scalar/collection style independent of the
    document-wide scalarStyle/collectionStyle settings.

Impact

Anything that needs to preserve or manipulate YAML at the anchor/alias
level — deduplicating repeated structures on emit, editing a document while
keeping its existing anchors intact, round-tripping a hand-authored file
without expanding every alias into a full copy — has no way to do this with
PureYAML today. This is one of the two or three concrete things the
feature-parity audit identified as an actual blocker to switching from Yams,
not just a nice-to-have.

Work

  • Design a Model (or Tagged-adjacent) node type carrying tag, anchor,
    and style alongside each scalar/mapping/sequence, plus a real alias case,
    parallel to how Model.LocatedValue already carries SourceRange
    alongside Value for the position-tracking use case — same shape of
    problem (an opt-in parallel tree, not a change to the plain Value API).
  • Decide whether this is parse-only (read a node tree, inspect anchors/tags)
    or also needs dump-side support (emit a node tree back out with anchors
    re-introduced, not fully expanded).
  • Prove round-tripping: parse a document with anchors/aliases into the new
    type, dump it, reparse, and confirm the alias structure survives (not
    just the resolved values), the same discipline already applied elsewhere
    in this package for round-trip claims.

See NodetteHQ/PureYAMLYamsComparison's FEATURE-PARITY.md for the full
audit, including the two related but separate gaps (coarser emitter
controls, no built-in tag constructors) that were not filed as their own
issues yet.

Part of #8.

## Status (2026-07-10) Open. Found by a public-API feature-parity audit against Yams (NodetteHQ/PureYAMLYamsComparison, `Reports/macos-2026-07-10-apisguru-sample-504/FEATURE-PARITY.md`), not by a corpus parse-success run: this is a capability gap, not a correctness bug, and every existing test suite passes around it because nothing currently exercises it. Yams's `Node` enum has 4 cases (`scalar`, `mapping`, `sequence`, `alias`), and every case carries `tag`, `anchor`, `mark`, and `style` (flow/block for collections, quoting for scalars). A consumer can construct or walk a `Node` tree directly, re-emit it with anchors and aliases intact, or force a specific node's style on output. PureYAML has no equivalent: - `Model.Value` (the primary parse result) has no tag, no anchor, no style field, and no alias case at all — aliases are resolved/expanded during parsing, not preserved. A document with `&a foo` / `*a` parses to two identical `Value`s with no trace that one was an alias of the other. - `Tagged.Node` (`parseTagged(_:)`, a separate parser entry point) carries tags but still has no anchor preservation, no style, and is read-only — there is no dump-side use of it, so even the tag information it does capture cannot be re-emitted. - `Emitting.Options` has no way to re-introduce an alias into output, or to force a specific node's scalar/collection style independent of the document-wide `scalarStyle`/`collectionStyle` settings. ## Impact Anything that needs to preserve or manipulate YAML at the anchor/alias level — deduplicating repeated structures on emit, editing a document while keeping its existing anchors intact, round-tripping a hand-authored file without expanding every alias into a full copy — has no way to do this with PureYAML today. This is one of the two or three concrete things the feature-parity audit identified as an actual blocker to switching from Yams, not just a nice-to-have. ## Work - Design a `Model` (or `Tagged`-adjacent) node type carrying tag, anchor, and style alongside each scalar/mapping/sequence, plus a real alias case, parallel to how `Model.LocatedValue` already carries `SourceRange` alongside `Value` for the position-tracking use case — same shape of problem (an opt-in parallel tree, not a change to the plain `Value` API). - Decide whether this is parse-only (read a node tree, inspect anchors/tags) or also needs dump-side support (emit a node tree back out with anchors re-introduced, not fully expanded). - Prove round-tripping: parse a document with anchors/aliases into the new type, dump it, reparse, and confirm the alias structure survives (not just the resolved values), the same discipline already applied elsewhere in this package for round-trip claims. See NodetteHQ/PureYAMLYamsComparison's `FEATURE-PARITY.md` for the full audit, including the two related but separate gaps (coarser emitter controls, no built-in tag constructors) that were not filed as their own issues yet. Part of #8.
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 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: NodetteHQ/PureYAML#9
No description provided.