cuelang.org/go@v0.10.1/internal/core/adt/kind.go (about) 1 // 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 15 package adt 16 17 import ( 18 "fmt" 19 "math/bits" 20 "strings" 21 ) 22 23 // Concreteness is a measure of the level of concreteness of a value, where 24 // lower values mean more concrete. 25 type Concreteness int 26 27 const ( 28 BottomLevel Concreteness = iota 29 30 // Concrete indicates a concrete scalar value, list or struct. 31 Concrete 32 33 // Constraint indicates a non-concrete scalar value that is more specific, 34 // than a top-level type. 35 Constraint 36 37 // PrimitiveType indicates a top-level specific type, for instance, string, 38 // bytes, number, or bool. 39 Type 40 41 // Any indicates any value, or top. 42 Any 43 ) 44 45 // IsConcrete returns whether a value is concrete. 46 func IsConcrete(v Value) bool { 47 if x, ok := v.(*Vertex); ok { 48 return x.IsConcrete() 49 } 50 if v == nil { 51 return false 52 } 53 return v.Concreteness() <= Concrete 54 } 55 56 // Kind reports the Value kind. 57 type Kind uint16 58 59 const ( 60 NullKind Kind = (1 << iota) 61 BoolKind 62 IntKind 63 FloatKind 64 StringKind 65 BytesKind 66 FuncKind 67 ListKind 68 StructKind 69 70 allKinds 71 72 _numberKind 73 74 BottomKind Kind = 0 75 76 NumberKind = IntKind | FloatKind 77 TopKind Kind = (allKinds - 1) // all kinds, but not references 78 ScalarKinds = NullKind | BoolKind | 79 IntKind | FloatKind | StringKind | BytesKind 80 81 CompositeKind = StructKind | ListKind 82 ) 83 84 func kind(v Value) Kind { 85 if v == nil { 86 return BottomKind 87 } 88 return v.Kind() 89 } 90 91 // IsAnyOf reports whether k is any of the given kinds. 92 // 93 // For instances, k.IsAnyOf(String|Bytes) reports whether k overlaps with 94 // the String or Bytes kind. 95 func (k Kind) IsAnyOf(of Kind) bool { 96 return k&of != BottomKind 97 } 98 99 // CanString reports whether the given type can convert to a string. 100 func (k Kind) CanString() bool { 101 return k&StringKind|ScalarKinds != BottomKind 102 } 103 104 // String returns the representation of the Kind as 105 // a CUE expression. For example: 106 // 107 // (IntKind|ListKind).String() 108 // 109 // will return: 110 // 111 // (int|[...]) 112 func (k Kind) String() string { 113 return toString(k, kindStrs) 114 } 115 116 // TypeString is like String, but returns a string representation of a valid 117 // CUE type. 118 func (k Kind) TypeString() string { 119 return toString(k, typeStrs) 120 } 121 122 func toString(k Kind, m map[Kind]string) string { 123 if k == BottomKind { 124 return "_|_" 125 } 126 if k == TopKind { 127 return "_" 128 } 129 if (k & NumberKind) == NumberKind { 130 k = (k &^ NumberKind) | _numberKind 131 } 132 var buf strings.Builder 133 multiple := bits.OnesCount(uint(k)) > 1 134 if multiple { 135 buf.WriteByte('(') 136 } 137 for count := 0; ; count++ { 138 n := bits.TrailingZeros(uint(k)) 139 if n == bits.UintSize { 140 break 141 } 142 bit := Kind(1 << uint(n)) 143 k &^= bit 144 s, ok := m[bit] 145 if !ok { 146 s = fmt.Sprintf("bad(%d)", n) 147 } 148 if count > 0 { 149 buf.WriteByte('|') 150 } 151 buf.WriteString(s) 152 } 153 if multiple { 154 buf.WriteByte(')') 155 } 156 return buf.String() 157 } 158 159 var kindStrs = map[Kind]string{ 160 NullKind: "null", 161 BoolKind: "bool", 162 IntKind: "int", 163 FloatKind: "float", 164 StringKind: "string", 165 BytesKind: "bytes", 166 FuncKind: "func", 167 StructKind: "struct", 168 ListKind: "list", 169 _numberKind: "number", 170 } 171 172 // used to generate a parseable CUE type. 173 var typeStrs = map[Kind]string{ 174 NullKind: "null", 175 BoolKind: "bool", 176 IntKind: "int", 177 FloatKind: "float", 178 StringKind: "string", 179 BytesKind: "bytes", 180 FuncKind: "_", 181 StructKind: "{...}", 182 ListKind: "[...]", 183 _numberKind: "number", 184 }