* lang/funcs/flatten: accept sets and tuples, return tuples

* lang/funcs: flatten should handle sets and tuples

* flatten now returns a tuple
This commit is contained in:
Kristin Laemmert 2019-05-01 10:19:40 -04:00 committed by GitHub
parent 6adcc7ab73
commit 8520f4e4a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 65 additions and 12 deletions

View File

@ -427,32 +427,47 @@ var FlattenFunc = function.New(&function.Spec{
Params: []function.Parameter{ Params: []function.Parameter{
{ {
Name: "list", Name: "list",
Type: cty.List(cty.DynamicPseudoType), Type: cty.DynamicPseudoType,
}, },
}, },
Type: function.StaticReturnType(cty.List(cty.DynamicPseudoType)), Type: func(args []cty.Value) (cty.Type, error) {
if !args[0].IsWhollyKnown() {
return cty.DynamicPseudoType, nil
}
argTy := args[0].Type()
if !argTy.IsListType() && !argTy.IsSetType() && !argTy.IsTupleType() {
return cty.NilType, fmt.Errorf("can only flatten lists, sets and tuples")
}
outputList := make([]cty.Value, 0)
retVal := flattener(outputList, args[0])
tys := make([]cty.Type, len(retVal))
for i, ty := range retVal {
tys[i] = ty.Type()
}
return cty.Tuple(tys), nil
},
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) { Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
inputList := args[0] inputList := args[0]
if !inputList.IsWhollyKnown() { if !inputList.IsWhollyKnown() {
return cty.UnknownVal(retType), nil return cty.UnknownVal(retType), nil
} }
if inputList.LengthInt() == 0 { if inputList.LengthInt() == 0 {
return cty.ListValEmpty(retType.ElementType()), nil return cty.EmptyTupleVal, nil
} }
outputList := make([]cty.Value, 0) outputList := make([]cty.Value, 0)
return cty.ListVal(flattener(outputList, inputList)), nil return cty.TupleVal(flattener(outputList, inputList)), nil
}, },
}) })
// Flatten until it's not a cty.List // Flatten until it's not a cty.List
func flattener(finalList []cty.Value, flattenList cty.Value) []cty.Value { func flattener(finalList []cty.Value, flattenList cty.Value) []cty.Value {
for it := flattenList.ElementIterator(); it.Next(); { for it := flattenList.ElementIterator(); it.Next(); {
_, val := it.Element() _, val := it.Element()
if val.Type().IsListType() { if val.Type().IsListType() || val.Type().IsSetType() || val.Type().IsTupleType() {
finalList = flattener(finalList, val) finalList = flattener(finalList, val)
} else { } else {
finalList = append(finalList, val) finalList = append(finalList, val)

View File

@ -1035,7 +1035,7 @@ func TestFlatten(t *testing.T) {
cty.StringVal("d"), cty.StringVal("d"),
}), }),
}), }),
cty.ListVal([]cty.Value{ cty.TupleVal([]cty.Value{
cty.StringVal("a"), cty.StringVal("a"),
cty.StringVal("b"), cty.StringVal("b"),
cty.StringVal("c"), cty.StringVal("c"),
@ -1054,12 +1054,50 @@ func TestFlatten(t *testing.T) {
cty.StringVal("d"), cty.StringVal("d"),
}), }),
}), }),
cty.UnknownVal(cty.List(cty.DynamicPseudoType)), cty.DynamicVal,
false, false,
}, },
{ {
cty.ListValEmpty(cty.String), cty.ListValEmpty(cty.String),
cty.ListValEmpty(cty.DynamicPseudoType), cty.EmptyTupleVal,
false,
},
{
cty.SetVal([]cty.Value{
cty.SetVal([]cty.Value{
cty.StringVal("a"),
cty.StringVal("b"),
}),
cty.SetVal([]cty.Value{
cty.StringVal("c"),
cty.StringVal("d"),
}),
}),
cty.TupleVal([]cty.Value{
cty.StringVal("a"),
cty.StringVal("b"),
cty.StringVal("c"),
cty.StringVal("d"),
}),
false,
},
{
cty.TupleVal([]cty.Value{
cty.SetVal([]cty.Value{
cty.StringVal("a"),
cty.StringVal("b"),
}),
cty.ListVal([]cty.Value{
cty.StringVal("c"),
cty.StringVal("d"),
}),
}),
cty.TupleVal([]cty.Value{
cty.StringVal("a"),
cty.StringVal("b"),
cty.StringVal("c"),
cty.StringVal("d"),
}),
false, false,
}, },
} }

View File

@ -309,8 +309,8 @@ func TestFunctions(t *testing.T) {
"flatten": { "flatten": {
{ {
`flatten([tolist(["a", "b"]), tolist(["c", "d"])])`, `flatten([["a", "b"], ["c", "d"]])`,
cty.ListVal([]cty.Value{ cty.TupleVal([]cty.Value{
cty.StringVal("a"), cty.StringVal("a"),
cty.StringVal("b"), cty.StringVal("b"),
cty.StringVal("c"), cty.StringVal("c"),