This is useful, for example, when printing source snippets to the terminal
as part of diagnostics, in order to detect the portion of the source code
that coincides with the subject or context of each diagnostic.
This can be useful, for example, when using Expression.Variables to
pre-validate all of the referenced variables before evaluation, so that
the traversal source ranges can be included in any generated diagnostics.
As an extra level of confidence in addition to the unit tests, this
integration test verifies that a certain set of features that Terraform
uses are able to work properly together.
Terraform is used as an example here just because it's a more advanced
consumer of HCL and thus it exercises some codepaths that most
applications don't need, such as ExprList and AbsTraversalForExpr.
This helper allows a calling application to require a given expression be
some sort of list constructor (tuple constructor in native syntax, or
array in JSON) and peel off that outer level of list to obtain a slice
of the Expression objects inside.
This is useful in rare cases where the calling application needs to
extract the expressions within the list without evaluating the entire list
expression first. For example, the expressions that result from this
function might be passed into AbsTraversalForExpr in situations where the
caller requires a static list of static traversals that will never
actually be evaluated.
These functions permit a calling application to recognize when an
expression represents a static absolute traversal and obtain that
traversal. This allows for the unusual-but-valid case where an application
wishes to access the expression source rather than its resulting value,
when the expression source is something that can be understood as a
traversal.
An example use-case is an attribute that takes a list of other attributes
it depends on, expressed as traversals. In this case the calling
application needs to access the attribute names themselves rather than
their values, e.g. to build some sort of dependency graph to gradually
populate the scope for evaluation.
This function returns the type of value that should be returned when
decoding the given spec. As well as being generally useful to the caller
for book-keeping purposes, this also allows us to return correct type
information when we are returning null and empty values, where before we
were leaning a little too much on cty.DynamicPseudoType.
A BlockLabelSpec can be placed in the nested spec structure of one of the
block specs to require and obtain labels on that block.
This is a more generic methodology than BlockMapSpec since it allows the
result to be a list or set with the labels inside the values, rather than
forcing all the label tuples to be unique and losing the ordering by
collapsing into a map structure.
Using *reflect.StructField as map key results in a data race. I honestly
do not understand why yet and can only reproduce this in the consul
codebase with high concurrency but this patch fixes it.
The same problem also exists in mitchellh/mapstructure.
Rather than writing a nil hcl.Expression, as a special case we'll deal
with this within the cty type system, which we assume is what the caller
wants if they are decoding into a hcl.Expression rather than a native Go
type.
Sometimes we want an expression that just wraps a static value, e.g. for
testing or to provide a default value for a missing attribute.
StaticExpr gives us a convenient way to do that, returning a value that
implements the Expression interface by returning just the given static
value.
This is a super-invasive update since the "zcl" package in particular
is referenced all over.
There are probably still a few zcl references hanging around in comments,
etc but this takes care of most of it.
The main "zcl" package requires a bit more care because of how many
callers it has and because of its two subpackages, so we'll take care
of that one separately.
This package was a prototype of wrapping the HCL/HIL API in the new zcl
API as a compatibility strategy. This avenue wasn't chosen in the end, so
we'll remove this to avoid confusion as we rename everything else in this
repository to be called "hcl" now.
This package implements a language extension that allows configuration
authors to include the content of another file into a body, using syntax
like this:
include {
path = "./foo.zcl"
}
This is implemented as a transform.Transformer so that it can be used
as part of a transform chain when decoding nested block structures to
allow includes at any arbitrary point.
This capability is not built into the language because certain
applications will offer higher-level constructs for connecting multiple
separate config files, which may e.g. have a separate evaluation scope
for each file, etc.
This utility is intended to support the extension packages that are
siblings of this package, along with third-party extensions, by providing
a way to transform bodies in arbitrary ways.
The "Deep" function then provides a means to apply a particular transform
recursively to a nested block tree, allowing a particular extension to
be supported at arbitrary nesting levels.
This functionality is provided in terms of the standard zcl.Body
interface, so that transform results can be used with any code that
operates generically on bodies. This includes the zcldec and gozcl
packages, so files with extensions can still be decoded in the usual
way.
This package provides helper function that looks in a given body for
blocks that define functions, returning a function map suitable for use
in a zcl.EvalContext.
These will provide additional language features that are implemented in
terms of the basic zcl functionality, so that applications can opt-in to
some more-dynamic behavior if desired.
The general pattern here will be to provide a function that
partially-decodes a given zcl.Body to look for certain block types and
then returns its result along with a zcl.Body representing the remaining,
as-yet-unprocessed content.
Terraform interprets HIL variables in such a way that it allows numeric
attribute names which then get interpreted as numeric indices into a
list. This is used to work around the fact that the splat expressions
don't work for the index operator.
zcl has "full splats" that _do_ support the index operator, but to allow
old Terraform configs to be processed by zcl we'll accept this special
case within attribute-only-splats only.
For the moment this is a special exception made by this specific
implementation of zcl rather than part of the spec, since it's
specifically a pragmatic Terraform migration strategy, but it might get
upgraded to full spec status later if we end up needing to support it
in other host languages.
This requires the scanner to be a little more picky about the ending
of numeric literals, so that they won't absorb the trailing period after
the number in foo.*.baz.1.baz . This is okay because the spec doesn't
allow trailing periods anyway, and this is not actually a change in
final behavior because the parser was already catching this situation
and rejecting it at a later point.
While this does create some ambiguity with arithmetic on variables, like
a-b, this is permitted by HCL and so we'll permit it for zcl too, at the
expense of requiring spaces to be used around minus signs for correct
interpretation.