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