1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package debug
21
22 import (
23 "fmt"
24 "io"
25 "strconv"
26 "strings"
27
28 "cuelang.org/go/cue/errors"
29 "cuelang.org/go/cue/literal"
30 "cuelang.org/go/internal/core/adt"
31 )
32
33 const (
34 openTuple = "\u3008"
35 closeTuple = "\u3009"
36 )
37
38 type Config struct {
39 Cwd string
40 Compact bool
41 Raw bool
42 }
43
44
45 func WriteNode(w io.Writer, i adt.StringIndexer, n adt.Node, config *Config) {
46 if config == nil {
47 config = &Config{}
48 }
49 p := printer{Writer: w, index: i, cfg: config}
50 if config.Compact {
51 p := compactPrinter{p}
52 p.node(n)
53 } else {
54 p.node(n)
55 }
56 }
57
58
59
60
61
62 func NodeString(i adt.StringIndexer, n adt.Node, config *Config) string {
63 b := &strings.Builder{}
64 WriteNode(b, i, n, config)
65 return b.String()
66 }
67
68 type printer struct {
69 io.Writer
70 index adt.StringIndexer
71 indent string
72 cfg *Config
73
74
75
76
77
78
79 }
80
81 func (w *printer) string(s string) {
82 s = strings.Replace(s, "\n", "\n"+w.indent, -1)
83 _, _ = io.WriteString(w, s)
84 }
85
86 func (w *printer) label(f adt.Feature) {
87 w.string(w.labelString(f))
88 }
89
90 func (w *printer) ident(f adt.Feature) {
91 w.string(f.IdentString(w.index))
92 }
93
94
95 func (w *printer) labelString(f adt.Feature) string {
96 switch {
97 case f.IsHidden():
98 ident := f.IdentString(w.index)
99 if pkgName := f.PkgID(w.index); pkgName != "_" {
100 ident = fmt.Sprintf("%s(%s)", ident, pkgName)
101 }
102 return ident
103
104 case f.IsLet():
105 ident := f.RawString(w.index)
106 ident = strings.Replace(ident, "\x00", "#", 1)
107 return ident
108
109 default:
110 return f.SelectorString(w.index)
111 }
112 }
113
114 func (w *printer) shortError(errs errors.Error) {
115 for {
116 msg, args := errs.Msg()
117 fmt.Fprintf(w, msg, args...)
118
119 err := errors.Unwrap(errs)
120 if err == nil {
121 break
122 }
123
124 if errs, _ = err.(errors.Error); errs != nil {
125 w.string(err.Error())
126 break
127 }
128 }
129 }
130
131 func (w *printer) interpolation(x *adt.Interpolation) {
132 quote := `"`
133 if x.K == adt.BytesKind {
134 quote = `'`
135 }
136 w.string(quote)
137 for i := 0; i < len(x.Parts); i += 2 {
138 switch x.K {
139 case adt.StringKind:
140 if s, ok := x.Parts[i].(*adt.String); ok {
141 w.string(s.Str)
142 } else {
143 w.string("<bad string>")
144 }
145 case adt.BytesKind:
146 if s, ok := x.Parts[i].(*adt.Bytes); ok {
147 _, _ = w.Write(s.B)
148 } else {
149 w.string("<bad bytes>")
150 }
151 }
152 if i+1 < len(x.Parts) {
153 w.string(`\(`)
154 w.node(x.Parts[i+1])
155 w.string(`)`)
156 }
157 }
158 w.string(quote)
159 }
160
161 func (w *printer) node(n adt.Node) {
162 switch x := n.(type) {
163 case *adt.Vertex:
164 var kind adt.Kind
165 if x.BaseValue != nil {
166 kind = x.BaseValue.Kind()
167 }
168
169 kindStr := kind.String()
170
171
172 if x.IsClosedList() || x.IsClosedStruct() {
173 if kind == adt.ListKind || kind == adt.StructKind {
174 kindStr = "#" + kindStr
175 }
176 }
177
178 fmt.Fprintf(w, "(%s){", kindStr)
179
180 saved := w.indent
181 w.indent += " "
182 defer func() { w.indent = saved }()
183
184 switch v := x.BaseValue.(type) {
185 case nil:
186 case *adt.Bottom:
187
188 saved := w.indent
189 w.indent += "// "
190 w.string("\n")
191 fmt.Fprintf(w, "[%v]", v.Code)
192 if !v.ChildError {
193 msg := errors.Details(v.Err, &errors.Config{
194 Cwd: w.cfg.Cwd,
195 ToSlash: true,
196 })
197 msg = strings.TrimSpace(msg)
198 if msg != "" {
199 w.string(" ")
200 w.string(msg)
201 }
202 }
203 w.indent = saved
204
205 case *adt.StructMarker, *adt.ListMarker:
206
207
208
209
210
211 case adt.Value:
212 if len(x.Arcs) == 0 {
213 w.string(" ")
214 w.node(v)
215 w.string(" }")
216 return
217 }
218 w.string("\n")
219 w.node(v)
220 }
221
222 for _, a := range x.Arcs {
223 if a.ArcType == adt.ArcNotPresent {
224 continue
225 }
226 if a.Label.IsLet() {
227 w.string("\n")
228 w.string("let ")
229 w.label(a.Label)
230 if a.MultiLet {
231 w.string("multi")
232 }
233 w.string(" = ")
234 if c := a.Conjuncts[0]; a.MultiLet {
235 w.node(c.Expr())
236 continue
237 }
238 w.node(a)
239 } else {
240 w.string("\n")
241 w.label(a.Label)
242 w.string(a.ArcType.Suffix())
243 w.string(": ")
244 w.node(a)
245 }
246 }
247
248 if x.BaseValue == nil {
249 w.indent += "// "
250 w.string("// ")
251 for i, c := range x.Conjuncts {
252 if c.CloseInfo.FromDef || c.CloseInfo.FromEmbed {
253 w.string("[")
254 if c.CloseInfo.FromDef {
255 w.string("d")
256 }
257 if c.CloseInfo.FromEmbed {
258 w.string("e")
259 }
260 w.string("]")
261 }
262 if i > 0 {
263 w.string(" & ")
264 }
265 w.node(c.Elem())
266 }
267 }
268
269 w.indent = saved
270 w.string("\n")
271 w.string("}")
272
273 case *adt.StructMarker:
274 w.string("struct")
275
276 case *adt.ListMarker:
277 w.string("list")
278
279 case *adt.StructLit:
280 if len(x.Decls) == 0 {
281 w.string("{}")
282 break
283 }
284 w.string("{")
285 w.indent += " "
286 for _, d := range x.Decls {
287 w.string("\n")
288 w.node(d)
289 }
290 w.indent = w.indent[:len(w.indent)-2]
291 w.string("\n}")
292
293 case *adt.ListLit:
294 if len(x.Elems) == 0 {
295 w.string("[]")
296 break
297 }
298 w.string("[")
299 w.indent += " "
300 for _, d := range x.Elems {
301 w.string("\n")
302 w.node(d)
303 w.string(",")
304 }
305 w.indent = w.indent[:len(w.indent)-2]
306 w.string("\n]")
307
308 case *adt.Field:
309 s := w.labelString(x.Label)
310 w.string(s)
311 w.string(x.ArcType.Suffix())
312 w.string(":")
313 w.string(" ")
314 w.node(x.Value)
315
316 case *adt.LetField:
317 w.string("let ")
318 s := w.labelString(x.Label)
319 w.string(s)
320 if x.IsMulti {
321 w.string("multi")
322 }
323 w.string(" = ")
324 w.node(x.Value)
325
326 case *adt.BulkOptionalField:
327 w.string("[")
328 w.node(x.Filter)
329 w.string("]: ")
330 w.node(x.Value)
331
332 case *adt.DynamicField:
333 w.node(x.Key)
334 w.string(x.ArcType.Suffix())
335 w.string(": ")
336 w.node(x.Value)
337
338 case *adt.Ellipsis:
339 w.string("...")
340 if x.Value != nil {
341 w.node(x.Value)
342 }
343
344 case *adt.Bottom:
345 w.string(`_|_`)
346 if x.Err != nil {
347 w.string("(")
348 w.shortError(x.Err)
349 w.string(")")
350 }
351
352 case *adt.Null:
353 w.string("null")
354
355 case *adt.Bool:
356 fmt.Fprint(w, x.B)
357
358 case *adt.Num:
359 fmt.Fprint(w, &x.X)
360
361 case *adt.String:
362 w.string(literal.String.Quote(x.Str))
363
364 case *adt.Bytes:
365 w.string(literal.Bytes.Quote(string(x.B)))
366
367 case *adt.Top:
368 w.string("_")
369
370 case *adt.BasicType:
371 fmt.Fprint(w, x.K)
372
373 case *adt.BoundExpr:
374 fmt.Fprint(w, x.Op)
375 w.node(x.Expr)
376
377 case *adt.BoundValue:
378 fmt.Fprint(w, x.Op)
379 w.node(x.Value)
380
381 case *adt.NodeLink:
382 w.string(openTuple)
383 for i, f := range x.Node.Path() {
384 if i > 0 {
385 w.string(".")
386 }
387 w.label(f)
388 }
389 w.string(closeTuple)
390
391 case *adt.FieldReference:
392 w.string(openTuple)
393 w.string(strconv.Itoa(int(x.UpCount)))
394 w.string(";")
395 w.label(x.Label)
396 w.string(closeTuple)
397
398 case *adt.ValueReference:
399 w.string(openTuple)
400 w.string(strconv.Itoa(int(x.UpCount)))
401 w.string(closeTuple)
402
403 case *adt.LabelReference:
404 w.string(openTuple)
405 w.string(strconv.Itoa(int(x.UpCount)))
406 w.string(";-")
407 w.string(closeTuple)
408
409 case *adt.DynamicReference:
410 w.string(openTuple)
411 w.string(strconv.Itoa(int(x.UpCount)))
412 w.string(";(")
413 w.node(x.Label)
414 w.string(")")
415 w.string(closeTuple)
416
417 case *adt.ImportReference:
418 w.string(openTuple + "import;")
419 w.label(x.ImportPath)
420 w.string(closeTuple)
421
422 case *adt.LetReference:
423 w.string(openTuple)
424 w.string(strconv.Itoa(int(x.UpCount)))
425 w.string(";let ")
426 w.label(x.Label)
427 w.string(closeTuple)
428
429 case *adt.SelectorExpr:
430 w.node(x.X)
431 w.string(".")
432 w.label(x.Sel)
433
434 case *adt.IndexExpr:
435 w.node(x.X)
436 w.string("[")
437 w.node(x.Index)
438 w.string("]")
439
440 case *adt.SliceExpr:
441 w.node(x.X)
442 w.string("[")
443 if x.Lo != nil {
444 w.node(x.Lo)
445 }
446 w.string(":")
447 if x.Hi != nil {
448 w.node(x.Hi)
449 }
450 if x.Stride != nil {
451 w.string(":")
452 w.node(x.Stride)
453 }
454 w.string("]")
455
456 case *adt.Interpolation:
457 w.interpolation(x)
458
459 case *adt.UnaryExpr:
460 fmt.Fprint(w, x.Op)
461 w.node(x.X)
462
463 case *adt.BinaryExpr:
464 w.string("(")
465 w.node(x.X)
466 fmt.Fprint(w, " ", x.Op, " ")
467 w.node(x.Y)
468 w.string(")")
469
470 case *adt.CallExpr:
471 w.node(x.Fun)
472 w.string("(")
473 for i, a := range x.Args {
474 if i > 0 {
475 w.string(", ")
476 }
477 w.node(a)
478 }
479 w.string(")")
480
481 case *adt.Builtin:
482 if x.Package != 0 {
483 w.label(x.Package)
484 w.string(".")
485 }
486 w.string(x.Name)
487
488 case *adt.BuiltinValidator:
489 w.node(x.Builtin)
490 w.string("(")
491 for i, a := range x.Args {
492 if i > 0 {
493 w.string(", ")
494 }
495 w.node(a)
496 }
497 w.string(")")
498
499 case *adt.DisjunctionExpr:
500 w.string("(")
501 for i, a := range x.Values {
502 if i > 0 {
503 w.string("|")
504 }
505
506 if a.Default {
507 w.string("*")
508 }
509 w.node(a.Val)
510 }
511 w.string(")")
512
513 case *adt.Conjunction:
514 w.string("&(")
515 for i, c := range x.Values {
516 if i > 0 {
517 w.string(", ")
518 }
519 w.node(c)
520 }
521 w.string(")")
522
523 case *adt.ConjunctGroup:
524 w.string("&[")
525 for i, c := range *x {
526 if i > 0 {
527 w.string(", ")
528 }
529 w.node(c.Expr())
530 }
531 w.string("]")
532
533 case *adt.Disjunction:
534 w.string("|(")
535 for i, c := range x.Values {
536 if i > 0 {
537 w.string(", ")
538 }
539 if i < x.NumDefaults {
540 w.string("*")
541 }
542 w.node(c)
543 }
544 w.string(")")
545
546 case *adt.Comprehension:
547 for _, c := range x.Clauses {
548 w.node(c)
549 }
550 w.node(adt.ToExpr(x.Value))
551
552 case *adt.ForClause:
553 w.string("for ")
554 w.ident(x.Key)
555 w.string(", ")
556 w.ident(x.Value)
557 w.string(" in ")
558 w.node(x.Src)
559 w.string(" ")
560
561 case *adt.IfClause:
562 w.string("if ")
563 w.node(x.Condition)
564 w.string(" ")
565
566 case *adt.LetClause:
567 w.string("let ")
568 w.ident(x.Label)
569 w.string(" = ")
570 w.node(x.Expr)
571 w.string(" ")
572
573 case *adt.ValueClause:
574
575 default:
576 panic(fmt.Sprintf("unknown type %T", x))
577 }
578 }
579
View as plain text