aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/hil/ast
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/hil/ast')
-rw-r--r--vendor/github.com/hashicorp/hil/ast/arithmetic.go43
-rw-r--r--vendor/github.com/hashicorp/hil/ast/arithmetic_op.go24
-rw-r--r--vendor/github.com/hashicorp/hil/ast/ast.go99
-rw-r--r--vendor/github.com/hashicorp/hil/ast/call.go47
-rw-r--r--vendor/github.com/hashicorp/hil/ast/conditional.go36
-rw-r--r--vendor/github.com/hashicorp/hil/ast/index.go76
-rw-r--r--vendor/github.com/hashicorp/hil/ast/literal.go88
-rw-r--r--vendor/github.com/hashicorp/hil/ast/output.go78
-rw-r--r--vendor/github.com/hashicorp/hil/ast/scope.go90
-rw-r--r--vendor/github.com/hashicorp/hil/ast/stack.go25
-rw-r--r--vendor/github.com/hashicorp/hil/ast/type_string.go54
-rw-r--r--vendor/github.com/hashicorp/hil/ast/unknown.go30
-rw-r--r--vendor/github.com/hashicorp/hil/ast/variable_access.go36
-rw-r--r--vendor/github.com/hashicorp/hil/ast/variables_helper.go63
14 files changed, 789 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hil/ast/arithmetic.go b/vendor/github.com/hashicorp/hil/ast/arithmetic.go
new file mode 100644
index 0000000..94dc24f
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/arithmetic.go
@@ -0,0 +1,43 @@
1package ast
2
3import (
4 "bytes"
5 "fmt"
6)
7
8// Arithmetic represents a node where the result is arithmetic of
9// two or more operands in the order given.
10type Arithmetic struct {
11 Op ArithmeticOp
12 Exprs []Node
13 Posx Pos
14}
15
16func (n *Arithmetic) Accept(v Visitor) Node {
17 for i, expr := range n.Exprs {
18 n.Exprs[i] = expr.Accept(v)
19 }
20
21 return v(n)
22}
23
24func (n *Arithmetic) Pos() Pos {
25 return n.Posx
26}
27
28func (n *Arithmetic) GoString() string {
29 return fmt.Sprintf("*%#v", *n)
30}
31
32func (n *Arithmetic) String() string {
33 var b bytes.Buffer
34 for _, expr := range n.Exprs {
35 b.WriteString(fmt.Sprintf("%s", expr))
36 }
37
38 return b.String()
39}
40
41func (n *Arithmetic) Type(Scope) (Type, error) {
42 return TypeInt, nil
43}
diff --git a/vendor/github.com/hashicorp/hil/ast/arithmetic_op.go b/vendor/github.com/hashicorp/hil/ast/arithmetic_op.go
new file mode 100644
index 0000000..18880c6
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/arithmetic_op.go
@@ -0,0 +1,24 @@
1package ast
2
3// ArithmeticOp is the operation to use for the math.
4type ArithmeticOp int
5
6const (
7 ArithmeticOpInvalid ArithmeticOp = 0
8
9 ArithmeticOpAdd ArithmeticOp = iota
10 ArithmeticOpSub
11 ArithmeticOpMul
12 ArithmeticOpDiv
13 ArithmeticOpMod
14
15 ArithmeticOpLogicalAnd
16 ArithmeticOpLogicalOr
17
18 ArithmeticOpEqual
19 ArithmeticOpNotEqual
20 ArithmeticOpLessThan
21 ArithmeticOpLessThanOrEqual
22 ArithmeticOpGreaterThan
23 ArithmeticOpGreaterThanOrEqual
24)
diff --git a/vendor/github.com/hashicorp/hil/ast/ast.go b/vendor/github.com/hashicorp/hil/ast/ast.go
new file mode 100644
index 0000000..c6350f8
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/ast.go
@@ -0,0 +1,99 @@
1package ast
2
3import (
4 "fmt"
5)
6
7// Node is the interface that all AST nodes must implement.
8type Node interface {
9 // Accept is called to dispatch to the visitors. It must return the
10 // resulting Node (which might be different in an AST transform).
11 Accept(Visitor) Node
12
13 // Pos returns the position of this node in some source.
14 Pos() Pos
15
16 // Type returns the type of this node for the given context.
17 Type(Scope) (Type, error)
18}
19
20// Pos is the starting position of an AST node
21type Pos struct {
22 Column, Line int // Column/Line number, starting at 1
23 Filename string // Optional source filename, if known
24}
25
26func (p Pos) String() string {
27 if p.Filename == "" {
28 return fmt.Sprintf("%d:%d", p.Line, p.Column)
29 } else {
30 return fmt.Sprintf("%s:%d:%d", p.Filename, p.Line, p.Column)
31 }
32}
33
34// InitPos is an initiaial position value. This should be used as
35// the starting position (presets the column and line to 1).
36var InitPos = Pos{Column: 1, Line: 1}
37
38// Visitors are just implementations of this function.
39//
40// The function must return the Node to replace this node with. "nil" is
41// _not_ a valid return value. If there is no replacement, the original node
42// should be returned. We build this replacement directly into the visitor
43// pattern since AST transformations are a common and useful tool and
44// building it into the AST itself makes it required for future Node
45// implementations and very easy to do.
46//
47// Note that this isn't a true implementation of the visitor pattern, which
48// generally requires proper type dispatch on the function. However,
49// implementing this basic visitor pattern style is still very useful even
50// if you have to type switch.
51type Visitor func(Node) Node
52
53//go:generate stringer -type=Type
54
55// Type is the type of any value.
56type Type uint32
57
58const (
59 TypeInvalid Type = 0
60 TypeAny Type = 1 << iota
61 TypeBool
62 TypeString
63 TypeInt
64 TypeFloat
65 TypeList
66 TypeMap
67
68 // This is a special type used by Terraform to mark "unknown" values.
69 // It is impossible for this type to be introduced into your HIL programs
70 // unless you explicitly set a variable to this value. In that case,
71 // any operation including the variable will return "TypeUnknown" as the
72 // type.
73 TypeUnknown
74)
75
76func (t Type) Printable() string {
77 switch t {
78 case TypeInvalid:
79 return "invalid type"
80 case TypeAny:
81 return "any type"
82 case TypeBool:
83 return "type bool"
84 case TypeString:
85 return "type string"
86 case TypeInt:
87 return "type int"
88 case TypeFloat:
89 return "type float"
90 case TypeList:
91 return "type list"
92 case TypeMap:
93 return "type map"
94 case TypeUnknown:
95 return "type unknown"
96 default:
97 return "unknown type"
98 }
99}
diff --git a/vendor/github.com/hashicorp/hil/ast/call.go b/vendor/github.com/hashicorp/hil/ast/call.go
new file mode 100644
index 0000000..0557011
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/call.go
@@ -0,0 +1,47 @@
1package ast
2
3import (
4 "fmt"
5 "strings"
6)
7
8// Call represents a function call.
9type Call struct {
10 Func string
11 Args []Node
12 Posx Pos
13}
14
15func (n *Call) Accept(v Visitor) Node {
16 for i, a := range n.Args {
17 n.Args[i] = a.Accept(v)
18 }
19
20 return v(n)
21}
22
23func (n *Call) Pos() Pos {
24 return n.Posx
25}
26
27func (n *Call) String() string {
28 args := make([]string, len(n.Args))
29 for i, arg := range n.Args {
30 args[i] = fmt.Sprintf("%s", arg)
31 }
32
33 return fmt.Sprintf("Call(%s, %s)", n.Func, strings.Join(args, ", "))
34}
35
36func (n *Call) Type(s Scope) (Type, error) {
37 f, ok := s.LookupFunc(n.Func)
38 if !ok {
39 return TypeInvalid, fmt.Errorf("unknown function: %s", n.Func)
40 }
41
42 return f.ReturnType, nil
43}
44
45func (n *Call) GoString() string {
46 return fmt.Sprintf("*%#v", *n)
47}
diff --git a/vendor/github.com/hashicorp/hil/ast/conditional.go b/vendor/github.com/hashicorp/hil/ast/conditional.go
new file mode 100644
index 0000000..be48f89
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/conditional.go
@@ -0,0 +1,36 @@
1package ast
2
3import (
4 "fmt"
5)
6
7type Conditional struct {
8 CondExpr Node
9 TrueExpr Node
10 FalseExpr Node
11 Posx Pos
12}
13
14// Accept passes the given visitor to the child nodes in this order:
15// CondExpr, TrueExpr, FalseExpr. It then finally passes itself to the visitor.
16func (n *Conditional) Accept(v Visitor) Node {
17 n.CondExpr = n.CondExpr.Accept(v)
18 n.TrueExpr = n.TrueExpr.Accept(v)
19 n.FalseExpr = n.FalseExpr.Accept(v)
20
21 return v(n)
22}
23
24func (n *Conditional) Pos() Pos {
25 return n.Posx
26}
27
28func (n *Conditional) Type(Scope) (Type, error) {
29 // This is not actually a useful value; the type checker ignores
30 // this function when analyzing conditionals, just as with Arithmetic.
31 return TypeInt, nil
32}
33
34func (n *Conditional) GoString() string {
35 return fmt.Sprintf("*%#v", *n)
36}
diff --git a/vendor/github.com/hashicorp/hil/ast/index.go b/vendor/github.com/hashicorp/hil/ast/index.go
new file mode 100644
index 0000000..860c25f
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/index.go
@@ -0,0 +1,76 @@
1package ast
2
3import (
4 "fmt"
5 "strings"
6)
7
8// Index represents an indexing operation into another data structure
9type Index struct {
10 Target Node
11 Key Node
12 Posx Pos
13}
14
15func (n *Index) Accept(v Visitor) Node {
16 n.Target = n.Target.Accept(v)
17 n.Key = n.Key.Accept(v)
18 return v(n)
19}
20
21func (n *Index) Pos() Pos {
22 return n.Posx
23}
24
25func (n *Index) String() string {
26 return fmt.Sprintf("Index(%s, %s)", n.Target, n.Key)
27}
28
29func (n *Index) Type(s Scope) (Type, error) {
30 variableAccess, ok := n.Target.(*VariableAccess)
31 if !ok {
32 return TypeInvalid, fmt.Errorf("target is not a variable")
33 }
34
35 variable, ok := s.LookupVar(variableAccess.Name)
36 if !ok {
37 return TypeInvalid, fmt.Errorf("unknown variable accessed: %s", variableAccess.Name)
38 }
39
40 switch variable.Type {
41 case TypeList:
42 return n.typeList(variable, variableAccess.Name)
43 case TypeMap:
44 return n.typeMap(variable, variableAccess.Name)
45 default:
46 return TypeInvalid, fmt.Errorf("invalid index operation into non-indexable type: %s", variable.Type)
47 }
48}
49
50func (n *Index) typeList(variable Variable, variableName string) (Type, error) {
51 // We assume type checking has already determined that this is a list
52 list := variable.Value.([]Variable)
53
54 return VariableListElementTypesAreHomogenous(variableName, list)
55}
56
57func (n *Index) typeMap(variable Variable, variableName string) (Type, error) {
58 // We assume type checking has already determined that this is a map
59 vmap := variable.Value.(map[string]Variable)
60
61 return VariableMapValueTypesAreHomogenous(variableName, vmap)
62}
63
64func reportTypes(typesFound map[Type]struct{}) string {
65 stringTypes := make([]string, len(typesFound))
66 i := 0
67 for k, _ := range typesFound {
68 stringTypes[0] = k.String()
69 i++
70 }
71 return strings.Join(stringTypes, ", ")
72}
73
74func (n *Index) GoString() string {
75 return fmt.Sprintf("*%#v", *n)
76}
diff --git a/vendor/github.com/hashicorp/hil/ast/literal.go b/vendor/github.com/hashicorp/hil/ast/literal.go
new file mode 100644
index 0000000..da6014f
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/literal.go
@@ -0,0 +1,88 @@
1package ast
2
3import (
4 "fmt"
5 "reflect"
6)
7
8// LiteralNode represents a single literal value, such as "foo" or
9// 42 or 3.14159. Based on the Type, the Value can be safely cast.
10type LiteralNode struct {
11 Value interface{}
12 Typex Type
13 Posx Pos
14}
15
16// NewLiteralNode returns a new literal node representing the given
17// literal Go value, which must correspond to one of the primitive types
18// supported by HIL. Lists and maps cannot currently be constructed via
19// this function.
20//
21// If an inappropriately-typed value is provided, this function will
22// return an error. The main intended use of this function is to produce
23// "synthetic" literals from constants in code, where the value type is
24// well known at compile time. To easily store these in global variables,
25// see also MustNewLiteralNode.
26func NewLiteralNode(value interface{}, pos Pos) (*LiteralNode, error) {
27 goType := reflect.TypeOf(value)
28 var hilType Type
29
30 switch goType.Kind() {
31 case reflect.Bool:
32 hilType = TypeBool
33 case reflect.Int:
34 hilType = TypeInt
35 case reflect.Float64:
36 hilType = TypeFloat
37 case reflect.String:
38 hilType = TypeString
39 default:
40 return nil, fmt.Errorf("unsupported literal node type: %T", value)
41 }
42
43 return &LiteralNode{
44 Value: value,
45 Typex: hilType,
46 Posx: pos,
47 }, nil
48}
49
50// MustNewLiteralNode wraps NewLiteralNode and panics if an error is
51// returned, thus allowing valid literal nodes to be easily assigned to
52// global variables.
53func MustNewLiteralNode(value interface{}, pos Pos) *LiteralNode {
54 node, err := NewLiteralNode(value, pos)
55 if err != nil {
56 panic(err)
57 }
58 return node
59}
60
61func (n *LiteralNode) Accept(v Visitor) Node {
62 return v(n)
63}
64
65func (n *LiteralNode) Pos() Pos {
66 return n.Posx
67}
68
69func (n *LiteralNode) GoString() string {
70 return fmt.Sprintf("*%#v", *n)
71}
72
73func (n *LiteralNode) String() string {
74 return fmt.Sprintf("Literal(%s, %v)", n.Typex, n.Value)
75}
76
77func (n *LiteralNode) Type(Scope) (Type, error) {
78 return n.Typex, nil
79}
80
81// IsUnknown returns true either if the node's value is itself unknown
82// of if it is a collection containing any unknown elements, deeply.
83func (n *LiteralNode) IsUnknown() bool {
84 return IsUnknown(Variable{
85 Type: n.Typex,
86 Value: n.Value,
87 })
88}
diff --git a/vendor/github.com/hashicorp/hil/ast/output.go b/vendor/github.com/hashicorp/hil/ast/output.go
new file mode 100644
index 0000000..1e27f97
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/output.go
@@ -0,0 +1,78 @@
1package ast
2
3import (
4 "bytes"
5 "fmt"
6)
7
8// Output represents the root node of all interpolation evaluations. If the
9// output only has one expression which is either a TypeList or TypeMap, the
10// Output can be type-asserted to []interface{} or map[string]interface{}
11// respectively. Otherwise the Output evaluates as a string, and concatenates
12// the evaluation of each expression.
13type Output struct {
14 Exprs []Node
15 Posx Pos
16}
17
18func (n *Output) Accept(v Visitor) Node {
19 for i, expr := range n.Exprs {
20 n.Exprs[i] = expr.Accept(v)
21 }
22
23 return v(n)
24}
25
26func (n *Output) Pos() Pos {
27 return n.Posx
28}
29
30func (n *Output) GoString() string {
31 return fmt.Sprintf("*%#v", *n)
32}
33
34func (n *Output) String() string {
35 var b bytes.Buffer
36 for _, expr := range n.Exprs {
37 b.WriteString(fmt.Sprintf("%s", expr))
38 }
39
40 return b.String()
41}
42
43func (n *Output) Type(s Scope) (Type, error) {
44 // Special case no expressions for backward compatibility
45 if len(n.Exprs) == 0 {
46 return TypeString, nil
47 }
48
49 // Special case a single expression of types list or map
50 if len(n.Exprs) == 1 {
51 exprType, err := n.Exprs[0].Type(s)
52 if err != nil {
53 return TypeInvalid, err
54 }
55 switch exprType {
56 case TypeList:
57 return TypeList, nil
58 case TypeMap:
59 return TypeMap, nil
60 }
61 }
62
63 // Otherwise ensure all our expressions are strings
64 for index, expr := range n.Exprs {
65 exprType, err := expr.Type(s)
66 if err != nil {
67 return TypeInvalid, err
68 }
69 // We only look for things we know we can't coerce with an implicit conversion func
70 if exprType == TypeList || exprType == TypeMap {
71 return TypeInvalid, fmt.Errorf(
72 "multi-expression HIL outputs may only have string inputs: %d is type %s",
73 index, exprType)
74 }
75 }
76
77 return TypeString, nil
78}
diff --git a/vendor/github.com/hashicorp/hil/ast/scope.go b/vendor/github.com/hashicorp/hil/ast/scope.go
new file mode 100644
index 0000000..7a975d9
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/scope.go
@@ -0,0 +1,90 @@
1package ast
2
3import (
4 "fmt"
5 "reflect"
6)
7
8// Scope is the interface used to look up variables and functions while
9// evaluating. How these functions/variables are defined are up to the caller.
10type Scope interface {
11 LookupFunc(string) (Function, bool)
12 LookupVar(string) (Variable, bool)
13}
14
15// Variable is a variable value for execution given as input to the engine.
16// It records the value of a variables along with their type.
17type Variable struct {
18 Value interface{}
19 Type Type
20}
21
22// NewVariable creates a new Variable for the given value. This will
23// attempt to infer the correct type. If it can't, an error will be returned.
24func NewVariable(v interface{}) (result Variable, err error) {
25 switch v := reflect.ValueOf(v); v.Kind() {
26 case reflect.String:
27 result.Type = TypeString
28 default:
29 err = fmt.Errorf("Unknown type: %s", v.Kind())
30 }
31
32 result.Value = v
33 return
34}
35
36// String implements Stringer on Variable, displaying the type and value
37// of the Variable.
38func (v Variable) String() string {
39 return fmt.Sprintf("{Variable (%s): %+v}", v.Type, v.Value)
40}
41
42// Function defines a function that can be executed by the engine.
43// The type checker will validate that the proper types will be called
44// to the callback.
45type Function struct {
46 // ArgTypes is the list of types in argument order. These are the
47 // required arguments.
48 //
49 // ReturnType is the type of the returned value. The Callback MUST
50 // return this type.
51 ArgTypes []Type
52 ReturnType Type
53
54 // Variadic, if true, says that this function is variadic, meaning
55 // it takes a variable number of arguments. In this case, the
56 // VariadicType must be set.
57 Variadic bool
58 VariadicType Type
59
60 // Callback is the function called for a function. The argument
61 // types are guaranteed to match the spec above by the type checker.
62 // The length of the args is strictly == len(ArgTypes) unless Varidiac
63 // is true, in which case its >= len(ArgTypes).
64 Callback func([]interface{}) (interface{}, error)
65}
66
67// BasicScope is a simple scope that looks up variables and functions
68// using a map.
69type BasicScope struct {
70 FuncMap map[string]Function
71 VarMap map[string]Variable
72}
73
74func (s *BasicScope) LookupFunc(n string) (Function, bool) {
75 if s == nil {
76 return Function{}, false
77 }
78
79 v, ok := s.FuncMap[n]
80 return v, ok
81}
82
83func (s *BasicScope) LookupVar(n string) (Variable, bool) {
84 if s == nil {
85 return Variable{}, false
86 }
87
88 v, ok := s.VarMap[n]
89 return v, ok
90}
diff --git a/vendor/github.com/hashicorp/hil/ast/stack.go b/vendor/github.com/hashicorp/hil/ast/stack.go
new file mode 100644
index 0000000..bd2bc15
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/stack.go
@@ -0,0 +1,25 @@
1package ast
2
3// Stack is a stack of Node.
4type Stack struct {
5 stack []Node
6}
7
8func (s *Stack) Len() int {
9 return len(s.stack)
10}
11
12func (s *Stack) Push(n Node) {
13 s.stack = append(s.stack, n)
14}
15
16func (s *Stack) Pop() Node {
17 x := s.stack[len(s.stack)-1]
18 s.stack[len(s.stack)-1] = nil
19 s.stack = s.stack[:len(s.stack)-1]
20 return x
21}
22
23func (s *Stack) Reset() {
24 s.stack = nil
25}
diff --git a/vendor/github.com/hashicorp/hil/ast/type_string.go b/vendor/github.com/hashicorp/hil/ast/type_string.go
new file mode 100644
index 0000000..1f51a98
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/type_string.go
@@ -0,0 +1,54 @@
1// Code generated by "stringer -type=Type"; DO NOT EDIT
2
3package ast
4
5import "fmt"
6
7const (
8 _Type_name_0 = "TypeInvalid"
9 _Type_name_1 = "TypeAny"
10 _Type_name_2 = "TypeBool"
11 _Type_name_3 = "TypeString"
12 _Type_name_4 = "TypeInt"
13 _Type_name_5 = "TypeFloat"
14 _Type_name_6 = "TypeList"
15 _Type_name_7 = "TypeMap"
16 _Type_name_8 = "TypeUnknown"
17)
18
19var (
20 _Type_index_0 = [...]uint8{0, 11}
21 _Type_index_1 = [...]uint8{0, 7}
22 _Type_index_2 = [...]uint8{0, 8}
23 _Type_index_3 = [...]uint8{0, 10}
24 _Type_index_4 = [...]uint8{0, 7}
25 _Type_index_5 = [...]uint8{0, 9}
26 _Type_index_6 = [...]uint8{0, 8}
27 _Type_index_7 = [...]uint8{0, 7}
28 _Type_index_8 = [...]uint8{0, 11}
29)
30
31func (i Type) String() string {
32 switch {
33 case i == 0:
34 return _Type_name_0
35 case i == 2:
36 return _Type_name_1
37 case i == 4:
38 return _Type_name_2
39 case i == 8:
40 return _Type_name_3
41 case i == 16:
42 return _Type_name_4
43 case i == 32:
44 return _Type_name_5
45 case i == 64:
46 return _Type_name_6
47 case i == 128:
48 return _Type_name_7
49 case i == 256:
50 return _Type_name_8
51 default:
52 return fmt.Sprintf("Type(%d)", i)
53 }
54}
diff --git a/vendor/github.com/hashicorp/hil/ast/unknown.go b/vendor/github.com/hashicorp/hil/ast/unknown.go
new file mode 100644
index 0000000..d6ddaec
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/unknown.go
@@ -0,0 +1,30 @@
1package ast
2
3// IsUnknown reports whether a variable is unknown or contains any value
4// that is unknown. This will recurse into lists and maps and so on.
5func IsUnknown(v Variable) bool {
6 // If it is unknown itself, return true
7 if v.Type == TypeUnknown {
8 return true
9 }
10
11 // If it is a container type, check the values
12 switch v.Type {
13 case TypeList:
14 for _, el := range v.Value.([]Variable) {
15 if IsUnknown(el) {
16 return true
17 }
18 }
19 case TypeMap:
20 for _, el := range v.Value.(map[string]Variable) {
21 if IsUnknown(el) {
22 return true
23 }
24 }
25 default:
26 }
27
28 // Not a container type or survive the above checks
29 return false
30}
diff --git a/vendor/github.com/hashicorp/hil/ast/variable_access.go b/vendor/github.com/hashicorp/hil/ast/variable_access.go
new file mode 100644
index 0000000..4c1362d
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/variable_access.go
@@ -0,0 +1,36 @@
1package ast
2
3import (
4 "fmt"
5)
6
7// VariableAccess represents a variable access.
8type VariableAccess struct {
9 Name string
10 Posx Pos
11}
12
13func (n *VariableAccess) Accept(v Visitor) Node {
14 return v(n)
15}
16
17func (n *VariableAccess) Pos() Pos {
18 return n.Posx
19}
20
21func (n *VariableAccess) GoString() string {
22 return fmt.Sprintf("*%#v", *n)
23}
24
25func (n *VariableAccess) String() string {
26 return fmt.Sprintf("Variable(%s)", n.Name)
27}
28
29func (n *VariableAccess) Type(s Scope) (Type, error) {
30 v, ok := s.LookupVar(n.Name)
31 if !ok {
32 return TypeInvalid, fmt.Errorf("unknown variable: %s", n.Name)
33 }
34
35 return v.Type, nil
36}
diff --git a/vendor/github.com/hashicorp/hil/ast/variables_helper.go b/vendor/github.com/hashicorp/hil/ast/variables_helper.go
new file mode 100644
index 0000000..06bd18d
--- /dev/null
+++ b/vendor/github.com/hashicorp/hil/ast/variables_helper.go
@@ -0,0 +1,63 @@
1package ast
2
3import "fmt"
4
5func VariableListElementTypesAreHomogenous(variableName string, list []Variable) (Type, error) {
6 if len(list) == 0 {
7 return TypeInvalid, fmt.Errorf("list %q does not have any elements so cannot determine type.", variableName)
8 }
9
10 elemType := TypeUnknown
11 for _, v := range list {
12 if v.Type == TypeUnknown {
13 continue
14 }
15
16 if elemType == TypeUnknown {
17 elemType = v.Type
18 continue
19 }
20
21 if v.Type != elemType {
22 return TypeInvalid, fmt.Errorf(
23 "list %q does not have homogenous types. found %s and then %s",
24 variableName,
25 elemType, v.Type,
26 )
27 }
28
29 elemType = v.Type
30 }
31
32 return elemType, nil
33}
34
35func VariableMapValueTypesAreHomogenous(variableName string, vmap map[string]Variable) (Type, error) {
36 if len(vmap) == 0 {
37 return TypeInvalid, fmt.Errorf("map %q does not have any elements so cannot determine type.", variableName)
38 }
39
40 elemType := TypeUnknown
41 for _, v := range vmap {
42 if v.Type == TypeUnknown {
43 continue
44 }
45
46 if elemType == TypeUnknown {
47 elemType = v.Type
48 continue
49 }
50
51 if v.Type != elemType {
52 return TypeInvalid, fmt.Errorf(
53 "map %q does not have homogenous types. found %s and then %s",
54 variableName,
55 elemType, v.Type,
56 )
57 }
58
59 elemType = v.Type
60 }
61
62 return elemType, nil
63}