1package cty
2
3import (
4	"fmt"
5	"math/big"
6
7	"github.com/zclconf/go-cty/cty/set"
8)
9
10// GoString is an implementation of fmt.GoStringer that produces concise
11// source-like representations of values suitable for use in debug messages.
12func (val Value) GoString() string {
13	if val.IsMarked() {
14		unVal, marks := val.Unmark()
15		if len(marks) == 1 {
16			var mark interface{}
17			for m := range marks {
18				mark = m
19			}
20			return fmt.Sprintf("%#v.Mark(%#v)", unVal, mark)
21		}
22		return fmt.Sprintf("%#v.WithMarks(%#v)", unVal, marks)
23	}
24
25	if val == NilVal {
26		return "cty.NilVal"
27	}
28
29	if val.IsNull() {
30		return fmt.Sprintf("cty.NullVal(%#v)", val.ty)
31	}
32	if val == DynamicVal { // is unknown, so must be before the IsKnown check below
33		return "cty.DynamicVal"
34	}
35	if !val.IsKnown() {
36		return fmt.Sprintf("cty.UnknownVal(%#v)", val.ty)
37	}
38
39	// By the time we reach here we've dealt with all of the exceptions around
40	// unknowns and nulls, so we're guaranteed that the values are the
41	// canonical internal representation of the given type.
42
43	switch val.ty {
44	case Bool:
45		if val.v.(bool) {
46			return "cty.True"
47		}
48		return "cty.False"
49	case Number:
50		fv := val.v.(*big.Float)
51		// We'll try to use NumberIntVal or NumberFloatVal if we can, since
52		// the fully-general initializer call is pretty ugly-looking.
53		if fv.IsInt() {
54			return fmt.Sprintf("cty.NumberIntVal(%#v)", fv)
55		}
56		if rfv, accuracy := fv.Float64(); accuracy == big.Exact {
57			return fmt.Sprintf("cty.NumberFloatVal(%#v)", rfv)
58		}
59		return fmt.Sprintf("cty.MustParseNumberVal(%q)", fv.Text('f', -1))
60	case String:
61		return fmt.Sprintf("cty.StringVal(%#v)", val.v)
62	}
63
64	switch {
65	case val.ty.IsSetType():
66		vals := val.AsValueSlice()
67		if len(vals) == 0 {
68			return fmt.Sprintf("cty.SetValEmpty(%#v)", val.ty.ElementType())
69		}
70		return fmt.Sprintf("cty.SetVal(%#v)", vals)
71	case val.ty.IsListType():
72		vals := val.AsValueSlice()
73		if len(vals) == 0 {
74			return fmt.Sprintf("cty.ListValEmpty(%#v)", val.ty.ElementType())
75		}
76		return fmt.Sprintf("cty.ListVal(%#v)", vals)
77	case val.ty.IsMapType():
78		vals := val.AsValueMap()
79		if len(vals) == 0 {
80			return fmt.Sprintf("cty.MapValEmpty(%#v)", val.ty.ElementType())
81		}
82		return fmt.Sprintf("cty.MapVal(%#v)", vals)
83	case val.ty.IsTupleType():
84		if val.ty.Equals(EmptyTuple) {
85			return "cty.EmptyTupleVal"
86		}
87		vals := val.AsValueSlice()
88		return fmt.Sprintf("cty.TupleVal(%#v)", vals)
89	case val.ty.IsObjectType():
90		if val.ty.Equals(EmptyObject) {
91			return "cty.EmptyObjectVal"
92		}
93		vals := val.AsValueMap()
94		return fmt.Sprintf("cty.ObjectVal(%#v)", vals)
95	case val.ty.IsCapsuleType():
96		impl := val.ty.CapsuleOps().GoString
97		if impl == nil {
98			return fmt.Sprintf("cty.CapsuleVal(%#v, %#v)", val.ty, val.v)
99		}
100		return impl(val.EncapsulatedValue())
101	}
102
103	// Default exposes implementation details, so should actually cover
104	// all of the cases above for good caller UX.
105	return fmt.Sprintf("cty.Value{ty: %#v, v: %#v}", val.ty, val.v)
106}
107
108// Equals returns True if the receiver and the given other value have the
109// same type and are exactly equal in value.
110//
111// As a special case, two null values are always equal regardless of type.
112//
113// The usual short-circuit rules apply, so the result will be unknown if
114// either of the given values are.
115//
116// Use RawEquals to compare if two values are equal *ignoring* the
117// short-circuit rules and the exception for null values.
118func (val Value) Equals(other Value) Value {
119	if val.IsMarked() || other.IsMarked() {
120		val, valMarks := val.Unmark()
121		other, otherMarks := other.Unmark()
122		return val.Equals(other).WithMarks(valMarks, otherMarks)
123	}
124
125	// Start by handling Unknown values before considering types.
126	// This needs to be done since Null values are always equal regardless of
127	// type.
128	switch {
129	case !val.IsKnown() && !other.IsKnown():
130		// both unknown
131		return UnknownVal(Bool)
132	case val.IsKnown() && !other.IsKnown():
133		switch {
134		case val.IsNull(), other.ty.HasDynamicTypes():
135			// If known is Null, we need to wait for the unknown value since
136			// nulls of any type are equal.
137			// An unknown with a dynamic type compares as unknown, which we need
138			// to check before the type comparison below.
139			return UnknownVal(Bool)
140		case !val.ty.Equals(other.ty):
141			// There is no null comparison or dynamic types, so unequal types
142			// will never be equal.
143			return False
144		default:
145			return UnknownVal(Bool)
146		}
147	case other.IsKnown() && !val.IsKnown():
148		switch {
149		case other.IsNull(), val.ty.HasDynamicTypes():
150			// If known is Null, we need to wait for the unknown value since
151			// nulls of any type are equal.
152			// An unknown with a dynamic type compares as unknown, which we need
153			// to check before the type comparison below.
154			return UnknownVal(Bool)
155		case !other.ty.Equals(val.ty):
156			// There's no null comparison or dynamic types, so unequal types
157			// will never be equal.
158			return False
159		default:
160			return UnknownVal(Bool)
161		}
162	}
163
164	switch {
165	case val.IsNull() && other.IsNull():
166		// Nulls are always equal, regardless of type
167		return BoolVal(true)
168	case val.IsNull() || other.IsNull():
169		// If only one is null then the result must be false
170		return BoolVal(false)
171	}
172
173	// Check if there are any nested dynamic values making this comparison
174	// unknown.
175	if !val.HasWhollyKnownType() || !other.HasWhollyKnownType() {
176		// Even if we have dynamic values, we can still determine inequality if
177		// there is no way the types could later conform.
178		if val.ty.TestConformance(other.ty) != nil && other.ty.TestConformance(val.ty) != nil {
179			return BoolVal(false)
180		}
181
182		return UnknownVal(Bool)
183	}
184
185	if !val.ty.Equals(other.ty) {
186		return BoolVal(false)
187	}
188
189	ty := val.ty
190	result := false
191
192	switch {
193	case ty == Number:
194		result = val.v.(*big.Float).Cmp(other.v.(*big.Float)) == 0
195	case ty == Bool:
196		result = val.v.(bool) == other.v.(bool)
197	case ty == String:
198		// Simple equality is safe because we NFC-normalize strings as they
199		// enter our world from StringVal, and so we can assume strings are
200		// always in normal form.
201		result = val.v.(string) == other.v.(string)
202	case ty.IsObjectType():
203		oty := ty.typeImpl.(typeObject)
204		result = true
205		for attr, aty := range oty.AttrTypes {
206			lhs := Value{
207				ty: aty,
208				v:  val.v.(map[string]interface{})[attr],
209			}
210			rhs := Value{
211				ty: aty,
212				v:  other.v.(map[string]interface{})[attr],
213			}
214			eq := lhs.Equals(rhs)
215			if !eq.IsKnown() {
216				return UnknownVal(Bool)
217			}
218			if eq.False() {
219				result = false
220				break
221			}
222		}
223	case ty.IsTupleType():
224		tty := ty.typeImpl.(typeTuple)
225		result = true
226		for i, ety := range tty.ElemTypes {
227			lhs := Value{
228				ty: ety,
229				v:  val.v.([]interface{})[i],
230			}
231			rhs := Value{
232				ty: ety,
233				v:  other.v.([]interface{})[i],
234			}
235			eq := lhs.Equals(rhs)
236			if !eq.IsKnown() {
237				return UnknownVal(Bool)
238			}
239			if eq.False() {
240				result = false
241				break
242			}
243		}
244	case ty.IsListType():
245		ety := ty.typeImpl.(typeList).ElementTypeT
246		if len(val.v.([]interface{})) == len(other.v.([]interface{})) {
247			result = true
248			for i := range val.v.([]interface{}) {
249				lhs := Value{
250					ty: ety,
251					v:  val.v.([]interface{})[i],
252				}
253				rhs := Value{
254					ty: ety,
255					v:  other.v.([]interface{})[i],
256				}
257				eq := lhs.Equals(rhs)
258				if !eq.IsKnown() {
259					return UnknownVal(Bool)
260				}
261				if eq.False() {
262					result = false
263					break
264				}
265			}
266		}
267	case ty.IsSetType():
268		s1 := val.v.(set.Set)
269		s2 := other.v.(set.Set)
270		equal := true
271
272		// Two sets are equal if all of their values are known and all values
273		// in one are also in the other.
274		for it := s1.Iterator(); it.Next(); {
275			rv := it.Value()
276			if rv == unknown { // "unknown" is the internal representation of unknown-ness
277				return UnknownVal(Bool)
278			}
279			if !s2.Has(rv) {
280				equal = false
281			}
282		}
283		for it := s2.Iterator(); it.Next(); {
284			rv := it.Value()
285			if rv == unknown { // "unknown" is the internal representation of unknown-ness
286				return UnknownVal(Bool)
287			}
288			if !s1.Has(rv) {
289				equal = false
290			}
291		}
292
293		result = equal
294	case ty.IsMapType():
295		ety := ty.typeImpl.(typeMap).ElementTypeT
296		if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) {
297			result = true
298			for k := range val.v.(map[string]interface{}) {
299				if _, ok := other.v.(map[string]interface{})[k]; !ok {
300					result = false
301					break
302				}
303				lhs := Value{
304					ty: ety,
305					v:  val.v.(map[string]interface{})[k],
306				}
307				rhs := Value{
308					ty: ety,
309					v:  other.v.(map[string]interface{})[k],
310				}
311				eq := lhs.Equals(rhs)
312				if !eq.IsKnown() {
313					return UnknownVal(Bool)
314				}
315				if eq.False() {
316					result = false
317					break
318				}
319			}
320		}
321	case ty.IsCapsuleType():
322		impl := val.ty.CapsuleOps().Equals
323		if impl == nil {
324			impl := val.ty.CapsuleOps().RawEquals
325			if impl == nil {
326				// A capsule type's encapsulated value is a pointer to a value of its
327				// native type, so we can just compare these to get the identity test
328				// we need.
329				return BoolVal(val.v == other.v)
330			}
331			return BoolVal(impl(val.v, other.v))
332		}
333		ret := impl(val.v, other.v)
334		if !ret.Type().Equals(Bool) {
335			panic(fmt.Sprintf("Equals for %#v returned %#v, not cty.Bool", ty, ret.Type()))
336		}
337		return ret
338
339	default:
340		// should never happen
341		panic(fmt.Errorf("unsupported value type %#v in Equals", ty))
342	}
343
344	return BoolVal(result)
345}
346
347// NotEqual is a shorthand for Equals followed by Not.
348func (val Value) NotEqual(other Value) Value {
349	return val.Equals(other).Not()
350}
351
352// True returns true if the receiver is True, false if False, and panics if
353// the receiver is not of type Bool.
354//
355// This is a helper function to help write application logic that works with
356// values, rather than a first-class operation. It does not work with unknown
357// or null values. For more robust handling with unknown value
358// short-circuiting, use val.Equals(cty.True).
359func (val Value) True() bool {
360	val.assertUnmarked()
361	if val.ty != Bool {
362		panic("not bool")
363	}
364	return val.Equals(True).v.(bool)
365}
366
367// False is the opposite of True.
368func (val Value) False() bool {
369	return !val.True()
370}
371
372// RawEquals returns true if and only if the two given values have the same
373// type and equal value, ignoring the usual short-circuit rules about
374// unknowns and dynamic types.
375//
376// This method is more appropriate for testing than for real use, since it
377// skips over usual semantics around unknowns but as a consequence allows
378// testing the result of another operation that is expected to return unknown.
379// It returns a primitive Go bool rather than a Value to remind us that it
380// is not a first-class value operation.
381func (val Value) RawEquals(other Value) bool {
382	if !val.ty.Equals(other.ty) {
383		return false
384	}
385	if !val.HasSameMarks(other) {
386		return false
387	}
388	// Since we've now checked the marks, we'll unmark for the rest of this...
389	val = val.unmarkForce()
390	other = other.unmarkForce()
391
392	if (!val.IsKnown()) && (!other.IsKnown()) {
393		return true
394	}
395	if (val.IsKnown() && !other.IsKnown()) || (other.IsKnown() && !val.IsKnown()) {
396		return false
397	}
398	if val.IsNull() && other.IsNull() {
399		return true
400	}
401	if (val.IsNull() && !other.IsNull()) || (other.IsNull() && !val.IsNull()) {
402		return false
403	}
404	if val.ty == DynamicPseudoType && other.ty == DynamicPseudoType {
405		return true
406	}
407
408	ty := val.ty
409	switch {
410	case ty == Number || ty == Bool || ty == String || ty == DynamicPseudoType:
411		return val.Equals(other).True()
412	case ty.IsObjectType():
413		oty := ty.typeImpl.(typeObject)
414		for attr, aty := range oty.AttrTypes {
415			lhs := Value{
416				ty: aty,
417				v:  val.v.(map[string]interface{})[attr],
418			}
419			rhs := Value{
420				ty: aty,
421				v:  other.v.(map[string]interface{})[attr],
422			}
423			eq := lhs.RawEquals(rhs)
424			if !eq {
425				return false
426			}
427		}
428		return true
429	case ty.IsTupleType():
430		tty := ty.typeImpl.(typeTuple)
431		for i, ety := range tty.ElemTypes {
432			lhs := Value{
433				ty: ety,
434				v:  val.v.([]interface{})[i],
435			}
436			rhs := Value{
437				ty: ety,
438				v:  other.v.([]interface{})[i],
439			}
440			eq := lhs.RawEquals(rhs)
441			if !eq {
442				return false
443			}
444		}
445		return true
446	case ty.IsListType():
447		ety := ty.typeImpl.(typeList).ElementTypeT
448		if len(val.v.([]interface{})) == len(other.v.([]interface{})) {
449			for i := range val.v.([]interface{}) {
450				lhs := Value{
451					ty: ety,
452					v:  val.v.([]interface{})[i],
453				}
454				rhs := Value{
455					ty: ety,
456					v:  other.v.([]interface{})[i],
457				}
458				eq := lhs.RawEquals(rhs)
459				if !eq {
460					return false
461				}
462			}
463			return true
464		}
465		return false
466
467	case ty.IsSetType():
468		// Convert the set values into a slice so that we can compare each
469		// value. This is safe because the underlying sets are ordered (see
470		// setRules in set_internals.go), and so the results are guaranteed to
471		// be in a consistent order for two equal sets
472		setList1 := val.AsValueSlice()
473		setList2 := other.AsValueSlice()
474
475		// If both physical sets have the same length and they have all of their
476		// _known_ values in common, we know that both sets also have the same
477		// number of unknown values.
478		if len(setList1) != len(setList2) {
479			return false
480		}
481
482		for i := range setList1 {
483			eq := setList1[i].RawEquals(setList2[i])
484			if !eq {
485				return false
486			}
487		}
488
489		// If we got here without returning false already then our sets are
490		// equal enough for RawEquals purposes.
491		return true
492
493	case ty.IsMapType():
494		ety := ty.typeImpl.(typeMap).ElementTypeT
495		if len(val.v.(map[string]interface{})) == len(other.v.(map[string]interface{})) {
496			for k := range val.v.(map[string]interface{}) {
497				if _, ok := other.v.(map[string]interface{})[k]; !ok {
498					return false
499				}
500				lhs := Value{
501					ty: ety,
502					v:  val.v.(map[string]interface{})[k],
503				}
504				rhs := Value{
505					ty: ety,
506					v:  other.v.(map[string]interface{})[k],
507				}
508				eq := lhs.RawEquals(rhs)
509				if !eq {
510					return false
511				}
512			}
513			return true
514		}
515		return false
516	case ty.IsCapsuleType():
517		impl := val.ty.CapsuleOps().RawEquals
518		if impl == nil {
519			// A capsule type's encapsulated value is a pointer to a value of its
520			// native type, so we can just compare these to get the identity test
521			// we need.
522			return val.v == other.v
523		}
524		return impl(val.v, other.v)
525
526	default:
527		// should never happen
528		panic(fmt.Errorf("unsupported value type %#v in RawEquals", ty))
529	}
530}
531
532// Add returns the sum of the receiver and the given other value. Both values
533// must be numbers; this method will panic if not.
534func (val Value) Add(other Value) Value {
535	if val.IsMarked() || other.IsMarked() {
536		val, valMarks := val.Unmark()
537		other, otherMarks := other.Unmark()
538		return val.Add(other).WithMarks(valMarks, otherMarks)
539	}
540
541	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
542		shortCircuit = forceShortCircuitType(shortCircuit, Number)
543		return *shortCircuit
544	}
545
546	ret := new(big.Float)
547	ret.Add(val.v.(*big.Float), other.v.(*big.Float))
548	return NumberVal(ret)
549}
550
551// Subtract returns receiver minus the given other value. Both values must be
552// numbers; this method will panic if not.
553func (val Value) Subtract(other Value) Value {
554	if val.IsMarked() || other.IsMarked() {
555		val, valMarks := val.Unmark()
556		other, otherMarks := other.Unmark()
557		return val.Subtract(other).WithMarks(valMarks, otherMarks)
558	}
559
560	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
561		shortCircuit = forceShortCircuitType(shortCircuit, Number)
562		return *shortCircuit
563	}
564
565	return val.Add(other.Negate())
566}
567
568// Negate returns the numeric negative of the receiver, which must be a number.
569// This method will panic when given a value of any other type.
570func (val Value) Negate() Value {
571	if val.IsMarked() {
572		val, valMarks := val.Unmark()
573		return val.Negate().WithMarks(valMarks)
574	}
575
576	if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
577		shortCircuit = forceShortCircuitType(shortCircuit, Number)
578		return *shortCircuit
579	}
580
581	ret := new(big.Float).Neg(val.v.(*big.Float))
582	return NumberVal(ret)
583}
584
585// Multiply returns the product of the receiver and the given other value.
586// Both values must be numbers; this method will panic if not.
587func (val Value) Multiply(other Value) Value {
588	if val.IsMarked() || other.IsMarked() {
589		val, valMarks := val.Unmark()
590		other, otherMarks := other.Unmark()
591		return val.Multiply(other).WithMarks(valMarks, otherMarks)
592	}
593
594	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
595		shortCircuit = forceShortCircuitType(shortCircuit, Number)
596		return *shortCircuit
597	}
598
599	// find the larger precision of the arguments
600	resPrec := val.v.(*big.Float).Prec()
601	otherPrec := other.v.(*big.Float).Prec()
602	if otherPrec > resPrec {
603		resPrec = otherPrec
604	}
605
606	// make sure we have enough precision for the product
607	ret := new(big.Float).SetPrec(512)
608	ret.Mul(val.v.(*big.Float), other.v.(*big.Float))
609
610	// now reduce the precision back to the greater argument, or the minimum
611	// required by the product.
612	minPrec := ret.MinPrec()
613	if minPrec > resPrec {
614		resPrec = minPrec
615	}
616	ret.SetPrec(resPrec)
617
618	return NumberVal(ret)
619}
620
621// Divide returns the quotient of the receiver and the given other value.
622// Both values must be numbers; this method will panic if not.
623//
624// If the "other" value is exactly zero, this operation will return either
625// PositiveInfinity or NegativeInfinity, depending on the sign of the
626// receiver value. For some use-cases the presence of infinities may be
627// undesirable, in which case the caller should check whether the
628// other value equals zero before calling and raise an error instead.
629//
630// If both values are zero or infinity, this function will panic with
631// an instance of big.ErrNaN.
632func (val Value) Divide(other Value) Value {
633	if val.IsMarked() || other.IsMarked() {
634		val, valMarks := val.Unmark()
635		other, otherMarks := other.Unmark()
636		return val.Divide(other).WithMarks(valMarks, otherMarks)
637	}
638
639	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
640		shortCircuit = forceShortCircuitType(shortCircuit, Number)
641		return *shortCircuit
642	}
643
644	ret := new(big.Float)
645	ret.Quo(val.v.(*big.Float), other.v.(*big.Float))
646	return NumberVal(ret)
647}
648
649// Modulo returns the remainder of an integer division of the receiver and
650// the given other value. Both values must be numbers; this method will panic
651// if not.
652//
653// If the "other" value is exactly zero, this operation will return either
654// PositiveInfinity or NegativeInfinity, depending on the sign of the
655// receiver value. For some use-cases the presence of infinities may be
656// undesirable, in which case the caller should check whether the
657// other value equals zero before calling and raise an error instead.
658//
659// This operation is primarily here for use with nonzero natural numbers.
660// Modulo with "other" as a non-natural number gets somewhat philosophical,
661// and this function takes a position on what that should mean, but callers
662// may wish to disallow such things outright or implement their own modulo
663// if they disagree with the interpretation used here.
664func (val Value) Modulo(other Value) Value {
665	if val.IsMarked() || other.IsMarked() {
666		val, valMarks := val.Unmark()
667		other, otherMarks := other.Unmark()
668		return val.Modulo(other).WithMarks(valMarks, otherMarks)
669	}
670
671	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
672		shortCircuit = forceShortCircuitType(shortCircuit, Number)
673		return *shortCircuit
674	}
675
676	// We cheat a bit here with infinities, just abusing the Multiply operation
677	// to get an infinite result of the correct sign.
678	if val == PositiveInfinity || val == NegativeInfinity || other == PositiveInfinity || other == NegativeInfinity {
679		return val.Multiply(other)
680	}
681
682	if other.RawEquals(Zero) {
683		return val
684	}
685
686	// FIXME: This is a bit clumsy. Should come back later and see if there's a
687	// more straightforward way to do this.
688	rat := val.Divide(other)
689	ratFloorInt, _ := rat.v.(*big.Float).Int(nil)
690
691	// start with a copy of the original larger value so that we do not lose
692	// precision.
693	v := val.v.(*big.Float)
694	work := new(big.Float).Copy(v).SetInt(ratFloorInt)
695	work.Mul(other.v.(*big.Float), work)
696	work.Sub(v, work)
697
698	return NumberVal(work)
699}
700
701// Absolute returns the absolute (signless) value of the receiver, which must
702// be a number or this method will panic.
703func (val Value) Absolute() Value {
704	if val.IsMarked() {
705		val, valMarks := val.Unmark()
706		return val.Absolute().WithMarks(valMarks)
707	}
708
709	if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
710		shortCircuit = forceShortCircuitType(shortCircuit, Number)
711		return *shortCircuit
712	}
713
714	ret := (&big.Float{}).Abs(val.v.(*big.Float))
715	return NumberVal(ret)
716}
717
718// GetAttr returns the value of the given attribute of the receiver, which
719// must be of an object type that has an attribute of the given name.
720// This method will panic if the receiver type is not compatible.
721//
722// The method will also panic if the given attribute name is not defined
723// for the value's type. Use the attribute-related methods on Type to
724// check for the validity of an attribute before trying to use it.
725//
726// This method may be called on a value whose type is DynamicPseudoType,
727// in which case the result will also be DynamicVal.
728func (val Value) GetAttr(name string) Value {
729	if val.IsMarked() {
730		val, valMarks := val.Unmark()
731		return val.GetAttr(name).WithMarks(valMarks)
732	}
733
734	if val.ty == DynamicPseudoType {
735		return DynamicVal
736	}
737
738	if !val.ty.IsObjectType() {
739		panic("value is not an object")
740	}
741
742	name = NormalizeString(name)
743	if !val.ty.HasAttribute(name) {
744		panic("value has no attribute of that name")
745	}
746
747	attrType := val.ty.AttributeType(name)
748
749	if !val.IsKnown() {
750		return UnknownVal(attrType)
751	}
752
753	return Value{
754		ty: attrType,
755		v:  val.v.(map[string]interface{})[name],
756	}
757}
758
759// Index returns the value of an element of the receiver, which must have
760// either a list, map or tuple type. This method will panic if the receiver
761// type is not compatible.
762//
763// The key value must be the correct type for the receving collection: a
764// number if the collection is a list or tuple, or a string if it is a map.
765// In the case of a list or tuple, the given number must be convertable to int
766// or this method will panic. The key may alternatively be of
767// DynamicPseudoType, in which case the result itself is an unknown of the
768// collection's element type.
769//
770// The result is of the receiver collection's element type, or in the case
771// of a tuple the type of the specific element index requested.
772//
773// This method may be called on a value whose type is DynamicPseudoType,
774// in which case the result will also be the DynamicValue.
775func (val Value) Index(key Value) Value {
776	if val.IsMarked() || key.IsMarked() {
777		val, valMarks := val.Unmark()
778		key, keyMarks := key.Unmark()
779		return val.Index(key).WithMarks(valMarks, keyMarks)
780	}
781
782	if val.ty == DynamicPseudoType {
783		return DynamicVal
784	}
785
786	switch {
787	case val.Type().IsListType():
788		elty := val.Type().ElementType()
789		if key.Type() == DynamicPseudoType {
790			return UnknownVal(elty)
791		}
792
793		if key.Type() != Number {
794			panic("element key for list must be number")
795		}
796		if !key.IsKnown() {
797			return UnknownVal(elty)
798		}
799
800		if !val.IsKnown() {
801			return UnknownVal(elty)
802		}
803
804		index, accuracy := key.v.(*big.Float).Int64()
805		if accuracy != big.Exact || index < 0 {
806			panic("element key for list must be non-negative integer")
807		}
808
809		return Value{
810			ty: elty,
811			v:  val.v.([]interface{})[index],
812		}
813	case val.Type().IsMapType():
814		elty := val.Type().ElementType()
815		if key.Type() == DynamicPseudoType {
816			return UnknownVal(elty)
817		}
818
819		if key.Type() != String {
820			panic("element key for map must be string")
821		}
822		if !key.IsKnown() {
823			return UnknownVal(elty)
824		}
825
826		if !val.IsKnown() {
827			return UnknownVal(elty)
828		}
829
830		keyStr := key.v.(string)
831
832		return Value{
833			ty: elty,
834			v:  val.v.(map[string]interface{})[keyStr],
835		}
836	case val.Type().IsTupleType():
837		if key.Type() == DynamicPseudoType {
838			return DynamicVal
839		}
840
841		if key.Type() != Number {
842			panic("element key for tuple must be number")
843		}
844		if !key.IsKnown() {
845			return DynamicVal
846		}
847
848		index, accuracy := key.v.(*big.Float).Int64()
849		if accuracy != big.Exact || index < 0 {
850			panic("element key for list must be non-negative integer")
851		}
852
853		eltys := val.Type().TupleElementTypes()
854
855		if !val.IsKnown() {
856			return UnknownVal(eltys[index])
857		}
858
859		return Value{
860			ty: eltys[index],
861			v:  val.v.([]interface{})[index],
862		}
863	default:
864		panic("not a list, map, or tuple type")
865	}
866}
867
868// HasIndex returns True if the receiver (which must be supported for Index)
869// has an element with the given index key, or False if it does not.
870//
871// The result will be UnknownVal(Bool) if either the collection or the
872// key value are unknown.
873//
874// This method will panic if the receiver is not indexable, but does not
875// impose any panic-causing type constraints on the key.
876func (val Value) HasIndex(key Value) Value {
877	if val.IsMarked() || key.IsMarked() {
878		val, valMarks := val.Unmark()
879		key, keyMarks := key.Unmark()
880		return val.HasIndex(key).WithMarks(valMarks, keyMarks)
881	}
882
883	if val.ty == DynamicPseudoType {
884		return UnknownVal(Bool)
885	}
886
887	switch {
888	case val.Type().IsListType():
889		if key.Type() == DynamicPseudoType {
890			return UnknownVal(Bool)
891		}
892
893		if key.Type() != Number {
894			return False
895		}
896		if !key.IsKnown() {
897			return UnknownVal(Bool)
898		}
899		if !val.IsKnown() {
900			return UnknownVal(Bool)
901		}
902
903		index, accuracy := key.v.(*big.Float).Int64()
904		if accuracy != big.Exact || index < 0 {
905			return False
906		}
907
908		return BoolVal(int(index) < len(val.v.([]interface{})) && index >= 0)
909	case val.Type().IsMapType():
910		if key.Type() == DynamicPseudoType {
911			return UnknownVal(Bool)
912		}
913
914		if key.Type() != String {
915			return False
916		}
917		if !key.IsKnown() {
918			return UnknownVal(Bool)
919		}
920		if !val.IsKnown() {
921			return UnknownVal(Bool)
922		}
923
924		keyStr := key.v.(string)
925		_, exists := val.v.(map[string]interface{})[keyStr]
926
927		return BoolVal(exists)
928	case val.Type().IsTupleType():
929		if key.Type() == DynamicPseudoType {
930			return UnknownVal(Bool)
931		}
932
933		if key.Type() != Number {
934			return False
935		}
936		if !key.IsKnown() {
937			return UnknownVal(Bool)
938		}
939
940		index, accuracy := key.v.(*big.Float).Int64()
941		if accuracy != big.Exact || index < 0 {
942			return False
943		}
944
945		length := val.Type().Length()
946		return BoolVal(int(index) < length && index >= 0)
947	default:
948		panic("not a list, map, or tuple type")
949	}
950}
951
952// HasElement returns True if the receiver (which must be of a set type)
953// has the given value as an element, or False if it does not.
954//
955// The result will be UnknownVal(Bool) if either the set or the
956// given value are unknown.
957//
958// This method will panic if the receiver is not a set, or if it is a null set.
959func (val Value) HasElement(elem Value) Value {
960	if val.IsMarked() || elem.IsMarked() {
961		val, valMarks := val.Unmark()
962		elem, elemMarks := elem.Unmark()
963		return val.HasElement(elem).WithMarks(valMarks, elemMarks)
964	}
965
966	ty := val.Type()
967
968	if !ty.IsSetType() {
969		panic("not a set type")
970	}
971	if !val.IsKnown() || !elem.IsKnown() {
972		return UnknownVal(Bool)
973	}
974	if val.IsNull() {
975		panic("can't call HasElement on a nil value")
976	}
977	if !ty.ElementType().Equals(elem.Type()) {
978		return False
979	}
980
981	s := val.v.(set.Set)
982	return BoolVal(s.Has(elem.v))
983}
984
985// Length returns the length of the receiver, which must be a collection type
986// or tuple type, as a number value. If the receiver is not a compatible type
987// then this method will panic.
988//
989// If the receiver is unknown then the result is also unknown.
990//
991// If the receiver is null then this function will panic.
992//
993// Note that Length is not supported for strings. To determine the length
994// of a string, use the Length function in funcs/stdlib.
995func (val Value) Length() Value {
996	if val.IsMarked() {
997		val, valMarks := val.Unmark()
998		return val.Length().WithMarks(valMarks)
999	}
1000
1001	if val.Type().IsTupleType() {
1002		// For tuples, we can return the length even if the value is not known.
1003		return NumberIntVal(int64(val.Type().Length()))
1004	}
1005
1006	if !val.IsKnown() {
1007		return UnknownVal(Number)
1008	}
1009	if val.Type().IsSetType() {
1010		// The Length rules are a little different for sets because if any
1011		// unknown values are present then the values they are standing in for
1012		// may or may not be equal to other elements in the set, and thus they
1013		// may or may not coalesce with other elements and produce fewer
1014		// items in the resulting set.
1015		storeLength := int64(val.v.(set.Set).Length())
1016		if storeLength == 1 || val.IsWhollyKnown() {
1017			// If our set is wholly known then we know its length.
1018			//
1019			// We also know the length if the physical store has only one
1020			// element, even if that element is unknown, because there's
1021			// nothing else in the set for it to coalesce with and a single
1022			// unknown value cannot represent more than one known value.
1023			return NumberIntVal(storeLength)
1024		}
1025		// Otherwise, we cannot predict the length.
1026		return UnknownVal(Number)
1027	}
1028
1029	return NumberIntVal(int64(val.LengthInt()))
1030}
1031
1032// LengthInt is like Length except it returns an int. It has the same behavior
1033// as Length except that it will panic if the receiver is unknown.
1034//
1035// This is an integration method provided for the convenience of code bridging
1036// into Go's type system.
1037//
1038// For backward compatibility with an earlier implementation error, LengthInt's
1039// result can disagree with Length's result for any set containing unknown
1040// values. Length can potentially indicate the set's length is unknown in that
1041// case, whereas LengthInt will return the maximum possible length as if the
1042// unknown values were each a placeholder for a value not equal to any other
1043// value in the set.
1044func (val Value) LengthInt() int {
1045	val.assertUnmarked()
1046	if val.Type().IsTupleType() {
1047		// For tuples, we can return the length even if the value is not known.
1048		return val.Type().Length()
1049	}
1050	if val.Type().IsObjectType() {
1051		// For objects, the length is the number of attributes associated with the type.
1052		return len(val.Type().AttributeTypes())
1053	}
1054	if !val.IsKnown() {
1055		panic("value is not known")
1056	}
1057	if val.IsNull() {
1058		panic("value is null")
1059	}
1060
1061	switch {
1062
1063	case val.ty.IsListType():
1064		return len(val.v.([]interface{}))
1065
1066	case val.ty.IsSetType():
1067		// NOTE: This is technically not correct in cases where the set
1068		// contains unknown values, because in that case we can't know how
1069		// many known values those unknown values are standing in for -- they
1070		// might coalesce with other values once known.
1071		//
1072		// However, this incorrect behavior is preserved for backward
1073		// compatibility with callers that were relying on LengthInt rather
1074		// than calling Length. Instead of panicking when a set contains an
1075		// unknown value, LengthInt returns the largest possible length.
1076		return val.v.(set.Set).Length()
1077
1078	case val.ty.IsMapType():
1079		return len(val.v.(map[string]interface{}))
1080
1081	default:
1082		panic("value is not a collection")
1083	}
1084}
1085
1086// ElementIterator returns an ElementIterator for iterating the elements
1087// of the receiver, which must be a collection type, a tuple type, or an object
1088// type. If called on a method of any other type, this method will panic.
1089//
1090// The value must be Known and non-Null, or this method will panic.
1091//
1092// If the receiver is of a list type, the returned keys will be of type Number
1093// and the values will be of the list's element type.
1094//
1095// If the receiver is of a map type, the returned keys will be of type String
1096// and the value will be of the map's element type. Elements are passed in
1097// ascending lexicographical order by key.
1098//
1099// If the receiver is of a set type, each element is returned as both the
1100// key and the value, since set members are their own identity.
1101//
1102// If the receiver is of a tuple type, the returned keys will be of type Number
1103// and the value will be of the corresponding element's type.
1104//
1105// If the receiver is of an object type, the returned keys will be of type
1106// String and the value will be of the corresponding attributes's type.
1107//
1108// ElementIterator is an integration method, so it cannot handle Unknown
1109// values. This method will panic if the receiver is Unknown.
1110func (val Value) ElementIterator() ElementIterator {
1111	val.assertUnmarked()
1112	if !val.IsKnown() {
1113		panic("can't use ElementIterator on unknown value")
1114	}
1115	if val.IsNull() {
1116		panic("can't use ElementIterator on null value")
1117	}
1118	return elementIterator(val)
1119}
1120
1121// CanIterateElements returns true if the receiver can support the
1122// ElementIterator method (and by extension, ForEachElement) without panic.
1123func (val Value) CanIterateElements() bool {
1124	return canElementIterator(val)
1125}
1126
1127// ForEachElement executes a given callback function for each element of
1128// the receiver, which must be a collection type or tuple type, or this method
1129// will panic.
1130//
1131// ForEachElement uses ElementIterator internally, and so the values passed
1132// to the callback are as described for ElementIterator.
1133//
1134// Returns true if the iteration exited early due to the callback function
1135// returning true, or false if the loop ran to completion.
1136//
1137// ForEachElement is an integration method, so it cannot handle Unknown
1138// values. This method will panic if the receiver is Unknown.
1139func (val Value) ForEachElement(cb ElementCallback) bool {
1140	val.assertUnmarked()
1141	it := val.ElementIterator()
1142	for it.Next() {
1143		key, val := it.Element()
1144		stop := cb(key, val)
1145		if stop {
1146			return true
1147		}
1148	}
1149	return false
1150}
1151
1152// Not returns the logical inverse of the receiver, which must be of type
1153// Bool or this method will panic.
1154func (val Value) Not() Value {
1155	if val.IsMarked() {
1156		val, valMarks := val.Unmark()
1157		return val.Not().WithMarks(valMarks)
1158	}
1159
1160	if shortCircuit := mustTypeCheck(Bool, Bool, val); shortCircuit != nil {
1161		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1162		return *shortCircuit
1163	}
1164
1165	return BoolVal(!val.v.(bool))
1166}
1167
1168// And returns the result of logical AND with the receiver and the other given
1169// value, which must both be of type Bool or this method will panic.
1170func (val Value) And(other Value) Value {
1171	if val.IsMarked() || other.IsMarked() {
1172		val, valMarks := val.Unmark()
1173		other, otherMarks := other.Unmark()
1174		return val.And(other).WithMarks(valMarks, otherMarks)
1175	}
1176
1177	if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
1178		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1179		return *shortCircuit
1180	}
1181
1182	return BoolVal(val.v.(bool) && other.v.(bool))
1183}
1184
1185// Or returns the result of logical OR with the receiver and the other given
1186// value, which must both be of type Bool or this method will panic.
1187func (val Value) Or(other Value) Value {
1188	if val.IsMarked() || other.IsMarked() {
1189		val, valMarks := val.Unmark()
1190		other, otherMarks := other.Unmark()
1191		return val.Or(other).WithMarks(valMarks, otherMarks)
1192	}
1193
1194	if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
1195		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1196		return *shortCircuit
1197	}
1198
1199	return BoolVal(val.v.(bool) || other.v.(bool))
1200}
1201
1202// LessThan returns True if the receiver is less than the other given value,
1203// which must both be numbers or this method will panic.
1204func (val Value) LessThan(other Value) Value {
1205	if val.IsMarked() || other.IsMarked() {
1206		val, valMarks := val.Unmark()
1207		other, otherMarks := other.Unmark()
1208		return val.LessThan(other).WithMarks(valMarks, otherMarks)
1209	}
1210
1211	if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
1212		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1213		return *shortCircuit
1214	}
1215
1216	return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) < 0)
1217}
1218
1219// GreaterThan returns True if the receiver is greater than the other given
1220// value, which must both be numbers or this method will panic.
1221func (val Value) GreaterThan(other Value) Value {
1222	if val.IsMarked() || other.IsMarked() {
1223		val, valMarks := val.Unmark()
1224		other, otherMarks := other.Unmark()
1225		return val.GreaterThan(other).WithMarks(valMarks, otherMarks)
1226	}
1227
1228	if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
1229		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1230		return *shortCircuit
1231	}
1232
1233	return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) > 0)
1234}
1235
1236// LessThanOrEqualTo is equivalent to LessThan and Equal combined with Or.
1237func (val Value) LessThanOrEqualTo(other Value) Value {
1238	return val.LessThan(other).Or(val.Equals(other))
1239}
1240
1241// GreaterThanOrEqualTo is equivalent to GreaterThan and Equal combined with Or.
1242func (val Value) GreaterThanOrEqualTo(other Value) Value {
1243	return val.GreaterThan(other).Or(val.Equals(other))
1244}
1245
1246// AsString returns the native string from a non-null, non-unknown cty.String
1247// value, or panics if called on any other value.
1248func (val Value) AsString() string {
1249	val.assertUnmarked()
1250	if val.ty != String {
1251		panic("not a string")
1252	}
1253	if val.IsNull() {
1254		panic("value is null")
1255	}
1256	if !val.IsKnown() {
1257		panic("value is unknown")
1258	}
1259
1260	return val.v.(string)
1261}
1262
1263// AsBigFloat returns a big.Float representation of a non-null, non-unknown
1264// cty.Number value, or panics if called on any other value.
1265//
1266// For more convenient conversions to other native numeric types, use the
1267// "gocty" package.
1268func (val Value) AsBigFloat() *big.Float {
1269	val.assertUnmarked()
1270	if val.ty != Number {
1271		panic("not a number")
1272	}
1273	if val.IsNull() {
1274		panic("value is null")
1275	}
1276	if !val.IsKnown() {
1277		panic("value is unknown")
1278	}
1279
1280	// Copy the float so that callers can't mutate our internal state
1281	ret := *(val.v.(*big.Float))
1282
1283	return &ret
1284}
1285
1286// AsValueSlice returns a []cty.Value representation of a non-null, non-unknown
1287// value of any type that CanIterateElements, or panics if called on
1288// any other value.
1289//
1290// For more convenient conversions to slices of more specific types, use
1291// the "gocty" package.
1292func (val Value) AsValueSlice() []Value {
1293	val.assertUnmarked()
1294	l := val.LengthInt()
1295	if l == 0 {
1296		return nil
1297	}
1298
1299	ret := make([]Value, 0, l)
1300	for it := val.ElementIterator(); it.Next(); {
1301		_, v := it.Element()
1302		ret = append(ret, v)
1303	}
1304	return ret
1305}
1306
1307// AsValueMap returns a map[string]cty.Value representation of a non-null,
1308// non-unknown value of any type that CanIterateElements, or panics if called
1309// on any other value.
1310//
1311// For more convenient conversions to maps of more specific types, use
1312// the "gocty" package.
1313func (val Value) AsValueMap() map[string]Value {
1314	val.assertUnmarked()
1315	l := val.LengthInt()
1316	if l == 0 {
1317		return nil
1318	}
1319
1320	ret := make(map[string]Value, l)
1321	for it := val.ElementIterator(); it.Next(); {
1322		k, v := it.Element()
1323		ret[k.AsString()] = v
1324	}
1325	return ret
1326}
1327
1328// AsValueSet returns a ValueSet representation of a non-null,
1329// non-unknown value of any collection type, or panics if called
1330// on any other value.
1331//
1332// Unlike AsValueSlice and AsValueMap, this method requires specifically a
1333// collection type (list, set or map) and does not allow structural types
1334// (tuple or object), because the ValueSet type requires homogenous
1335// element types.
1336//
1337// The returned ValueSet can store only values of the receiver's element type.
1338func (val Value) AsValueSet() ValueSet {
1339	val.assertUnmarked()
1340	if !val.Type().IsCollectionType() {
1341		panic("not a collection type")
1342	}
1343
1344	// We don't give the caller our own set.Set (assuming we're a cty.Set value)
1345	// because then the caller could mutate our internals, which is forbidden.
1346	// Instead, we will construct a new set and append our elements into it.
1347	ret := NewValueSet(val.Type().ElementType())
1348	for it := val.ElementIterator(); it.Next(); {
1349		_, v := it.Element()
1350		ret.Add(v)
1351	}
1352	return ret
1353}
1354
1355// EncapsulatedValue returns the native value encapsulated in a non-null,
1356// non-unknown capsule-typed value, or panics if called on any other value.
1357//
1358// The result is the same pointer that was passed to CapsuleVal to create
1359// the value. Since cty considers values to be immutable, it is strongly
1360// recommended to treat the encapsulated value itself as immutable too.
1361func (val Value) EncapsulatedValue() interface{} {
1362	val.assertUnmarked()
1363	if !val.Type().IsCapsuleType() {
1364		panic("not a capsule-typed value")
1365	}
1366
1367	return val.v
1368}
1369