blob: b3d0bccca250b5157d2bdaa481990f3617928cb8 [file] [log] [blame]
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001// Copyright 2018 The CUE Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package cue
16
17import (
18 "bytes"
19 "encoding/json"
20 "fmt"
21 "io"
22 "math"
23 "math/big"
Marcel van Lohuizenb9b62d32019-03-14 23:50:15 +010024 "strconv"
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010025 "strings"
26
27 "cuelang.org/go/cue/ast"
28 "cuelang.org/go/cue/errors"
29 "cuelang.org/go/cue/token"
30 "github.com/cockroachdb/apd"
31)
32
33// Kind determines the underlying type of a Value.
34type Kind int
35
36const (
37 // BottomKind is the error value.
38 BottomKind Kind = 1 << iota
39
40 // NullKind indicates a null value.
41 NullKind
42
43 // BoolKind indicates a boolean value.
44 BoolKind
45
Marcel van Lohuizen52cc1092019-05-06 11:43:15 +020046 // IntKind represents an integral number.
47 IntKind
48
49 // FloatKind represents a decimal float point number that cannot be
50 // converted to an integer. The underlying number may still be integral,
51 // but resulting from an operation that enforces the float type.
52 FloatKind
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010053
54 // StringKind indicates any kind of string.
55 StringKind
56
57 // BytesKind is a blob of data.
58 BytesKind
59
60 // StructKind is a kev-value map.
61 StructKind
62
63 // ListKind indicates a list of values.
64 ListKind
65
66 nextKind
Marcel van Lohuizen52cc1092019-05-06 11:43:15 +020067
68 // NumberKind represents any kind of number.
69 NumberKind = IntKind | FloatKind
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +010070)
71
72// An structValue represents a JSON object.
73//
74// TODO: remove
75type structValue struct {
76 ctx *context
77 path *valueData
78 n *structLit
79}
80
81// Len reports the number of fields in this struct.
82func (o *structValue) Len() int {
83 return len(o.n.arcs)
84}
85
86// At reports the key and value of the ith field, i < o.Len().
87func (o *structValue) At(i int) (key string, v Value) {
88 a := o.n.arcs[i]
89 v = newChildValue(o, i)
90 return o.ctx.labelStr(a.feature), v
91}
92
93// Lookup reports the field for the given key. The returned Value is invalid
94// if it does not exist.
95func (o *structValue) Lookup(key string) Value {
96 f := o.ctx.strLabel(key)
97 i := 0
98 for ; i < len(o.n.arcs); i++ {
99 if o.n.arcs[i].feature == f {
100 break
101 }
102 }
103 if i == len(o.n.arcs) {
104 // TODO: better message.
105 return newValueRoot(o.ctx, o.ctx.mkErr(o.n, codeNotExist,
106 "value %q not found", key))
107 }
108 // v, _ := o.n.lookup(o.ctx, f)
109 // v = o.ctx.manifest(v)
110 return newChildValue(o, i)
111}
112
113// MarshalJSON returns a valid JSON encoding or reports an error if any of the
114// fields is invalid.
115func (o *structValue) MarshalJSON() (b []byte, err error) {
116 b = append(b, '{')
117 n := o.Len()
118 for i := 0; i < n; i++ {
119 k, v := o.At(i)
120 s, err := json.Marshal(k)
121 if err != nil {
122 return nil, err
123 }
124 b = append(b, s...)
125 b = append(b, ':')
126 bb, err := json.Marshal(v)
127 if err != nil {
128 return nil, err
129 }
130 b = append(b, bb...)
131 if i < n-1 {
132 b = append(b, ',')
133 }
134 }
135 b = append(b, '}')
136 return b, nil
137}
138
139// An Iterator iterates over values.
140//
141type Iterator struct {
Marcel van Lohuizenb9b62d32019-03-14 23:50:15 +0100142 val Value
143 ctx *context
144 iter iterAtter
145 len int
146 p int
147 cur Value
148 f label
149 attrs *attributes
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100150}
151
152// Next advances the iterator to the next value and reports whether there was
153// any. It must be called before the first call to Value or Key.
154func (i *Iterator) Next() bool {
155 if i.p >= i.len {
156 i.cur = Value{}
157 return false
158 }
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100159 arc := i.iter.iterAt(i.ctx, i.p)
160 i.cur = i.val.makeChild(i.ctx, uint32(i.p), arc)
161 i.f = arc.feature
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100162 i.p++
163 return true
164}
165
166// Value returns the current value in the list. It will panic if Next advanced
167// past the last entry.
168func (i *Iterator) Value() Value {
169 return i.cur
170}
171
172// Label reports the label of the value if i iterates over struct fields and
173// "" otherwise.
174func (i *Iterator) Label() string {
175 if i.f == 0 {
176 return ""
177 }
178 return i.ctx.labelStr(i.f)
179}
180
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200181// IsHidden reports if a field is hidden from the data model.
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100182func (i *Iterator) IsHidden() bool {
183 return i.f&hidden != 0
184}
185
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200186// IsOptional reports if a field is optional.
187func (i *Iterator) IsOptional() bool {
188 return i.cur.path.arc.optional
189}
190
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100191// marshalJSON iterates over the list and generates JSON output. HasNext
192// will return false after this operation.
193func marshalList(l *Iterator) (b []byte, err error) {
194 b = append(b, '[')
195 if l.Next() {
196 for {
197 x, err := json.Marshal(l.Value())
198 if err != nil {
199 return nil, err
200 }
201 b = append(b, x...)
202 if !l.Next() {
203 break
204 }
205 b = append(b, ',')
206 }
207 }
208 b = append(b, ']')
209 return b, nil
210}
211
212func (v Value) getNum(k kind) (*numLit, error) {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200213 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100214 if err := v.checkKind(v.ctx(), k); err != nil {
215 return nil, err
216 }
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100217 n, _ := v.path.cache.(*numLit)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100218 return n, nil
219}
220
221// MantExp breaks x into its mantissa and exponent components and returns the
222// exponent. If a non-nil mant argument is provided its value is set to the
223// mantissa of x. The components satisfy x == mant × 10**exp. It returns an
224// error if v is not a number.
225//
226// The components are not normalized. For instance, 2.00 is represented mant ==
227// 200 and exp == -2. Calling MantExp with a nil argument is an efficient way to
228// get the exponent of the receiver.
229func (v Value) MantExp(mant *big.Int) (exp int, err error) {
230 n, err := v.getNum(numKind)
231 if err != nil {
232 return 0, err
233 }
234 if n.v.Form != 0 {
235 return 0, ErrInfinite
236 }
237 if mant != nil {
238 mant.Set(&n.v.Coeff)
239 if n.v.Negative {
240 mant.Neg(mant)
241 }
242 }
243 return int(n.v.Exponent), nil
244}
245
246// AppendInt appends the string representation of x in the given base to buf and
247// returns the extended buffer, or an error if the underlying number was not
248// an integer.
249func (v Value) AppendInt(buf []byte, base int) ([]byte, error) {
250 i, err := v.Int(nil)
251 if err != nil {
252 return nil, err
253 }
254 return i.Append(buf, base), nil
255}
256
257// AppendFloat appends to buf the string form of the floating-point number x.
258// It returns an error if v is not a number.
259func (v Value) AppendFloat(buf []byte, fmt byte, prec int) ([]byte, error) {
260 n, err := v.getNum(numKind)
261 if err != nil {
262 return nil, err
263 }
264 ctx := apd.BaseContext
265 nd := int(apd.NumDigits(&n.v.Coeff)) + int(n.v.Exponent)
266 if n.v.Form == apd.Infinite {
267 if n.v.Negative {
268 buf = append(buf, '-')
269 }
270 return append(buf, string('∞')...), nil
271 }
272 if fmt == 'f' && nd > 0 {
273 ctx.Precision = uint32(nd + prec)
274 } else {
275 ctx.Precision = uint32(prec)
276 }
277 var d apd.Decimal
278 ctx.Round(&d, &n.v)
279 return d.Append(buf, fmt), nil
280}
281
282var (
283 // ErrBelow indicates that a value was rounded down in a conversion.
284 ErrBelow = errors.New("cue: value was rounded down")
285
286 // ErrAbove indicates that a value was rounded up in a conversion.
287 ErrAbove = errors.New("cue: value was rounded up")
288
289 // ErrInfinite indicates that a value is infinite.
290 ErrInfinite = errors.New("cue: infinite")
291)
292
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100293// Int converts the underlying integral number to an big.Int. It reports an
294// error if the underlying value is not an integer type. If a non-nil *Int
295// argument z is provided, Int stores the result in z instead of allocating a
296// new Int.
297func (v Value) Int(z *big.Int) (*big.Int, error) {
298 n, err := v.getNum(intKind)
299 if err != nil {
300 return nil, err
301 }
302 if z == nil {
303 z = &big.Int{}
304 }
305 if n.v.Exponent != 0 {
306 panic("cue: exponent should always be nil for integer types")
307 }
308 z.Set(&n.v.Coeff)
309 if n.v.Negative {
310 z.Neg(z)
311 }
312 return z, nil
313}
314
315// Int64 converts the underlying integral number to int64. It reports an
316// error if the underlying value is not an integer type or cannot be represented
317// as an int64. The result is (math.MinInt64, ErrAbove) for x < math.MinInt64,
318// and (math.MaxInt64, ErrBelow) for x > math.MaxInt64.
319func (v Value) Int64() (int64, error) {
320 n, err := v.getNum(intKind)
321 if err != nil {
322 return 0, err
323 }
324 if !n.v.Coeff.IsInt64() {
325 if n.v.Negative {
326 return math.MinInt64, ErrAbove
327 }
328 return math.MaxInt64, ErrBelow
329 }
330 i := n.v.Coeff.Int64()
331 if n.v.Negative {
332 i = -i
333 }
334 return i, nil
335}
336
337// Uint64 converts the underlying integral number to uint64. It reports an
338// error if the underlying value is not an integer type or cannot be represented
339// as a uint64. The result is (0, ErrAbove) for x < 0, and
340// (math.MaxUint64, ErrBelow) for x > math.MaxUint64.
341func (v Value) Uint64() (uint64, error) {
342 n, err := v.getNum(intKind)
343 if err != nil {
344 return 0, err
345 }
346 if n.v.Negative {
347 return 0, ErrAbove
348 }
349 if !n.v.Coeff.IsUint64() {
350 return math.MaxUint64, ErrBelow
351 }
352 i := n.v.Coeff.Uint64()
353 return i, nil
354}
355
356// trimZeros trims 0's for better JSON respresentations.
357func trimZeros(s string) string {
358 n1 := len(s)
359 s2 := strings.TrimRight(s, "0")
360 n2 := len(s2)
361 if p := strings.IndexByte(s2, '.'); p != -1 {
362 if p == n2-1 {
363 return s[:len(s2)+1]
364 }
365 return s2
366 }
367 if n1-n2 <= 4 {
368 return s
369 }
370 return fmt.Sprint(s2, "e+", n1-n2)
371}
372
373var (
374 smallestPosFloat64 *apd.Decimal
375 smallestNegFloat64 *apd.Decimal
376 maxPosFloat64 *apd.Decimal
377 maxNegFloat64 *apd.Decimal
378)
379
380func init() {
381 const (
382 // math.SmallestNonzeroFloat64: 1 / 2**(1023 - 1 + 52)
383 smallest = "4.940656458412465441765687928682213723651e-324"
384 // math.MaxFloat64: 2**1023 * (2**53 - 1) / 2**52
385 max = "1.797693134862315708145274237317043567981e+308"
386 )
387 ctx := apd.BaseContext
388 ctx.Precision = 40
389
390 var err error
391 smallestPosFloat64, _, err = ctx.NewFromString(smallest)
392 if err != nil {
393 panic(err)
394 }
395 smallestNegFloat64, _, err = ctx.NewFromString("-" + smallest)
396 if err != nil {
397 panic(err)
398 }
399 maxPosFloat64, _, err = ctx.NewFromString(max)
400 if err != nil {
401 panic(err)
402 }
403 maxNegFloat64, _, err = ctx.NewFromString("-" + max)
404 if err != nil {
405 panic(err)
406 }
407}
408
409// Float64 returns the float64 value nearest to x. It reports an error if v is
410// not a number. If x is too small to be represented by a float64 (|x| <
411// math.SmallestNonzeroFloat64), the result is (0, ErrBelow) or (-0, ErrAbove),
412// respectively, depending on the sign of x. If x is too large to be represented
413// by a float64 (|x| > math.MaxFloat64), the result is (+Inf, ErrAbove) or
414// (-Inf, ErrBelow), depending on the sign of x.
415func (v Value) Float64() (float64, error) {
416 n, err := v.getNum(numKind)
417 if err != nil {
418 return 0, err
419 }
420 if n.v.Negative {
421 if n.v.Cmp(smallestNegFloat64) == 1 {
422 return -0, ErrAbove
423 }
424 if n.v.Cmp(maxNegFloat64) == -1 {
425 return math.Inf(-1), ErrBelow
426 }
427 } else {
428 if n.v.Cmp(smallestPosFloat64) == -1 {
429 return 0, ErrBelow
430 }
431 if n.v.Cmp(maxPosFloat64) == 1 {
432 return math.Inf(1), ErrAbove
433 }
434 }
435 f, _ := n.v.Float64()
436 return f, nil
437}
438
439type valueData struct {
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100440 parent *valueData
441 index uint32
442 arc
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100443}
444
445// Value holds any value, which may be a Boolean, Error, List, Null, Number,
446// Struct, or String.
447type Value struct {
448 idx *index
449 path *valueData
450}
451
452func newValueRoot(ctx *context, x value) Value {
453 v := x.evalPartial(ctx)
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100454 return Value{ctx.index, &valueData{nil, 0, arc{cache: v, v: x}}}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100455}
456
457func newChildValue(obj *structValue, i int) Value {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100458 a := obj.n.arcs[i]
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200459 a.cache = obj.n.at(obj.ctx, i)
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100460
461 return Value{obj.ctx.index, &valueData{obj.path, uint32(i), a}}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100462}
463
Marcel van Lohuizen0519f252019-05-06 18:06:48 +0200464func remakeValue(base Value, v value) Value {
465 path := *base.path
466 path.v = v
467 path.cache = v.evalPartial(base.ctx())
468 return Value{base.idx, &path}
469}
470
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100471func (v Value) ctx() *context {
472 return v.idx.newContext()
473}
474
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100475func (v Value) makeChild(ctx *context, i uint32, a arc) Value {
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100476 return Value{v.idx, &valueData{v.path, i, a}}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100477}
478
479func (v Value) eval(ctx *context) value {
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100480 if v.path == nil || v.path.cache == nil {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100481 panic("undefined value")
482 }
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100483 return ctx.manifest(v.path.cache)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100484}
485
Marcel van Lohuizen0519f252019-05-06 18:06:48 +0200486// Eval resolves the references of a value and returns the result.
487// This method is not necessary to obtain concrete values.
488func (v Value) Eval() Value {
489 if v.path == nil {
490 return v
491 }
492 return remakeValue(v, v.path.v.evalPartial(v.ctx()))
493}
494
495// Default reports the default value and whether it existed. It returns the
496// normal value if there is no default.
497func (v Value) Default() (Value, bool) {
498 if v.path == nil {
499 return v, false
500 }
501 x := v.ctx().manifest(v.path.v)
502 if x != v.path.v {
503 return remakeValue(v, x), true
504 }
505 return v, false
506}
507
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100508// Label reports he label used to obtain this value from the enclosing struct.
509//
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200510// TODO: get rid of this somehow. Probably by including a FieldInfo struct
511// or the like.
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100512func (v Value) Label() (string, bool) {
513 if v.path.feature == 0 {
514 return "", false
515 }
516 return v.idx.labelStr(v.path.feature), true
517}
518
519// Kind returns the kind of value. It returns BottomKind for atomic values that
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100520// are not concrete. For instance, it will return BottomKind for the bounds
521// >=0.
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100522func (v Value) Kind() Kind {
Marcel van Lohuizen52cc1092019-05-06 11:43:15 +0200523 if v.path == nil {
524 return BottomKind
525 }
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200526 k := v.path.v.evalPartial(v.ctx()).kind()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100527 if k.isGround() {
528 switch {
529 case k.isAnyOf(nullKind):
530 return NullKind
531 case k.isAnyOf(boolKind):
532 return BoolKind
Marcel van Lohuizen52cc1092019-05-06 11:43:15 +0200533 case k&numKind == (intKind):
534 return IntKind
535 case k&numKind == (floatKind):
536 return FloatKind
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100537 case k.isAnyOf(numKind):
538 return NumberKind
539 case k.isAnyOf(bytesKind):
540 return BytesKind
541 case k.isAnyOf(stringKind):
542 return StringKind
543 case k.isAnyOf(structKind):
544 return StructKind
545 case k.isAnyOf(listKind):
546 return ListKind
547 }
548 }
549 return BottomKind
550}
551
552// IncompleteKind returns a mask of all kinds that this value may be.
553func (v Value) IncompleteKind() Kind {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200554 if v.path == nil {
555 return BottomKind
556 }
557 k := v.path.v.evalPartial(v.ctx()).kind()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100558 vk := BottomKind // Everything is a bottom kind.
559 for i := kind(1); i < nonGround; i <<= 1 {
560 if k&i != 0 {
561 switch i {
562 case nullKind:
563 vk |= NullKind
564 case boolKind:
565 vk |= BoolKind
Marcel van Lohuizen52cc1092019-05-06 11:43:15 +0200566 case intKind:
567 vk |= IntKind
568 case floatKind:
569 vk |= FloatKind
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100570 case stringKind:
571 vk |= StringKind
572 case bytesKind:
573 vk |= BytesKind
574 case structKind:
575 vk |= StructKind
576 case listKind:
577 vk |= ListKind
578 }
579 }
580 }
581 return vk
582}
583
584// MarshalJSON marshalls this value into valid JSON.
585func (v Value) MarshalJSON() (b []byte, err error) {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200586 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100587 if v.path == nil {
588 return json.Marshal(nil)
589 }
590 ctx := v.idx.newContext()
591 x := v.eval(ctx)
592 // TODO: implement marshalles in value.
593 switch k := x.kind(); k {
594 case nullKind:
595 return json.Marshal(nil)
596 case boolKind:
597 return json.Marshal(x.(*boolLit).b)
598 case intKind, floatKind, numKind:
599 return x.(*numLit).v.MarshalText()
600 case stringKind:
601 return json.Marshal(x.(*stringLit).str)
602 case bytesKind:
603 return json.Marshal(x.(*bytesLit).b)
604 case listKind:
605 l := x.(*list)
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +0200606 i := Iterator{ctx: ctx, val: v, iter: l, len: len(l.elem.arcs)}
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100607 return marshalList(&i)
608 case structKind:
609 obj, _ := v.structVal(ctx)
610 return obj.MarshalJSON()
611 case bottomKind:
612 return nil, x.(*bottom)
613 default:
614 if k.hasReferences() {
615 return nil, v.idx.mkErr(x, "value %q contains unresolved references", debugStr(ctx, x))
616 }
617 if !k.isGround() {
618 return nil, v.idx.mkErr(x, "cannot convert incomplete value %q to JSON", debugStr(ctx, x))
619 }
620 return nil, v.idx.mkErr(x, "cannot convert value %q of type %T to JSON", debugStr(ctx, x), x)
621 }
622}
623
624// Syntax converts the possibly partially evaluated value into syntax. This
625// can use used to print the value with package format.
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200626func (v Value) Syntax(opts ...Option) ast.Expr {
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100627 if v.path == nil || v.path.cache == nil {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100628 return nil
629 }
630 ctx := v.ctx()
Marcel van Lohuizen0519f252019-05-06 18:06:48 +0200631 o := getOptions(opts)
632 if o.raw {
633 return export(ctx, v.path.v, o)
634 }
635 return export(ctx, v.path.cache, o)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100636}
637
638// Decode initializes x with Value v. If x is a struct, it will validate the
639// constraints specified in the field tags.
640func (v Value) Decode(x interface{}) error {
641 // TODO: optimize
642 b, err := v.MarshalJSON()
643 if err != nil {
644 return err
645 }
646 return json.Unmarshal(b, x)
647}
648
649// // EncodeJSON generates JSON for the given value.
650// func (v Value) EncodeJSON(w io.Writer, v Value) error {
651// return nil
652// }
653
654// Split returns a list of values from which v originated such that
655// the unification of all these values equals v and for all returned values
656// Source returns a non-nil value.
657func (v Value) Split() []Value {
658 if v.path == nil {
659 return nil
660 }
661 ctx := v.ctx()
662 a := []Value{}
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100663 for _, x := range separate(v.path.v) {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100664 path := *v.path
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100665 path.cache = x.evalPartial(ctx)
666 path.v = x
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100667 a = append(a, Value{v.idx, &path})
668 }
669 return a
670}
671
672func separate(v value) (a []value) {
673 c := v.computed()
Marcel van Lohuizen0519f252019-05-06 18:06:48 +0200674 if c == nil || c.op != opUnify {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100675 return []value{v}
676 }
677 if c.x != nil {
678 a = append(a, separate(c.x)...)
679 }
680 if c.y != nil {
681 a = append(a, separate(c.y)...)
682 }
683 return a
684}
685
686// Source returns the original node for this value. The return value may not
687// be a syntax.Expr. For instance, a struct kind may be represented by a
688// struct literal, a field comprehension, or a file. It returns nil for
689// computed nodes. Use Split to get all source values that apply to a field.
690func (v Value) Source() ast.Node {
691 if v.path == nil {
692 return nil
693 }
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100694 return v.path.v.syntax()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100695}
696
697// Err returns the error represented by v or nil v is not an error.
698func (v Value) Err() error {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200699 // TODO(incomplete): change to not return an error for incomplete.
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100700 if err := v.checkKind(v.ctx(), bottomKind); err != nil {
701 return err
702 }
703 return nil
704}
705
706// Pos returns position information.
707func (v Value) Pos() token.Position {
708 if v.path == nil || v.Source() == nil {
709 return token.Position{}
710 }
711 pos := v.Source().Pos()
712 return v.idx.fset.Position(pos)
713}
714
Marcel van Lohuizen0519f252019-05-06 18:06:48 +0200715// IsConcrete reports whether the current value is a concrete scalar value,
716// not relying on default values, a terminal error, a list, or a struct.
717// It does not verify that values of lists or structs are concrete themselves.
718// To check whether there is a concrete default, use v.Default().IsConcrete().
719func (v Value) IsConcrete() bool {
720 if v.path == nil {
721 return false // any is neither concrete, not a list or struct.
722 }
723 x := v.path.v.evalPartial(v.ctx())
724
725 // Errors marked as incomplete are treated as not complete.
726 if isIncomplete(x) {
727 return false
728 }
729 // Other errors are considered ground.
730 return x.kind().isGround()
731}
732
733// IsIncomplete is deprecated.
734//
735// It indicates that the value cannot be fully evaluated due to
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100736// insufficient information.
737func (v Value) IsIncomplete() bool {
Marcel van Lohuizen0519f252019-05-06 18:06:48 +0200738 // TODO: remove
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100739 x := v.eval(v.ctx())
740 if x.kind().hasReferences() || !x.kind().isGround() {
741 return true
742 }
743 return isIncomplete(x)
744}
745
746// IsValid reports whether this value is defined and evaluates to something
747// other than an error.
748func (v Value) IsValid() bool {
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +0100749 if v.path == nil || v.path.cache == nil {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100750 return false
751 }
752 k := v.eval(v.ctx()).kind()
753 return k != bottomKind && !v.IsIncomplete()
754}
755
756// Exists reports whether this value existed in the configuration.
757func (v Value) Exists() bool {
758 if v.path == nil {
759 return false
760 }
761 return exists(v.eval(v.ctx()))
762}
763
764func (v Value) checkKind(ctx *context, want kind) *bottom {
765 if v.path == nil {
766 return errNotExists
767 }
768 // TODO: use checkKind
769 x := v.eval(ctx)
770 if b, ok := x.(*bottom); ok {
771 return b
772 }
773 got := x.kind()
Marcel van Lohuizen0018c742019-02-20 01:25:39 +0100774 if want != bottomKind {
775 if got&want&concreteKind == bottomKind {
776 return ctx.mkErr(x, "not of right kind (%v vs %v)", got, want)
777 }
778 if !got.isGround() {
779 return ctx.mkErr(x, codeIncomplete,
780 "non-concrete value %v", got)
781 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100782 }
783 return nil
784}
785
Marcel van Lohuizen0519f252019-05-06 18:06:48 +0200786func makeInt(v Value, x int64) Value {
787 n := &numLit{numBase: numBase{baseValue: v.path.v.base()}}
788 n.v.SetInt64(x)
789 return remakeValue(v, n)
790}
791
792// Len returns the number of items of the underlying value.
793// For lists it reports the capacity of the list. For structs it indicates the
794// number of fields, for bytes the number of bytes.
795func (v Value) Len() Value {
796 if v.path != nil {
797 switch x := v.path.v.evalPartial(v.ctx()).(type) {
798 case *list:
799 return remakeValue(v, x.len.evalPartial(v.ctx()))
800 case *bytesLit:
801 return makeInt(v, int64(x.len()))
802 case *stringLit:
803 return makeInt(v, int64(x.len()))
804 }
805 }
806 const msg = "len not supported for type %v"
807 return remakeValue(v, v.ctx().mkErr(v.path.v, msg, v.Kind()))
808}
809
810// Elem returns the value of undefined element types of lists and structs.
811func (v Value) Elem() (Value, bool) {
812 ctx := v.ctx()
813 switch x := v.path.cache.(type) {
814 case *structLit:
815 if x.template == nil {
816 break
817 }
818 fn, ok := ctx.manifest(x.template).(*lambdaExpr)
819 if !ok {
820 // TODO: return an error instead.
821 break
822 }
823 // Note, this template does not maintain the relation between the
824 // the attribute value and the instance.
825 y := fn.call(ctx, x, &basicType{x.baseValue, stringKind})
826 return newValueRoot(ctx, y), true
827 case *list:
828 return newValueRoot(ctx, x.typ), true
829 }
830 return Value{}, false
831}
832
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100833// List creates an iterator over the values of a list or reports an error if
834// v is not a list.
835func (v Value) List() (Iterator, error) {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200836 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100837 ctx := v.ctx()
838 if err := v.checkKind(ctx, listKind); err != nil {
839 return Iterator{ctx: ctx}, err
840 }
841 l := v.eval(ctx).(*list)
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +0200842 return Iterator{ctx: ctx, val: v, iter: l, len: len(l.elem.arcs)}, nil
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100843}
844
845// Null reports an error if v is not null.
846func (v Value) Null() error {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200847 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100848 if err := v.checkKind(v.ctx(), nullKind); err != nil {
849 return err
850 }
851 return nil
852}
853
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200854// // IsNull reports whether v is null.
855// func (v Value) IsNull() bool {
856// return v.Null() == nil
857// }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100858
859// Bool returns the bool value of v or false and an error if v is not a boolean.
860func (v Value) Bool() (bool, error) {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200861 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100862 ctx := v.ctx()
863 if err := v.checkKind(ctx, boolKind); err != nil {
864 return false, err
865 }
866 return v.eval(ctx).(*boolLit).b, nil
867}
868
869// String returns the string value if v is a string or an error otherwise.
870func (v Value) String() (string, error) {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200871 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100872 ctx := v.ctx()
873 if err := v.checkKind(ctx, stringKind); err != nil {
874 return "", err
875 }
876 return v.eval(ctx).(*stringLit).str, nil
877}
878
879// Bytes returns a byte slice if v represents a list of bytes or an error
880// otherwise.
881func (v Value) Bytes() ([]byte, error) {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200882 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100883 ctx := v.ctx()
884 switch x := v.eval(ctx).(type) {
885 case *bytesLit:
886 return append([]byte(nil), x.b...), nil
887 case *stringLit:
888 return []byte(x.str), nil
889 }
890 return nil, v.checkKind(ctx, bytesKind|stringKind)
891}
892
893// Reader returns a new Reader if v is a string or bytes type and an error
894// otherwise.
895func (v Value) Reader() (io.Reader, error) {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200896 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100897 ctx := v.ctx()
898 switch x := v.eval(ctx).(type) {
899 case *bytesLit:
900 return bytes.NewReader(x.b), nil
901 case *stringLit:
902 return strings.NewReader(x.str), nil
903 }
904 return nil, v.checkKind(ctx, stringKind|bytesKind)
905}
906
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100907// TODO: distinguish between optional, hidden, etc. Probably the best approach
908// is to mark options in context and have a single function for creating
909// a structVal.
910
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100911// structVal returns an structVal or an error if v is not a struct.
912func (v Value) structVal(ctx *context) (structValue, error) {
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200913 return v.structValOpts(ctx, options{
914 omitHidden: true,
915 omitOptional: true,
916 })
917}
918
919// structVal returns an structVal or an error if v is not a struct.
920func (v Value) structValOpts(ctx *context, o options) (structValue, error) {
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +0200921 v, _ = v.Default()
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100922 if err := v.checkKind(ctx, structKind); err != nil {
923 return structValue{}, err
924 }
925 obj := v.eval(ctx).(*structLit)
926
Marcel van Lohuizen7f48df72019-02-01 17:24:59 +0100927 // TODO: This is expansion appropriate?
928 obj = obj.expandFields(ctx) // expand comprehensions
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100929
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200930 // check if any fields can be omitted
931 needFilter := false
932 if o.omitHidden || o.omitOptional {
933 f := label(0)
934 for _, a := range obj.arcs {
935 f |= a.feature
936 if o.omitOptional && a.optional {
937 needFilter = true
938 }
939 }
940 needFilter = needFilter || f&hidden != 0
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100941 }
942
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200943 if needFilter {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100944 arcs := make([]arc, len(obj.arcs))
945 k := 0
946 for _, a := range obj.arcs {
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100947 if a.feature&hidden == 0 && !a.optional {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100948 arcs[k] = a
949 k++
950 }
951 }
952 arcs = arcs[:k]
953 obj = &structLit{
954 obj.baseValue,
955 obj.emit,
956 obj.template,
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100957 nil,
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100958 arcs,
Marcel van Lohuizen7f48df72019-02-01 17:24:59 +0100959 nil,
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100960 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100961 }
962 return structValue{ctx, v.path, obj}, nil
963}
964
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100965// Fields creates an iterator over v's fields if v is a struct or an error
966// otherwise.
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200967func (v Value) Fields(opts ...Option) (Iterator, error) {
968 o := options{omitHidden: true, omitOptional: true}
969 o.updateOptions(opts)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100970 ctx := v.ctx()
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +0200971 obj, err := v.structValOpts(ctx, o)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100972 if err != nil {
973 return Iterator{ctx: ctx}, err
974 }
975 return Iterator{ctx: ctx, val: v, iter: obj.n, len: len(obj.n.arcs)}, nil
976}
977
978// Lookup reports the value starting from v, or an error if the path is not
979// found. The empty path returns v itself.
980//
981// Lookup cannot be used to look up hidden fields.
982func (v Value) Lookup(path ...string) Value {
983 ctx := v.ctx()
984 for _, k := range path {
985 obj, err := v.structVal(ctx)
986 if err != nil {
987 return newValueRoot(ctx, err.(*bottom))
988 }
989 v = obj.Lookup(k)
990 }
991 return v
992}
993
994// Template returns a function that represents the template definition for a
995// struct in a configuration file. It returns nil if v is not a struct kind or
996// if there is no template associated with the struct.
997//
998// The returned function returns the value that would be unified with field
999// given its name.
1000func (v Value) Template() func(label string) Value {
1001 ctx := v.ctx()
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +01001002 x, ok := v.path.cache.(*structLit)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001003 if !ok || x.template == nil {
1004 return nil
1005 }
1006 fn, ok := ctx.manifest(x.template).(*lambdaExpr)
1007 if !ok {
1008 return nil
1009 }
1010 return func(label string) Value {
1011 arg := &stringLit{x.baseValue, label}
1012 y := fn.call(ctx, x, arg)
1013 return newValueRoot(ctx, y)
1014 }
1015}
1016
1017// Subsumes reports whether w is an instance of v.
1018//
1019// Value v and w must be obtained from the same build.
1020// TODO: remove this requirement.
1021func (v Value) Subsumes(w Value) bool {
1022 ctx := v.ctx()
1023 return subsumes(ctx, v.eval(ctx), w.eval(ctx), subChoose)
1024}
1025
1026// Unify reports the greatest lower bound of v and w.
1027//
1028// Value v and w must be obtained from the same build.
1029// TODO: remove this requirement.
1030func (v Value) Unify(w Value) Value {
1031 ctx := v.ctx()
1032 if v.path == nil {
1033 return w
1034 }
1035 if w.path == nil {
1036 return v
1037 }
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +02001038 a := v.path.v
1039 b := w.path.v
Marcel van Lohuizen0e2bcd52019-04-03 22:33:14 +02001040 src := binSrc(token.NoPos, opUnify, a, b)
Marcel van Lohuizen9a0e4132019-05-06 11:39:40 +02001041 val := mkBin(ctx, src.Pos(), opUnify, a, b)
1042 if err := validate(ctx, val.evalPartial(ctx)); err != nil {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001043 val = err
1044 }
1045 return newValueRoot(ctx, val)
1046}
1047
1048// Format prints a debug version of a value.
1049func (v Value) Format(state fmt.State, verb rune) {
1050 ctx := v.ctx()
1051 if v.path == nil {
1052 fmt.Fprint(state, "<nil>")
1053 return
1054 }
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +01001055 io.WriteString(state, debugStr(ctx, v.path.cache))
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001056}
1057
Marcel van Lohuizen0519f252019-05-06 18:06:48 +02001058// Reference returns path from the root of the file referred to by this value
1059// or no path if this value is not a reference.
1060func (v Value) Reference() []string {
1061 // TODO: don't include references to hidden fields.
1062 if v.path == nil {
1063 return nil
1064 }
1065 sel, ok := v.path.v.(*selectorExpr)
1066 if !ok {
1067 return nil
1068 }
1069 return mkPath(v.ctx(), v.path, sel, 0)
1070}
1071
1072func mkPath(c *context, up *valueData, sel *selectorExpr, d int) (a []string) {
1073 switch x := sel.x.(type) {
1074 case *selectorExpr:
1075 a = mkPath(c, up.parent, x, d+1)
1076 case *nodeRef:
1077 // the parent must exist.
1078 for ; up != nil && up.cache != x.node.(value); up = up.parent {
1079 }
1080 a = mkFromRoot(c, up, d+1)
1081 default:
1082 panic("should not happend")
1083 }
1084 return append(a, c.labelStr(sel.feature))
1085}
1086
1087func mkFromRoot(c *context, up *valueData, d int) []string {
1088 if up == nil || up.parent == nil {
1089 return make([]string, 0, d)
1090 }
1091 a := mkFromRoot(c, up.parent, d+1)
1092 return append(a, c.labelStr(up.feature))
1093}
1094
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001095// References reports all references used to evaluate this value. It does not
1096// report references for sub fields if v is a struct.
Marcel van Lohuizen0519f252019-05-06 18:06:48 +02001097//
1098// Deprecated: can be implemented in terms of Reference and Expr.
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001099func (v Value) References() [][]string {
1100 ctx := v.ctx()
1101 pf := pathFinder{up: v.path}
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +01001102 raw := v.path.v
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001103 if raw == nil {
1104 return nil
1105 }
1106 rewrite(ctx, raw, pf.find)
1107 return pf.paths
1108}
1109
1110type pathFinder struct {
1111 paths [][]string
1112 stack []string
1113 up *valueData
1114}
1115
1116func (p *pathFinder) find(ctx *context, v value) (value, bool) {
1117 switch x := v.(type) {
1118 case *selectorExpr:
1119 i := len(p.stack)
1120 p.stack = append(p.stack, ctx.labelStr(x.feature))
1121 rewrite(ctx, x.x, p.find)
1122 p.stack = p.stack[:i]
1123 return v, false
1124 case *nodeRef:
1125 i := len(p.stack)
1126 up := p.up
Marcel van Lohuizen9bf93c02019-03-26 21:40:25 +01001127 for ; up != nil && up.cache != x.node.(value); up = up.parent {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001128 }
1129 for ; up != nil && up.feature > 0; up = up.parent {
1130 p.stack = append(p.stack, ctx.labelStr(up.feature))
1131 }
1132 path := make([]string, len(p.stack))
1133 for i, v := range p.stack {
1134 path[len(path)-1-i] = v
1135 }
1136 p.paths = append(p.paths, path)
1137 p.stack = p.stack[:i]
1138 return v, false
1139 case *structLit: // handled in sub fields
1140 return v, false
1141 }
1142 return v, true
1143}
1144
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001145type options struct {
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001146 concrete bool // enforce that values are concrete
1147 raw bool // show original values
1148 hasHidden bool
1149 omitHidden bool
1150 omitOptional bool
1151 omitAttrs bool
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001152}
1153
1154// An Option defines modes of evaluation.
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001155type Option option
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001156
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001157type option func(p *options)
1158
1159// Used in Iter, Validate, Subsume?, Fields() Syntax, Export
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001160
1161// TODO: could also be used for subsumption.
1162
Marcel van Lohuizenc47539e2019-04-26 22:11:23 +02001163// Concrete ensures that all values are concrete.
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001164//
1165// For Validate this means it returns an error if this is not the case.
1166// In other cases a non-concrete value will be replaced with an error.
Marcel van Lohuizenc47539e2019-04-26 22:11:23 +02001167func Concrete(concrete bool) Option {
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001168 return func(p *options) {
Marcel van Lohuizenc47539e2019-04-26 22:11:23 +02001169 if concrete {
1170 p.concrete = true
1171 if !p.hasHidden {
1172 p.omitHidden = true
1173 }
1174 } else {
1175 p.raw = true
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001176 }
1177 }
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001178}
1179
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001180// All indicates that all fields and values should be included in processing
1181// even if they can be elided or omitted.
1182func All() Option {
1183 return func(p *options) {
1184 p.omitAttrs = false
1185 p.omitHidden = false
1186 p.omitOptional = false
1187 }
1188}
1189
1190// Hidden indicates that hidden fields should be included.
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001191//
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001192// Hidden fields may still be included if include is false,
1193// even if a value is not concrete.
1194func Hidden(include bool) Option {
1195 return func(p *options) {
1196 p.hasHidden = true
1197 p.omitHidden = !include
1198 }
1199}
1200
1201// Optional indicates that optional fields should be included.
1202func Optional(include bool) Option {
1203 return func(p *options) { p.omitOptional = !include }
1204}
1205
1206// Attributes indicates that attributes should be included.
1207func Attributes(include bool) Option {
1208 return func(p *options) { p.omitAttrs = !include }
1209}
1210
1211func getOptions(opts []Option) (o options) {
1212 o.updateOptions(opts)
1213 return
1214}
1215
1216func (o *options) updateOptions(opts []Option) {
1217 for _, fn := range opts {
1218 fn(o)
1219 }
1220}
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001221
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001222// Validate reports any errors, recursively. The returned error may be an
1223// errors.List reporting multiple errors, where the total number of errors
1224// reported may be less than the actual number.
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001225func (v Value) Validate(opts ...Option) error {
Marcel van Lohuizen466e3f62019-04-06 14:16:50 +02001226 o := getOptions(opts)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001227 list := errors.List{}
1228 v.Walk(func(v Value) bool {
1229 if err := v.Err(); err != nil {
Marcel van Lohuizen0018c742019-02-20 01:25:39 +01001230 if !o.concrete && isIncomplete(v.eval(v.ctx())) {
1231 return false
1232 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001233 list.Add(err)
1234 if len(list) > 50 {
1235 return false // mostly to avoid some hypothetical cycle issue
1236 }
1237 }
Marcel van Lohuizen40f32e62019-04-10 18:08:34 +02001238 if o.concrete {
1239 if err := isGroundRecursive(v.ctx(), v.eval(v.ctx())); err != nil {
1240 list.Add(err)
1241 }
1242 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001243 return true
1244 }, nil)
1245 if len(list) > 0 {
1246 list.Sort()
1247 // list.RemoveMultiples() // TODO: use RemoveMultiples when it is fixed
Marcel van Lohuizen40f32e62019-04-10 18:08:34 +02001248 // return list
1249 return list[0]
1250 }
1251 return nil
1252}
1253
1254func isGroundRecursive(ctx *context, v value) error {
1255 switch x := v.(type) {
1256 case *list:
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +02001257 for i := 0; i < len(x.elem.arcs); i++ {
Marcel van Lohuizen40f32e62019-04-10 18:08:34 +02001258 v := ctx.manifest(x.at(ctx, i))
1259 if err := isGroundRecursive(ctx, v); err != nil {
1260 return err
1261 }
1262 }
1263 default:
1264 if !x.kind().isGround() {
1265 return ctx.mkErr(v, "incomplete value %q", debugStr(ctx, v))
1266 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001267 }
1268 return nil
1269}
1270
1271// Walk descends into all values of v, calling f. If f returns false, Walk
1272// will not descent further.
1273func (v Value) Walk(before func(Value) bool, after func(Value)) {
1274 ctx := v.ctx()
1275 switch v.Kind() {
1276 case StructKind:
1277 if before != nil && !before(v) {
1278 return
1279 }
1280 obj, _ := v.structVal(ctx)
1281 for i := 0; i < obj.Len(); i++ {
1282 _, v := obj.At(i)
1283 v.Walk(before, after)
1284 }
1285 case ListKind:
1286 if before != nil && !before(v) {
1287 return
1288 }
1289 list, _ := v.List()
1290 for list.Next() {
1291 list.Value().Walk(before, after)
1292 }
1293 default:
1294 if before != nil {
1295 before(v)
1296 }
1297 }
1298 if after != nil {
1299 after(v)
1300 }
1301}
Marcel van Lohuizenb9b62d32019-03-14 23:50:15 +01001302
1303// Attribute returns the attribute data for the given key.
1304// The returned attribute will return an error for any of its methods if there
1305// is no attribute for the requested key.
1306func (v Value) Attribute(key string) Attribute {
1307 // look up the attributes
1308 if v.path == nil || v.path.attrs == nil {
1309 return Attribute{err: errNotExists}
1310 }
1311 for _, a := range v.path.attrs.attr {
1312 if a.key() != key {
1313 continue
1314 }
1315 at := Attribute{}
1316 if err := parseAttrBody(v.ctx(), nil, a.body(), &at.attr); err != nil {
1317 return Attribute{err: err.(error)}
1318 }
1319 return at
1320 }
1321 return Attribute{err: errNotExists}
1322}
1323
1324var (
1325 errNoSuchAttribute = errors.New("entry for key does not exist")
1326)
1327
1328// An Attribute contains meta data about a field.
1329type Attribute struct {
1330 attr parsedAttr
1331 err error
1332}
1333
1334// Err returns the error associated with this Attribute or nil if this
1335// attribute is valid.
1336func (a *Attribute) Err() error {
1337 return a.err
1338}
1339
1340func (a *Attribute) hasPos(p int) error {
1341 if a.err != nil {
1342 return a.err
1343 }
1344 if p >= len(a.attr.fields) {
1345 return fmt.Errorf("field does not exist")
1346 }
1347 return nil
1348}
1349
1350// String reports the possibly empty string value at the given position or
1351// an error the attribute is invalid or if the position does not exist.
1352func (a *Attribute) String(pos int) (string, error) {
1353 if err := a.hasPos(pos); err != nil {
1354 return "", err
1355 }
1356 return a.attr.fields[pos].text(), nil
1357}
1358
1359// Int reports the integer at the given position or an error if the attribute is
1360// invalid, the position does not exist, or the value at the given position is
1361// not an integer.
1362func (a *Attribute) Int(pos int) (int64, error) {
1363 if err := a.hasPos(pos); err != nil {
1364 return 0, err
1365 }
1366 // TODO: use CUE's literal parser once it exists, allowing any of CUE's
1367 // number types.
1368 return strconv.ParseInt(a.attr.fields[pos].text(), 10, 64)
1369}
1370
1371// Flag reports whether an entry with the given name exists at position pos or
1372// onwards or an error if the attribute is invalid or if the first pos-1 entries
1373// are not defined.
1374func (a *Attribute) Flag(pos int, key string) (bool, error) {
1375 if err := a.hasPos(pos - 1); err != nil {
1376 return false, err
1377 }
1378 for _, kv := range a.attr.fields[pos:] {
1379 if kv.text() == key {
1380 return true, nil
1381 }
1382 }
1383 return false, nil
1384}
1385
1386// Lookup searches for an entry of the form key=value from position pos onwards
1387// and reports the value if found. It reports an error if the attribute is
1388// invalid or if the first pos-1 entries are not defined.
1389func (a *Attribute) Lookup(pos int, key string) (val string, found bool, err error) {
1390 if err := a.hasPos(pos - 1); err != nil {
1391 return "", false, err
1392 }
1393 for _, kv := range a.attr.fields[pos:] {
1394 if kv.key() == key {
1395 return kv.value(), true, nil
1396 }
1397 }
1398 return "", false, nil
1399}
Marcel van Lohuizen0519f252019-05-06 18:06:48 +02001400
1401// Expr reports the operation of the underlying expression and the values it
1402// operates on. The returned values are appended to the given slice, which may
1403// be nil.
1404//
1405// For unary expressions, it returns the single value of the expression.
1406//
1407// For binary expressions it returns first the left and right value, in that
1408// order. For associative operations however, (for instance '&' and '|'), it may
1409// return more than two values, where the operation is to be applied in
1410// sequence.
1411//
1412// For selector and index expressions it returns the subject and then the index.
1413// For selectors, the index is the string value of the identifier. For slice
1414// expressions, it returns the subject, low value, and high value, in that
1415// order.
1416//
1417// For interpolations it returns a sequence of values to be concatenated, some
1418// of which will be literal strings and some unevaluated expressions.
1419//
1420// A builtin call expression returns the value of the builtin followed by the
1421// args of the call.
1422//
1423// If v is not an expression, Partial append v itself.
1424// TODO: return v if this is complete? Yes for now
1425// TODO: add values if a == nil?
1426func (v Value) Expr() (Op, []Value) {
1427 if v.path == nil {
1428 return NoOp, nil
1429 }
1430 // TODO: replace appends with []Value{}. For not leave.
1431 a := []Value{}
1432 op := NoOp
1433 switch x := v.path.v.(type) {
1434 case *binaryExpr:
1435 a = append(a, remakeValue(v, x.left))
1436 a = append(a, remakeValue(v, x.right))
1437 op = opToOp[x.op]
1438 case *unaryExpr:
1439 a = append(a, remakeValue(v, x.x))
1440 op = opToOp[x.op]
1441 case *bound:
1442 a = append(a, remakeValue(v, x.value))
1443 op = opToOp[x.op]
1444 case *unification:
1445 // pre-expanded unification
1446 for _, conjunct := range x.values {
1447 a = append(a, remakeValue(v, conjunct))
1448 }
1449 op = AndOp
1450 case *disjunction:
1451 // Filter defaults that are subsumed by another value.
1452 count := 0
1453 outer:
1454 for _, disjunct := range x.values {
1455 if disjunct.marked {
1456 for _, n := range x.values {
1457 if !n.marked && subsumes(v.ctx(), n.val, disjunct.val, 0) {
1458 continue outer
1459 }
1460 }
1461 }
1462 count++
1463 a = append(a, remakeValue(v, disjunct.val))
1464 }
1465 if count > 1 {
1466 op = OrOp
1467 }
1468 case *interpolation:
1469 for _, p := range x.parts {
1470 a = append(a, remakeValue(v, p))
1471 }
1472 op = InterpolationOp
1473 case *selectorExpr:
1474 a = append(a, remakeValue(v, x.x))
1475 a = append(a, remakeValue(v, &stringLit{
1476 x.baseValue,
1477 v.ctx().labelStr(x.feature),
1478 }))
1479 op = SelectorOp
1480 case *indexExpr:
1481 a = append(a, remakeValue(v, x.x))
1482 a = append(a, remakeValue(v, x.index))
1483 op = IndexOp
1484 case *sliceExpr:
1485 a = append(a, remakeValue(v, x.x))
1486 a = append(a, remakeValue(v, x.lo))
1487 a = append(a, remakeValue(v, x.hi))
1488 op = SliceOp
1489 case *callExpr:
1490 a = append(a, remakeValue(v, x.x))
1491 for _, arg := range x.args {
1492 a = append(a, remakeValue(v, arg))
1493 }
1494 op = CallOp
1495 default:
1496 a = append(a, v)
1497 }
1498 return op, a
1499}