diff --git a/cmd/hcldec/spec-format.md b/cmd/hcldec/spec-format.md index 2126d69..69b21b8 100644 --- a/cmd/hcldec/spec-format.md +++ b/cmd/hcldec/spec-format.md @@ -274,7 +274,8 @@ literal { `literal` spec blocks accept the following argument: -* `value` (required) - The value to return. +* `value` (required) - The value to return. This attribute may be an expression + that uses [functions](#functions). `literal` is a leaf spec type, so no nested spec blocks are permitted. @@ -330,6 +331,30 @@ transform { spec. The variable `nested` is defined when evaluating this expression, with the result value of the nested spec. +The `result` expression may use [functions](#functions). + +## Functions + +Certain expressions within a specification may use the following functions. +The documentation for each spec type above specifies where functions may +be used. + +* `abs(number)` returns the absolute (positive) value of the given number. +* `coalesce(vals...)` returns the first non-null value given. +* `concat(lists...)` concatenates together all of the given lists to produce a new list. +* `hasindex(val, idx)` returns true if the expression `val[idx]` could succeed. +* `int(number)` returns the integer portion of the given number, rounding towards zero. +* `jsondecode(str)` interprets the given string as JSON and returns the resulting data structure. +* `jsonencode(val)` returns a JSON-serialized version of the given value. +* `length(collection)` returns the number of elements in the given collection (list, set, map, object, or tuple). +* `lower(string)` returns the given string with all uppercase letters converted to lowercase. +* `max(numbers...)` returns the greatest of the given numbers. +* `min(numbers...)` returns the smallest of the given numbers. +* `reverse(string)` returns the given string with all of the characters in reverse order. +* `strlen(string)` returns the number of characters in the given string. +* `substr(string, offset, length)` returns the requested substring of the given string. +* `upper(string)` returns the given string with all lowercase letters converted to uppercase. + ## Type Expressions Type expressions are used to describe the expected type of an attribute, as diff --git a/cmd/hcldec/spec.go b/cmd/hcldec/spec.go index fa09663..8010919 100644 --- a/cmd/hcldec/spec.go +++ b/cmd/hcldec/spec.go @@ -9,6 +9,10 @@ import ( "github.com/zclconf/go-cty/cty" ) +var specCtx = &hcl.EvalContext{ + Functions: specFuncs, +} + func loadSpecFile(filename string) (hcldec.Spec, hcl.Diagnostics) { file, diags := parser.ParseHCLFile(filename) if diags.HasErrors() { @@ -382,7 +386,7 @@ func decodeLiteralSpec(body hcl.Body) (hcldec.Spec, hcl.Diagnostics) { } var args content - diags := gohcl.DecodeBody(body, nil, &args) + diags := gohcl.DecodeBody(body, specCtx, &args) if diags.HasErrors() { return errSpec, diags } @@ -455,8 +459,9 @@ func decodeTransformSpec(body hcl.Body) (hcldec.Spec, hcl.Diagnostics) { } spec := &hcldec.TransformExprSpec{ - Expr: args.Result, - VarName: "nested", + Expr: args.Result, + VarName: "nested", + TransformCtx: specCtx, } nestedContent, nestedDiags := args.Nested.Content(specSchemaUnlabelled) diff --git a/cmd/hcldec/spec_funcs.go b/cmd/hcldec/spec_funcs.go new file mode 100644 index 0000000..99c8ea6 --- /dev/null +++ b/cmd/hcldec/spec_funcs.go @@ -0,0 +1,24 @@ +package main + +import ( + "github.com/zclconf/go-cty/cty/function" + "github.com/zclconf/go-cty/cty/function/stdlib" +) + +var specFuncs = map[string]function.Function{ + "abs": stdlib.AbsoluteFunc, + "coalesce": stdlib.CoalesceFunc, + "concat": stdlib.ConcatFunc, + "hasindex": stdlib.HasIndexFunc, + "int": stdlib.IntFunc, + "jsondecode": stdlib.JSONDecodeFunc, + "jsonencode": stdlib.JSONEncodeFunc, + "length": stdlib.LengthFunc, + "lower": stdlib.LowerFunc, + "max": stdlib.MaxFunc, + "min": stdlib.MinFunc, + "reverse": stdlib.ReverseFunc, + "strlen": stdlib.StrlenFunc, + "substr": stdlib.SubstrFunc, + "upper": stdlib.UpperFunc, +}