Skip to content

encoding/yaml: decode anchors without expanding them #3818

@mvdan

Description

@mvdan

YAML has anchors, allowing to name nodes and reference them later in the document without repeating their content:

$ cat f.yaml
foo: &name "long expression"
bar: *name

Currently, our YAML decoder fully expands these references, even when importing as CUE:

$ cue def f.yaml
foo: "long expression"
bar: "long expression"
$ cue import f.yaml
$ cat f.cue
foo: "long expression"
bar: "long expression"

We could be a bit smarter and translate some of these anchors to CUE references, such as:

$ cat f.cue
name=foo: "long expression"
bar: name
$ cue export f.cue
{
    "foo": "long expression",
    "bar": "long expression"
}

However, note that anchors won't always translate one-to-one to CUE references. One example is scoping; YAML anchors always work as long as the anchor is defined earlier in the document, whereas in CUE, references must follow scoping rules, meaning that an earlier alias or field might no longer be in scope.

$ cat f.yaml
foo:
  nested: &name "long expression"
bar:
  nested: *name
$ cue export f.yaml
{
    "foo": {
        "nested": "long expression"
    },
    "bar": {
        "nested": "long expression"
    }
}
$ cat f.cue
foo: name=nested: "long expression"
bar: nested: name
$ cue export f.cue
foo: unreferenced alias or let clause name:
    ./f.cue:1:6
bar.nested: reference "name" not found:
    ./f.cue:2:14

One potential solution would be to always place anchors at the top level as let fields or definitions, such as the following, which does work, but somewhat loses the semblance with YAML:

let name = "long expression"
foo: nested: name
bar: nested: name

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions