diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hil/ast')
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/arithmetic.go | 43 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/arithmetic_op.go | 24 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/ast.go | 99 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/call.go | 47 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/conditional.go | 36 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/index.go | 76 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/literal.go | 88 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/output.go | 78 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/scope.go | 90 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/stack.go | 25 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/type_string.go | 54 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/unknown.go | 30 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/variable_access.go | 36 | ||||
-rw-r--r-- | vendor/github.com/hashicorp/hil/ast/variables_helper.go | 63 |
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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
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. | ||
10 | type Arithmetic struct { | ||
11 | Op ArithmeticOp | ||
12 | Exprs []Node | ||
13 | Posx Pos | ||
14 | } | ||
15 | |||
16 | func (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 | |||
24 | func (n *Arithmetic) Pos() Pos { | ||
25 | return n.Posx | ||
26 | } | ||
27 | |||
28 | func (n *Arithmetic) GoString() string { | ||
29 | return fmt.Sprintf("*%#v", *n) | ||
30 | } | ||
31 | |||
32 | func (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 | |||
41 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | // ArithmeticOp is the operation to use for the math. | ||
4 | type ArithmeticOp int | ||
5 | |||
6 | const ( | ||
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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | // Node is the interface that all AST nodes must implement. | ||
8 | type 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 | ||
21 | type Pos struct { | ||
22 | Column, Line int // Column/Line number, starting at 1 | ||
23 | Filename string // Optional source filename, if known | ||
24 | } | ||
25 | |||
26 | func (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). | ||
36 | var 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. | ||
51 | type Visitor func(Node) Node | ||
52 | |||
53 | //go:generate stringer -type=Type | ||
54 | |||
55 | // Type is the type of any value. | ||
56 | type Type uint32 | ||
57 | |||
58 | const ( | ||
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 | |||
76 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "strings" | ||
6 | ) | ||
7 | |||
8 | // Call represents a function call. | ||
9 | type Call struct { | ||
10 | Func string | ||
11 | Args []Node | ||
12 | Posx Pos | ||
13 | } | ||
14 | |||
15 | func (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 | |||
23 | func (n *Call) Pos() Pos { | ||
24 | return n.Posx | ||
25 | } | ||
26 | |||
27 | func (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 | |||
36 | func (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 | |||
45 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | type 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. | ||
16 | func (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 | |||
24 | func (n *Conditional) Pos() Pos { | ||
25 | return n.Posx | ||
26 | } | ||
27 | |||
28 | func (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 | |||
34 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "strings" | ||
6 | ) | ||
7 | |||
8 | // Index represents an indexing operation into another data structure | ||
9 | type Index struct { | ||
10 | Target Node | ||
11 | Key Node | ||
12 | Posx Pos | ||
13 | } | ||
14 | |||
15 | func (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 | |||
21 | func (n *Index) Pos() Pos { | ||
22 | return n.Posx | ||
23 | } | ||
24 | |||
25 | func (n *Index) String() string { | ||
26 | return fmt.Sprintf("Index(%s, %s)", n.Target, n.Key) | ||
27 | } | ||
28 | |||
29 | func (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 | |||
50 | func (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 | |||
57 | func (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 | |||
64 | func 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 | |||
74 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
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. | ||
10 | type 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. | ||
26 | func 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. | ||
53 | func 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 | |||
61 | func (n *LiteralNode) Accept(v Visitor) Node { | ||
62 | return v(n) | ||
63 | } | ||
64 | |||
65 | func (n *LiteralNode) Pos() Pos { | ||
66 | return n.Posx | ||
67 | } | ||
68 | |||
69 | func (n *LiteralNode) GoString() string { | ||
70 | return fmt.Sprintf("*%#v", *n) | ||
71 | } | ||
72 | |||
73 | func (n *LiteralNode) String() string { | ||
74 | return fmt.Sprintf("Literal(%s, %v)", n.Typex, n.Value) | ||
75 | } | ||
76 | |||
77 | func (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. | ||
83 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
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. | ||
13 | type Output struct { | ||
14 | Exprs []Node | ||
15 | Posx Pos | ||
16 | } | ||
17 | |||
18 | func (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 | |||
26 | func (n *Output) Pos() Pos { | ||
27 | return n.Posx | ||
28 | } | ||
29 | |||
30 | func (n *Output) GoString() string { | ||
31 | return fmt.Sprintf("*%#v", *n) | ||
32 | } | ||
33 | |||
34 | func (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 | |||
43 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
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. | ||
10 | type 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. | ||
17 | type 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. | ||
24 | func 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. | ||
38 | func (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. | ||
45 | type 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. | ||
69 | type BasicScope struct { | ||
70 | FuncMap map[string]Function | ||
71 | VarMap map[string]Variable | ||
72 | } | ||
73 | |||
74 | func (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 | |||
83 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | // Stack is a stack of Node. | ||
4 | type Stack struct { | ||
5 | stack []Node | ||
6 | } | ||
7 | |||
8 | func (s *Stack) Len() int { | ||
9 | return len(s.stack) | ||
10 | } | ||
11 | |||
12 | func (s *Stack) Push(n Node) { | ||
13 | s.stack = append(s.stack, n) | ||
14 | } | ||
15 | |||
16 | func (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 | |||
23 | func (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 | |||
3 | package ast | ||
4 | |||
5 | import "fmt" | ||
6 | |||
7 | const ( | ||
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 | |||
19 | var ( | ||
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 | |||
31 | func (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 @@ | |||
1 | package 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. | ||
5 | func 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 @@ | |||
1 | package ast | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | ) | ||
6 | |||
7 | // VariableAccess represents a variable access. | ||
8 | type VariableAccess struct { | ||
9 | Name string | ||
10 | Posx Pos | ||
11 | } | ||
12 | |||
13 | func (n *VariableAccess) Accept(v Visitor) Node { | ||
14 | return v(n) | ||
15 | } | ||
16 | |||
17 | func (n *VariableAccess) Pos() Pos { | ||
18 | return n.Posx | ||
19 | } | ||
20 | |||
21 | func (n *VariableAccess) GoString() string { | ||
22 | return fmt.Sprintf("*%#v", *n) | ||
23 | } | ||
24 | |||
25 | func (n *VariableAccess) String() string { | ||
26 | return fmt.Sprintf("Variable(%s)", n.Name) | ||
27 | } | ||
28 | |||
29 | func (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 @@ | |||
1 | package ast | ||
2 | |||
3 | import "fmt" | ||
4 | |||
5 | func 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 | |||
35 | func 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 | } | ||