1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package cue
16
17 import (
18 "fmt"
19 "math/bits"
20 "strconv"
21 "strings"
22
23 "cuelang.org/go/cue/ast"
24 "cuelang.org/go/cue/errors"
25 "cuelang.org/go/cue/literal"
26 "cuelang.org/go/cue/parser"
27 "cuelang.org/go/cue/token"
28 "cuelang.org/go/internal/astinternal"
29 "cuelang.org/go/internal/core/adt"
30 "github.com/cockroachdb/apd/v3"
31 )
32
33
34
35 type SelectorType uint16
36
37 const (
38
39 StringLabel SelectorType = 1 << iota
40
41 IndexLabel
42
43 DefinitionLabel
44
45 HiddenLabel
46
47 HiddenDefinitionLabel
48
49
50 OptionalConstraint
51
52 RequiredConstraint
53
54
55 PatternConstraint
56
57 InvalidSelectorType SelectorType = 0
58 )
59
60
61 func fromArcType(t adt.ArcType) SelectorType {
62 switch t {
63 case adt.ArcMember:
64 return 0
65 case adt.ArcOptional:
66 return OptionalConstraint
67 case adt.ArcRequired:
68 return RequiredConstraint
69 default:
70 panic("arc type not supported")
71 }
72 }
73
74
75 func (t SelectorType) LabelType() SelectorType {
76 return t & 0b0001_1111
77 }
78
79
80 func (t SelectorType) ConstraintType() SelectorType {
81 return t & 0b1110_0000
82 }
83
84 var selectorTypeStrings = [...]string{
85 "InvalidSelectorType",
86 "StringLabel",
87 "IndexLabel",
88 "DefinitionLabel",
89 "HiddenLabel",
90 "HiddenDefinitionLabel",
91 "OptionalConstraint",
92 "RequiredConstraint",
93 "PatternConstraint",
94 }
95
96 func (t SelectorType) String() string {
97 if t.LabelType() == 0 && t.ConstraintType() == 0 {
98 return "NoLabels"
99 }
100 single := bits.OnesCount16(uint16(t)) == 1
101 var buf strings.Builder
102 for i := range selectorTypeStrings[:len(selectorTypeStrings)-1] {
103 if t&(SelectorType(1)<<i) == 0 {
104 continue
105 }
106 if single {
107 return selectorTypeStrings[i+1]
108 }
109 if buf.Len() > 0 {
110 buf.WriteByte('|')
111 }
112 buf.WriteString(selectorTypeStrings[i+1])
113 }
114 return buf.String()
115 }
116
117
118
119 func (t SelectorType) IsHidden() bool {
120 t = t.LabelType()
121 return t == HiddenLabel || t == HiddenDefinitionLabel
122 }
123
124
125
126 func (t SelectorType) IsDefinition() bool {
127 t = t.LabelType()
128 return t == HiddenDefinitionLabel || t == DefinitionLabel
129 }
130
131
132 type Selector struct {
133 sel selector
134 }
135
136
137 func (sel Selector) String() string {
138 return sel.sel.String()
139 }
140
141
142
143 func (sel Selector) Unquoted() string {
144 if sel.LabelType() != StringLabel ||
145 sel.ConstraintType() >= PatternConstraint {
146 panic("Selector.Unquoted invoked on non-string label")
147 }
148 switch s := sel.sel.(type) {
149 case stringSelector:
150 return string(s)
151 case constraintSelector:
152 return string(s.selector.(stringSelector))
153 }
154 panic(fmt.Sprintf("unreachable %T", sel.sel))
155 }
156
157
158
159
160 func (sel Selector) IsConstraint() bool {
161 return sel.Type().ConstraintType() != 0
162 }
163
164
165
166 func (sel Selector) IsString() bool {
167
168 t := sel.Type()
169 t &^= OptionalConstraint | RequiredConstraint
170 return t == StringLabel
171 }
172
173
174 func (sel Selector) IsDefinition() bool {
175 return sel.Type().IsDefinition()
176 }
177
178
179 func (sel Selector) Type() SelectorType {
180 return sel.sel.labelType() | sel.sel.constraintType()
181 }
182
183
184 func (sel Selector) LabelType() SelectorType {
185 return sel.sel.labelType()
186 }
187
188
189 func (sel Selector) ConstraintType() SelectorType {
190 return sel.sel.constraintType()
191 }
192
193
194
195 func (sel Selector) PkgPath() string {
196 s, _ := sel.sel.(scopedSelector)
197 return s.pkg
198 }
199
200
201
202 func (sel Selector) Index() int {
203
204
205
206 s, ok := sel.sel.(indexSelector)
207 if !ok {
208 panic("Index called on non-index selector")
209 }
210 return adt.Feature(s).Index()
211 }
212
213 var (
214
215
216
217
218
219 anyDefinition = Selector{sel: anySelector(adt.AnyDefinition)}
220
221
222
223 AnyIndex = anyIndex
224 anyIndex = Selector{sel: anySelector(adt.AnyIndex)}
225
226
227
228
229 AnyString = anyString
230 anyString = Selector{sel: anySelector(adt.AnyString)}
231 )
232
233
234
235
236
237
238 func (sel Selector) Optional() Selector {
239 return wrapConstraint(sel, OptionalConstraint)
240 }
241
242
243
244
245
246
247 func (sel Selector) Required() Selector {
248 return wrapConstraint(sel, RequiredConstraint)
249 }
250
251 type selector interface {
252 String() string
253
254 feature(ctx adt.Runtime) adt.Feature
255 labelType() SelectorType
256 constraintType() SelectorType
257 isConstraint() bool
258 }
259
260
261 type Path struct {
262 path []Selector
263 }
264
265
266 func MakePath(selectors ...Selector) Path {
267 return Path{path: selectors}
268 }
269
270
271 func pathToStrings(p Path) (a []string) {
272 for _, sel := range p.Selectors() {
273 a = append(a, sel.String())
274 }
275 return a
276 }
277
278
279
280
281
282
283
284
285
286 func ParsePath(s string) Path {
287 if s == "" {
288 return Path{}
289 }
290 expr, err := parser.ParseExpr("", s)
291 if err != nil {
292 return MakePath(Selector{pathError{errors.Promote(err, "invalid path")}})
293 }
294
295 p := Path{path: toSelectors(expr)}
296 for _, sel := range p.path {
297 if sel.Type().IsHidden() {
298 return MakePath(Selector{pathError{errors.Newf(token.NoPos,
299 "invalid path: hidden fields not allowed in path %s", s)}})
300 }
301 }
302 return p
303 }
304
305
306 func (p Path) Selectors() []Selector {
307 return p.path
308 }
309
310
311 func (p Path) String() string {
312 if err := p.Err(); err != nil {
313 return "_|_"
314 }
315
316 b := &strings.Builder{}
317 for i, sel := range p.path {
318 switch {
319 case sel.Type() == IndexLabel:
320
321 b.WriteByte('[')
322 b.WriteString(sel.sel.String())
323 b.WriteByte(']')
324 continue
325 case i > 0:
326 b.WriteByte('.')
327 }
328
329 b.WriteString(sel.sel.String())
330 }
331 return b.String()
332 }
333
334
335
336
337 func (p Path) Optional() Path {
338 q := make([]Selector, 0, len(p.path))
339 for _, s := range p.path {
340 q = appendSelector(q, wrapConstraint(s, OptionalConstraint))
341 }
342 return Path{path: q}
343 }
344
345 func toSelectors(expr ast.Expr) []Selector {
346 switch x := expr.(type) {
347 case *ast.Ident:
348 return []Selector{Label(x)}
349
350 case *ast.BasicLit:
351 return []Selector{basicLitSelector(x)}
352
353 case *ast.IndexExpr:
354 a := toSelectors(x.X)
355 var sel Selector
356 if b, ok := x.Index.(*ast.BasicLit); !ok {
357 sel = Selector{pathError{
358 errors.Newf(token.NoPos, "non-constant expression %s",
359 astinternal.DebugStr(x.Index))}}
360 } else {
361 sel = basicLitSelector(b)
362 }
363 return appendSelector(a, sel)
364
365 case *ast.SelectorExpr:
366 a := toSelectors(x.X)
367 return appendSelector(a, Label(x.Sel))
368
369 default:
370 return []Selector{{pathError{
371 errors.Newf(token.NoPos, "invalid label %s ", astinternal.DebugStr(x)),
372 }}}
373 }
374 }
375
376
377
378 func appendSelector(a []Selector, sel Selector) []Selector {
379 err, isErr := sel.sel.(pathError)
380 if len(a) == 1 {
381 if p, ok := a[0].sel.(pathError); ok {
382 if isErr {
383 p.Error = errors.Append(p.Error, err.Error)
384 }
385 return a
386 }
387 }
388 if isErr {
389 return []Selector{sel}
390 }
391 return append(a, sel)
392 }
393
394 func basicLitSelector(b *ast.BasicLit) Selector {
395 switch b.Kind {
396 case token.INT:
397 var n literal.NumInfo
398 if err := literal.ParseNum(b.Value, &n); err != nil {
399 return Selector{pathError{
400 errors.Newf(token.NoPos, "invalid string index %s", b.Value),
401 }}
402 }
403 var d apd.Decimal
404 _ = n.Decimal(&d)
405 i, err := d.Int64()
406 if err != nil {
407 return Selector{pathError{
408 errors.Newf(token.NoPos, "integer %s out of range", b.Value),
409 }}
410 }
411 return Index(int(i))
412
413 case token.STRING:
414 info, _, _, _ := literal.ParseQuotes(b.Value, b.Value)
415 if !info.IsDouble() {
416 return Selector{pathError{
417 errors.Newf(token.NoPos, "invalid string index %s", b.Value)}}
418 }
419 s, _ := literal.Unquote(b.Value)
420 return Selector{stringSelector(s)}
421
422 default:
423 return Selector{pathError{
424 errors.Newf(token.NoPos, "invalid literal %s", b.Value),
425 }}
426 }
427 }
428
429
430 func Label(label ast.Label) Selector {
431 switch x := label.(type) {
432 case *ast.Ident:
433 switch s := x.Name; {
434 case strings.HasPrefix(s, "_"):
435
436 return Selector{pathError{errors.Newf(token.NoPos,
437 "invalid path: hidden label %s not allowed", s),
438 }}
439 case strings.HasPrefix(s, "#"):
440 return Selector{definitionSelector(x.Name)}
441 default:
442 return Selector{stringSelector(x.Name)}
443 }
444
445 case *ast.BasicLit:
446 return basicLitSelector(x)
447
448 default:
449 return Selector{pathError{
450 errors.Newf(token.NoPos, "invalid label %s ", astinternal.DebugStr(x)),
451 }}
452 }
453 }
454
455
456 func (p Path) Err() error {
457 var errs errors.Error
458 for _, x := range p.path {
459 if err, ok := x.sel.(pathError); ok {
460 errs = errors.Append(errs, err.Error)
461 }
462 }
463 return errs
464 }
465
466 func isHiddenOrDefinition(s string) bool {
467 return strings.HasPrefix(s, "#") || strings.HasPrefix(s, "_")
468 }
469
470
471
472
473 func Hid(name, pkg string) Selector {
474 if !ast.IsValidIdent(name) {
475 panic(fmt.Sprintf("invalid identifier %s", name))
476 }
477 if !strings.HasPrefix(name, "_") {
478 panic(fmt.Sprintf("%s is not a hidden field identifier", name))
479 }
480 if pkg == "" {
481 panic(fmt.Sprintf("missing package for hidden identifier %s", name))
482 }
483 return Selector{scopedSelector{name, pkg}}
484 }
485
486 type scopedSelector struct {
487 name, pkg string
488 }
489
490
491 func (s scopedSelector) String() string {
492 return s.name
493 }
494 func (scopedSelector) isConstraint() bool { return false }
495
496 func (s scopedSelector) labelType() SelectorType {
497 if strings.HasPrefix(s.name, "_#") {
498 return HiddenDefinitionLabel
499 }
500 return HiddenLabel
501 }
502 func (s scopedSelector) constraintType() SelectorType { return 0 }
503
504 func (s scopedSelector) feature(r adt.Runtime) adt.Feature {
505 return adt.MakeIdentLabel(r, s.name, s.pkg)
506 }
507
508
509
510
511 func Def(s string) Selector {
512 if !strings.HasPrefix(s, "#") && !strings.HasPrefix(s, "_#") {
513 s = "#" + s
514 }
515 if !ast.IsValidIdent(s) {
516 panic(fmt.Sprintf("invalid definition %s", s))
517 }
518 return Selector{definitionSelector(s)}
519 }
520
521 type definitionSelector string
522
523
524 func (d definitionSelector) String() string {
525 return string(d)
526 }
527
528 func (d definitionSelector) isConstraint() bool { return false }
529
530 func (d definitionSelector) labelType() SelectorType {
531 return DefinitionLabel
532 }
533
534 func (s definitionSelector) constraintType() SelectorType { return 0 }
535
536 func (d definitionSelector) feature(r adt.Runtime) adt.Feature {
537 return adt.MakeIdentLabel(r, string(d), "")
538 }
539
540
541 func Str(s string) Selector {
542 return Selector{stringSelector(s)}
543 }
544
545 type stringSelector string
546
547 func (s stringSelector) String() string {
548 str := string(s)
549 if isHiddenOrDefinition(str) || !ast.IsValidIdent(str) {
550 return literal.Label.Quote(str)
551 }
552 return str
553 }
554
555 func (s stringSelector) isConstraint() bool { return false }
556 func (s stringSelector) labelType() SelectorType { return StringLabel }
557 func (s stringSelector) constraintType() SelectorType { return 0 }
558
559 func (s stringSelector) feature(r adt.Runtime) adt.Feature {
560 return adt.MakeStringLabel(r, string(s))
561 }
562
563
564 func Index(x int) Selector {
565 f, err := adt.MakeLabel(nil, int64(x), adt.IntLabel)
566 if err != nil {
567 return Selector{pathError{err}}
568 }
569 return Selector{indexSelector(f)}
570 }
571
572 type indexSelector adt.Feature
573
574 func (s indexSelector) String() string {
575 return strconv.Itoa(adt.Feature(s).Index())
576 }
577
578 func (s indexSelector) labelType() SelectorType { return IndexLabel }
579 func (s indexSelector) constraintType() SelectorType { return 0 }
580
581 func (s indexSelector) isConstraint() bool { return false }
582
583 func (s indexSelector) feature(r adt.Runtime) adt.Feature {
584 return adt.Feature(s)
585 }
586
587
588 type anySelector adt.Feature
589
590 func (s anySelector) String() string { return "[_]" }
591 func (s anySelector) isConstraint() bool { return true }
592 func (s anySelector) labelType() SelectorType {
593
594
595
596
597 return SelectorType((1 << adt.Feature(s).Typ()) >> 1)
598 }
599 func (s anySelector) constraintType() SelectorType { return PatternConstraint }
600
601 func (s anySelector) feature(r adt.Runtime) adt.Feature {
602 return adt.Feature(s)
603 }
604
605
606
607
608
609
610
611
612
613 type constraintSelector struct {
614 selector
615 constraint SelectorType
616 }
617
618 func (s constraintSelector) labelType() SelectorType {
619 return s.selector.labelType()
620 }
621
622 func (s constraintSelector) constraintType() SelectorType {
623 return s.constraint
624 }
625
626 func wrapConstraint(s Selector, t SelectorType) Selector {
627 sel := s.sel
628 if c, ok := sel.(constraintSelector); ok {
629 if c.constraint == t {
630 return s
631 }
632 sel = c.selector
633 }
634 return Selector{constraintSelector{sel, t}}
635 }
636
637
638
639
640
641
642 func (s constraintSelector) isConstraint() bool {
643 return true
644 }
645
646 func (s constraintSelector) String() string {
647 var suffix string
648 switch s.constraint {
649 case OptionalConstraint:
650 suffix = "?"
651 case RequiredConstraint:
652 suffix = "!"
653 }
654 return s.selector.String() + suffix
655 }
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672 type pathError struct {
673 errors.Error
674 }
675
676 func (p pathError) String() string { return "" }
677 func (p pathError) isConstraint() bool { return false }
678 func (p pathError) labelType() SelectorType { return InvalidSelectorType }
679 func (p pathError) constraintType() SelectorType { return 0 }
680 func (p pathError) feature(r adt.Runtime) adt.Feature {
681 return adt.InvalidLabel
682 }
683
684 func valueToSel(v adt.Value) Selector {
685 switch x := adt.Unwrap(v).(type) {
686 case *adt.Num:
687 i, err := x.X.Int64()
688 if err != nil {
689 return Selector{&pathError{errors.Promote(err, "invalid number")}}
690 }
691 return Index(int(i))
692 case *adt.String:
693 return Str(x.Str)
694 default:
695 return Selector{pathError{errors.Newf(token.NoPos, "dynamic selector")}}
696 }
697 }
698
699 func featureToSel(f adt.Feature, r adt.Runtime) Selector {
700 switch f.Typ() {
701 case adt.StringLabel:
702 return Str(f.StringValue(r))
703 case adt.IntLabel:
704 return Index(f.Index())
705 case adt.DefinitionLabel:
706 return Def(f.IdentString(r))
707 case adt.HiddenLabel, adt.HiddenDefinitionLabel:
708 ident := f.IdentString(r)
709 pkg := f.PkgID(r)
710 return Hid(ident, pkg)
711 }
712 return Selector{pathError{
713 errors.Newf(token.NoPos, "unexpected feature type %v", f.Typ()),
714 }}
715 }
716
717 func featureToSelType(f adt.Feature, at adt.ArcType) (st SelectorType) {
718 switch f.Typ() {
719 case adt.StringLabel:
720 st = StringLabel
721 case adt.IntLabel:
722 st = IndexLabel
723 case adt.DefinitionLabel:
724 st = DefinitionLabel
725 case adt.HiddenLabel:
726 st = HiddenLabel
727 case adt.HiddenDefinitionLabel:
728 st = HiddenDefinitionLabel
729 default:
730 panic("unsupported arc type")
731 }
732 return st | fromArcType(at)
733 }
734
View as plain text