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