]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression_ops.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / hcl2 / hcl / hclsyntax / expression_ops.go
CommitLineData
15c0b25d
AP
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) {
107c1cdb
ND
132 w(e.LHS)
133 w(e.RHS)
15c0b25d
AP
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{
107c1cdb
ND
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 Expression: e.LHS,
158 EvalContext: ctx,
15c0b25d
AP
159 })
160 }
161 rhsVal, err := convert.Convert(givenRHSVal, rhsParam.Type)
162 if err != nil {
163 diags = append(diags, &hcl.Diagnostic{
107c1cdb
ND
164 Severity: hcl.DiagError,
165 Summary: "Invalid operand",
166 Detail: fmt.Sprintf("Unsuitable value for right operand: %s.", err),
167 Subject: e.RHS.Range().Ptr(),
168 Context: &e.SrcRange,
169 Expression: e.RHS,
170 EvalContext: ctx,
15c0b25d
AP
171 })
172 }
173
174 if diags.HasErrors() {
175 // Don't actually try the call if we have errors already, since the
176 // this will probably just produce a confusing duplicative diagnostic.
177 return cty.UnknownVal(e.Op.Type), diags
178 }
179
180 args := []cty.Value{lhsVal, rhsVal}
181 result, err := impl.Call(args)
182 if err != nil {
183 diags = append(diags, &hcl.Diagnostic{
184 // FIXME: This diagnostic is useless.
107c1cdb
ND
185 Severity: hcl.DiagError,
186 Summary: "Operation failed",
187 Detail: fmt.Sprintf("Error during operation: %s.", err),
188 Subject: &e.SrcRange,
189 Expression: e,
190 EvalContext: ctx,
15c0b25d
AP
191 })
192 return cty.UnknownVal(e.Op.Type), diags
193 }
194
195 return result, diags
196}
197
198func (e *BinaryOpExpr) Range() hcl.Range {
199 return e.SrcRange
200}
201
202func (e *BinaryOpExpr) StartRange() hcl.Range {
203 return e.LHS.StartRange()
204}
205
206type UnaryOpExpr struct {
207 Op *Operation
208 Val Expression
209
210 SrcRange hcl.Range
211 SymbolRange hcl.Range
212}
213
214func (e *UnaryOpExpr) walkChildNodes(w internalWalkFunc) {
107c1cdb 215 w(e.Val)
15c0b25d
AP
216}
217
218func (e *UnaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
219 impl := e.Op.Impl // assumed to be a function taking exactly one argument
220 params := impl.Params()
221 param := params[0]
222
223 givenVal, diags := e.Val.Value(ctx)
224
225 val, err := convert.Convert(givenVal, param.Type)
226 if err != nil {
227 diags = append(diags, &hcl.Diagnostic{
107c1cdb
ND
228 Severity: hcl.DiagError,
229 Summary: "Invalid operand",
230 Detail: fmt.Sprintf("Unsuitable value for unary operand: %s.", err),
231 Subject: e.Val.Range().Ptr(),
232 Context: &e.SrcRange,
233 Expression: e.Val,
234 EvalContext: ctx,
15c0b25d
AP
235 })
236 }
237
238 if diags.HasErrors() {
239 // Don't actually try the call if we have errors already, since the
240 // this will probably just produce a confusing duplicative diagnostic.
241 return cty.UnknownVal(e.Op.Type), diags
242 }
243
244 args := []cty.Value{val}
245 result, err := impl.Call(args)
246 if err != nil {
247 diags = append(diags, &hcl.Diagnostic{
248 // FIXME: This diagnostic is useless.
107c1cdb
ND
249 Severity: hcl.DiagError,
250 Summary: "Operation failed",
251 Detail: fmt.Sprintf("Error during operation: %s.", err),
252 Subject: &e.SrcRange,
253 Expression: e,
254 EvalContext: ctx,
15c0b25d
AP
255 })
256 return cty.UnknownVal(e.Op.Type), diags
257 }
258
259 return result, diags
260}
261
262func (e *UnaryOpExpr) Range() hcl.Range {
263 return e.SrcRange
264}
265
266func (e *UnaryOpExpr) StartRange() hcl.Range {
267 return e.SymbolRange
268}