blob: 98636312e335e40723a768766da6c0b43221b02c [file] [log] [blame]
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +01001// 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
15package cue
16
17import (
18 "bytes"
19 "fmt"
20 "strconv"
21 "strings"
22)
23
24func debugStr(ctx *context, v value) string {
25 p := &printer{
26 ctx: ctx,
27 w: &bytes.Buffer{},
28 }
29 p.debugStr(v)
30 return p.w.String()
31}
32
33func (c *context) ref(v scope) string {
34 v = c.deref(v)
35 if c.nodeRefs == nil {
36 c.nodeRefs = map[scope]string{}
37 }
38 ref, ok := c.nodeRefs[v]
39 if ok {
40 return ref
41 }
42 ref = strconv.Itoa(len(c.nodeRefs))
43 c.nodeRefs[v] = ref
44 return ref
45}
46
47func (c *context) indent() {
48 fmt.Print(strings.Repeat(" ", c.level))
49}
50
51func (c *context) debugPrint(args ...interface{}) {
52 if c.trace {
53 c.indent()
54 c.println(args...)
55 }
56}
57
58func (c *context) println(args ...interface{}) {
59 for i, a := range args {
60 if i != 0 {
61 fmt.Print(" ")
62 }
63 switch x := a.(type) {
64 case value:
65 fmt.Print(debugStr(c, x))
66 default:
67 fmt.Print(x)
68 }
69 }
70 fmt.Println()
71}
72
73// func trace(c *context, r rewriter, n *node) (*context, rewriter, *node) {
74// n = derefNode(n)
75// name := "evaluate"
76// if r != nil {
77// name = fmt.Sprintf("%T", r)
78// }
79// c.debugPrint("---", name, c.ref(n))
80// if n.obj != nil {
81// c.debugPrint("<<< node: ", debugStr(c, n.obj))
82// }
83// if n.expr != nil {
84// c.debugPrint("<<< expr: ", debugStr(c, n.expr))
85// }
86// if n.value != nil {
87// c.debugPrint("<<< value:", debugStr(c, n.value))
88// }
89// c.level++
90// return c, r, n
91// }
92
93// func un(c *context, r rewriter, n *node) {
94// n = derefNode(n)
95// c.level--
96// if n.expr != nil {
97// c.debugPrint(">>> expr:", debugStr(c, n.expr))
98// }
99// if n.value != nil {
100// c.debugPrint(">>> value:", debugStr(c, n.value))
101// }
102// if n.obj != nil {
103// c.debugPrint(">>> node: ", debugStr(c, n.obj))
104// }
105// }
106
107func indent(c *context, msg string, x value) (_ *context, m, v string) {
108 str := debugStr(c, x)
109 c.debugPrint("...", msg)
110 c.level++
111 c.debugPrint("in:", str)
112 return c, msg, str
113}
114
115func uni(c *context, msg, oldValue string) {
116 c.debugPrint("was: ", oldValue)
117 c.level--
118 c.debugPrint("...", msg)
119}
120
121func newPrinter(ctx *context) *printer {
122 return &printer{
123 ctx: ctx,
124 w: &bytes.Buffer{},
125 }
126}
127
128type printer struct {
129 ctx *context
130 w *bytes.Buffer
131}
132
133func (p *printer) str(v value) string {
134 p.debugStr(v)
135 str := p.w.String()
136 p.w.Reset()
137 return str
138}
139
140func (p *printer) label(f label) string {
141 if p.ctx == nil {
142 return strconv.Itoa(int(f))
143 }
144 return p.ctx.labelStr(f)
145}
146
147func (p *printer) writef(format string, args ...interface{}) {
148 fmt.Fprintf(p.w, format, args...)
149}
150
151func (p *printer) write(args ...interface{}) {
152 fmt.Fprint(p.w, args...)
153}
154
155func (p *printer) debugStr(v interface{}) {
156 writef := p.writef
157 write := p.write
158 switch x := v.(type) {
159 case nil:
160 write("*nil*")
161 case string:
162 write(x)
163 case *builtin:
164 write("builtin:")
165 p.debugStr(x.Name)
166 case *nodeRef:
167 writef("<%s>", p.ctx.ref(x.node))
168 // p.debugStr(x.node)
169 case *selectorExpr:
170 p.debugStr(x.x)
171 writef(".%v", p.label(x.feature))
172 case *indexExpr:
173 p.debugStr(x.x)
174 write("[")
175 p.debugStr(x.index)
176 write("]")
177 case *sliceExpr:
178 p.debugStr(x.x)
179 write("[")
180 if x.lo != nil {
181 p.debugStr(x.lo)
182 }
183 write(":")
184 if x.hi != nil {
185 p.debugStr(x.hi)
186 }
187 write("]")
188 case *callExpr:
189 p.debugStr(x.x)
190 write(" (")
191 for i, a := range x.args {
192 p.debugStr(a)
193 if i < len(x.args)-1 {
194 write(",")
195 }
196 }
197 write(")")
198 case *unaryExpr:
199 write(x.op)
200 p.debugStr(x.x)
201 case *binaryExpr:
202 write("(")
203 p.debugStr(x.left)
204 writef(" %v ", x.op)
205 p.debugStr(x.right)
206 write(")")
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100207 case *unification:
208 write("(")
209 for i, v := range x.values {
210 if i != 0 {
211 writef(" & ")
212 }
213 p.debugStr(v)
214 }
215 write(")")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100216 case *disjunction:
217 write("(")
218 for i, v := range x.values {
219 if i != 0 {
220 writef(" | ")
221 }
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100222 if v.marked {
223 writef("*")
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100224 }
Marcel van Lohuizenc9b3cb22019-01-30 11:32:41 +0100225 p.debugStr(v.val)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100226 }
227 write(")")
228 case *lambdaExpr:
229 writef("<%s>(", p.ctx.ref(x))
230 p.debugStr(x.params.arcs)
231 write(")->")
232 p.debugStr(x.value)
233
234 case *structLit:
235 if x == nil {
236 write("*nil node*")
237 break
238 }
239 p.writef("<%s>", p.ctx.ref(x))
240 writef("{")
241 if x.template != nil {
242 write("<>: ")
243 p.debugStr(x.template)
244 write(", ")
245 }
246 p.debugStr(x.arcs)
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100247 for i, c := range x.comprehensions {
248 p.debugStr(c)
249 if i < len(x.comprehensions)-1 {
250 p.write(", ")
251 }
252 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100253 write("}")
254
255 case []arc:
256 for i, a := range x {
257 p.debugStr(a)
258
259 if i < len(x)-1 {
260 p.write(", ")
261 }
262 }
263
264 case arc:
265 n := x.v
266 orig := p.label(x.feature)
267 str := strconv.Quote(orig)
268 if len(orig)+2 == len(str) {
269 str = str[1 : len(str)-1]
270 }
271 p.writef(str)
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100272 if x.optional {
273 p.write("?")
274 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100275 p.write(": ")
276 p.debugStr(n)
Marcel van Lohuizenb9b62d32019-03-14 23:50:15 +0100277 if x.attrs != nil {
278 for _, a := range x.attrs.attr {
279 p.write(" ", a.text)
280 }
281 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100282
Marcel van Lohuizen66db9202018-12-17 19:02:08 +0100283 case *fieldComprehension:
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100284 p.debugStr(x.clauses)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100285
286 case *listComprehension:
287 writef("[")
288 p.debugStr(x.clauses)
289 write(" ]")
290
291 case *yield:
292 writef(" yield ")
293 writef("(")
294 p.debugStr(x.key)
Marcel van Lohuizen08a0ef22019-03-28 09:12:19 +0100295 if x.opt {
296 writef("?")
297 }
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100298 writef("): ")
299 p.debugStr(x.value)
300
301 case *feed:
302 writef(" <%s>for ", p.ctx.ref(x.fn))
303 a := x.fn.params.arcs[0]
304 p.writef(p.label(a.feature))
305 writef(", ")
306 a = x.fn.params.arcs[1]
307 p.writef(p.label(a.feature))
308 writef(" in ")
309 p.debugStr(x.source)
310 p.debugStr(x.fn.value)
311
312 case *guard:
313 writef(" if ")
314 p.debugStr(x.condition)
315 p.debugStr(x.value)
316
317 case *nullLit:
318 write("null")
319 case *boolLit:
320 writef("%v", x.b)
321 case *stringLit:
322 writef("%q", x.str)
323 case *bytesLit:
324 str := strconv.Quote(string(x.b))
325 str = str[1 : len(str)-1]
326 writef("'%s'", str)
327 case *numLit:
328 if x.k&intKind != 0 {
329 write(x.v.Text('f')) // also render info
330 } else {
331 write(x.v.Text('g')) // also render info
332 }
333 case *durationLit:
334 write(x.d.String())
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100335 case *bound:
Marcel van Lohuizen4a360992019-05-11 18:18:31 +0200336 switch x.k & numKind {
337 case intKind:
338 p.writef("int & ")
339 case floatKind:
340 p.writef("float & ")
341 }
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100342 p.writef("%v", x.op)
343 p.debugStr(x.value)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100344 case *interpolation:
345 for i, e := range x.parts {
346 if i != 0 {
347 write("+")
348 }
349 p.debugStr(e)
350 }
351 case *list:
352 // TODO: do not evaluate
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100353 max := maxNum(x.len).evalPartial(p.ctx)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100354 inCast := false
355 ellipsis := false
356 n, ok := max.(*numLit)
357 if !ok {
358 // TODO: do not evaluate
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100359 min := minNum(x.len).evalPartial(p.ctx)
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100360 n, _ = min.(*numLit)
361 }
362 ln := 0
363 if n != nil {
364 x, _ := n.v.Int64()
365 ln = int(x)
366 }
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100367 open := false
368 switch max.(type) {
369 case *top, *basicType:
370 open = true
371 }
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +0200372 if !ok || ln > len(x.elem.arcs) {
Marcel van Lohuizen7d0797b2019-02-07 18:35:28 +0100373 if !open && !isTop(x.typ) {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100374 p.debugStr(x.len)
375 write("*[")
376 p.debugStr(x.typ)
377 write("]")
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +0200378 if len(x.elem.arcs) == 0 {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100379 break
380 }
381 write("(")
382 inCast = true
383 }
384 ellipsis = true
385 }
386 write("[")
Marcel van Lohuizen9ee652d2019-04-25 17:16:01 +0200387 for i, a := range x.elem.arcs {
388 p.debugStr(a.v)
389 if i < len(x.elem.arcs)-1 {
Marcel van Lohuizen17157ea2018-12-11 10:41:10 +0100390 write(",")
391 }
392 }
393 if ellipsis {
394 write(", ...")
395 if !isTop(x.typ) {
396 p.debugStr(x.typ)
397 }
398 }
399 write("]")
400 if inCast {
401 write(")")
402 }
403
404 case *bottom:
405 write("_|_")
406 if x.value != nil || x.msg != "" {
407 write("(")
408 if x.value != nil {
409 writef("%s:", debugStr(p.ctx, x.value))
410 }
411 write(x.msg)
412 write(")")
413 }
414 case *top:
415 write("_") // ⊤
416 case *basicType:
417 write(x.k.String())
418
419 default:
420 panic(fmt.Sprintf("unimplemented type %T", x))
421 }
422}