Proposal: Generalize the idea of using [*] in traversals to describe "traversal patterns"#805
Open
apparentlymart wants to merge 6 commits into
Open
Proposal: Generalize the idea of using [*] in traversals to describe "traversal patterns"#805apparentlymart wants to merge 6 commits into
[*] in traversals to describe "traversal patterns"#805apparentlymart wants to merge 6 commits into
Conversation
Our current hcl.AbsTraversalForExpr function and our planned future hcl.AbsTraversalPatternForExpr depend on the overall shape of AST that the parser produces for certain combinations of traversal and splat expressions, so this test is intended to ensure we preserve those AST shapes under future changes to the parser, and doubles as a set of examples for which AST shapes we're intending to support in this way. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Contributor
Author
|
I see that the "copyright headers" check is failing but I'm not sure what exactly it's wanting me to do, since the files it mentioned do seem to have the "Copyright IBM Corp" headers in them. 🤔 |
Contributor
|
It was complaining because the modified files should get updated with 2026 - I don't know if you want me pushing a commit to your branch but I can do it, or you can. (Hi Martin!!! 👋🏻 ❤️ ) |
30483e6 to
e7fdd16
Compare
Contributor
Author
|
Hello! 👋😀 Thanks for explaining what that check is looking for. I've pushed an additional commit to meet its expectations. ✔️ |
The hclsyntax.ParseTraversalPartial function previously introduced the idea of using the splat expression syntax to represent a wildcard index, exploiting the accidentally-left-over hcl.TraverseSplat traverser type to represent the wildcard steps. But that idea wasn't previously generalized to work with expressions that appear as part of a configuration file or expression. This retroactively adopts the term "traversal pattern" to describe this special kind of hcl.Traversal that has at least one TraverseSplat step, renames the existing function to hclsyntax.ParseTraversalAbsPattern to reflect that new nomenclature, and then introduces hcl.AbsTraversalPatternForExpr as the corresponding companion to hcl.AbsTraversalForExpr, so that expression types can have their own rules for whether and how they can be interpreted as traversal patterns. This commit does not yet include any implementations of AsTraversalPattern. Those will follow in subsequent commits. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Previously there was no explicit representation of what kind of splat we had parsed and instead it was just implied by the shape of the AST, which varies due to attribute-only splat having different precedence relative to the index operator. Now we'll make that explicit as a new field. We're not using that field yet here, but a future commit will use it to support treating a splat expression as a "traversal pattern", but only when using the modern splat syntax because attribute-only splat's precedence isn't appropriate for being treated as a step in a traversal. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
Implementing the AsTraversalPattern method makes SplatExpr eligible to be interpreted as a "traversal pattern" as long as everything nested inside it can be suitably flattened into a series of traversal steps. This must be AsTraversalPattern rather than just AsTraversal because this particular expression type causes hcl.TraverseSplat steps to be included, which makes the result a traversal pattern rather than a concrete traversal. The test added here is more general, also covering various expressions that don't include SplatExpr but are nonetheless eligible to be treated as traversal patterns. The ones without SplatExpr actually return concrete traversals rather than traversal patterns, but all concrete traversals can be used as patterns that match exactly one traversal. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This makes expressions from JSON source files be compatible with the recently-added hcl.AbsTraversalPatternForExpr, following the same principle as how we've previously been handling hcl.AbsTraversalForExpr: the JSON representation is a JSON string containing a traversal pattern in HCL native syntax. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This repository's checking tool is written under the assumption that only IBM contributes to this repository and so expects the copyright year associated with that company to be updated on every change. The changes that prompted this update (the previous five commits) are actually Copyright 2026 Spacelift, Inc, but contributed to HCL under the terms of the Mozilla public license. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
e7fdd16 to
b5698d9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The earlier PR #673 introduced
hclsyntax.ParseTraversalPartialthat is a variant ofhclsyntax.ParseTraversalAbswhich additionally accepts[*]steps representing placeholders for arbitrary indices. It introduced a new use of the previously-vestigialhcl.TraverseSplattype1 as the representation of those placeholders.However, that idea wasn't generalized to the other main way callers can produce
hcl.Traversalvalues: asking HCL to perform static analysis of an already-parsed expression, like Terraform does when it's analyzing references in parts of its language likedepends_onand thefrom/toexpressions inmoved,removed, andimportblocks.This PR is proposing to generalize this idea of "traversals with wildcards" into a new first-class concept that I've called "traversal patterns". This new idea extends the idea of "traversal" to include the possibility of
hcl.TraverseSplatsteps, and makes it possible to turn both source code and certain already-parsed expressions into traversal patterns.Of course I have my own reasons to propose this, but as a "closer-to-home" motivation consider that Terraform could hypothetically use this to support wildcard patterns in
removedblocks:...or for wildcard index steps in
ignore_changesfor list-based blocks, without having to write out every possible index explicitly (hashicorp/terraform#5666):I understand that there'd be a lot more work to do in Terraform to do these things than just merging this PR, but this changeset would create a new building block in the HCL grammar for languages like Terraform's to use.
The
ParseTraversalPartialfunction was already producing traversals that can't supportTraversal.Value, and that remains true for the concept of "traversal pattern" introduced here. However, calls toValuenow return an error diagnostic instead of panicking as before.Turning an AST that includes a mixture of absolute traversals, relative traversals, and splat expressions into a flat
hcl.Traversalis kinda annoying to achieve and so the code I wrote for it here is honestly quite dense and tricky to follow, but I tried to write a good suite of unit tests covering it, both at the parser level (to make sure the parser generates the AST that the flattening code expects) and at the "as traversal pattern" level.Footnotes
That
TraverseSplattype originated from a much earlier implementation of splat expressions in the ZCL library that HCL 2 was forked from, where they were treated as a special kind of traversal step instead of as the separate expression typehclsyntax.SplatExpr.I forgot to actually remove the
TraverseSplattype after rewriting the implementation of splat expressions and so it ended up surviving into the first stable release of HCL 2 but without any uses untilhclsyntax.ParseTraversalPartialcame along and gave it a new purpose. ↩