aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go')
-rw-r--r--vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go258
1 files changed, 258 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go
new file mode 100644
index 0000000..9a5da04
--- /dev/null
+++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go
@@ -0,0 +1,258 @@
1package hclsyntax
2
3import (
4 "fmt"
5
6 "github.com/hashicorp/hcl2/hcl"
7 "github.com/zclconf/go-cty/cty"
8 "github.com/zclconf/go-cty/cty/convert"
9 "github.com/zclconf/go-cty/cty/function"
10 "github.com/zclconf/go-cty/cty/function/stdlib"
11)
12
13type Operation struct {
14 Impl function.Function
15 Type cty.Type
16}
17
18var (
19 OpLogicalOr = &Operation{
20 Impl: stdlib.OrFunc,
21 Type: cty.Bool,
22 }
23 OpLogicalAnd = &Operation{
24 Impl: stdlib.AndFunc,
25 Type: cty.Bool,
26 }
27 OpLogicalNot = &Operation{
28 Impl: stdlib.NotFunc,
29 Type: cty.Bool,
30 }
31
32 OpEqual = &Operation{
33 Impl: stdlib.EqualFunc,
34 Type: cty.Bool,
35 }
36 OpNotEqual = &Operation{
37 Impl: stdlib.NotEqualFunc,
38 Type: cty.Bool,
39 }
40
41 OpGreaterThan = &Operation{
42 Impl: stdlib.GreaterThanFunc,
43 Type: cty.Bool,
44 }
45 OpGreaterThanOrEqual = &Operation{
46 Impl: stdlib.GreaterThanOrEqualToFunc,
47 Type: cty.Bool,
48 }
49 OpLessThan = &Operation{
50 Impl: stdlib.LessThanFunc,
51 Type: cty.Bool,
52 }
53 OpLessThanOrEqual = &Operation{
54 Impl: stdlib.LessThanOrEqualToFunc,
55 Type: cty.Bool,
56 }
57
58 OpAdd = &Operation{
59 Impl: stdlib.AddFunc,
60 Type: cty.Number,
61 }
62 OpSubtract = &Operation{
63 Impl: stdlib.SubtractFunc,
64 Type: cty.Number,
65 }
66 OpMultiply = &Operation{
67 Impl: stdlib.MultiplyFunc,
68 Type: cty.Number,
69 }
70 OpDivide = &Operation{
71 Impl: stdlib.DivideFunc,
72 Type: cty.Number,
73 }
74 OpModulo = &Operation{
75 Impl: stdlib.ModuloFunc,
76 Type: cty.Number,
77 }
78 OpNegate = &Operation{
79 Impl: stdlib.NegateFunc,
80 Type: cty.Number,
81 }
82)
83
84var binaryOps []map[TokenType]*Operation
85
86func init() {
87 // This operation table maps from the operator's token type
88 // to the AST operation type. All expressions produced from
89 // binary operators are BinaryOp nodes.
90 //
91 // Binary operator groups are listed in order of precedence, with
92 // the *lowest* precedence first. Operators within the same group
93 // have left-to-right associativity.
94 binaryOps = []map[TokenType]*Operation{
95 {
96 TokenOr: OpLogicalOr,
97 },
98 {
99 TokenAnd: OpLogicalAnd,
100 },
101 {
102 TokenEqualOp: OpEqual,
103 TokenNotEqual: OpNotEqual,
104 },
105 {
106 TokenGreaterThan: OpGreaterThan,
107 TokenGreaterThanEq: OpGreaterThanOrEqual,
108 TokenLessThan: OpLessThan,
109 TokenLessThanEq: OpLessThanOrEqual,
110 },
111 {
112 TokenPlus: OpAdd,
113 TokenMinus: OpSubtract,
114 },
115 {
116 TokenStar: OpMultiply,
117 TokenSlash: OpDivide,
118 TokenPercent: OpModulo,
119 },
120 }
121}
122
123type BinaryOpExpr struct {
124 LHS Expression
125 Op *Operation
126 RHS Expression
127
128 SrcRange hcl.Range
129}
130
131func (e *BinaryOpExpr) walkChildNodes(w internalWalkFunc) {
132 e.LHS = w(e.LHS).(Expression)
133 e.RHS = w(e.RHS).(Expression)
134}
135
136func (e *BinaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
137 impl := e.Op.Impl // assumed to be a function taking exactly two arguments
138 params := impl.Params()
139 lhsParam := params[0]
140 rhsParam := params[1]
141
142 var diags hcl.Diagnostics
143
144 givenLHSVal, lhsDiags := e.LHS.Value(ctx)
145 givenRHSVal, rhsDiags := e.RHS.Value(ctx)
146 diags = append(diags, lhsDiags...)
147 diags = append(diags, rhsDiags...)
148
149 lhsVal, err := convert.Convert(givenLHSVal, lhsParam.Type)
150 if err != nil {
151 diags = append(diags, &hcl.Diagnostic{
152 Severity: hcl.DiagError,
153 Summary: "Invalid operand",
154 Detail: fmt.Sprintf("Unsuitable value for left operand: %s.", err),
155 Subject: e.LHS.Range().Ptr(),
156 Context: &e.SrcRange,
157 })
158 }
159 rhsVal, err := convert.Convert(givenRHSVal, rhsParam.Type)
160 if err != nil {
161 diags = append(diags, &hcl.Diagnostic{
162 Severity: hcl.DiagError,
163 Summary: "Invalid operand",
164 Detail: fmt.Sprintf("Unsuitable value for right operand: %s.", err),
165 Subject: e.RHS.Range().Ptr(),
166 Context: &e.SrcRange,
167 })
168 }
169
170 if diags.HasErrors() {
171 // Don't actually try the call if we have errors already, since the
172 // this will probably just produce a confusing duplicative diagnostic.
173 return cty.UnknownVal(e.Op.Type), diags
174 }
175
176 args := []cty.Value{lhsVal, rhsVal}
177 result, err := impl.Call(args)
178 if err != nil {
179 diags = append(diags, &hcl.Diagnostic{
180 // FIXME: This diagnostic is useless.
181 Severity: hcl.DiagError,
182 Summary: "Operation failed",
183 Detail: fmt.Sprintf("Error during operation: %s.", err),
184 Subject: &e.SrcRange,
185 })
186 return cty.UnknownVal(e.Op.Type), diags
187 }
188
189 return result, diags
190}
191
192func (e *BinaryOpExpr) Range() hcl.Range {
193 return e.SrcRange
194}
195
196func (e *BinaryOpExpr) StartRange() hcl.Range {
197 return e.LHS.StartRange()
198}
199
200type UnaryOpExpr struct {
201 Op *Operation
202 Val Expression
203
204 SrcRange hcl.Range
205 SymbolRange hcl.Range
206}
207
208func (e *UnaryOpExpr) walkChildNodes(w internalWalkFunc) {
209 e.Val = w(e.Val).(Expression)
210}
211
212func (e *UnaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
213 impl := e.Op.Impl // assumed to be a function taking exactly one argument
214 params := impl.Params()
215 param := params[0]
216
217 givenVal, diags := e.Val.Value(ctx)
218
219 val, err := convert.Convert(givenVal, param.Type)
220 if err != nil {
221 diags = append(diags, &hcl.Diagnostic{
222 Severity: hcl.DiagError,
223 Summary: "Invalid operand",
224 Detail: fmt.Sprintf("Unsuitable value for unary operand: %s.", err),
225 Subject: e.Val.Range().Ptr(),
226 Context: &e.SrcRange,
227 })
228 }
229
230 if diags.HasErrors() {
231 // Don't actually try the call if we have errors already, since the
232 // this will probably just produce a confusing duplicative diagnostic.
233 return cty.UnknownVal(e.Op.Type), diags
234 }
235
236 args := []cty.Value{val}
237 result, err := impl.Call(args)
238 if err != nil {
239 diags = append(diags, &hcl.Diagnostic{
240 // FIXME: This diagnostic is useless.
241 Severity: hcl.DiagError,
242 Summary: "Operation failed",
243 Detail: fmt.Sprintf("Error during operation: %s.", err),
244 Subject: &e.SrcRange,
245 })
246 return cty.UnknownVal(e.Op.Type), diags
247 }
248
249 return result, diags
250}
251
252func (e *UnaryOpExpr) Range() hcl.Range {
253 return e.SrcRange
254}
255
256func (e *UnaryOpExpr) StartRange() hcl.Range {
257 return e.SymbolRange
258}