aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/spec.md
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/spec.md')
-rw-r--r--vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/spec.md149
1 files changed, 76 insertions, 73 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/spec.md b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/spec.md
index 49b9a3e..091c1c2 100644
--- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/spec.md
+++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/spec.md
@@ -4,18 +4,18 @@ This is the specification of the syntax and semantics of the native syntax
4for HCL. HCL is a system for defining configuration languages for applications. 4for HCL. HCL is a system for defining configuration languages for applications.
5The HCL information model is designed to support multiple concrete syntaxes 5The HCL information model is designed to support multiple concrete syntaxes
6for configuration, but this native syntax is considered the primary format 6for configuration, but this native syntax is considered the primary format
7and is optimized for human authoring and maintenence, as opposed to machine 7and is optimized for human authoring and maintenance, as opposed to machine
8generation of configuration. 8generation of configuration.
9 9
10The language consists of three integrated sub-languages: 10The language consists of three integrated sub-languages:
11 11
12* The _structural_ language defines the overall heirarchical configuration 12- The _structural_ language defines the overall hierarchical configuration
13 structure, and is a serialization of HCL bodies, blocks and attributes. 13 structure, and is a serialization of HCL bodies, blocks and attributes.
14 14
15* The _expression_ language is used to express attribute values, either as 15- The _expression_ language is used to express attribute values, either as
16 literals or as derivations of other values. 16 literals or as derivations of other values.
17 17
18* The _template_ language is used to compose values together into strings, 18- The _template_ language is used to compose values together into strings,
19 as one of several types of expression in the expression language. 19 as one of several types of expression in the expression language.
20 20
21In normal use these three sub-languages are used together within configuration 21In normal use these three sub-languages are used together within configuration
@@ -30,19 +30,19 @@ Within this specification a semi-formal notation is used to illustrate the
30details of syntax. This notation is intended for human consumption rather 30details of syntax. This notation is intended for human consumption rather
31than machine consumption, with the following conventions: 31than machine consumption, with the following conventions:
32 32
33* A naked name starting with an uppercase letter is a global production, 33- A naked name starting with an uppercase letter is a global production,
34 common to all of the syntax specifications in this document. 34 common to all of the syntax specifications in this document.
35* A naked name starting with a lowercase letter is a local production, 35- A naked name starting with a lowercase letter is a local production,
36 meaningful only within the specification where it is defined. 36 meaningful only within the specification where it is defined.
37* Double and single quotes (`"` and `'`) are used to mark literal character 37- Double and single quotes (`"` and `'`) are used to mark literal character
38 sequences, which may be either punctuation markers or keywords. 38 sequences, which may be either punctuation markers or keywords.
39* The default operator for combining items, which has no punctuation, 39- The default operator for combining items, which has no punctuation,
40 is concatenation. 40 is concatenation.
41* The symbol `|` indicates that any one of its left and right operands may 41- The symbol `|` indicates that any one of its left and right operands may
42 be present. 42 be present.
43* The `*` symbol indicates zero or more repetitions of the item to its left. 43- The `*` symbol indicates zero or more repetitions of the item to its left.
44* The `?` symbol indicates zero or one of the item to its left. 44- The `?` symbol indicates zero or one of the item to its left.
45* Parentheses (`(` and `)`) are used to group items together to apply 45- Parentheses (`(` and `)`) are used to group items together to apply
46 the `|`, `*` and `?` operators to them collectively. 46 the `|`, `*` and `?` operators to them collectively.
47 47
48The grammar notation does not fully describe the language. The prose may 48The grammar notation does not fully describe the language. The prose may
@@ -77,11 +77,11 @@ are not valid within HCL native syntax.
77 77
78Comments serve as program documentation and come in two forms: 78Comments serve as program documentation and come in two forms:
79 79
80* _Line comments_ start with either the `//` or `#` sequences and end with 80- _Line comments_ start with either the `//` or `#` sequences and end with
81 the next newline sequence. A line comments is considered equivalent to a 81 the next newline sequence. A line comments is considered equivalent to a
82 newline sequence. 82 newline sequence.
83 83
84* _Inline comments_ start with the `/*` sequence and end with the `*/` 84- _Inline comments_ start with the `/*` sequence and end with the `*/`
85 sequence, and may have any characters within except the ending sequence. 85 sequence, and may have any characters within except the ending sequence.
86 An inline comments is considered equivalent to a whitespace sequence. 86 An inline comments is considered equivalent to a whitespace sequence.
87 87
@@ -91,7 +91,7 @@ template literals except inside an interpolation sequence or template directive.
91### Identifiers 91### Identifiers
92 92
93Identifiers name entities such as blocks, attributes and expression variables. 93Identifiers name entities such as blocks, attributes and expression variables.
94Identifiers are interpreted as per [UAX #31][UAX31] Section 2. Specifically, 94Identifiers are interpreted as per [UAX #31][uax31] Section 2. Specifically,
95their syntax is defined in terms of the `ID_Start` and `ID_Continue` 95their syntax is defined in terms of the `ID_Start` and `ID_Continue`
96character properties as follows: 96character properties as follows:
97 97
@@ -109,7 +109,7 @@ that is not part of the unicode `ID_Continue` definition. This is to allow
109attribute names and block type names to contain dashes, although underscores 109attribute names and block type names to contain dashes, although underscores
110as word separators are considered the idiomatic usage. 110as word separators are considered the idiomatic usage.
111 111
112[UAX31]: http://unicode.org/reports/tr31/ "Unicode Identifier and Pattern Syntax" 112[uax31]: http://unicode.org/reports/tr31/ "Unicode Identifier and Pattern Syntax"
113 113
114### Keywords 114### Keywords
115 115
@@ -150,18 +150,19 @@ expmark = ('e' | 'E') ("+" | "-")?;
150The structural language consists of syntax representing the following 150The structural language consists of syntax representing the following
151constructs: 151constructs:
152 152
153* _Attributes_, which assign a value to a specified name. 153- _Attributes_, which assign a value to a specified name.
154* _Blocks_, which create a child body annotated by a type and optional labels. 154- _Blocks_, which create a child body annotated by a type and optional labels.
155* _Body Content_, which consists of a collection of attributes and blocks. 155- _Body Content_, which consists of a collection of attributes and blocks.
156 156
157These constructs correspond to the similarly-named concepts in the 157These constructs correspond to the similarly-named concepts in the
158language-agnostic HCL information model. 158language-agnostic HCL information model.
159 159
160```ebnf 160```ebnf
161ConfigFile = Body; 161ConfigFile = Body;
162Body = (Attribute | Block)*; 162Body = (Attribute | Block | OneLineBlock)*;
163Attribute = Identifier "=" Expression Newline; 163Attribute = Identifier "=" Expression Newline;
164Block = Identifier (StringLit|Identifier)* "{" Newline Body "}" Newline; 164Block = Identifier (StringLit|Identifier)* "{" Newline Body "}" Newline;
165OneLineBlock = Identifier (StringLit|Identifier)* "{" (Identifier "=" Expression)? "}" Newline;
165``` 166```
166 167
167### Configuration Files 168### Configuration Files
@@ -186,7 +187,7 @@ for later evaluation by the calling application.
186### Blocks 187### Blocks
187 188
188A _block_ creates a child body that is annotated with a block _type_ and 189A _block_ creates a child body that is annotated with a block _type_ and
189zero or more block _labels_. Blocks create a structural heirachy which can be 190zero or more block _labels_. Blocks create a structural hierachy which can be
190interpreted by the calling application. 191interpreted by the calling application.
191 192
192Block labels can either be quoted literal strings or naked identifiers. 193Block labels can either be quoted literal strings or naked identifiers.
@@ -252,9 +253,9 @@ LiteralValue = (
252); 253);
253``` 254```
254 255
255* Numeric literals represent values of type _number_. 256- Numeric literals represent values of type _number_.
256* The `true` and `false` keywords represent values of type _bool_. 257- The `true` and `false` keywords represent values of type _bool_.
257* The `null` keyword represents a null value of the dynamic pseudo-type. 258- The `null` keyword represents a null value of the dynamic pseudo-type.
258 259
259String literals are not directly available in the expression sub-language, but 260String literals are not directly available in the expression sub-language, but
260are available via the template sub-language, which can in turn be incorporated 261are available via the template sub-language, which can in turn be incorporated
@@ -285,8 +286,8 @@ When specifying an object element, an identifier is interpreted as a literal
285attribute name as opposed to a variable reference. To populate an item key 286attribute name as opposed to a variable reference. To populate an item key
286from a variable, use parentheses to disambiguate: 287from a variable, use parentheses to disambiguate:
287 288
288* `{foo = "baz"}` is interpreted as an attribute literally named `foo`. 289- `{foo = "baz"}` is interpreted as an attribute literally named `foo`.
289* `{(foo) = "baz"}` is interpreted as an attribute whose name is taken 290- `{(foo) = "baz"}` is interpreted as an attribute whose name is taken
290 from the variable named `foo`. 291 from the variable named `foo`.
291 292
292Between the open and closing delimiters of these sequences, newline sequences 293Between the open and closing delimiters of these sequences, newline sequences
@@ -296,14 +297,14 @@ There is a syntax ambiguity between _for expressions_ and collection values
296whose first element is a reference to a variable named `for`. The 297whose first element is a reference to a variable named `for`. The
297_for expression_ interpretation has priority, so to produce a tuple whose 298_for expression_ interpretation has priority, so to produce a tuple whose
298first element is the value of a variable named `for`, or an object with a 299first element is the value of a variable named `for`, or an object with a
299key named `for`, use paretheses to disambiguate: 300key named `for`, use parentheses to disambiguate:
300 301
301* `[for, foo, baz]` is a syntax error. 302- `[for, foo, baz]` is a syntax error.
302* `[(for), foo, baz]` is a tuple whose first element is the value of variable 303- `[(for), foo, baz]` is a tuple whose first element is the value of variable
303 `for`. 304 `for`.
304* `{for: 1, baz: 2}` is a syntax error. 305- `{for: 1, baz: 2}` is a syntax error.
305* `{(for): 1, baz: 2}` is an object with an attribute literally named `for`. 306- `{(for): 1, baz: 2}` is an object with an attribute literally named `for`.
306* `{baz: 2, for: 1}` is equivalent to the previous example, and resolves the 307- `{baz: 2, for: 1}` is equivalent to the previous example, and resolves the
307 ambiguity by reordering. 308 ambiguity by reordering.
308 309
309### Template Expressions 310### Template Expressions
@@ -311,9 +312,9 @@ key named `for`, use paretheses to disambiguate:
311A _template expression_ embeds a program written in the template sub-language 312A _template expression_ embeds a program written in the template sub-language
312as an expression. Template expressions come in two forms: 313as an expression. Template expressions come in two forms:
313 314
314* A _quoted_ template expression is delimited by quote characters (`"`) and 315- A _quoted_ template expression is delimited by quote characters (`"`) and
315 defines a template as a single-line expression with escape characters. 316 defines a template as a single-line expression with escape characters.
316* A _heredoc_ template expression is introduced by a `<<` sequence and 317- A _heredoc_ template expression is introduced by a `<<` sequence and
317 defines a template via a multi-line sequence terminated by a user-chosen 318 defines a template via a multi-line sequence terminated by a user-chosen
318 delimiter. 319 delimiter.
319 320
@@ -321,7 +322,7 @@ In both cases the template interpolation and directive syntax is available for
321use within the delimiters, and any text outside of these special sequences is 322use within the delimiters, and any text outside of these special sequences is
322interpreted as a literal string. 323interpreted as a literal string.
323 324
324In _quoted_ template expressions any literal string sequences within the 325In _quoted_ template expressions any literal string sequences within the
325template behave in a special way: literal newline sequences are not permitted 326template behave in a special way: literal newline sequences are not permitted
326and instead _escape sequences_ can be included, starting with the 327and instead _escape sequences_ can be included, starting with the
327backslash `\`: 328backslash `\`:
@@ -457,14 +458,14 @@ are provided, the first is the key and the second is the value.
457Tuple, object, list, map, and set types are iterable. The type of collection 458Tuple, object, list, map, and set types are iterable. The type of collection
458used defines how the key and value variables are populated: 459used defines how the key and value variables are populated:
459 460
460* For tuple and list types, the _key_ is the zero-based index into the 461- For tuple and list types, the _key_ is the zero-based index into the
461 sequence for each element, and the _value_ is the element value. The 462 sequence for each element, and the _value_ is the element value. The
462 elements are visited in index order. 463 elements are visited in index order.
463* For object and map types, the _key_ is the string attribute name or element 464- For object and map types, the _key_ is the string attribute name or element
464 key, and the _value_ is the attribute or element value. The elements are 465 key, and the _value_ is the attribute or element value. The elements are
465 visited in the order defined by a lexicographic sort of the attribute names 466 visited in the order defined by a lexicographic sort of the attribute names
466 or keys. 467 or keys.
467* For set types, the _key_ and _value_ are both the element value. The elements 468- For set types, the _key_ and _value_ are both the element value. The elements
468 are visited in an undefined but consistent order. 469 are visited in an undefined but consistent order.
469 470
470The expression after the colon and (in the case of object `for`) the expression 471The expression after the colon and (in the case of object `for`) the expression
@@ -482,16 +483,16 @@ object.
482In the case of object `for`, it is an error if two input elements produce 483In the case of object `for`, it is an error if two input elements produce
483the same result from the attribute name expression, since duplicate 484the same result from the attribute name expression, since duplicate
484attributes are not possible. If the ellipsis symbol (`...`) appears 485attributes are not possible. If the ellipsis symbol (`...`) appears
485immediately after the value experssion, this activates the grouping mode in 486immediately after the value expression, this activates the grouping mode in
486which each value in the resulting object is a _tuple_ of all of the values 487which each value in the resulting object is a _tuple_ of all of the values
487that were produced against each distinct key. 488that were produced against each distinct key.
488 489
489* `[for v in ["a", "b"]: v]` returns `["a", "b"]`. 490- `[for v in ["a", "b"]: v]` returns `["a", "b"]`.
490* `[for i, v in ["a", "b"]: i]` returns `[0, 1]`. 491- `[for i, v in ["a", "b"]: i]` returns `[0, 1]`.
491* `{for i, v in ["a", "b"]: v => i}` returns `{a = 0, b = 1}`. 492- `{for i, v in ["a", "b"]: v => i}` returns `{a = 0, b = 1}`.
492* `{for i, v in ["a", "a", "b"]: k => v}` produces an error, because attribute 493- `{for i, v in ["a", "a", "b"]: k => v}` produces an error, because attribute
493 `a` is defined twice. 494 `a` is defined twice.
494* `{for i, v in ["a", "a", "b"]: v => i...}` returns `{a = [0, 1], b = [2]}`. 495- `{for i, v in ["a", "a", "b"]: v => i...}` returns `{a = [0, 1], b = [2]}`.
495 496
496If the `if` keyword is used after the element expression(s), it applies an 497If the `if` keyword is used after the element expression(s), it applies an
497additional predicate that can be used to conditionally filter elements from 498additional predicate that can be used to conditionally filter elements from
@@ -501,7 +502,7 @@ element expression(s). It must evaluate to a boolean value; if `true`, the
501element will be evaluated as normal, while if `false` the element will be 502element will be evaluated as normal, while if `false` the element will be
502skipped. 503skipped.
503 504
504* `[for i, v in ["a", "b", "c"]: v if i < 2]` returns `["a", "b"]`. 505- `[for i, v in ["a", "b", "c"]: v if i < 2]` returns `["a", "b"]`.
505 506
506If the collection value, element expression(s) or condition expression return 507If the collection value, element expression(s) or condition expression return
507unknown values that are otherwise type-valid, the result is a value of the 508unknown values that are otherwise type-valid, the result is a value of the
@@ -566,10 +567,10 @@ elements in a tuple, list, or set value.
566 567
567There are two kinds of "splat" operator: 568There are two kinds of "splat" operator:
568 569
569* The _attribute-only_ splat operator supports only attribute lookups into 570- The _attribute-only_ splat operator supports only attribute lookups into
570 the elements from a list, but supports an arbitrary number of them. 571 the elements from a list, but supports an arbitrary number of them.
571 572
572* The _full_ splat operator additionally supports indexing into the elements 573- The _full_ splat operator additionally supports indexing into the elements
573 from a list, and allows any combination of attribute access and index 574 from a list, and allows any combination of attribute access and index
574 operations. 575 operations.
575 576
@@ -582,9 +583,9 @@ fullSplat = "[" "*" "]" (GetAttr | Index)*;
582The splat operators can be thought of as shorthands for common operations that 583The splat operators can be thought of as shorthands for common operations that
583could otherwise be performed using _for expressions_: 584could otherwise be performed using _for expressions_:
584 585
585* `tuple.*.foo.bar[0]` is approximately equivalent to 586- `tuple.*.foo.bar[0]` is approximately equivalent to
586 `[for v in tuple: v.foo.bar][0]`. 587 `[for v in tuple: v.foo.bar][0]`.
587* `tuple[*].foo.bar[0]` is approximately equivalent to 588- `tuple[*].foo.bar[0]` is approximately equivalent to
588 `[for v in tuple: v.foo.bar[0]]` 589 `[for v in tuple: v.foo.bar[0]]`
589 590
590Note the difference in how the trailing index operator is interpreted in 591Note the difference in how the trailing index operator is interpreted in
@@ -596,13 +597,15 @@ _for expressions_ shown above: if a splat operator is applied to a value that
596is _not_ of tuple, list, or set type, the value is coerced automatically into 597is _not_ of tuple, list, or set type, the value is coerced automatically into
597a single-value list of the value type: 598a single-value list of the value type:
598 599
599* `any_object.*.id` is equivalent to `[any_object.id]`, assuming that `any_object` 600- `any_object.*.id` is equivalent to `[any_object.id]`, assuming that `any_object`
600 is a single object. 601 is a single object.
601* `any_number.*` is equivalent to `[any_number]`, assuming that `any_number` 602- `any_number.*` is equivalent to `[any_number]`, assuming that `any_number`
602 is a single number. 603 is a single number.
603 604
604If the left operand of a splat operator is an unknown value of any type, the 605If applied to a null value that is not tuple, list, or set, the result is always
605result is a value of the dynamic pseudo-type. 606an empty tuple, which allows conveniently converting a possibly-null scalar
607value into a tuple of zero or one elements. It is illegal to apply a splat
608operator to a null value of tuple, list, or set type.
606 609
607### Operations 610### Operations
608 611
@@ -683,7 +686,7 @@ Arithmetic operations are considered to be performed in an arbitrary-precision
683number space. 686number space.
684 687
685If either operand of an arithmetic operator is an unknown number or a value 688If either operand of an arithmetic operator is an unknown number or a value
686of the dynamic pseudo-type, the result is an unknown number. 689of the dynamic pseudo-type, the result is an unknown number.
687 690
688### Logic Operators 691### Logic Operators
689 692
@@ -708,7 +711,7 @@ the outcome of a boolean expression.
708Conditional = Expression "?" Expression ":" Expression; 711Conditional = Expression "?" Expression ":" Expression;
709``` 712```
710 713
711The first expression is the _predicate_, which is evaluated and must produce 714The first expression is the _predicate_, which is evaluated and must produce
712a boolean result. If the predicate value is `true`, the result of the second 715a boolean result. If the predicate value is `true`, the result of the second
713expression is the result of the conditional. If the predicate value is 716expression is the result of the conditional. If the predicate value is
714`false`, the result of the third expression is the result of the conditional. 717`false`, the result of the third expression is the result of the conditional.
@@ -769,15 +772,15 @@ sequence is escaped as `%%{`.
769 772
770When the template sub-language is embedded in the expression language via 773When the template sub-language is embedded in the expression language via
771_template expressions_, additional constraints and transforms are applied to 774_template expressions_, additional constraints and transforms are applied to
772template literalsas described in the definition of template expressions. 775template literals as described in the definition of template expressions.
773 776
774The value of a template literal can be modified by _strip markers_ in any 777The value of a template literal can be modified by _strip markers_ in any
775interpolations or directives that are adjacent to it. A strip marker is 778interpolations or directives that are adjacent to it. A strip marker is
776a tilde (`~`) placed immediately after the opening `{` or before the closing 779a tilde (`~`) placed immediately after the opening `{` or before the closing
777`}` of a template sequence: 780`}` of a template sequence:
778 781
779* `hello ${~ "world" }` produces `"helloworld"`. 782- `hello ${~ "world" }` produces `"helloworld"`.
780* `%{ if true ~} hello %{~ endif }` produces `"hello"`. 783- `%{ if true ~} hello %{~ endif }` produces `"hello"`.
781 784
782When a strip marker is present, any spaces adjacent to it in the corresponding 785When a strip marker is present, any spaces adjacent to it in the corresponding
783string literal (if any) are removed before producing the final value. Space 786string literal (if any) are removed before producing the final value. Space
@@ -786,7 +789,7 @@ characters are interpreted as per Unicode's definition.
786Stripping is done at syntax level rather than value level. Values returned 789Stripping is done at syntax level rather than value level. Values returned
787by interpolations or directives are not subject to stripping: 790by interpolations or directives are not subject to stripping:
788 791
789* `${"hello" ~}${" world"}` produces `"hello world"`, and not `"helloworld"`, 792- `${"hello" ~}${" world"}` produces `"hello world"`, and not `"helloworld"`,
790 because the space is not in a template literal directly adjacent to the 793 because the space is not in a template literal directly adjacent to the
791 strip marker. 794 strip marker.
792 795
@@ -824,9 +827,9 @@ TemplateIf = (
824The evaluation of the `if` directive is equivalent to the conditional 827The evaluation of the `if` directive is equivalent to the conditional
825expression, with the following exceptions: 828expression, with the following exceptions:
826 829
827* The two sub-templates always produce strings, and thus the result value is 830- The two sub-templates always produce strings, and thus the result value is
828 also always a string. 831 also always a string.
829* The `else` clause may be omitted, in which case the conditional's third 832- The `else` clause may be omitted, in which case the conditional's third
830 expression result is implied to be the empty string. 833 expression result is implied to be the empty string.
831 834
832### Template For Directive 835### Template For Directive
@@ -846,9 +849,9 @@ TemplateFor = (
846The evaluation of the `for` directive is equivalent to the _for expression_ 849The evaluation of the `for` directive is equivalent to the _for expression_
847when producing a tuple, with the following exceptions: 850when producing a tuple, with the following exceptions:
848 851
849* The sub-template always produces a string. 852- The sub-template always produces a string.
850* There is no equivalent of the "if" clause on the for expression. 853- There is no equivalent of the "if" clause on the for expression.
851* The elements of the resulting tuple are all converted to strings and 854- The elements of the resulting tuple are all converted to strings and
852 concatenated to produce a flat string result. 855 concatenated to produce a flat string result.
853 856
854### Template Interpolation Unwrapping 857### Template Interpolation Unwrapping
@@ -864,13 +867,13 @@ template or expression syntax. Unwrapping allows arbitrary expressions to be
864used to populate attributes when strings in such languages are interpreted 867used to populate attributes when strings in such languages are interpreted
865as templates. 868as templates.
866 869
867* `${true}` produces the boolean value `true` 870- `${true}` produces the boolean value `true`
868* `${"${true}"}` produces the boolean value `true`, because both the inner 871- `${"${true}"}` produces the boolean value `true`, because both the inner
869 and outer interpolations are subject to unwrapping. 872 and outer interpolations are subject to unwrapping.
870* `hello ${true}` produces the string `"hello true"` 873- `hello ${true}` produces the string `"hello true"`
871* `${""}${true}` produces the string `"true"` because there are two 874- `${""}${true}` produces the string `"true"` because there are two
872 interpolation sequences, even though one produces an empty result. 875 interpolation sequences, even though one produces an empty result.
873* `%{ for v in [true] }${v}%{ endif }` produces the string `true` because 876- `%{ for v in [true] }${v}%{ endif }` produces the string `true` because
874 the presence of the `for` directive circumvents the unwrapping even though 877 the presence of the `for` directive circumvents the unwrapping even though
875 the final result is a single value. 878 the final result is a single value.
876 879
@@ -903,7 +906,7 @@ key/value pairs given are returned as the static pairs, with no further
903interpretation. 906interpretation.
904 907
905The usual requirement that an attribute name be interpretable as a string 908The usual requirement that an attribute name be interpretable as a string
906does not apply to this static analyis, allowing callers to provide map-like 909does not apply to this static analysis, allowing callers to provide map-like
907constructs with different key types by building on the map syntax. 910constructs with different key types by building on the map syntax.
908 911
909### Static Call 912### Static Call