mirror of
https://github.com/opentffoundation/opentf.git
synced 2026-04-14 15:02:01 -04: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>
63 lines
2.0 KiB
Go
63 lines
2.0 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
|
|
|
|
// Attribute is implemented for the fixed set of types that can be returned
|
|
// from [SymbolTable.ResolveAttr] implementations.
|
|
//
|
|
// This is a closed interface implemented only by types within this package.
|
|
type Attribute interface {
|
|
attributeImpl()
|
|
}
|
|
|
|
// NestedSymbolTable constructs an [Attribute] representing a nested symbol
|
|
// table, which must therefore be traversed through by a subsequent attribute
|
|
// step.
|
|
//
|
|
// For example, a module instance acting as a symbol table would respond to
|
|
// a lookup of the attribute "var" by returning a nested symbol table whose
|
|
// symbols correspond to all of the input variables declared in the module,
|
|
// so that a reference like "var.foo" would then look up "foo" in the nested
|
|
// table.
|
|
func NestedSymbolTable(table SymbolTable) Attribute {
|
|
return nestedSymbolTable{table}
|
|
}
|
|
|
|
// ValueOf constructs an [Attribute] representing the endpoint of a static
|
|
// traversal, where a dynamic value should be placed.
|
|
func ValueOf(v Valuer) Attribute {
|
|
return valueOf{v}
|
|
}
|
|
|
|
// NestedSymbolTableFromAttribute returns the symbol table from an attribute
|
|
// that was returned from [NestedSymbolTable], or nil for any other kind of
|
|
// attribute.
|
|
func NestedSymbolTableFromAttribute(attr Attribute) SymbolTable {
|
|
withTable, ok := attr.(nestedSymbolTable)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return withTable.SymbolTable
|
|
}
|
|
|
|
// nestedSymbolTable is the [Attribute] implementation for symbols that act as
|
|
// nested symbol tables, resolving another set of child attributes within.
|
|
type nestedSymbolTable struct {
|
|
SymbolTable
|
|
}
|
|
|
|
// scopeStep implements [Attribute].
|
|
func (n nestedSymbolTable) attributeImpl() {}
|
|
|
|
// valueOf is the [Attribute] implementation for symbols that correspond to
|
|
// leaf values, produced by implementations of [Valuer].
|
|
type valueOf struct {
|
|
Valuer
|
|
}
|
|
|
|
// scopeStep implements [Attribute].
|
|
func (v valueOf) attributeImpl() {}
|