github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/lang/funcs/collection.go (about)

     1  package funcs
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math/big"
     7  	"sort"
     8  
     9  	"github.com/zclconf/go-cty/cty"
    10  	"github.com/zclconf/go-cty/cty/convert"
    11  	"github.com/zclconf/go-cty/cty/function"
    12  	"github.com/zclconf/go-cty/cty/function/stdlib"
    13  	"github.com/zclconf/go-cty/cty/gocty"
    14  )
    15  
    16  var LengthFunc = function.New(&function.Spec{
    17  	Params: []function.Parameter{
    18  		{
    19  			Name:             "value",
    20  			Type:             cty.DynamicPseudoType,
    21  			AllowDynamicType: true,
    22  			AllowUnknown:     true,
    23  			AllowMarked:      true,
    24  		},
    25  	},
    26  	Type: func(args []cty.Value) (cty.Type, error) {
    27  		collTy := args[0].Type()
    28  		switch {
    29  		case collTy == cty.String || collTy.IsTupleType() || collTy.IsObjectType() || collTy.IsListType() || collTy.IsMapType() || collTy.IsSetType() || collTy == cty.DynamicPseudoType:
    30  			return cty.Number, nil
    31  		default:
    32  			return cty.Number, errors.New("argument must be a string, a collection type, or a structural type")
    33  		}
    34  	},
    35  	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
    36  		coll := args[0]
    37  		collTy := args[0].Type()
    38  		marks := coll.Marks()
    39  		switch {
    40  		case collTy == cty.DynamicPseudoType:
    41  			return cty.UnknownVal(cty.Number).WithMarks(marks), nil
    42  		case collTy.IsTupleType():
    43  			l := len(collTy.TupleElementTypes())
    44  			return cty.NumberIntVal(int64(l)).WithMarks(marks), nil
    45  		case collTy.IsObjectType():
    46  			l := len(collTy.AttributeTypes())
    47  			return cty.NumberIntVal(int64(l)).WithMarks(marks), nil
    48  		case collTy == cty.String:
    49  			// We'll delegate to the cty stdlib strlen function here, because
    50  			// it deals with all of the complexities of tokenizing unicode
    51  			// grapheme clusters.
    52  			return stdlib.Strlen(coll)
    53  		case collTy.IsListType() || collTy.IsSetType() || collTy.IsMapType():
    54  			return coll.Length(), nil
    55  		default:
    56  			// Should never happen, because of the checks in our Type func above
    57  			return cty.UnknownVal(cty.Number), errors.New("impossible value type for length(...)")
    58  		}
    59  	},
    60  })
    61  
    62  // AllTrueFunc constructs a function that returns true if all elements of the
    63  // list are true. If the list is empty, return true.
    64  var AllTrueFunc = function.New(&function.Spec{
    65  	Params: []function.Parameter{
    66  		{
    67  			Name: "list",
    68  			Type: cty.List(cty.Bool),
    69  		},
    70  	},
    71  	Type: function.StaticReturnType(cty.Bool),
    72  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
    73  		result := cty.True
    74  		for it := args[0].ElementIterator(); it.Next(); {
    75  			_, v := it.Element()
    76  			if !v.IsKnown() {
    77  				return cty.UnknownVal(cty.Bool), nil
    78  			}
    79  			if v.IsNull() {
    80  				return cty.False, nil
    81  			}
    82  			result = result.And(v)
    83  			if result.False() {
    84  				return cty.False, nil
    85  			}
    86  		}
    87  		return result, nil
    88  	},
    89  })
    90  
    91  // AnyTrueFunc constructs a function that returns true if any element of the
    92  // list is true. If the list is empty, return false.
    93  var AnyTrueFunc = function.New(&function.Spec{
    94  	Params: []function.Parameter{
    95  		{
    96  			Name: "list",
    97  			Type: cty.List(cty.Bool),
    98  		},
    99  	},
   100  	Type: function.StaticReturnType(cty.Bool),
   101  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   102  		result := cty.False
   103  		var hasUnknown bool
   104  		for it := args[0].ElementIterator(); it.Next(); {
   105  			_, v := it.Element()
   106  			if !v.IsKnown() {
   107  				hasUnknown = true
   108  				continue
   109  			}
   110  			if v.IsNull() {
   111  				continue
   112  			}
   113  			result = result.Or(v)
   114  			if result.True() {
   115  				return cty.True, nil
   116  			}
   117  		}
   118  		if hasUnknown {
   119  			return cty.UnknownVal(cty.Bool), nil
   120  		}
   121  		return result, nil
   122  	},
   123  })
   124  
   125  // CoalesceFunc constructs a function that takes any number of arguments and
   126  // returns the first one that isn't empty. This function was copied from go-cty
   127  // stdlib and modified so that it returns the first *non-empty* non-null element
   128  // from a sequence, instead of merely the first non-null.
   129  var CoalesceFunc = function.New(&function.Spec{
   130  	Params: []function.Parameter{},
   131  	VarParam: &function.Parameter{
   132  		Name:             "vals",
   133  		Type:             cty.DynamicPseudoType,
   134  		AllowUnknown:     true,
   135  		AllowDynamicType: true,
   136  		AllowNull:        true,
   137  	},
   138  	Type: func(args []cty.Value) (ret cty.Type, err error) {
   139  		argTypes := make([]cty.Type, len(args))
   140  		for i, val := range args {
   141  			argTypes[i] = val.Type()
   142  		}
   143  		retType, _ := convert.UnifyUnsafe(argTypes)
   144  		if retType == cty.NilType {
   145  			return cty.NilType, errors.New("all arguments must have the same type")
   146  		}
   147  		return retType, nil
   148  	},
   149  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   150  		for _, argVal := range args {
   151  			// We already know this will succeed because of the checks in our Type func above
   152  			argVal, _ = convert.Convert(argVal, retType)
   153  			if !argVal.IsKnown() {
   154  				return cty.UnknownVal(retType), nil
   155  			}
   156  			if argVal.IsNull() {
   157  				continue
   158  			}
   159  			if retType == cty.String && argVal.RawEquals(cty.StringVal("")) {
   160  				continue
   161  			}
   162  
   163  			return argVal, nil
   164  		}
   165  		return cty.NilVal, errors.New("no non-null, non-empty-string arguments")
   166  	},
   167  })
   168  
   169  // IndexFunc constructs a function that finds the element index for a given value in a list.
   170  var IndexFunc = function.New(&function.Spec{
   171  	Params: []function.Parameter{
   172  		{
   173  			Name: "list",
   174  			Type: cty.DynamicPseudoType,
   175  		},
   176  		{
   177  			Name: "value",
   178  			Type: cty.DynamicPseudoType,
   179  		},
   180  	},
   181  	Type: function.StaticReturnType(cty.Number),
   182  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   183  		if !(args[0].Type().IsListType() || args[0].Type().IsTupleType()) {
   184  			return cty.NilVal, errors.New("argument must be a list or tuple")
   185  		}
   186  
   187  		if !args[0].IsKnown() {
   188  			return cty.UnknownVal(cty.Number), nil
   189  		}
   190  
   191  		if args[0].LengthInt() == 0 { // Easy path
   192  			return cty.NilVal, errors.New("cannot search an empty list")
   193  		}
   194  
   195  		for it := args[0].ElementIterator(); it.Next(); {
   196  			i, v := it.Element()
   197  			eq, err := stdlib.Equal(v, args[1])
   198  			if err != nil {
   199  				return cty.NilVal, err
   200  			}
   201  			if !eq.IsKnown() {
   202  				return cty.UnknownVal(cty.Number), nil
   203  			}
   204  			if eq.True() {
   205  				return i, nil
   206  			}
   207  		}
   208  		return cty.NilVal, errors.New("item not found")
   209  
   210  	},
   211  })
   212  
   213  // LookupFunc constructs a function that performs dynamic lookups of map types.
   214  var LookupFunc = function.New(&function.Spec{
   215  	Params: []function.Parameter{
   216  		{
   217  			Name:        "inputMap",
   218  			Type:        cty.DynamicPseudoType,
   219  			AllowMarked: true,
   220  		},
   221  		{
   222  			Name:        "key",
   223  			Type:        cty.String,
   224  			AllowMarked: true,
   225  		},
   226  	},
   227  	VarParam: &function.Parameter{
   228  		Name:             "default",
   229  		Type:             cty.DynamicPseudoType,
   230  		AllowUnknown:     true,
   231  		AllowDynamicType: true,
   232  		AllowNull:        true,
   233  		AllowMarked:      true,
   234  	},
   235  	Type: func(args []cty.Value) (ret cty.Type, err error) {
   236  		if len(args) < 1 || len(args) > 3 {
   237  			return cty.NilType, fmt.Errorf("lookup() takes two or three arguments, got %d", len(args))
   238  		}
   239  
   240  		ty := args[0].Type()
   241  
   242  		switch {
   243  		case ty.IsObjectType():
   244  			if !args[1].IsKnown() {
   245  				return cty.DynamicPseudoType, nil
   246  			}
   247  
   248  			keyVal, _ := args[1].Unmark()
   249  			key := keyVal.AsString()
   250  			if ty.HasAttribute(key) {
   251  				return args[0].GetAttr(key).Type(), nil
   252  			} else if len(args) == 3 {
   253  				// if the key isn't found but a default is provided,
   254  				// return the default type
   255  				return args[2].Type(), nil
   256  			}
   257  			return cty.DynamicPseudoType, function.NewArgErrorf(0, "the given object has no attribute %q", key)
   258  		case ty.IsMapType():
   259  			if len(args) == 3 {
   260  				_, err = convert.Convert(args[2], ty.ElementType())
   261  				if err != nil {
   262  					return cty.NilType, function.NewArgErrorf(2, "the default value must have the same type as the map elements")
   263  				}
   264  			}
   265  			return ty.ElementType(), nil
   266  		default:
   267  			return cty.NilType, function.NewArgErrorf(0, "lookup() requires a map as the first argument")
   268  		}
   269  	},
   270  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   271  		var defaultVal cty.Value
   272  		defaultValueSet := false
   273  
   274  		if len(args) == 3 {
   275  			// intentionally leave default value marked
   276  			defaultVal = args[2]
   277  			defaultValueSet = true
   278  		}
   279  
   280  		// keep track of marks from the collection and key
   281  		var markses []cty.ValueMarks
   282  
   283  		// unmark collection, retain marks to reapply later
   284  		mapVar, mapMarks := args[0].Unmark()
   285  		markses = append(markses, mapMarks)
   286  
   287  		// include marks on the key in the result
   288  		keyVal, keyMarks := args[1].Unmark()
   289  		if len(keyMarks) > 0 {
   290  			markses = append(markses, keyMarks)
   291  		}
   292  		lookupKey := keyVal.AsString()
   293  
   294  		if !mapVar.IsKnown() {
   295  			return cty.UnknownVal(retType).WithMarks(markses...), nil
   296  		}
   297  
   298  		if mapVar.Type().IsObjectType() {
   299  			if mapVar.Type().HasAttribute(lookupKey) {
   300  				return mapVar.GetAttr(lookupKey).WithMarks(markses...), nil
   301  			}
   302  		} else if mapVar.HasIndex(cty.StringVal(lookupKey)) == cty.True {
   303  			return mapVar.Index(cty.StringVal(lookupKey)).WithMarks(markses...), nil
   304  		}
   305  
   306  		if defaultValueSet {
   307  			defaultVal, err = convert.Convert(defaultVal, retType)
   308  			if err != nil {
   309  				return cty.NilVal, err
   310  			}
   311  			return defaultVal.WithMarks(markses...), nil
   312  		}
   313  
   314  		return cty.UnknownVal(cty.DynamicPseudoType), fmt.Errorf(
   315  			"lookup failed to find key %s", redactIfSensitive(lookupKey, keyMarks))
   316  	},
   317  })
   318  
   319  // MatchkeysFunc constructs a function that constructs a new list by taking a
   320  // subset of elements from one list whose indexes match the corresponding
   321  // indexes of values in another list.
   322  var MatchkeysFunc = function.New(&function.Spec{
   323  	Params: []function.Parameter{
   324  		{
   325  			Name: "values",
   326  			Type: cty.List(cty.DynamicPseudoType),
   327  		},
   328  		{
   329  			Name: "keys",
   330  			Type: cty.List(cty.DynamicPseudoType),
   331  		},
   332  		{
   333  			Name: "searchset",
   334  			Type: cty.List(cty.DynamicPseudoType),
   335  		},
   336  	},
   337  	Type: func(args []cty.Value) (cty.Type, error) {
   338  		ty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})
   339  		if ty == cty.NilType {
   340  			return cty.NilType, errors.New("keys and searchset must be of the same type")
   341  		}
   342  
   343  		// the return type is based on args[0] (values)
   344  		return args[0].Type(), nil
   345  	},
   346  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   347  		if !args[0].IsKnown() {
   348  			return cty.UnknownVal(cty.List(retType.ElementType())), nil
   349  		}
   350  
   351  		if args[0].LengthInt() != args[1].LengthInt() {
   352  			return cty.ListValEmpty(retType.ElementType()), errors.New("length of keys and values should be equal")
   353  		}
   354  
   355  		output := make([]cty.Value, 0)
   356  		values := args[0]
   357  
   358  		// Keys and searchset must be the same type.
   359  		// We can skip error checking here because we've already verified that
   360  		// they can be unified in the Type function
   361  		ty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})
   362  		keys, _ := convert.Convert(args[1], ty)
   363  		searchset, _ := convert.Convert(args[2], ty)
   364  
   365  		// if searchset is empty, return an empty list.
   366  		if searchset.LengthInt() == 0 {
   367  			return cty.ListValEmpty(retType.ElementType()), nil
   368  		}
   369  
   370  		if !values.IsWhollyKnown() || !keys.IsWhollyKnown() {
   371  			return cty.UnknownVal(retType), nil
   372  		}
   373  
   374  		i := 0
   375  		for it := keys.ElementIterator(); it.Next(); {
   376  			_, key := it.Element()
   377  			for iter := searchset.ElementIterator(); iter.Next(); {
   378  				_, search := iter.Element()
   379  				eq, err := stdlib.Equal(key, search)
   380  				if err != nil {
   381  					return cty.NilVal, err
   382  				}
   383  				if !eq.IsKnown() {
   384  					return cty.ListValEmpty(retType.ElementType()), nil
   385  				}
   386  				if eq.True() {
   387  					v := values.Index(cty.NumberIntVal(int64(i)))
   388  					output = append(output, v)
   389  					break
   390  				}
   391  			}
   392  			i++
   393  		}
   394  
   395  		// if we haven't matched any key, then output is an empty list.
   396  		if len(output) == 0 {
   397  			return cty.ListValEmpty(retType.ElementType()), nil
   398  		}
   399  		return cty.ListVal(output), nil
   400  	},
   401  })
   402  
   403  // OneFunc returns either the first element of a one-element list, or null
   404  // if given a zero-element list.
   405  var OneFunc = function.New(&function.Spec{
   406  	Params: []function.Parameter{
   407  		{
   408  			Name: "list",
   409  			Type: cty.DynamicPseudoType,
   410  		},
   411  	},
   412  	Type: func(args []cty.Value) (cty.Type, error) {
   413  		ty := args[0].Type()
   414  		switch {
   415  		case ty.IsListType() || ty.IsSetType():
   416  			return ty.ElementType(), nil
   417  		case ty.IsTupleType():
   418  			etys := ty.TupleElementTypes()
   419  			switch len(etys) {
   420  			case 0:
   421  				// No specific type information, so we'll ultimately return
   422  				// a null value of unknown type.
   423  				return cty.DynamicPseudoType, nil
   424  			case 1:
   425  				return etys[0], nil
   426  			}
   427  		}
   428  		return cty.NilType, function.NewArgErrorf(0, "must be a list, set, or tuple value with either zero or one elements")
   429  	},
   430  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   431  		val := args[0]
   432  		ty := val.Type()
   433  
   434  		// Our parameter spec above doesn't set AllowUnknown or AllowNull,
   435  		// so we can assume our top-level collection is both known and non-null
   436  		// in here.
   437  
   438  		switch {
   439  		case ty.IsListType() || ty.IsSetType():
   440  			lenVal := val.Length()
   441  			if !lenVal.IsKnown() {
   442  				return cty.UnknownVal(retType), nil
   443  			}
   444  			var l int
   445  			err := gocty.FromCtyValue(lenVal, &l)
   446  			if err != nil {
   447  				// It would be very strange to get here, because that would
   448  				// suggest that the length is either not a number or isn't
   449  				// an integer, which would suggest a bug in cty.
   450  				return cty.NilVal, fmt.Errorf("invalid collection length: %s", err)
   451  			}
   452  			switch l {
   453  			case 0:
   454  				return cty.NullVal(retType), nil
   455  			case 1:
   456  				var ret cty.Value
   457  				// We'll use an iterator here because that works for both lists
   458  				// and sets, whereas indexing directly would only work for lists.
   459  				// Since we've just checked the length, we should only actually
   460  				// run this loop body once.
   461  				for it := val.ElementIterator(); it.Next(); {
   462  					_, ret = it.Element()
   463  				}
   464  				return ret, nil
   465  			}
   466  		case ty.IsTupleType():
   467  			etys := ty.TupleElementTypes()
   468  			switch len(etys) {
   469  			case 0:
   470  				return cty.NullVal(retType), nil
   471  			case 1:
   472  				ret := val.Index(cty.NumberIntVal(0))
   473  				return ret, nil
   474  			}
   475  		}
   476  		return cty.NilVal, function.NewArgErrorf(0, "must be a list, set, or tuple value with either zero or one elements")
   477  	},
   478  })
   479  
   480  // SumFunc constructs a function that returns the sum of all
   481  // numbers provided in a list
   482  var SumFunc = function.New(&function.Spec{
   483  	Params: []function.Parameter{
   484  		{
   485  			Name: "list",
   486  			Type: cty.DynamicPseudoType,
   487  		},
   488  	},
   489  	Type: function.StaticReturnType(cty.Number),
   490  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   491  
   492  		if !args[0].CanIterateElements() {
   493  			return cty.NilVal, function.NewArgErrorf(0, "cannot sum noniterable")
   494  		}
   495  
   496  		if args[0].LengthInt() == 0 { // Easy path
   497  			return cty.NilVal, function.NewArgErrorf(0, "cannot sum an empty list")
   498  		}
   499  
   500  		arg := args[0].AsValueSlice()
   501  		ty := args[0].Type()
   502  
   503  		if !ty.IsListType() && !ty.IsSetType() && !ty.IsTupleType() {
   504  			return cty.NilVal, function.NewArgErrorf(0, fmt.Sprintf("argument must be list, set, or tuple. Received %s", ty.FriendlyName()))
   505  		}
   506  
   507  		if !args[0].IsWhollyKnown() {
   508  			return cty.UnknownVal(cty.Number), nil
   509  		}
   510  
   511  		// big.Float.Add can panic if the input values are opposing infinities,
   512  		// so we must catch that here in order to remain within
   513  		// the cty Function abstraction.
   514  		defer func() {
   515  			if r := recover(); r != nil {
   516  				if _, ok := r.(big.ErrNaN); ok {
   517  					ret = cty.NilVal
   518  					err = fmt.Errorf("can't compute sum of opposing infinities")
   519  				} else {
   520  					// not a panic we recognize
   521  					panic(r)
   522  				}
   523  			}
   524  		}()
   525  
   526  		s := arg[0]
   527  		if s.IsNull() {
   528  			return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
   529  		}
   530  		s, err = convert.Convert(s, cty.Number)
   531  		if err != nil {
   532  			return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
   533  		}
   534  		for _, v := range arg[1:] {
   535  			if v.IsNull() {
   536  				return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
   537  			}
   538  			v, err = convert.Convert(v, cty.Number)
   539  			if err != nil {
   540  				return cty.NilVal, function.NewArgErrorf(0, "argument must be list, set, or tuple of number values")
   541  			}
   542  			s = s.Add(v)
   543  		}
   544  
   545  		return s, nil
   546  	},
   547  })
   548  
   549  // TransposeFunc constructs a function that takes a map of lists of strings and
   550  // swaps the keys and values to produce a new map of lists of strings.
   551  var TransposeFunc = function.New(&function.Spec{
   552  	Params: []function.Parameter{
   553  		{
   554  			Name: "values",
   555  			Type: cty.Map(cty.List(cty.String)),
   556  		},
   557  	},
   558  	Type: function.StaticReturnType(cty.Map(cty.List(cty.String))),
   559  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   560  		inputMap := args[0]
   561  		if !inputMap.IsWhollyKnown() {
   562  			return cty.UnknownVal(retType), nil
   563  		}
   564  
   565  		outputMap := make(map[string]cty.Value)
   566  		tmpMap := make(map[string][]string)
   567  
   568  		for it := inputMap.ElementIterator(); it.Next(); {
   569  			inKey, inVal := it.Element()
   570  			for iter := inVal.ElementIterator(); iter.Next(); {
   571  				_, val := iter.Element()
   572  				if !val.Type().Equals(cty.String) {
   573  					return cty.MapValEmpty(cty.List(cty.String)), errors.New("input must be a map of lists of strings")
   574  				}
   575  
   576  				outKey := val.AsString()
   577  				if _, ok := tmpMap[outKey]; !ok {
   578  					tmpMap[outKey] = make([]string, 0)
   579  				}
   580  				outVal := tmpMap[outKey]
   581  				outVal = append(outVal, inKey.AsString())
   582  				sort.Strings(outVal)
   583  				tmpMap[outKey] = outVal
   584  			}
   585  		}
   586  
   587  		for outKey, outVal := range tmpMap {
   588  			values := make([]cty.Value, 0)
   589  			for _, v := range outVal {
   590  				values = append(values, cty.StringVal(v))
   591  			}
   592  			outputMap[outKey] = cty.ListVal(values)
   593  		}
   594  
   595  		if len(outputMap) == 0 {
   596  			return cty.MapValEmpty(cty.List(cty.String)), nil
   597  		}
   598  
   599  		return cty.MapVal(outputMap), nil
   600  	},
   601  })
   602  
   603  // ListFunc constructs a function that takes an arbitrary number of arguments
   604  // and returns a list containing those values in the same order.
   605  //
   606  // This function is deprecated in Terraform v0.12
   607  var ListFunc = function.New(&function.Spec{
   608  	Params: []function.Parameter{},
   609  	VarParam: &function.Parameter{
   610  		Name:             "vals",
   611  		Type:             cty.DynamicPseudoType,
   612  		AllowUnknown:     true,
   613  		AllowDynamicType: true,
   614  		AllowNull:        true,
   615  	},
   616  	Type: func(args []cty.Value) (ret cty.Type, err error) {
   617  		return cty.DynamicPseudoType, fmt.Errorf("the \"list\" function was deprecated in Terraform v0.12 and is no longer available; use tolist([ ... ]) syntax to write a literal list")
   618  	},
   619  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   620  		return cty.DynamicVal, fmt.Errorf("the \"list\" function was deprecated in Terraform v0.12 and is no longer available; use tolist([ ... ]) syntax to write a literal list")
   621  	},
   622  })
   623  
   624  // MapFunc constructs a function that takes an even number of arguments and
   625  // returns a map whose elements are constructed from consecutive pairs of arguments.
   626  //
   627  // This function is deprecated in Terraform v0.12
   628  var MapFunc = function.New(&function.Spec{
   629  	Params: []function.Parameter{},
   630  	VarParam: &function.Parameter{
   631  		Name:             "vals",
   632  		Type:             cty.DynamicPseudoType,
   633  		AllowUnknown:     true,
   634  		AllowDynamicType: true,
   635  		AllowNull:        true,
   636  	},
   637  	Type: func(args []cty.Value) (ret cty.Type, err error) {
   638  		return cty.DynamicPseudoType, fmt.Errorf("the \"map\" function was deprecated in Terraform v0.12 and is no longer available; use tomap({ ... }) syntax to write a literal map")
   639  	},
   640  	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
   641  		return cty.DynamicVal, fmt.Errorf("the \"map\" function was deprecated in Terraform v0.12 and is no longer available; use tomap({ ... }) syntax to write a literal map")
   642  	},
   643  })
   644  
   645  // Length returns the number of elements in the given collection or number of
   646  // Unicode characters in the given string.
   647  func Length(collection cty.Value) (cty.Value, error) {
   648  	return LengthFunc.Call([]cty.Value{collection})
   649  }
   650  
   651  // AllTrue returns true if all elements of the list are true. If the list is empty,
   652  // return true.
   653  func AllTrue(collection cty.Value) (cty.Value, error) {
   654  	return AllTrueFunc.Call([]cty.Value{collection})
   655  }
   656  
   657  // AnyTrue returns true if any element of the list is true. If the list is empty,
   658  // return false.
   659  func AnyTrue(collection cty.Value) (cty.Value, error) {
   660  	return AnyTrueFunc.Call([]cty.Value{collection})
   661  }
   662  
   663  // Coalesce takes any number of arguments and returns the first one that isn't empty.
   664  func Coalesce(args ...cty.Value) (cty.Value, error) {
   665  	return CoalesceFunc.Call(args)
   666  }
   667  
   668  // Index finds the element index for a given value in a list.
   669  func Index(list, value cty.Value) (cty.Value, error) {
   670  	return IndexFunc.Call([]cty.Value{list, value})
   671  }
   672  
   673  // List takes any number of arguments of types that can unify into a single
   674  // type and returns a list containing those values in the same order, or
   675  // returns an error if there is no single element type that all values can
   676  // convert to.
   677  func List(args ...cty.Value) (cty.Value, error) {
   678  	return ListFunc.Call(args)
   679  }
   680  
   681  // Lookup performs a dynamic lookup into a map.
   682  // There are two required arguments, map and key, plus an optional default,
   683  // which is a value to return if no key is found in map.
   684  func Lookup(args ...cty.Value) (cty.Value, error) {
   685  	return LookupFunc.Call(args)
   686  }
   687  
   688  // Map takes an even number of arguments and returns a map whose elements are constructed
   689  // from consecutive pairs of arguments.
   690  func Map(args ...cty.Value) (cty.Value, error) {
   691  	return MapFunc.Call(args)
   692  }
   693  
   694  // Matchkeys constructs a new list by taking a subset of elements from one list
   695  // whose indexes match the corresponding indexes of values in another list.
   696  func Matchkeys(values, keys, searchset cty.Value) (cty.Value, error) {
   697  	return MatchkeysFunc.Call([]cty.Value{values, keys, searchset})
   698  }
   699  
   700  // One returns either the first element of a one-element list, or null
   701  // if given a zero-element list..
   702  func One(list cty.Value) (cty.Value, error) {
   703  	return OneFunc.Call([]cty.Value{list})
   704  }
   705  
   706  // Sum adds numbers in a list, set, or tuple
   707  func Sum(list cty.Value) (cty.Value, error) {
   708  	return SumFunc.Call([]cty.Value{list})
   709  }
   710  
   711  // Transpose takes a map of lists of strings and swaps the keys and values to
   712  // produce a new map of lists of strings.
   713  func Transpose(values cty.Value) (cty.Value, error) {
   714  	return TransposeFunc.Call([]cty.Value{values})
   715  }