vendor: update HIL to support more eval in indexes, implicit conversion
This commit is contained in:
parent
c7c31677d9
commit
e678222d56
|
@ -13,11 +13,8 @@ type Index struct {
|
|||
}
|
||||
|
||||
func (n *Index) Accept(v Visitor) Node {
|
||||
// the Key may have further interpolations
|
||||
switch n.Key.(type) {
|
||||
case *Call, *VariableAccess:
|
||||
n.Key = n.Key.Accept(v)
|
||||
}
|
||||
n.Target = n.Target.Accept(v)
|
||||
n.Key = n.Key.Accept(v)
|
||||
return v(n)
|
||||
}
|
||||
|
||||
|
|
|
@ -305,30 +305,35 @@ type typeCheckIndex struct {
|
|||
}
|
||||
|
||||
func (tc *typeCheckIndex) TypeCheck(v *TypeCheck) (ast.Node, error) {
|
||||
keyType := v.StackPop()
|
||||
targetType := v.StackPop()
|
||||
|
||||
// Ensure we have a VariableAccess as the target
|
||||
varAccessNode, ok := tc.n.Target.(*ast.VariableAccess)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("target of an index must be a VariableAccess node, was %T", tc.n.Target)
|
||||
return nil, fmt.Errorf(
|
||||
"target of an index must be a VariableAccess node, was %T", tc.n.Target)
|
||||
}
|
||||
|
||||
// Get the variable
|
||||
variable, ok := v.Scope.LookupVar(varAccessNode.Name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown variable accessed: %s", varAccessNode.Name)
|
||||
return nil, fmt.Errorf(
|
||||
"unknown variable accessed: %s", varAccessNode.Name)
|
||||
}
|
||||
|
||||
keyType, err := tc.n.Key.Type(v.Scope)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch variable.Type {
|
||||
switch targetType {
|
||||
case ast.TypeList:
|
||||
if keyType != ast.TypeInt {
|
||||
return nil, fmt.Errorf("key of an index must be an int, was %s", keyType)
|
||||
tc.n.Key = v.ImplicitConversion(keyType, ast.TypeInt, tc.n.Key)
|
||||
if tc.n.Key == nil {
|
||||
return nil, fmt.Errorf(
|
||||
"key of an index must be an int, was %s", keyType)
|
||||
}
|
||||
}
|
||||
|
||||
valType, err := ast.VariableListElementTypesAreHomogenous(varAccessNode.Name, variable.Value.([]ast.Variable))
|
||||
valType, err := ast.VariableListElementTypesAreHomogenous(
|
||||
varAccessNode.Name, variable.Value.([]ast.Variable))
|
||||
if err != nil {
|
||||
return tc.n, err
|
||||
}
|
||||
|
@ -337,10 +342,15 @@ func (tc *typeCheckIndex) TypeCheck(v *TypeCheck) (ast.Node, error) {
|
|||
return tc.n, nil
|
||||
case ast.TypeMap:
|
||||
if keyType != ast.TypeString {
|
||||
return nil, fmt.Errorf("key of an index must be a string, was %s", keyType)
|
||||
tc.n.Key = v.ImplicitConversion(keyType, ast.TypeString, tc.n.Key)
|
||||
if tc.n.Key == nil {
|
||||
return nil, fmt.Errorf(
|
||||
"key of an index must be a string, was %s", keyType)
|
||||
}
|
||||
}
|
||||
|
||||
valType, err := ast.VariableMapValueTypesAreHomogenous(varAccessNode.Name, variable.Value.(map[string]ast.Variable))
|
||||
valType, err := ast.VariableMapValueTypesAreHomogenous(
|
||||
varAccessNode.Name, variable.Value.(map[string]ast.Variable))
|
||||
if err != nil {
|
||||
return tc.n, err
|
||||
}
|
||||
|
|
|
@ -244,39 +244,20 @@ func (v *evalCall) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, e
|
|||
type evalIndex struct{ *ast.Index }
|
||||
|
||||
func (v *evalIndex) Eval(scope ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) {
|
||||
evalVarAccess, err := evalNode(v.Target)
|
||||
if err != nil {
|
||||
return nil, ast.TypeInvalid, err
|
||||
}
|
||||
target, targetType, err := evalVarAccess.Eval(scope, stack)
|
||||
|
||||
evalKey, err := evalNode(v.Key)
|
||||
if err != nil {
|
||||
return nil, ast.TypeInvalid, err
|
||||
}
|
||||
|
||||
key, keyType, err := evalKey.Eval(scope, stack)
|
||||
if err != nil {
|
||||
return nil, ast.TypeInvalid, err
|
||||
}
|
||||
key := stack.Pop().(*ast.LiteralNode)
|
||||
target := stack.Pop().(*ast.LiteralNode)
|
||||
|
||||
variableName := v.Index.Target.(*ast.VariableAccess).Name
|
||||
|
||||
switch targetType {
|
||||
switch target.Typex {
|
||||
case ast.TypeList:
|
||||
if keyType != ast.TypeInt {
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("key for indexing list %q must be an int, is %s", variableName, keyType)
|
||||
}
|
||||
|
||||
return v.evalListIndex(variableName, target, key)
|
||||
return v.evalListIndex(variableName, target.Value, key.Value)
|
||||
case ast.TypeMap:
|
||||
if keyType != ast.TypeString {
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("key for indexing map %q must be a string, is %s", variableName, keyType)
|
||||
}
|
||||
|
||||
return v.evalMapIndex(variableName, target, key)
|
||||
return v.evalMapIndex(variableName, target.Value, key.Value)
|
||||
default:
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("target %q for indexing must be ast.TypeList or ast.TypeMap, is %s", variableName, targetType)
|
||||
return nil, ast.TypeInvalid, fmt.Errorf(
|
||||
"target %q for indexing must be ast.TypeList or ast.TypeMap, is %s",
|
||||
variableName, target.Typex)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -285,12 +266,14 @@ func (v *evalIndex) evalListIndex(variableName string, target interface{}, key i
|
|||
// is a list and key is an int
|
||||
list, ok := target.([]ast.Variable)
|
||||
if !ok {
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast target to []Variable")
|
||||
return nil, ast.TypeInvalid, fmt.Errorf(
|
||||
"cannot cast target to []Variable, is: %T", target)
|
||||
}
|
||||
|
||||
keyInt, ok := key.(int)
|
||||
if !ok {
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast key to int")
|
||||
return nil, ast.TypeInvalid, fmt.Errorf(
|
||||
"cannot cast key to int, is: %T", key)
|
||||
}
|
||||
|
||||
if len(list) == 0 {
|
||||
|
@ -298,12 +281,13 @@ func (v *evalIndex) evalListIndex(variableName string, target interface{}, key i
|
|||
}
|
||||
|
||||
if keyInt < 0 || len(list) < keyInt+1 {
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("index %d out of range for list %s (max %d)", keyInt, variableName, len(list))
|
||||
return nil, ast.TypeInvalid, fmt.Errorf(
|
||||
"index %d out of range for list %s (max %d)",
|
||||
keyInt, variableName, len(list))
|
||||
}
|
||||
|
||||
returnVal := list[keyInt].Value
|
||||
returnType := list[keyInt].Type
|
||||
|
||||
return returnVal, returnType, nil
|
||||
}
|
||||
|
||||
|
@ -312,12 +296,14 @@ func (v *evalIndex) evalMapIndex(variableName string, target interface{}, key in
|
|||
// is a map and key is a string
|
||||
vmap, ok := target.(map[string]ast.Variable)
|
||||
if !ok {
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast target to map[string]Variable")
|
||||
return nil, ast.TypeInvalid, fmt.Errorf(
|
||||
"cannot cast target to map[string]Variable, is: %T", target)
|
||||
}
|
||||
|
||||
keyString, ok := key.(string)
|
||||
if !ok {
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast key to string")
|
||||
return nil, ast.TypeInvalid, fmt.Errorf(
|
||||
"cannot cast key to string, is: %T", key)
|
||||
}
|
||||
|
||||
if len(vmap) == 0 {
|
||||
|
@ -326,7 +312,8 @@ func (v *evalIndex) evalMapIndex(variableName string, target interface{}, key in
|
|||
|
||||
value, ok := vmap[keyString]
|
||||
if !ok {
|
||||
return nil, ast.TypeInvalid, fmt.Errorf("key %q does not exist in map %s", keyString, variableName)
|
||||
return nil, ast.TypeInvalid, fmt.Errorf(
|
||||
"key %q does not exist in map %s", keyString, variableName)
|
||||
}
|
||||
|
||||
return value.Value, value.Type, nil
|
||||
|
|
|
@ -1232,16 +1232,16 @@
|
|||
"revisionTime": "2016-10-08T07:35:57Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "OrnLOmhc0FcHYs02wtbu1siIsnM=",
|
||||
"checksumSHA1": "RYz/9y1RMZfg+oMgEyJIWiSl1dU=",
|
||||
"path": "github.com/hashicorp/hil",
|
||||
"revision": "37d5c183ca6a28a9177e5a375a3f0f3663160742",
|
||||
"revisionTime": "2016-10-12T19:56:11Z"
|
||||
"revision": "3e00ff29065d64c0f8e9ef7efed82686bbda81ca",
|
||||
"revisionTime": "2016-10-14T17:08:44Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "2NAuBxZXtp0e9orDclwc5ucnTSw=",
|
||||
"checksumSHA1": "WYIQ+nJPa191qpQIUsauF4wXYSw=",
|
||||
"path": "github.com/hashicorp/hil/ast",
|
||||
"revision": "37d5c183ca6a28a9177e5a375a3f0f3663160742",
|
||||
"revisionTime": "2016-10-12T19:56:11Z"
|
||||
"revision": "3e00ff29065d64c0f8e9ef7efed82686bbda81ca",
|
||||
"revisionTime": "2016-10-14T17:08:44Z"
|
||||
},
|
||||
{
|
||||
"path": "github.com/hashicorp/logutils",
|
||||
|
|
Loading…
Reference in New Issue