1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package export
16
17 import (
18 "fmt"
19 "strings"
20
21 "cuelang.org/go/cue/ast"
22 "cuelang.org/go/cue/ast/astutil"
23 "cuelang.org/go/cue/literal"
24 "cuelang.org/go/cue/token"
25 "cuelang.org/go/internal"
26 "cuelang.org/go/internal/core/adt"
27 )
28
29 func (e *exporter) bareValue(v adt.Value) ast.Expr {
30 switch x := v.(type) {
31 case *adt.Vertex:
32 return e.vertex(x)
33 case adt.Value:
34 a := &adt.Vertex{BaseValue: x}
35 return e.vertex(a)
36 default:
37 panic("unreachable")
38 }
39
40 }
41
42
43
44
45 func (e *exporter) vertex(n *adt.Vertex) (result ast.Expr) {
46 var attrs []*ast.Attribute
47 if e.cfg.ShowAttributes {
48 attrs = ExtractDeclAttrs(n)
49 }
50
51 s, saved := e.pushFrame(n, n.Conjuncts)
52 e.top().upCount++
53 defer func() {
54 e.top().upCount--
55 e.popFrame(saved)
56 }()
57
58 for _, c := range n.Conjuncts {
59 e.markLets(c.Expr().Source(), s)
60 }
61
62 switch x := n.BaseValue.(type) {
63 case nil:
64
65 case *adt.StructMarker:
66 result = e.structComposite(n, attrs)
67
68 case *adt.ListMarker:
69 if e.showArcs(n) || attrs != nil {
70 result = e.structComposite(n, attrs)
71 } else {
72 result = e.listComposite(n)
73 }
74
75 case *adt.Bottom:
76 switch {
77 case n.ArcType == adt.ArcOptional:
78
79
80 case e.cfg.ShowErrors && x.ChildError:
81
82 if len(n.Arcs) > 0 && n.Arcs[0].Label.IsInt() && !e.showArcs(n) && attrs == nil {
83 result = e.listComposite(n)
84 } else {
85 result = e.structComposite(n, attrs)
86 }
87
88 case !x.IsIncomplete() || len(n.Conjuncts) == 0 || e.cfg.Final:
89 result = e.bottom(x)
90 }
91
92 case adt.Value:
93 if e.showArcs(n) || attrs != nil {
94 result = e.structComposite(n, attrs)
95 } else {
96 result = e.value(x, n.Conjuncts...)
97 }
98
99 default:
100 panic("unknown value")
101 }
102 if result == nil {
103
104 a := []ast.Expr{}
105 for _, c := range n.Conjuncts {
106 if x := e.expr(c.Env, c.Elem()); x != dummyTop {
107 a = append(a, x)
108 }
109 }
110 result = ast.NewBinExpr(token.AND, a...)
111 }
112
113 if len(s.Elts) > 0 {
114 filterUnusedLets(s)
115 }
116 if result != s && len(s.Elts) > 0 {
117
118
119 result = e.adt(nil, n)
120 }
121
122 return result
123 }
124
125 func (e *exporter) value(n adt.Value, a ...adt.Conjunct) (result ast.Expr) {
126 if e.cfg.TakeDefaults {
127 n = adt.Default(n)
128 }
129
130
131
132
133
134
135 switch x := n.(type) {
136 case *adt.Bottom:
137 result = e.bottom(x)
138
139 case *adt.Null:
140 result = e.null(x)
141
142 case *adt.Bool:
143 result = e.bool(x)
144
145 case *adt.Num:
146 result = e.num(x, a)
147
148 case *adt.String:
149 result = e.string(x, a)
150
151 case *adt.Bytes:
152 result = e.bytes(x, a)
153
154 case *adt.BasicType:
155 result = e.basicType(x)
156
157 case *adt.Top:
158 result = ast.NewIdent("_")
159
160 case *adt.BoundValue:
161 result = e.boundValue(x)
162
163 case *adt.Builtin:
164 result = e.builtin(x)
165
166 case *adt.BuiltinValidator:
167 result = e.builtinValidator(x)
168
169 case *adt.Vertex:
170 result = e.vertex(x)
171
172 case *adt.Conjunction:
173 switch len(x.Values) {
174 case 0:
175 return ast.NewIdent("_")
176 case 1:
177 if e.cfg.Simplify {
178 return e.expr(nil, x.Values[0])
179 }
180 return e.bareValue(x.Values[0])
181 }
182
183 a := []adt.Value{}
184 b := boundSimplifier{e: e}
185 for _, v := range x.Values {
186 if !e.cfg.Simplify || !b.add(v) {
187 a = append(a, v)
188 }
189 }
190
191 result = b.expr(e.ctx)
192 if result == nil {
193 a = x.Values
194 }
195
196 for _, x := range a {
197 result = wrapBin(result, e.bareValue(x), adt.AndOp)
198 }
199
200 case *adt.Disjunction:
201 a := []ast.Expr{}
202 for i, v := range x.Values {
203 var expr ast.Expr
204 if e.cfg.Simplify {
205 expr = e.bareValue(v)
206 } else {
207 expr = e.expr(nil, v)
208 }
209 if i < x.NumDefaults {
210 expr = &ast.UnaryExpr{Op: token.MUL, X: expr}
211 }
212 a = append(a, expr)
213 }
214 result = ast.NewBinExpr(token.OR, a...)
215
216 default:
217 panic(fmt.Sprintf("unsupported type %T", x))
218 }
219
220
221
222 return result
223 }
224
225 func (e *exporter) bottom(n *adt.Bottom) *ast.BottomLit {
226 err := &ast.BottomLit{}
227 if x := n.Err; x != nil {
228 msg := x.Error()
229 comment := &ast.Comment{Text: "// " + msg}
230 err.AddComment(&ast.CommentGroup{
231 Line: true,
232 Position: 2,
233 List: []*ast.Comment{comment},
234 })
235 }
236 return err
237 }
238
239 func (e *exporter) null(n *adt.Null) *ast.BasicLit {
240 return &ast.BasicLit{Kind: token.NULL, Value: "null"}
241 }
242
243 func (e *exporter) bool(n *adt.Bool) (b *ast.BasicLit) {
244 return ast.NewBool(n.B)
245 }
246
247 func extractBasic(a []adt.Conjunct) *ast.BasicLit {
248 for _, v := range a {
249 if b, ok := v.Source().(*ast.BasicLit); ok {
250 return &ast.BasicLit{Kind: b.Kind, Value: b.Value}
251 }
252 }
253 return nil
254 }
255
256 func (e *exporter) num(n *adt.Num, orig []adt.Conjunct) *ast.BasicLit {
257
258 if b := extractBasic(orig); b != nil {
259 return b
260 }
261 kind := token.FLOAT
262 if n.K&adt.IntKind != 0 {
263 kind = token.INT
264 }
265 s := n.X.String()
266 if kind == token.FLOAT && !strings.ContainsAny(s, "eE.") {
267 s += "."
268 }
269 return &ast.BasicLit{Kind: kind, Value: s}
270 }
271
272 func (e *exporter) string(n *adt.String, orig []adt.Conjunct) *ast.BasicLit {
273
274 if b := extractBasic(orig); b != nil {
275 return b
276 }
277 s := literal.String.WithOptionalTabIndent(len(e.stack)).Quote(n.Str)
278 return &ast.BasicLit{
279 Kind: token.STRING,
280 Value: s,
281 }
282 }
283
284 func (e *exporter) bytes(n *adt.Bytes, orig []adt.Conjunct) *ast.BasicLit {
285
286 if b := extractBasic(orig); b != nil {
287 return b
288 }
289 s := literal.Bytes.WithOptionalTabIndent(len(e.stack)).Quote(string(n.B))
290 return &ast.BasicLit{
291 Kind: token.STRING,
292 Value: s,
293 }
294 }
295
296 func (e *exporter) basicType(n *adt.BasicType) ast.Expr {
297
298 return ast.NewIdent(n.K.String())
299 }
300
301 func (e *exporter) boundValue(n *adt.BoundValue) ast.Expr {
302 return &ast.UnaryExpr{Op: n.Op.Token(), X: e.value(n.Value)}
303 }
304
305 func (e *exporter) builtin(x *adt.Builtin) ast.Expr {
306 if x.Package == 0 {
307 return ast.NewIdent(x.Name)
308 }
309 spec := ast.NewImport(nil, x.Package.StringValue(e.index))
310 info, _ := astutil.ParseImportSpec(spec)
311 ident := ast.NewIdent(info.Ident)
312 ident.Node = spec
313 return ast.NewSel(ident, x.Name)
314 }
315
316 func (e *exporter) builtinValidator(n *adt.BuiltinValidator) ast.Expr {
317 call := ast.NewCall(e.builtin(n.Builtin))
318 for _, a := range n.Args {
319 call.Args = append(call.Args, e.value(a))
320 }
321 return call
322 }
323
324 func (e *exporter) listComposite(v *adt.Vertex) ast.Expr {
325 l := &ast.ListLit{}
326 for _, a := range v.Arcs {
327 if !a.Label.IsInt() {
328 continue
329 }
330 elem := e.vertex(a)
331
332 if e.cfg.ShowDocs {
333 docs := ExtractDoc(a)
334 ast.SetComments(elem, docs)
335 }
336
337 l.Elts = append(l.Elts, elem)
338 }
339 m, ok := v.BaseValue.(*adt.ListMarker)
340 if !e.cfg.TakeDefaults && ok && m.IsOpen {
341 ellipsis := &ast.Ellipsis{}
342 typ := &adt.Vertex{
343 Parent: v,
344 Label: adt.AnyIndex,
345 }
346 v.MatchAndInsert(e.ctx, typ)
347 typ.Finalize(e.ctx)
348 if typ.Kind() != adt.TopKind {
349 ellipsis.Type = e.value(typ)
350 }
351
352 l.Elts = append(l.Elts, ellipsis)
353 }
354 return l
355 }
356
357 func (e exporter) showArcs(v *adt.Vertex) bool {
358 p := e.cfg
359 if !p.ShowHidden && !p.ShowDefinitions {
360 return false
361 }
362 for _, a := range v.Arcs {
363 switch {
364 case a.Label.IsDef() && p.ShowDefinitions:
365 return true
366 case a.Label.IsHidden() && p.ShowHidden:
367 return true
368 }
369 }
370 return false
371 }
372
373 func (e *exporter) structComposite(v *adt.Vertex, attrs []*ast.Attribute) ast.Expr {
374 s := e.top().scope
375
376 showRegular := false
377 switch x := v.BaseValue.(type) {
378 case *adt.StructMarker:
379 showRegular = true
380 case *adt.ListMarker:
381
382 defer e.addEmbed(e.listComposite(v))
383 case *adt.Bottom:
384 if !e.cfg.ShowErrors || !x.ChildError {
385
386
387 e.addEmbed(e.value(x))
388 return s
389 }
390
391
392 showRegular = true
393
394 for _, a := range v.Arcs {
395 if a.Label.IsInt() {
396 defer e.addEmbed(e.listComposite(v))
397 break
398 }
399 }
400
401 case adt.Value:
402 e.addEmbed(e.value(x))
403 }
404
405 for _, a := range attrs {
406 s.Elts = append(s.Elts, a)
407 }
408
409 p := e.cfg
410 for _, label := range VertexFeatures(e.ctx, v) {
411 show := false
412 switch label.Typ() {
413 case adt.StringLabel:
414 show = showRegular
415 case adt.IntLabel:
416 continue
417 case adt.DefinitionLabel:
418 show = p.ShowDefinitions
419 case adt.HiddenLabel, adt.HiddenDefinitionLabel:
420 show = p.ShowHidden && label.PkgID(e.ctx) == e.pkgID
421 }
422 if !show {
423 continue
424 }
425
426 f := &ast.Field{Label: e.stringLabel(label)}
427
428 e.addField(label, f, f.Value)
429
430 if label.IsDef() {
431 e.inDefinition++
432 }
433
434 arc := v.Lookup(label)
435 if arc == nil {
436 continue
437 }
438
439 if arc.ArcType == adt.ArcOptional && !p.ShowOptional {
440 continue
441 }
442
443
444
445
446 internal.SetConstraint(f, arc.ArcType.Token())
447
448 f.Value = e.vertex(arc)
449
450 if label.IsDef() {
451 e.inDefinition--
452 }
453
454 if p.ShowAttributes {
455 f.Attrs = ExtractFieldAttrs(arc)
456 }
457
458 if p.ShowDocs {
459 docs := ExtractDoc(arc)
460 ast.SetComments(f, docs)
461 }
462
463 s.Elts = append(s.Elts, f)
464 }
465
466 return s
467 }
468
View as plain text