mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-09-19 01:29:57 +00:00
961c878e0d
Switch to using Go modules. This migrates our vendor.json to use Go 1.11's modules system, and replaces the vendor folder with the output of go mod vendor. The vendored code should remain basically the same; I believe some tree shaking of packages and support scripts/licenses/READMEs/etc. happened. This also fixes Travis and our Makefile to no longer use govendor.
269 lines
6.0 KiB
Go
269 lines
6.0 KiB
Go
package hclsyntax
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/hcl2/hcl"
|
|
"github.com/zclconf/go-cty/cty"
|
|
"github.com/zclconf/go-cty/cty/convert"
|
|
"github.com/zclconf/go-cty/cty/function"
|
|
"github.com/zclconf/go-cty/cty/function/stdlib"
|
|
)
|
|
|
|
type Operation struct {
|
|
Impl function.Function
|
|
Type cty.Type
|
|
}
|
|
|
|
var (
|
|
OpLogicalOr = &Operation{
|
|
Impl: stdlib.OrFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
OpLogicalAnd = &Operation{
|
|
Impl: stdlib.AndFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
OpLogicalNot = &Operation{
|
|
Impl: stdlib.NotFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
|
|
OpEqual = &Operation{
|
|
Impl: stdlib.EqualFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
OpNotEqual = &Operation{
|
|
Impl: stdlib.NotEqualFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
|
|
OpGreaterThan = &Operation{
|
|
Impl: stdlib.GreaterThanFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
OpGreaterThanOrEqual = &Operation{
|
|
Impl: stdlib.GreaterThanOrEqualToFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
OpLessThan = &Operation{
|
|
Impl: stdlib.LessThanFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
OpLessThanOrEqual = &Operation{
|
|
Impl: stdlib.LessThanOrEqualToFunc,
|
|
Type: cty.Bool,
|
|
}
|
|
|
|
OpAdd = &Operation{
|
|
Impl: stdlib.AddFunc,
|
|
Type: cty.Number,
|
|
}
|
|
OpSubtract = &Operation{
|
|
Impl: stdlib.SubtractFunc,
|
|
Type: cty.Number,
|
|
}
|
|
OpMultiply = &Operation{
|
|
Impl: stdlib.MultiplyFunc,
|
|
Type: cty.Number,
|
|
}
|
|
OpDivide = &Operation{
|
|
Impl: stdlib.DivideFunc,
|
|
Type: cty.Number,
|
|
}
|
|
OpModulo = &Operation{
|
|
Impl: stdlib.ModuloFunc,
|
|
Type: cty.Number,
|
|
}
|
|
OpNegate = &Operation{
|
|
Impl: stdlib.NegateFunc,
|
|
Type: cty.Number,
|
|
}
|
|
)
|
|
|
|
var binaryOps []map[TokenType]*Operation
|
|
|
|
func init() {
|
|
// This operation table maps from the operator's token type
|
|
// to the AST operation type. All expressions produced from
|
|
// binary operators are BinaryOp nodes.
|
|
//
|
|
// Binary operator groups are listed in order of precedence, with
|
|
// the *lowest* precedence first. Operators within the same group
|
|
// have left-to-right associativity.
|
|
binaryOps = []map[TokenType]*Operation{
|
|
{
|
|
TokenOr: OpLogicalOr,
|
|
},
|
|
{
|
|
TokenAnd: OpLogicalAnd,
|
|
},
|
|
{
|
|
TokenEqualOp: OpEqual,
|
|
TokenNotEqual: OpNotEqual,
|
|
},
|
|
{
|
|
TokenGreaterThan: OpGreaterThan,
|
|
TokenGreaterThanEq: OpGreaterThanOrEqual,
|
|
TokenLessThan: OpLessThan,
|
|
TokenLessThanEq: OpLessThanOrEqual,
|
|
},
|
|
{
|
|
TokenPlus: OpAdd,
|
|
TokenMinus: OpSubtract,
|
|
},
|
|
{
|
|
TokenStar: OpMultiply,
|
|
TokenSlash: OpDivide,
|
|
TokenPercent: OpModulo,
|
|
},
|
|
}
|
|
}
|
|
|
|
type BinaryOpExpr struct {
|
|
LHS Expression
|
|
Op *Operation
|
|
RHS Expression
|
|
|
|
SrcRange hcl.Range
|
|
}
|
|
|
|
func (e *BinaryOpExpr) walkChildNodes(w internalWalkFunc) {
|
|
w(e.LHS)
|
|
w(e.RHS)
|
|
}
|
|
|
|
func (e *BinaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
|
|
impl := e.Op.Impl // assumed to be a function taking exactly two arguments
|
|
params := impl.Params()
|
|
lhsParam := params[0]
|
|
rhsParam := params[1]
|
|
|
|
var diags hcl.Diagnostics
|
|
|
|
givenLHSVal, lhsDiags := e.LHS.Value(ctx)
|
|
givenRHSVal, rhsDiags := e.RHS.Value(ctx)
|
|
diags = append(diags, lhsDiags...)
|
|
diags = append(diags, rhsDiags...)
|
|
|
|
lhsVal, err := convert.Convert(givenLHSVal, lhsParam.Type)
|
|
if err != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid operand",
|
|
Detail: fmt.Sprintf("Unsuitable value for left operand: %s.", err),
|
|
Subject: e.LHS.Range().Ptr(),
|
|
Context: &e.SrcRange,
|
|
Expression: e.LHS,
|
|
EvalContext: ctx,
|
|
})
|
|
}
|
|
rhsVal, err := convert.Convert(givenRHSVal, rhsParam.Type)
|
|
if err != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid operand",
|
|
Detail: fmt.Sprintf("Unsuitable value for right operand: %s.", err),
|
|
Subject: e.RHS.Range().Ptr(),
|
|
Context: &e.SrcRange,
|
|
Expression: e.RHS,
|
|
EvalContext: ctx,
|
|
})
|
|
}
|
|
|
|
if diags.HasErrors() {
|
|
// Don't actually try the call if we have errors already, since the
|
|
// this will probably just produce a confusing duplicative diagnostic.
|
|
return cty.UnknownVal(e.Op.Type), diags
|
|
}
|
|
|
|
args := []cty.Value{lhsVal, rhsVal}
|
|
result, err := impl.Call(args)
|
|
if err != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
// FIXME: This diagnostic is useless.
|
|
Severity: hcl.DiagError,
|
|
Summary: "Operation failed",
|
|
Detail: fmt.Sprintf("Error during operation: %s.", err),
|
|
Subject: &e.SrcRange,
|
|
Expression: e,
|
|
EvalContext: ctx,
|
|
})
|
|
return cty.UnknownVal(e.Op.Type), diags
|
|
}
|
|
|
|
return result, diags
|
|
}
|
|
|
|
func (e *BinaryOpExpr) Range() hcl.Range {
|
|
return e.SrcRange
|
|
}
|
|
|
|
func (e *BinaryOpExpr) StartRange() hcl.Range {
|
|
return e.LHS.StartRange()
|
|
}
|
|
|
|
type UnaryOpExpr struct {
|
|
Op *Operation
|
|
Val Expression
|
|
|
|
SrcRange hcl.Range
|
|
SymbolRange hcl.Range
|
|
}
|
|
|
|
func (e *UnaryOpExpr) walkChildNodes(w internalWalkFunc) {
|
|
w(e.Val)
|
|
}
|
|
|
|
func (e *UnaryOpExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
|
|
impl := e.Op.Impl // assumed to be a function taking exactly one argument
|
|
params := impl.Params()
|
|
param := params[0]
|
|
|
|
givenVal, diags := e.Val.Value(ctx)
|
|
|
|
val, err := convert.Convert(givenVal, param.Type)
|
|
if err != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid operand",
|
|
Detail: fmt.Sprintf("Unsuitable value for unary operand: %s.", err),
|
|
Subject: e.Val.Range().Ptr(),
|
|
Context: &e.SrcRange,
|
|
Expression: e.Val,
|
|
EvalContext: ctx,
|
|
})
|
|
}
|
|
|
|
if diags.HasErrors() {
|
|
// Don't actually try the call if we have errors already, since the
|
|
// this will probably just produce a confusing duplicative diagnostic.
|
|
return cty.UnknownVal(e.Op.Type), diags
|
|
}
|
|
|
|
args := []cty.Value{val}
|
|
result, err := impl.Call(args)
|
|
if err != nil {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
// FIXME: This diagnostic is useless.
|
|
Severity: hcl.DiagError,
|
|
Summary: "Operation failed",
|
|
Detail: fmt.Sprintf("Error during operation: %s.", err),
|
|
Subject: &e.SrcRange,
|
|
Expression: e,
|
|
EvalContext: ctx,
|
|
})
|
|
return cty.UnknownVal(e.Op.Type), diags
|
|
}
|
|
|
|
return result, diags
|
|
}
|
|
|
|
func (e *UnaryOpExpr) Range() hcl.Range {
|
|
return e.SrcRange
|
|
}
|
|
|
|
func (e *UnaryOpExpr) StartRange() hcl.Range {
|
|
return e.SymbolRange
|
|
}
|