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.ContainsMarked() || other.ContainsMarked() {
120		val, valMarks := val.UnmarkDeep()
121		other, otherMarks := other.UnmarkDeep()
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 !val.HasSameMarks(other) {
496			return false
497		}
498		valUn, _ := val.Unmark()
499		otherUn, _ := other.Unmark()
500		if len(valUn.v.(map[string]interface{})) == len(otherUn.v.(map[string]interface{})) {
501			for k := range valUn.v.(map[string]interface{}) {
502				if _, ok := otherUn.v.(map[string]interface{})[k]; !ok {
503					return false
504				}
505				lhs := Value{
506					ty: ety,
507					v:  valUn.v.(map[string]interface{})[k],
508				}
509				rhs := Value{
510					ty: ety,
511					v:  otherUn.v.(map[string]interface{})[k],
512				}
513				eq := lhs.RawEquals(rhs)
514				if !eq {
515					return false
516				}
517			}
518			return true
519		}
520		return false
521	case ty.IsCapsuleType():
522		impl := val.ty.CapsuleOps().RawEquals
523		if impl == nil {
524			// A capsule type's encapsulated value is a pointer to a value of its
525			// native type, so we can just compare these to get the identity test
526			// we need.
527			return val.v == other.v
528		}
529		return impl(val.v, other.v)
530
531	default:
532		// should never happen
533		panic(fmt.Errorf("unsupported value type %#v in RawEquals", ty))
534	}
535}
536
537// Add returns the sum of the receiver and the given other value. Both values
538// must be numbers; this method will panic if not.
539func (val Value) Add(other Value) Value {
540	if val.IsMarked() || other.IsMarked() {
541		val, valMarks := val.Unmark()
542		other, otherMarks := other.Unmark()
543		return val.Add(other).WithMarks(valMarks, otherMarks)
544	}
545
546	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
547		shortCircuit = forceShortCircuitType(shortCircuit, Number)
548		return *shortCircuit
549	}
550
551	ret := new(big.Float)
552	ret.Add(val.v.(*big.Float), other.v.(*big.Float))
553	return NumberVal(ret)
554}
555
556// Subtract returns receiver minus the given other value. Both values must be
557// numbers; this method will panic if not.
558func (val Value) Subtract(other Value) Value {
559	if val.IsMarked() || other.IsMarked() {
560		val, valMarks := val.Unmark()
561		other, otherMarks := other.Unmark()
562		return val.Subtract(other).WithMarks(valMarks, otherMarks)
563	}
564
565	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
566		shortCircuit = forceShortCircuitType(shortCircuit, Number)
567		return *shortCircuit
568	}
569
570	return val.Add(other.Negate())
571}
572
573// Negate returns the numeric negative of the receiver, which must be a number.
574// This method will panic when given a value of any other type.
575func (val Value) Negate() Value {
576	if val.IsMarked() {
577		val, valMarks := val.Unmark()
578		return val.Negate().WithMarks(valMarks)
579	}
580
581	if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
582		shortCircuit = forceShortCircuitType(shortCircuit, Number)
583		return *shortCircuit
584	}
585
586	ret := new(big.Float).Neg(val.v.(*big.Float))
587	return NumberVal(ret)
588}
589
590// Multiply returns the product of the receiver and the given other value.
591// Both values must be numbers; this method will panic if not.
592func (val Value) Multiply(other Value) Value {
593	if val.IsMarked() || other.IsMarked() {
594		val, valMarks := val.Unmark()
595		other, otherMarks := other.Unmark()
596		return val.Multiply(other).WithMarks(valMarks, otherMarks)
597	}
598
599	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
600		shortCircuit = forceShortCircuitType(shortCircuit, Number)
601		return *shortCircuit
602	}
603
604	// find the larger precision of the arguments
605	resPrec := val.v.(*big.Float).Prec()
606	otherPrec := other.v.(*big.Float).Prec()
607	if otherPrec > resPrec {
608		resPrec = otherPrec
609	}
610
611	// make sure we have enough precision for the product
612	ret := new(big.Float).SetPrec(512)
613	ret.Mul(val.v.(*big.Float), other.v.(*big.Float))
614
615	// now reduce the precision back to the greater argument, or the minimum
616	// required by the product.
617	minPrec := ret.MinPrec()
618	if minPrec > resPrec {
619		resPrec = minPrec
620	}
621	ret.SetPrec(resPrec)
622
623	return NumberVal(ret)
624}
625
626// Divide returns the quotient of the receiver and the given other value.
627// Both values must be numbers; this method will panic if not.
628//
629// If the "other" value is exactly zero, this operation will return either
630// PositiveInfinity or NegativeInfinity, depending on the sign of the
631// receiver value. For some use-cases the presence of infinities may be
632// undesirable, in which case the caller should check whether the
633// other value equals zero before calling and raise an error instead.
634//
635// If both values are zero or infinity, this function will panic with
636// an instance of big.ErrNaN.
637func (val Value) Divide(other Value) Value {
638	if val.IsMarked() || other.IsMarked() {
639		val, valMarks := val.Unmark()
640		other, otherMarks := other.Unmark()
641		return val.Divide(other).WithMarks(valMarks, otherMarks)
642	}
643
644	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
645		shortCircuit = forceShortCircuitType(shortCircuit, Number)
646		return *shortCircuit
647	}
648
649	ret := new(big.Float)
650	ret.Quo(val.v.(*big.Float), other.v.(*big.Float))
651	return NumberVal(ret)
652}
653
654// Modulo returns the remainder of an integer division of the receiver and
655// the given other value. Both values must be numbers; this method will panic
656// if not.
657//
658// If the "other" value is exactly zero, this operation will return either
659// PositiveInfinity or NegativeInfinity, depending on the sign of the
660// receiver value. For some use-cases the presence of infinities may be
661// undesirable, in which case the caller should check whether the
662// other value equals zero before calling and raise an error instead.
663//
664// This operation is primarily here for use with nonzero natural numbers.
665// Modulo with "other" as a non-natural number gets somewhat philosophical,
666// and this function takes a position on what that should mean, but callers
667// may wish to disallow such things outright or implement their own modulo
668// if they disagree with the interpretation used here.
669func (val Value) Modulo(other Value) Value {
670	if val.IsMarked() || other.IsMarked() {
671		val, valMarks := val.Unmark()
672		other, otherMarks := other.Unmark()
673		return val.Modulo(other).WithMarks(valMarks, otherMarks)
674	}
675
676	if shortCircuit := mustTypeCheck(Number, Number, val, other); shortCircuit != nil {
677		shortCircuit = forceShortCircuitType(shortCircuit, Number)
678		return *shortCircuit
679	}
680
681	// We cheat a bit here with infinities, just abusing the Multiply operation
682	// to get an infinite result of the correct sign.
683	if val == PositiveInfinity || val == NegativeInfinity || other == PositiveInfinity || other == NegativeInfinity {
684		return val.Multiply(other)
685	}
686
687	if other.RawEquals(Zero) {
688		return val
689	}
690
691	// FIXME: This is a bit clumsy. Should come back later and see if there's a
692	// more straightforward way to do this.
693	rat := val.Divide(other)
694	ratFloorInt, _ := rat.v.(*big.Float).Int(nil)
695
696	// start with a copy of the original larger value so that we do not lose
697	// precision.
698	v := val.v.(*big.Float)
699	work := new(big.Float).Copy(v).SetInt(ratFloorInt)
700	work.Mul(other.v.(*big.Float), work)
701	work.Sub(v, work)
702
703	return NumberVal(work)
704}
705
706// Absolute returns the absolute (signless) value of the receiver, which must
707// be a number or this method will panic.
708func (val Value) Absolute() Value {
709	if val.IsMarked() {
710		val, valMarks := val.Unmark()
711		return val.Absolute().WithMarks(valMarks)
712	}
713
714	if shortCircuit := mustTypeCheck(Number, Number, val); shortCircuit != nil {
715		shortCircuit = forceShortCircuitType(shortCircuit, Number)
716		return *shortCircuit
717	}
718
719	ret := (&big.Float{}).Abs(val.v.(*big.Float))
720	return NumberVal(ret)
721}
722
723// GetAttr returns the value of the given attribute of the receiver, which
724// must be of an object type that has an attribute of the given name.
725// This method will panic if the receiver type is not compatible.
726//
727// The method will also panic if the given attribute name is not defined
728// for the value's type. Use the attribute-related methods on Type to
729// check for the validity of an attribute before trying to use it.
730//
731// This method may be called on a value whose type is DynamicPseudoType,
732// in which case the result will also be DynamicVal.
733func (val Value) GetAttr(name string) Value {
734	if val.IsMarked() {
735		val, valMarks := val.Unmark()
736		return val.GetAttr(name).WithMarks(valMarks)
737	}
738
739	if val.ty == DynamicPseudoType {
740		return DynamicVal
741	}
742
743	if !val.ty.IsObjectType() {
744		panic("value is not an object")
745	}
746
747	name = NormalizeString(name)
748	if !val.ty.HasAttribute(name) {
749		panic("value has no attribute of that name")
750	}
751
752	attrType := val.ty.AttributeType(name)
753
754	if !val.IsKnown() {
755		return UnknownVal(attrType)
756	}
757
758	return Value{
759		ty: attrType,
760		v:  val.v.(map[string]interface{})[name],
761	}
762}
763
764// Index returns the value of an element of the receiver, which must have
765// either a list, map or tuple type. This method will panic if the receiver
766// type is not compatible.
767//
768// The key value must be the correct type for the receving collection: a
769// number if the collection is a list or tuple, or a string if it is a map.
770// In the case of a list or tuple, the given number must be convertable to int
771// or this method will panic. The key may alternatively be of
772// DynamicPseudoType, in which case the result itself is an unknown of the
773// collection's element type.
774//
775// The result is of the receiver collection's element type, or in the case
776// of a tuple the type of the specific element index requested.
777//
778// This method may be called on a value whose type is DynamicPseudoType,
779// in which case the result will also be the DynamicValue.
780func (val Value) Index(key Value) Value {
781	if val.IsMarked() || key.IsMarked() {
782		val, valMarks := val.Unmark()
783		key, keyMarks := key.Unmark()
784		return val.Index(key).WithMarks(valMarks, keyMarks)
785	}
786
787	if val.ty == DynamicPseudoType {
788		return DynamicVal
789	}
790
791	switch {
792	case val.Type().IsListType():
793		elty := val.Type().ElementType()
794		if key.Type() == DynamicPseudoType {
795			return UnknownVal(elty)
796		}
797
798		if key.Type() != Number {
799			panic("element key for list must be number")
800		}
801		if !key.IsKnown() {
802			return UnknownVal(elty)
803		}
804
805		if !val.IsKnown() {
806			return UnknownVal(elty)
807		}
808
809		index, accuracy := key.v.(*big.Float).Int64()
810		if accuracy != big.Exact || index < 0 {
811			panic("element key for list must be non-negative integer")
812		}
813
814		return Value{
815			ty: elty,
816			v:  val.v.([]interface{})[index],
817		}
818	case val.Type().IsMapType():
819		elty := val.Type().ElementType()
820		if key.Type() == DynamicPseudoType {
821			return UnknownVal(elty)
822		}
823
824		if key.Type() != String {
825			panic("element key for map must be string")
826		}
827		if !key.IsKnown() {
828			return UnknownVal(elty)
829		}
830
831		if !val.IsKnown() {
832			return UnknownVal(elty)
833		}
834
835		keyStr := key.v.(string)
836
837		return Value{
838			ty: elty,
839			v:  val.v.(map[string]interface{})[keyStr],
840		}
841	case val.Type().IsTupleType():
842		if key.Type() == DynamicPseudoType {
843			return DynamicVal
844		}
845
846		if key.Type() != Number {
847			panic("element key for tuple must be number")
848		}
849		if !key.IsKnown() {
850			return DynamicVal
851		}
852
853		index, accuracy := key.v.(*big.Float).Int64()
854		if accuracy != big.Exact || index < 0 {
855			panic("element key for list must be non-negative integer")
856		}
857
858		eltys := val.Type().TupleElementTypes()
859
860		if !val.IsKnown() {
861			return UnknownVal(eltys[index])
862		}
863
864		return Value{
865			ty: eltys[index],
866			v:  val.v.([]interface{})[index],
867		}
868	default:
869		panic("not a list, map, or tuple type")
870	}
871}
872
873// HasIndex returns True if the receiver (which must be supported for Index)
874// has an element with the given index key, or False if it does not.
875//
876// The result will be UnknownVal(Bool) if either the collection or the
877// key value are unknown.
878//
879// This method will panic if the receiver is not indexable, but does not
880// impose any panic-causing type constraints on the key.
881func (val Value) HasIndex(key Value) Value {
882	if val.IsMarked() || key.IsMarked() {
883		val, valMarks := val.Unmark()
884		key, keyMarks := key.Unmark()
885		return val.HasIndex(key).WithMarks(valMarks, keyMarks)
886	}
887
888	if val.ty == DynamicPseudoType {
889		return UnknownVal(Bool)
890	}
891
892	switch {
893	case val.Type().IsListType():
894		if key.Type() == DynamicPseudoType {
895			return UnknownVal(Bool)
896		}
897
898		if key.Type() != Number {
899			return False
900		}
901		if !key.IsKnown() {
902			return UnknownVal(Bool)
903		}
904		if !val.IsKnown() {
905			return UnknownVal(Bool)
906		}
907
908		index, accuracy := key.v.(*big.Float).Int64()
909		if accuracy != big.Exact || index < 0 {
910			return False
911		}
912
913		return BoolVal(int(index) < len(val.v.([]interface{})) && index >= 0)
914	case val.Type().IsMapType():
915		if key.Type() == DynamicPseudoType {
916			return UnknownVal(Bool)
917		}
918
919		if key.Type() != String {
920			return False
921		}
922		if !key.IsKnown() {
923			return UnknownVal(Bool)
924		}
925		if !val.IsKnown() {
926			return UnknownVal(Bool)
927		}
928
929		keyStr := key.v.(string)
930		_, exists := val.v.(map[string]interface{})[keyStr]
931
932		return BoolVal(exists)
933	case val.Type().IsTupleType():
934		if key.Type() == DynamicPseudoType {
935			return UnknownVal(Bool)
936		}
937
938		if key.Type() != Number {
939			return False
940		}
941		if !key.IsKnown() {
942			return UnknownVal(Bool)
943		}
944
945		index, accuracy := key.v.(*big.Float).Int64()
946		if accuracy != big.Exact || index < 0 {
947			return False
948		}
949
950		length := val.Type().Length()
951		return BoolVal(int(index) < length && index >= 0)
952	default:
953		panic("not a list, map, or tuple type")
954	}
955}
956
957// HasElement returns True if the receiver (which must be of a set type)
958// has the given value as an element, or False if it does not.
959//
960// The result will be UnknownVal(Bool) if either the set or the
961// given value are unknown.
962//
963// This method will panic if the receiver is not a set, or if it is a null set.
964func (val Value) HasElement(elem Value) Value {
965	if val.IsMarked() || elem.IsMarked() {
966		val, valMarks := val.Unmark()
967		elem, elemMarks := elem.Unmark()
968		return val.HasElement(elem).WithMarks(valMarks, elemMarks)
969	}
970
971	ty := val.Type()
972
973	if !ty.IsSetType() {
974		panic("not a set type")
975	}
976	if !val.IsKnown() || !elem.IsKnown() {
977		return UnknownVal(Bool)
978	}
979	if val.IsNull() {
980		panic("can't call HasElement on a nil value")
981	}
982	if !ty.ElementType().Equals(elem.Type()) {
983		return False
984	}
985
986	s := val.v.(set.Set)
987	return BoolVal(s.Has(elem.v))
988}
989
990// Length returns the length of the receiver, which must be a collection type
991// or tuple type, as a number value. If the receiver is not a compatible type
992// then this method will panic.
993//
994// If the receiver is unknown then the result is also unknown.
995//
996// If the receiver is null then this function will panic.
997//
998// Note that Length is not supported for strings. To determine the length
999// of a string, use the Length function in funcs/stdlib.
1000func (val Value) Length() Value {
1001	if val.IsMarked() {
1002		val, valMarks := val.Unmark()
1003		return val.Length().WithMarks(valMarks)
1004	}
1005
1006	if val.Type().IsTupleType() {
1007		// For tuples, we can return the length even if the value is not known.
1008		return NumberIntVal(int64(val.Type().Length()))
1009	}
1010
1011	if !val.IsKnown() {
1012		return UnknownVal(Number)
1013	}
1014	if val.Type().IsSetType() {
1015		// The Length rules are a little different for sets because if any
1016		// unknown values are present then the values they are standing in for
1017		// may or may not be equal to other elements in the set, and thus they
1018		// may or may not coalesce with other elements and produce fewer
1019		// items in the resulting set.
1020		storeLength := int64(val.v.(set.Set).Length())
1021		if storeLength == 1 || val.IsWhollyKnown() {
1022			// If our set is wholly known then we know its length.
1023			//
1024			// We also know the length if the physical store has only one
1025			// element, even if that element is unknown, because there's
1026			// nothing else in the set for it to coalesce with and a single
1027			// unknown value cannot represent more than one known value.
1028			return NumberIntVal(storeLength)
1029		}
1030		// Otherwise, we cannot predict the length.
1031		return UnknownVal(Number)
1032	}
1033
1034	return NumberIntVal(int64(val.LengthInt()))
1035}
1036
1037// LengthInt is like Length except it returns an int. It has the same behavior
1038// as Length except that it will panic if the receiver is unknown.
1039//
1040// This is an integration method provided for the convenience of code bridging
1041// into Go's type system.
1042//
1043// For backward compatibility with an earlier implementation error, LengthInt's
1044// result can disagree with Length's result for any set containing unknown
1045// values. Length can potentially indicate the set's length is unknown in that
1046// case, whereas LengthInt will return the maximum possible length as if the
1047// unknown values were each a placeholder for a value not equal to any other
1048// value in the set.
1049func (val Value) LengthInt() int {
1050	val.assertUnmarked()
1051	if val.Type().IsTupleType() {
1052		// For tuples, we can return the length even if the value is not known.
1053		return val.Type().Length()
1054	}
1055	if val.Type().IsObjectType() {
1056		// For objects, the length is the number of attributes associated with the type.
1057		return len(val.Type().AttributeTypes())
1058	}
1059	if !val.IsKnown() {
1060		panic("value is not known")
1061	}
1062	if val.IsNull() {
1063		panic("value is null")
1064	}
1065
1066	switch {
1067
1068	case val.ty.IsListType():
1069		return len(val.v.([]interface{}))
1070
1071	case val.ty.IsSetType():
1072		// NOTE: This is technically not correct in cases where the set
1073		// contains unknown values, because in that case we can't know how
1074		// many known values those unknown values are standing in for -- they
1075		// might coalesce with other values once known.
1076		//
1077		// However, this incorrect behavior is preserved for backward
1078		// compatibility with callers that were relying on LengthInt rather
1079		// than calling Length. Instead of panicking when a set contains an
1080		// unknown value, LengthInt returns the largest possible length.
1081		return val.v.(set.Set).Length()
1082
1083	case val.ty.IsMapType():
1084		return len(val.v.(map[string]interface{}))
1085
1086	default:
1087		panic("value is not a collection")
1088	}
1089}
1090
1091// ElementIterator returns an ElementIterator for iterating the elements
1092// of the receiver, which must be a collection type, a tuple type, or an object
1093// type. If called on a method of any other type, this method will panic.
1094//
1095// The value must be Known and non-Null, or this method will panic.
1096//
1097// If the receiver is of a list type, the returned keys will be of type Number
1098// and the values will be of the list's element type.
1099//
1100// If the receiver is of a map type, the returned keys will be of type String
1101// and the value will be of the map's element type. Elements are passed in
1102// ascending lexicographical order by key.
1103//
1104// If the receiver is of a set type, each element is returned as both the
1105// key and the value, since set members are their own identity.
1106//
1107// If the receiver is of a tuple type, the returned keys will be of type Number
1108// and the value will be of the corresponding element's type.
1109//
1110// If the receiver is of an object type, the returned keys will be of type
1111// String and the value will be of the corresponding attributes's type.
1112//
1113// ElementIterator is an integration method, so it cannot handle Unknown
1114// values. This method will panic if the receiver is Unknown.
1115func (val Value) ElementIterator() ElementIterator {
1116	val.assertUnmarked()
1117	if !val.IsKnown() {
1118		panic("can't use ElementIterator on unknown value")
1119	}
1120	if val.IsNull() {
1121		panic("can't use ElementIterator on null value")
1122	}
1123	return elementIterator(val)
1124}
1125
1126// CanIterateElements returns true if the receiver can support the
1127// ElementIterator method (and by extension, ForEachElement) without panic.
1128func (val Value) CanIterateElements() bool {
1129	return canElementIterator(val)
1130}
1131
1132// ForEachElement executes a given callback function for each element of
1133// the receiver, which must be a collection type or tuple type, or this method
1134// will panic.
1135//
1136// ForEachElement uses ElementIterator internally, and so the values passed
1137// to the callback are as described for ElementIterator.
1138//
1139// Returns true if the iteration exited early due to the callback function
1140// returning true, or false if the loop ran to completion.
1141//
1142// ForEachElement is an integration method, so it cannot handle Unknown
1143// values. This method will panic if the receiver is Unknown.
1144func (val Value) ForEachElement(cb ElementCallback) bool {
1145	val.assertUnmarked()
1146	it := val.ElementIterator()
1147	for it.Next() {
1148		key, val := it.Element()
1149		stop := cb(key, val)
1150		if stop {
1151			return true
1152		}
1153	}
1154	return false
1155}
1156
1157// Not returns the logical inverse of the receiver, which must be of type
1158// Bool or this method will panic.
1159func (val Value) Not() Value {
1160	if val.IsMarked() {
1161		val, valMarks := val.Unmark()
1162		return val.Not().WithMarks(valMarks)
1163	}
1164
1165	if shortCircuit := mustTypeCheck(Bool, Bool, val); shortCircuit != nil {
1166		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1167		return *shortCircuit
1168	}
1169
1170	return BoolVal(!val.v.(bool))
1171}
1172
1173// And returns the result of logical AND with the receiver and the other given
1174// value, which must both be of type Bool or this method will panic.
1175func (val Value) And(other Value) Value {
1176	if val.IsMarked() || other.IsMarked() {
1177		val, valMarks := val.Unmark()
1178		other, otherMarks := other.Unmark()
1179		return val.And(other).WithMarks(valMarks, otherMarks)
1180	}
1181
1182	if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
1183		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1184		return *shortCircuit
1185	}
1186
1187	return BoolVal(val.v.(bool) && other.v.(bool))
1188}
1189
1190// Or returns the result of logical OR with the receiver and the other given
1191// value, which must both be of type Bool or this method will panic.
1192func (val Value) Or(other Value) Value {
1193	if val.IsMarked() || other.IsMarked() {
1194		val, valMarks := val.Unmark()
1195		other, otherMarks := other.Unmark()
1196		return val.Or(other).WithMarks(valMarks, otherMarks)
1197	}
1198
1199	if shortCircuit := mustTypeCheck(Bool, Bool, val, other); shortCircuit != nil {
1200		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1201		return *shortCircuit
1202	}
1203
1204	return BoolVal(val.v.(bool) || other.v.(bool))
1205}
1206
1207// LessThan returns True if the receiver is less than the other given value,
1208// which must both be numbers or this method will panic.
1209func (val Value) LessThan(other Value) Value {
1210	if val.IsMarked() || other.IsMarked() {
1211		val, valMarks := val.Unmark()
1212		other, otherMarks := other.Unmark()
1213		return val.LessThan(other).WithMarks(valMarks, otherMarks)
1214	}
1215
1216	if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
1217		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1218		return *shortCircuit
1219	}
1220
1221	return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) < 0)
1222}
1223
1224// GreaterThan returns True if the receiver is greater than the other given
1225// value, which must both be numbers or this method will panic.
1226func (val Value) GreaterThan(other Value) Value {
1227	if val.IsMarked() || other.IsMarked() {
1228		val, valMarks := val.Unmark()
1229		other, otherMarks := other.Unmark()
1230		return val.GreaterThan(other).WithMarks(valMarks, otherMarks)
1231	}
1232
1233	if shortCircuit := mustTypeCheck(Number, Bool, val, other); shortCircuit != nil {
1234		shortCircuit = forceShortCircuitType(shortCircuit, Bool)
1235		return *shortCircuit
1236	}
1237
1238	return BoolVal(val.v.(*big.Float).Cmp(other.v.(*big.Float)) > 0)
1239}
1240
1241// LessThanOrEqualTo is equivalent to LessThan and Equal combined with Or.
1242func (val Value) LessThanOrEqualTo(other Value) Value {
1243	return val.LessThan(other).Or(val.Equals(other))
1244}
1245
1246// GreaterThanOrEqualTo is equivalent to GreaterThan and Equal combined with Or.
1247func (val Value) GreaterThanOrEqualTo(other Value) Value {
1248	return val.GreaterThan(other).Or(val.Equals(other))
1249}
1250
1251// AsString returns the native string from a non-null, non-unknown cty.String
1252// value, or panics if called on any other value.
1253func (val Value) AsString() string {
1254	val.assertUnmarked()
1255	if val.ty != String {
1256		panic("not a string")
1257	}
1258	if val.IsNull() {
1259		panic("value is null")
1260	}
1261	if !val.IsKnown() {
1262		panic("value is unknown")
1263	}
1264
1265	return val.v.(string)
1266}
1267
1268// AsBigFloat returns a big.Float representation of a non-null, non-unknown
1269// cty.Number value, or panics if called on any other value.
1270//
1271// For more convenient conversions to other native numeric types, use the
1272// "gocty" package.
1273func (val Value) AsBigFloat() *big.Float {
1274	val.assertUnmarked()
1275	if val.ty != Number {
1276		panic("not a number")
1277	}
1278	if val.IsNull() {
1279		panic("value is null")
1280	}
1281	if !val.IsKnown() {
1282		panic("value is unknown")
1283	}
1284
1285	// Copy the float so that callers can't mutate our internal state
1286	return new(big.Float).Copy(val.v.(*big.Float))
1287}
1288
1289// AsValueSlice returns a []cty.Value representation of a non-null, non-unknown
1290// value of any type that CanIterateElements, or panics if called on
1291// any other value.
1292//
1293// For more convenient conversions to slices of more specific types, use
1294// the "gocty" package.
1295func (val Value) AsValueSlice() []Value {
1296	val.assertUnmarked()
1297	l := val.LengthInt()
1298	if l == 0 {
1299		return nil
1300	}
1301
1302	ret := make([]Value, 0, l)
1303	for it := val.ElementIterator(); it.Next(); {
1304		_, v := it.Element()
1305		ret = append(ret, v)
1306	}
1307	return ret
1308}
1309
1310// AsValueMap returns a map[string]cty.Value representation of a non-null,
1311// non-unknown value of any type that CanIterateElements, or panics if called
1312// on any other value.
1313//
1314// For more convenient conversions to maps of more specific types, use
1315// the "gocty" package.
1316func (val Value) AsValueMap() map[string]Value {
1317	val.assertUnmarked()
1318	l := val.LengthInt()
1319	if l == 0 {
1320		return nil
1321	}
1322
1323	ret := make(map[string]Value, l)
1324	for it := val.ElementIterator(); it.Next(); {
1325		k, v := it.Element()
1326		ret[k.AsString()] = v
1327	}
1328	return ret
1329}
1330
1331// AsValueSet returns a ValueSet representation of a non-null,
1332// non-unknown value of any collection type, or panics if called
1333// on any other value.
1334//
1335// Unlike AsValueSlice and AsValueMap, this method requires specifically a
1336// collection type (list, set or map) and does not allow structural types
1337// (tuple or object), because the ValueSet type requires homogenous
1338// element types.
1339//
1340// The returned ValueSet can store only values of the receiver's element type.
1341func (val Value) AsValueSet() ValueSet {
1342	val.assertUnmarked()
1343	if !val.Type().IsCollectionType() {
1344		panic("not a collection type")
1345	}
1346
1347	// We don't give the caller our own set.Set (assuming we're a cty.Set value)
1348	// because then the caller could mutate our internals, which is forbidden.
1349	// Instead, we will construct a new set and append our elements into it.
1350	ret := NewValueSet(val.Type().ElementType())
1351	for it := val.ElementIterator(); it.Next(); {
1352		_, v := it.Element()
1353		ret.Add(v)
1354	}
1355	return ret
1356}
1357
1358// EncapsulatedValue returns the native value encapsulated in a non-null,
1359// non-unknown capsule-typed value, or panics if called on any other value.
1360//
1361// The result is the same pointer that was passed to CapsuleVal to create
1362// the value. Since cty considers values to be immutable, it is strongly
1363// recommended to treat the encapsulated value itself as immutable too.
1364func (val Value) EncapsulatedValue() interface{} {
1365	val.assertUnmarked()
1366	if !val.Type().IsCapsuleType() {
1367		panic("not a capsule-typed value")
1368	}
1369
1370	return val.v
1371}
1372