mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-21 10:47:34 -05:00
In "package tofu" today we try to do everything using a generic acyclic graph model and generic graph walk, which _works_ but tends to make every other part of the problem very hard to follow because we rely a lot on sidecar shared mutable data structures to propagate results between the isolated operations. This is the beginning of an experimental new way to do it where the "graph" is implied by a model that more closely represents how the language itself works, with explicit modelling of the relationships between different types of objects and letting results flow directly from one object to another without any big shared mutable state. There's still a lot to do before this is actually complete enough to evaluate whether it's a viable new design, but I'm considering this a good starting checkpoint since there's enough here to run a simple test of propagating data all the way from input variables to output values via intermediate local values. Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
52 lines
1.7 KiB
Go
52 lines
1.7 KiB
Go
// Copyright (c) The OpenTofu Authors
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright (c) 2023 HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package exprs
|
|
|
|
import (
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/zclconf/go-cty/cty"
|
|
"github.com/zclconf/go-cty/cty/convert"
|
|
)
|
|
|
|
// TraversalStepAttributeName attempts to interpret the given traversal step
|
|
// in a manner compatible with how [hcl.Index] would apply it to a value
|
|
// of an object type, returning the name of the attribute it would access.
|
|
//
|
|
// If the second return value is false then the given step is not valid to
|
|
// use in that situation.
|
|
//
|
|
// This is mainly for use in [Valuer.StaticCheckTraversal] implementations
|
|
// where the Value method would return an object type, to find out which
|
|
// attribute name the first traversal step would ultimately select.
|
|
func TraversalStepAttributeName(step hcl.Traverser) (string, bool) {
|
|
switch step := step.(type) {
|
|
case hcl.TraverseAttr:
|
|
return step.Name, true
|
|
case hcl.TraverseRoot:
|
|
return step.Name, true
|
|
case hcl.TraverseIndex:
|
|
v, err := convert.Convert(step.Key, cty.String)
|
|
if err != nil || v.IsNull() {
|
|
return "", false
|
|
}
|
|
if !v.IsKnown() {
|
|
// Unknown values should not typically appear in traversals
|
|
// because HCL itself only builds traversals from static
|
|
// traversal syntax, but this is here just in case we do
|
|
// something weird e.g. in a test that's constructing
|
|
// traversals by hand.
|
|
return "", false
|
|
}
|
|
// Likewise marked values should not typically appear in traversals
|
|
// for the same reason, so we're unmarking for robustness against
|
|
// weird contrived inputs only.
|
|
v, _ = v.Unmark()
|
|
return v.AsString(), true
|
|
default:
|
|
return "", false
|
|
}
|
|
}
|