this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cue: tweaks to selector API

- Move Qualifier (Sel previously) to the end of the terms
consistent with the rest of the API.

- Make SelectorType a bitmap.
This allows a Value.Field() method that takes a bitmap as
argument to select fields, isntead of the very verbose
functional syntax now.

- Remove IsOptional in favor of IsConstraint.

- Addjust FillPath logic a bit to make use of the bitmap.

We may still consider to use Kind, instead of Type
everywhere, also for consistency sake.

We coudl also consider calling StringLabel MemberLabel, consistent with JSON.

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: I5eadb9214890f6b75b25b5378799225d47811912
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/542824
Unity-Result: CUEcueckoo <cueckoo@cuelang.org>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>

+188 -104
+141 -61
cue/path.go
··· 16 16 17 17 import ( 18 18 "fmt" 19 + "math/bits" 19 20 "strconv" 20 21 "strings" 21 22 ··· 29 30 "github.com/cockroachdb/apd/v2" 30 31 ) 31 32 32 - // SelectorType represents the kind of a selector. 33 - type SelectorType byte 33 + // SelectorType represents the kind of a selector. It indicates both the label 34 + // type as well as whether it is a constraint or an actual value. 35 + type SelectorType uint16 34 36 35 37 const ( 36 - SelInvalid SelectorType = iota 37 - // SelString represents a regular non-definition field. 38 - SelString 39 - // SelHidden represents a hidden non-definition field. 40 - SelHidden 41 - // SelDefinition represents a definition. 42 - SelDefinition 43 - // SelHiddenDefinition represents a hidden definition. 44 - SelHiddenDefinition 45 - // SelIndex represents a numeric index into an array. 46 - SelIndex 47 - // SelPattern represents a selector of fields in a struct 38 + // StringLabel represents a regular non-definition field. 39 + StringLabel SelectorType = 1 << iota 40 + // HiddenLabel represents a hidden non-definition field. 41 + HiddenLabel 42 + // DefinitionLabel represents a definition. 43 + DefinitionLabel 44 + // HiddenDefinitionLabel represents a hidden definition. 45 + HiddenDefinitionLabel 46 + // IndexLabel represents a numeric index into an array. 47 + IndexLabel 48 + 49 + // OptionalConstraint represents an optional constraint (?). 50 + OptionalConstraint 51 + 52 + // PatternConstraint represents a selector of fields in a struct 48 53 // or array that match a constraint. 49 - SelPattern 54 + PatternConstraint 55 + 56 + InvalidSelectorType SelectorType = 0 50 57 ) 51 58 59 + // LabelType reports the label type of t. 60 + func (t SelectorType) LabelType() SelectorType { 61 + return t & 0b0001_1111 62 + } 63 + 64 + // ConstraintType reports the constraint type of t. 65 + func (t SelectorType) ConstraintType() SelectorType { 66 + return t & 0b0110_0000 67 + } 68 + 52 69 var selectorTypeStrings = [...]string{ 53 - SelInvalid: "SelInvalid", 54 - SelString: "SelString", 55 - SelHidden: "SelHidden", 56 - SelDefinition: "SelDefinition", 57 - SelHiddenDefinition: "SelHiddenDefinition", 58 - SelIndex: "SelIndex", 59 - SelPattern: "SelPattern", 70 + "InvalidSelectorType", 71 + "StringLabel", 72 + "HiddenLabel", 73 + "DefinitionLabel", 74 + "HiddenDefinitionLabel", 75 + "IndexLabel", 76 + "OptionalConstraint", 77 + "PatternConstraint", 60 78 } 61 79 62 80 func (t SelectorType) String() string { 63 - if int(t) >= len(selectorTypeStrings) { 64 - return fmt.Sprintf("SelInvalid%d", t) 81 + if t.LabelType() == 0 && t.ConstraintType() == 0 { 82 + return "NoLabels" 65 83 } 66 - return selectorTypeStrings[t] 84 + single := bits.OnesCount16(uint16(t)) == 1 85 + var buf strings.Builder 86 + for i := range selectorTypeStrings[:len(selectorTypeStrings)-1] { 87 + if t&(SelectorType(1)<<i) == 0 { 88 + continue 89 + } 90 + if single { 91 + return selectorTypeStrings[i+1] 92 + } 93 + if buf.Len() > 0 { 94 + buf.WriteByte('|') 95 + } 96 + buf.WriteString(selectorTypeStrings[i+1]) 97 + } 98 + return buf.String() 67 99 } 68 100 69 - // IsHidden reports whether t describes a hidden field. 101 + // IsHidden reports whether t describes a hidden field, regardless of 102 + // whether or not this is a constraint. 70 103 func (t SelectorType) IsHidden() bool { 71 - return t == SelHidden || t == SelHiddenDefinition 104 + t = t.LabelType() 105 + return t == HiddenLabel || t == HiddenDefinitionLabel 72 106 } 73 107 74 - // IsDefinition reports whether t describes a definition. 108 + // IsDefinition reports whether t describes a definition, regardless of 109 + // whether or not this is a constraint. 75 110 func (t SelectorType) IsDefinition() bool { 76 - return t == SelHiddenDefinition || t == SelDefinition 111 + t = t.LabelType() 112 + return t == HiddenDefinitionLabel || t == DefinitionLabel 77 113 } 78 114 79 115 // A Selector is a component of a path. ··· 86 122 return sel.sel.String() 87 123 } 88 124 89 - // Unquoted returns the unquoted value of a regular string label. 90 - // It panics unless sel.Type is SelString. 125 + // Unquoted returns the unquoted value of a string label. 126 + // It panics unless sel.LabelType is StringLabel and has a concrete name. 91 127 func (sel Selector) Unquoted() string { 92 - if sel.Type() != SelString { 128 + if sel.LabelType() != StringLabel || 129 + sel.ConstraintType() >= PatternConstraint { 93 130 panic("Selector.Unquoted invoked on non-string label") 94 131 } 95 132 switch s := sel.sel.(type) { ··· 98 135 case optionalSelector: 99 136 return string(s.selector.(stringSelector)) 100 137 } 101 - panic("unreachable") 138 + panic(fmt.Sprintf("unreachable %T", sel.sel)) 102 139 } 103 140 104 - // IsOptional reports whether s is an optional field or definition. 105 - func (sel Selector) IsOptional() bool { 106 - _, ok := sel.sel.(optionalSelector) 107 - return ok 141 + // IsConstraint reports whether s is optional or a pattern constraint. 142 + // Fields that are constraints are considered non-existing and their 143 + // values may be erroneous for a configuration to be valid.. 144 + func (sel Selector) IsConstraint() bool { 145 + return sel.Type().ConstraintType() != 0 108 146 } 109 147 110 - // IsString reports whether sel is a regular label type. 148 + // IsString reports whether sel represents an optional or regular member field. 111 149 func (sel Selector) IsString() bool { 112 - return sel.Type() == SelString 150 + // TODO: consider deprecating this method. It is a bit wonkey now. 151 + t := sel.Type() 152 + t &^= OptionalConstraint 153 + return t == StringLabel 113 154 } 114 155 115 - // IsDefinition reports whether sel is a non-hidden definition label type. 156 + // IsDefinition reports whether sel is a non-hidden definition and non-constraint label type. 116 157 func (sel Selector) IsDefinition() bool { 117 158 return sel.Type().IsDefinition() 118 159 } 119 160 120 161 // Type returns the type of the selector. 121 162 func (sel Selector) Type() SelectorType { 122 - return sel.sel.kind() 163 + return sel.sel.labelType() | sel.sel.constraintType() 164 + } 165 + 166 + // LabelType returns the type of the label part of a selector. 167 + func (sel Selector) LabelType() SelectorType { 168 + return sel.sel.labelType() 169 + } 170 + 171 + // ConstraintType returns the type of the constraint part of a selector. 172 + func (sel Selector) ConstraintType() SelectorType { 173 + return sel.sel.constraintType() 123 174 } 124 175 125 176 // PkgPath reports the package path associated with a hidden label or "" if ··· 171 222 String() string 172 223 173 224 feature(ctx adt.Runtime) adt.Feature 174 - kind() SelectorType 225 + labelType() SelectorType 226 + constraintType() SelectorType 175 227 optional() bool 176 228 } 177 229 ··· 233 285 234 286 b := &strings.Builder{} 235 287 for i, sel := range p.path { 236 - x := sel.sel 237 288 switch { 238 - case x.kind() == SelIndex: 289 + case sel.Type() == IndexLabel: 239 290 // TODO: use '.' in all cases, once supported. 240 291 b.WriteByte('[') 241 - b.WriteString(x.String()) 292 + b.WriteString(sel.sel.String()) 242 293 b.WriteByte(']') 243 294 continue 244 295 case i > 0: 245 296 b.WriteByte('.') 246 297 } 247 298 248 - b.WriteString(x.String()) 299 + b.WriteString(sel.sel.String()) 249 300 } 250 301 return b.String() 251 302 } ··· 412 463 } 413 464 func (scopedSelector) optional() bool { return false } 414 465 415 - func (s scopedSelector) kind() SelectorType { 466 + func (s scopedSelector) labelType() SelectorType { 416 467 if strings.HasPrefix(s.name, "_#") { 417 - return SelHiddenDefinition 468 + return HiddenDefinitionLabel 418 469 } 419 - return SelHidden 470 + return HiddenLabel 420 471 } 472 + func (s scopedSelector) constraintType() SelectorType { return 0 } 421 473 422 474 func (s scopedSelector) feature(r adt.Runtime) adt.Feature { 423 475 return adt.MakeIdentLabel(r, s.name, s.pkg) ··· 445 497 446 498 func (d definitionSelector) optional() bool { return false } 447 499 448 - func (d definitionSelector) kind() SelectorType { 449 - return SelDefinition 500 + func (d definitionSelector) labelType() SelectorType { 501 + return DefinitionLabel 450 502 } 503 + 504 + func (s definitionSelector) constraintType() SelectorType { return 0 } 451 505 452 506 func (d definitionSelector) feature(r adt.Runtime) adt.Feature { 453 507 return adt.MakeIdentLabel(r, string(d), "") ··· 468 522 return str 469 523 } 470 524 471 - func (s stringSelector) optional() bool { return false } 472 - func (s stringSelector) kind() SelectorType { return SelString } 525 + func (s stringSelector) optional() bool { return false } 526 + func (s stringSelector) labelType() SelectorType { return StringLabel } 527 + func (s stringSelector) constraintType() SelectorType { return 0 } 473 528 474 529 func (s stringSelector) feature(r adt.Runtime) adt.Feature { 475 530 return adt.MakeStringLabel(r, string(s)) ··· 490 545 return strconv.Itoa(adt.Feature(s).Index()) 491 546 } 492 547 493 - func (s indexSelector) kind() SelectorType { return SelIndex } 494 - func (s indexSelector) optional() bool { return false } 548 + func (s indexSelector) labelType() SelectorType { return IndexLabel } 549 + func (s indexSelector) constraintType() SelectorType { return 0 } 550 + 551 + func (s indexSelector) optional() bool { return false } 495 552 496 553 func (s indexSelector) feature(r adt.Runtime) adt.Feature { 497 554 return adt.Feature(s) ··· 500 557 // an anySelector represents a wildcard option of a particular type. 501 558 type anySelector adt.Feature 502 559 503 - func (s anySelector) String() string { return "[_]" } 504 - func (s anySelector) optional() bool { return true } 505 - func (s anySelector) kind() SelectorType { return SelPattern } 560 + func (s anySelector) String() string { return "[_]" } 561 + func (s anySelector) optional() bool { return true } 562 + func (s anySelector) labelType() SelectorType { 563 + var l SelectorType 564 + switch adt.Feature(s) { 565 + case adt.AnyString: 566 + l = StringLabel 567 + case adt.AnyIndex: 568 + l = IndexLabel 569 + case adt.AnyDefinition: 570 + l = DefinitionLabel 571 + case adt.AnyHidden: 572 + l = HiddenLabel 573 + } 574 + return l 575 + } 576 + func (s anySelector) constraintType() SelectorType { return PatternConstraint } 506 577 507 578 func (s anySelector) feature(r adt.Runtime) adt.Feature { 508 579 return adt.Feature(s) ··· 518 589 // } 519 590 type optionalSelector struct { 520 591 selector 592 + } 593 + 594 + func (s optionalSelector) labelType() SelectorType { 595 + return s.selector.labelType() 596 + } 597 + 598 + func (s optionalSelector) constraintType() SelectorType { 599 + return OptionalConstraint 521 600 } 522 601 523 602 func wrapOptional(sel Selector) Selector { ··· 557 636 errors.Error 558 637 } 559 638 560 - func (p pathError) String() string { return "" } 561 - func (p pathError) optional() bool { return false } 562 - func (p pathError) kind() SelectorType { return SelInvalid } 639 + func (p pathError) String() string { return "" } 640 + func (p pathError) optional() bool { return false } 641 + func (p pathError) labelType() SelectorType { return InvalidSelectorType } 642 + func (p pathError) constraintType() SelectorType { return 0 } 563 643 func (p pathError) feature(r adt.Runtime) adt.Feature { 564 644 return adt.InvalidLabel 565 645 }
+33 -28
cue/path_test.go
··· 161 161 unquoted string 162 162 index int 163 163 isHidden bool 164 - isOptional bool 164 + isConstraint bool 165 165 isDefinition bool 166 166 isString bool 167 167 pkgPath string 168 168 }{{ 169 169 sel: Str("foo"), 170 - stype: SelString, 170 + stype: StringLabel, 171 171 string: "foo", 172 172 unquoted: "foo", 173 173 isString: true, 174 174 }, { 175 175 sel: Str("_foo"), 176 - stype: SelString, 176 + stype: StringLabel, 177 177 string: `"_foo"`, 178 178 unquoted: "_foo", 179 179 isString: true, 180 180 }, { 181 181 sel: Str(`a "b`), 182 - stype: SelString, 182 + stype: StringLabel, 183 183 string: `"a \"b"`, 184 184 unquoted: `a "b`, 185 185 isString: true, 186 186 }, { 187 187 sel: Index(5), 188 - stype: SelIndex, 188 + stype: IndexLabel, 189 189 string: "5", 190 190 index: 5, 191 191 }, { 192 192 sel: Def("foo"), 193 - stype: SelDefinition, 193 + stype: DefinitionLabel, 194 194 string: "#foo", 195 195 isDefinition: true, 196 196 }, { 197 - sel: Str("foo").Optional(), 198 - stype: SelString, 199 - string: "foo?", 200 - unquoted: "foo", 201 - isString: true, 202 - isOptional: true, 197 + sel: Str("foo").Optional(), 198 + stype: StringLabel | OptionalConstraint, 199 + string: "foo?", 200 + unquoted: "foo", 201 + isString: true, 202 + isConstraint: true, 203 203 }, { 204 204 sel: Def("foo").Optional(), 205 - stype: SelDefinition, 205 + stype: DefinitionLabel | OptionalConstraint, 206 206 string: "#foo?", 207 207 isDefinition: true, 208 - isOptional: true, 208 + isConstraint: true, 209 209 }, { 210 - sel: AnyString, 211 - stype: SelPattern, 212 - string: "[_]", 210 + sel: AnyString, 211 + stype: StringLabel | PatternConstraint, 212 + string: "[_]", 213 + isConstraint: true, 213 214 }, { 214 - sel: AnyIndex, 215 - stype: SelPattern, 216 - string: "[_]", 215 + sel: AnyIndex, 216 + stype: IndexLabel | PatternConstraint, 217 + string: "[_]", 218 + isConstraint: true, 217 219 }, { 218 220 sel: Hid("_foo", "example.com"), 219 - stype: SelHidden, 221 + stype: HiddenLabel, 220 222 string: "_foo", 221 223 isHidden: true, 222 224 pkgPath: "example.com", 223 225 }, { 224 226 sel: Hid("_#foo", "example.com"), 225 - stype: SelHiddenDefinition, 227 + stype: HiddenDefinitionLabel, 226 228 string: "_#foo", 227 229 isHidden: true, 228 230 isDefinition: true, ··· 239 241 if got, want := sel.String(), tc.string; got != want { 240 242 t.Errorf("unexpected sel.String result; got %q want %q", got, want) 241 243 } 242 - if sel.Type() != SelString { 244 + if tc.unquoted == "" { 243 245 checkPanic(t, "Selector.Unquoted invoked on non-string label", func() { 244 246 sel.Unquoted() 245 247 }) ··· 248 250 t.Errorf("unexpected sel.Unquoted result; got %q want %q", got, want) 249 251 } 250 252 } 251 - if sel.Type() != SelIndex { 253 + if sel.Type() != IndexLabel { 252 254 checkPanic(t, "Index called on non-index selector", func() { 253 255 sel.Index() 254 256 }) ··· 260 262 if got, want := sel.Type().IsHidden(), tc.isHidden; got != want { 261 263 t.Errorf("unexpected sel.IsHidden result; got %v want %v", got, want) 262 264 } 263 - if got, want := sel.IsOptional(), tc.isOptional; got != want { 265 + if got, want := sel.IsConstraint(), tc.isConstraint; got != want { 264 266 t.Errorf("unexpected sel.IsOptional result; got %v want %v", got, want) 265 267 } 266 268 if got, want := sel.IsString(), tc.isString; got != want { ··· 277 279 } 278 280 279 281 func TestSelectorTypeString(t *testing.T) { 280 - if got, want := SelInvalid.String(), "SelInvalid"; got != want { 282 + if got, want := InvalidSelectorType.String(), "NoLabels"; got != want { 283 + t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want) 284 + } 285 + if got, want := PatternConstraint.String(), "PatternConstraint"; got != want { 281 286 t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want) 282 287 } 283 - if got, want := SelPattern.String(), "SelPattern"; got != want { 288 + if got, want := (StringLabel | OptionalConstraint).String(), "StringLabel|OptionalConstraint"; got != want { 284 289 t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want) 285 290 } 286 - if got, want := SelectorType(255).String(), "SelInvalid255"; got != want { 291 + if got, want := SelectorType(255).String(), "StringLabel|HiddenLabel|DefinitionLabel|HiddenDefinitionLabel|IndexLabel|OptionalConstraint|PatternConstraint"; got != want { 287 292 t.Errorf("unexpected SelectorType.String result; got %q want %q", got, want) 288 293 } 289 294 }
+14 -15
cue/types.go
··· 1708 1708 } 1709 1709 for i := len(p.path) - 1; i >= 0; i-- { 1710 1710 switch sel := p.path[i]; sel.Type() { 1711 - case SelPattern: 1712 - if sel.sel == AnyString.sel { 1713 - expr = &adt.StructLit{Decls: []adt.Decl{ 1714 - &adt.BulkOptionalField{ 1715 - Filter: &adt.BasicType{K: adt.StringKind}, 1716 - Value: expr, 1717 - }, 1718 - }} 1719 - } else { 1720 - expr = &adt.ListLit{Elems: []adt.Elem{ 1721 - &adt.Ellipsis{Value: expr}, 1722 - }} 1723 - } 1711 + case StringLabel | PatternConstraint: 1712 + expr = &adt.StructLit{Decls: []adt.Decl{ 1713 + &adt.BulkOptionalField{ 1714 + Filter: &adt.BasicType{K: adt.StringKind}, 1715 + Value: expr, 1716 + }, 1717 + }} 1718 + 1719 + case IndexLabel | PatternConstraint: 1720 + expr = &adt.ListLit{Elems: []adt.Elem{ 1721 + &adt.Ellipsis{Value: expr}, 1722 + }} 1724 1723 1725 - case SelIndex: 1724 + case IndexLabel: 1726 1725 i := sel.Index() 1727 1726 list := &adt.ListLit{} 1728 1727 any := &adt.Top{} ··· 1735 1734 1736 1735 default: 1737 1736 var d adt.Decl 1738 - if sel.IsOptional() { 1737 + if sel.ConstraintType() == OptionalConstraint { 1739 1738 d = &adt.OptionalField{ 1740 1739 Label: sel.sel.feature(v.idx), 1741 1740 Value: expr,