cuelang.org/go@v0.10.1/internal/core/debug/compact.go (about) 1 // Copyright 2020 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 debug prints a given ADT node. 16 // 17 // Note that the result is not valid CUE, but instead prints the internals 18 // of an ADT node in human-readable form. It uses a simple indentation algorithm 19 // for improved readability and diffing. 20 package debug 21 22 import ( 23 "fmt" 24 "strconv" 25 26 "cuelang.org/go/cue/literal" 27 "cuelang.org/go/internal/core/adt" 28 ) 29 30 type compactPrinter struct { 31 printer 32 } 33 34 func (w *compactPrinter) string(s string) { 35 w.dst = append(w.dst, s...) 36 } 37 38 func (w *compactPrinter) node(n adt.Node) { 39 switch x := n.(type) { 40 case *adt.Vertex: 41 if x.BaseValue == nil || (w.cfg.Raw && !x.IsData()) { 42 for i, c := range x.Conjuncts { 43 if i > 0 { 44 w.string(" & ") 45 } 46 w.node(c.Elem()) 47 } 48 return 49 } 50 51 switch v := x.BaseValue.(type) { 52 case *adt.StructMarker: 53 w.string("{") 54 for i, a := range x.Arcs { 55 if i > 0 { 56 w.string(",") 57 } 58 if a.Label.IsLet() { 59 w.string("let ") 60 w.label(a.Label) 61 if a.MultiLet { 62 w.string("m") 63 } 64 w.string("=") 65 if c := a.Conjuncts[0]; a.MultiLet { 66 w.node(c.Expr()) 67 continue 68 } 69 w.node(a) 70 } else { 71 w.label(a.Label) 72 w.string(a.ArcType.Suffix()) 73 w.string(":") 74 w.node(a) 75 } 76 } 77 w.string("}") 78 79 case *adt.ListMarker: 80 w.string("[") 81 for i, a := range x.Arcs { 82 if i > 0 { 83 w.string(",") 84 } 85 w.node(a) 86 } 87 w.string("]") 88 89 case *adt.Vertex: 90 if v, ok := w.printShared(x); !ok { 91 w.node(v) 92 } 93 94 case adt.Value: 95 w.node(v) 96 } 97 98 case *adt.StructMarker: 99 w.string("struct") 100 101 case *adt.ListMarker: 102 w.string("list") 103 104 case *adt.StructLit: 105 w.string("{") 106 for i, d := range x.Decls { 107 if i > 0 { 108 w.string(",") 109 } 110 w.node(d) 111 } 112 w.string("}") 113 114 case *adt.ListLit: 115 w.string("[") 116 for i, d := range x.Elems { 117 if i > 0 { 118 w.string(",") 119 } 120 w.node(d) 121 } 122 w.string("]") 123 124 case *adt.Field: 125 w.label(x.Label) 126 w.string(x.ArcType.Suffix()) 127 w.string(":") 128 w.node(x.Value) 129 130 case *adt.LetField: 131 w.string("let ") 132 w.label(x.Label) 133 if x.IsMulti { 134 w.string("m") 135 } 136 w.string("=") 137 w.node(x.Value) 138 139 case *adt.BulkOptionalField: 140 w.string("[") 141 w.node(x.Filter) 142 w.string("]:") 143 w.node(x.Value) 144 145 case *adt.DynamicField: 146 w.node(x.Key) 147 w.string(x.ArcType.Suffix()) 148 w.string(":") 149 w.node(x.Value) 150 151 case *adt.Ellipsis: 152 w.string("...") 153 if x.Value != nil { 154 w.node(x.Value) 155 } 156 157 case *adt.Bottom: 158 w.string(`_|_`) 159 if x.Err != nil { 160 w.string("(") 161 w.string(x.Err.Error()) 162 w.string(")") 163 } 164 165 case *adt.Null: 166 w.string("null") 167 168 case *adt.Bool: 169 w.dst = strconv.AppendBool(w.dst, x.B) 170 171 case *adt.Num: 172 w.string(x.X.String()) 173 174 case *adt.String: 175 w.dst = literal.String.Append(w.dst, x.Str) 176 177 case *adt.Bytes: 178 w.dst = literal.Bytes.Append(w.dst, string(x.B)) 179 180 case *adt.Top: 181 w.string("_") 182 183 case *adt.BasicType: 184 w.string(x.K.String()) 185 186 case *adt.BoundExpr: 187 w.string(x.Op.String()) 188 w.node(x.Expr) 189 190 case *adt.BoundValue: 191 w.string(x.Op.String()) 192 w.node(x.Value) 193 194 case *adt.NodeLink: 195 w.string(openTuple) 196 for i, f := range x.Node.Path() { 197 if i > 0 { 198 w.string(".") 199 } 200 w.label(f) 201 } 202 w.string(closeTuple) 203 204 case *adt.FieldReference: 205 w.label(x.Label) 206 207 case *adt.ValueReference: 208 w.label(x.Label) 209 210 case *adt.LabelReference: 211 if x.Src == nil { 212 w.string("LABEL") 213 } else { 214 w.string(x.Src.Name) 215 } 216 217 case *adt.DynamicReference: 218 w.node(x.Label) 219 220 case *adt.ImportReference: 221 w.label(x.ImportPath) 222 223 case *adt.LetReference: 224 w.ident(x.Label) 225 226 case *adt.SelectorExpr: 227 w.node(x.X) 228 w.string(".") 229 w.label(x.Sel) 230 231 case *adt.IndexExpr: 232 w.node(x.X) 233 w.string("[") 234 w.node(x.Index) 235 w.string("]") 236 237 case *adt.SliceExpr: 238 w.node(x.X) 239 w.string("[") 240 if x.Lo != nil { 241 w.node(x.Lo) 242 } 243 w.string(":") 244 if x.Hi != nil { 245 w.node(x.Hi) 246 } 247 if x.Stride != nil { 248 w.string(":") 249 w.node(x.Stride) 250 } 251 w.string("]") 252 253 case *adt.Interpolation: 254 w.interpolation(x) 255 256 case *adt.UnaryExpr: 257 w.string(x.Op.String()) 258 w.node(x.X) 259 260 case *adt.BinaryExpr: 261 w.string("(") 262 w.node(x.X) 263 w.string(" ") 264 w.string(x.Op.String()) 265 w.string(" ") 266 w.node(x.Y) 267 w.string(")") 268 269 case *adt.CallExpr: 270 w.node(x.Fun) 271 w.string("(") 272 for i, a := range x.Args { 273 if i > 0 { 274 w.string(", ") 275 } 276 w.node(a) 277 } 278 w.string(")") 279 280 case *adt.Builtin: 281 if x.Package != 0 { 282 w.label(x.Package) 283 w.string(".") 284 } 285 w.string(x.Name) 286 287 case *adt.BuiltinValidator: 288 w.node(x.Builtin) 289 w.string("(") 290 for i, a := range x.Args { 291 if i > 0 { 292 w.string(", ") 293 } 294 w.node(a) 295 } 296 w.string(")") 297 298 case *adt.DisjunctionExpr: 299 w.string("(") 300 for i, a := range x.Values { 301 if i > 0 { 302 w.string("|") 303 } 304 // Disjunct 305 if a.Default { 306 w.string("*") 307 } 308 w.node(a.Val) 309 } 310 w.string(")") 311 312 case *adt.Conjunction: 313 for i, c := range x.Values { 314 if i > 0 { 315 w.string(" & ") 316 } 317 w.node(c) 318 } 319 320 case *adt.ConjunctGroup: 321 for i, c := range *x { 322 if i > 0 { 323 w.string(" & ") 324 } 325 w.node(c.Expr()) 326 } 327 328 case *adt.Disjunction: 329 for i, c := range x.Values { 330 if i > 0 { 331 w.string(" | ") 332 } 333 if i < x.NumDefaults { 334 w.string("*") 335 } 336 w.node(c) 337 } 338 339 case *adt.Comprehension: 340 for _, c := range x.Clauses { 341 w.node(c) 342 } 343 w.node(adt.ToExpr(x.Value)) 344 345 case *adt.ForClause: 346 w.string("for ") 347 w.ident(x.Key) 348 w.string(", ") 349 w.ident(x.Value) 350 w.string(" in ") 351 w.node(x.Src) 352 w.string(" ") 353 354 case *adt.IfClause: 355 w.string("if ") 356 w.node(x.Condition) 357 w.string(" ") 358 359 case *adt.LetClause: 360 w.string("let ") 361 w.ident(x.Label) 362 w.string(" = ") 363 w.node(x.Expr) 364 w.string(" ") 365 366 case *adt.ValueClause: 367 368 default: 369 panic(fmt.Sprintf("unknown type %T", x)) 370 } 371 }