1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package export
16
17 import (
18 "fmt"
19 "sort"
20
21 "cuelang.org/go/cue/ast"
22 "cuelang.org/go/cue/token"
23 "cuelang.org/go/internal"
24 "cuelang.org/go/internal/core/adt"
25 )
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 var empty *adt.Vertex
52
53 func init() {
54
55 empty = &adt.Vertex{}
56 empty.ForceDone()
57 }
58
59
60 func (e *exporter) innerExpr(env *adt.Environment, v adt.Elem) (result ast.Expr) {
61 e.inExpression++
62 r := e.expr(env, v)
63 e.inExpression--
64 return r
65 }
66
67
68
69
70 func (e *exporter) expr(env *adt.Environment, v adt.Elem) (result ast.Expr) {
71 switch x := v.(type) {
72 case nil:
73 return nil
74
75 case *adt.Vertex:
76 if len(x.Conjuncts) == 0 || x.IsData() {
77
78 return e.value(x)
79 }
80
81 a := []conjunct{}
82 for _, c := range x.Conjuncts {
83 if c, ok := c.Elem().(*adt.Comprehension); ok && !c.DidResolve() {
84 continue
85 }
86 a = append(a, conjunct{c, 0})
87 }
88
89 return e.mergeValues(adt.InvalidLabel, x, a, x.Conjuncts...)
90
91 case *adt.StructLit:
92 c := adt.MakeRootConjunct(env, x)
93 return e.mergeValues(adt.InvalidLabel, nil, []conjunct{{c: c, up: 0}}, c)
94
95 case adt.Value:
96 return e.value(x)
97
98 default:
99 return e.adt(env, v)
100 }
101 }
102
103
104
105
106
107
108 func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct, orig ...adt.Conjunct) (expr ast.Expr) {
109
110 e := conjuncts{
111 exporter: x,
112 values: &adt.Vertex{},
113 fields: map[adt.Feature]field{},
114 attrs: []*ast.Attribute{},
115 }
116
117 s, saved := e.pushFrame(src, orig)
118 defer e.popFrame(saved)
119
120
121 var valueAlias *ast.Alias
122 for _, c := range a {
123 if f, ok := c.c.Field().Source().(*ast.Field); ok {
124 if a, ok := f.Value.(*ast.Alias); ok {
125 if valueAlias == nil {
126 if e.valueAlias == nil {
127 e.valueAlias = map[*ast.Alias]*ast.Alias{}
128 }
129 name := a.Ident.Name
130 name = e.uniqueAlias(name)
131 valueAlias = &ast.Alias{Ident: ast.NewIdent(name)}
132 }
133 e.valueAlias[a] = valueAlias
134 }
135 }
136 x.markLets(c.c.Expr().Source(), s)
137 }
138
139 defer filterUnusedLets(s)
140
141 defer func() {
142 if valueAlias != nil {
143 valueAlias.Expr = expr
144 expr = valueAlias
145 }
146 }()
147
148 hasAlias := len(s.Elts) > 0
149
150 for _, c := range a {
151 e.top().upCount = c.up
152 x := c.c.Elem()
153 e.addExpr(c.c.Env, src, x, false)
154 }
155
156 if src != nil {
157 for _, a := range src.Arcs {
158 if x, ok := e.fields[a.Label]; ok {
159 x.arc = a
160 x.arcType = a.ArcType
161 e.fields[a.Label] = x
162 }
163 }
164 }
165
166 for _, a := range e.attrs {
167 s.Elts = append(s.Elts, a)
168 }
169
170
171 if a := e.values.Conjuncts; len(a) > 0 {
172 e.values.Finalize(e.ctx)
173 e.embed = append(e.embed, e.value(e.values, a...))
174 }
175
176
177
178 fields := []adt.Feature{}
179 for f := range e.fields {
180 fields = append(fields, f)
181 }
182
183
184
185
186 sort.Slice(fields, func(i, j int) bool {
187 return fields[i] > fields[j]
188 })
189
190 if adt.DebugSort == 0 {
191 m := sortArcs(extractFeatures(e.structs))
192 sort.SliceStable(fields, func(i, j int) bool {
193 if m[fields[j]] == 0 {
194 return m[fields[i]] != 0
195 }
196 return m[fields[i]] > m[fields[j]]
197 })
198 } else {
199 adt.DebugSortFields(e.ctx, fields)
200 }
201
202 if len(e.fields) == 0 && !e.hasEllipsis {
203 switch len(e.embed) + len(e.conjuncts) {
204 case 0:
205 if len(e.attrs) > 0 {
206 break
207 }
208 if len(e.structs) > 0 || e.isData {
209 return e.wrapCloseIfNecessary(s, src)
210 }
211 return ast.NewIdent("_")
212 case 1:
213 var x ast.Expr
214 if len(e.conjuncts) == 1 {
215 x = e.conjuncts[0]
216 } else {
217 x = e.embed[0]
218 }
219 if len(e.attrs) == 0 && !hasAlias {
220 return x
221 }
222 if st, ok := x.(*ast.StructLit); ok {
223 s.Elts = append(s.Elts, st.Elts...)
224 return e.wrapCloseIfNecessary(s, src)
225 }
226 }
227 }
228
229 for _, x := range e.embed {
230 s.Elts = append(s.Elts, &ast.EmbedDecl{Expr: x})
231 }
232
233 for _, f := range fields {
234 if f.IsLet() {
235 continue
236 }
237 field := e.getField(f)
238 c := field.conjuncts
239
240 label := e.stringLabel(f)
241
242 if f.IsDef() {
243 x.inDefinition++
244 }
245
246 a := []adt.Conjunct{}
247 for _, cc := range c {
248 a = append(a, cc.c)
249 }
250
251 d := &ast.Field{Label: label}
252
253 top := e.frame(0)
254 if fr, ok := top.fields[f]; ok && fr.alias != "" {
255 setFieldAlias(d, fr.alias)
256 fr.node = d
257 top.fields[f] = fr
258 }
259
260 d.Value = e.mergeValues(f, field.arc, c, a...)
261
262 e.linkField(field.arc, d)
263
264 if f.IsDef() {
265 x.inDefinition--
266 }
267
268 internal.SetConstraint(d, field.arcType.Token())
269 if x.cfg.ShowDocs {
270 docs := extractDocs(src, a)
271 ast.SetComments(d, docs)
272 }
273 if x.cfg.ShowAttributes {
274 for _, c := range a {
275 d.Attrs = extractFieldAttrs(d.Attrs, c.Field())
276 }
277 }
278 s.Elts = append(s.Elts, d)
279 }
280 if e.hasEllipsis {
281 s.Elts = append(s.Elts, &ast.Ellipsis{})
282 }
283
284 ws := e.wrapCloseIfNecessary(s, src)
285 switch {
286 case len(e.conjuncts) == 0:
287 return ws
288
289 case len(e.structs) > 0, len(s.Elts) > 0:
290 e.conjuncts = append(e.conjuncts, ws)
291 }
292
293 return ast.NewBinExpr(token.AND, e.conjuncts...)
294 }
295
296 func (e *conjuncts) wrapCloseIfNecessary(s *ast.StructLit, v *adt.Vertex) ast.Expr {
297 if !e.hasEllipsis && v != nil {
298 if st, ok := v.BaseValue.(*adt.StructMarker); ok && st.NeedClose {
299 return ast.NewCall(ast.NewIdent("close"), s)
300 }
301 }
302 return s
303 }
304
305
306 type conjuncts struct {
307 *exporter
308
309 values *adt.Vertex
310 embed []ast.Expr
311 conjuncts []ast.Expr
312 structs []*adt.StructInfo
313 fields map[adt.Feature]field
314 attrs []*ast.Attribute
315 hasEllipsis bool
316
317
318
319 isData bool
320 }
321
322 func (c *conjuncts) getField(label adt.Feature) field {
323 f, ok := c.fields[label]
324 if !ok {
325 f.arcType = adt.ArcNotPresent
326 }
327 return f
328 }
329
330 func (c *conjuncts) addValueConjunct(src *adt.Vertex, env *adt.Environment, x adt.Elem) {
331 switch b, ok := x.(adt.BaseValue); {
332 case ok && src != nil && isTop(b) && !isTop(src.BaseValue):
333
334 default:
335 c.values.AddConjunct(adt.MakeRootConjunct(env, x))
336 }
337 }
338
339 func (c *conjuncts) addConjunct(f adt.Feature, t adt.ArcType, env *adt.Environment, n adt.Node) {
340 x := c.getField(f)
341 if t < x.arcType {
342 x.arcType = t
343 }
344
345 v := adt.MakeRootConjunct(env, n)
346 x.conjuncts = append(x.conjuncts, conjunct{
347 c: v,
348 up: c.top().upCount,
349 })
350
351 c.fields[f] = x
352 }
353
354 type field struct {
355 arcType adt.ArcType
356 arc *adt.Vertex
357 conjuncts []conjunct
358 }
359
360 type conjunct struct {
361 c adt.Conjunct
362 up int32
363 }
364
365 func (e *conjuncts) addExpr(env *adt.Environment, src *adt.Vertex, x adt.Elem, isEmbed bool) {
366 switch x := x.(type) {
367 case *adt.StructLit:
368 e.top().upCount++
369
370 if e.cfg.ShowAttributes {
371 e.attrs = extractDeclAttrs(e.attrs, x.Src)
372 }
373
374
375 if isComplexStruct(x) {
376 _, saved := e.pushFrame(src, nil)
377 e.embed = append(e.embed, e.adt(env, x))
378 e.top().upCount--
379 e.popFrame(saved)
380 return
381 }
382
383 e.structs = append(e.structs, &adt.StructInfo{StructLit: x, Env: env})
384
385 env = &adt.Environment{Up: env, Vertex: e.node()}
386
387 for _, d := range x.Decls {
388 var label adt.Feature
389 t := adt.ArcNotPresent
390 switch f := d.(type) {
391 case *adt.Field:
392 label = f.Label
393 t = f.ArcType
394
395 case *adt.LetField:
396 continue
397 case *adt.Ellipsis:
398 e.hasEllipsis = true
399 continue
400 case adt.Expr:
401 e.addExpr(env, nil, f, true)
402 continue
403
404
405 default:
406 panic(fmt.Sprintf("Unexpected type %T", d))
407 }
408 e.addConjunct(label, t, env, d)
409 }
410 e.top().upCount--
411
412 case adt.Value:
413 switch v := x.(type) {
414 case nil:
415 default:
416 e.addValueConjunct(src, env, x)
417
418 case *adt.Vertex:
419 if b, ok := v.BaseValue.(*adt.Bottom); ok {
420 if !b.IsIncomplete() || e.cfg.Final {
421 e.addExpr(env, v, b, false)
422 return
423 }
424 }
425
426 switch {
427 default:
428 for _, c := range v.Conjuncts {
429 e.addExpr(c.Env, v, c.Elem(), false)
430 }
431
432 case v.IsData():
433 e.structs = append(e.structs, v.Structs...)
434 e.isData = true
435
436 if y, ok := v.BaseValue.(adt.Value); ok {
437 e.addValueConjunct(src, env, y)
438 }
439
440 for _, a := range v.Arcs {
441 a.Finalize(e.ctx)
442
443 if !a.IsDefined(e.ctx) {
444 continue
445 }
446
447 e.addConjunct(a.Label, a.ArcType, env, a)
448 }
449 }
450 }
451
452 case *adt.BinaryExpr:
453 switch {
454 case x.Op == adt.AndOp && !isEmbed:
455 e.addExpr(env, src, x.X, false)
456 e.addExpr(env, src, x.Y, false)
457 case isSelfContained(x):
458 e.addValueConjunct(src, env, x)
459 default:
460 if isEmbed {
461 e.embed = append(e.embed, e.expr(env, x))
462 } else {
463 e.conjuncts = append(e.conjuncts, e.expr(env, x))
464 }
465 }
466
467 default:
468 switch {
469 case isSelfContained(x):
470 e.addValueConjunct(src, env, x)
471 case isEmbed:
472 e.embed = append(e.embed, e.expr(env, x))
473 default:
474 if x := e.expr(env, x); x != dummyTop {
475 e.conjuncts = append(e.conjuncts, x)
476 }
477 }
478 }
479 }
480
481 func isTop(x adt.BaseValue) bool {
482 switch v := x.(type) {
483 case *adt.Top:
484 return true
485 case *adt.BasicType:
486 return v.K == adt.TopKind
487 default:
488 return false
489 }
490 }
491
492 func isComplexStruct(s *adt.StructLit) bool {
493 for _, d := range s.Decls {
494 switch x := d.(type) {
495 case *adt.Field:
496
497
498 if x.Src != nil {
499 if _, ok := x.Src.Label.(*ast.Alias); ok {
500 return ok
501 }
502 }
503
504 case *adt.LetField:
505
506 case adt.Expr:
507
508 case *adt.Ellipsis:
509 if x.Value != nil {
510 return true
511 }
512
513 default:
514 return true
515 }
516 }
517 return false
518 }
519
520 func isSelfContained(expr adt.Elem) bool {
521 switch x := expr.(type) {
522 case *adt.BinaryExpr:
523 return isSelfContained(x.X) && isSelfContained(x.Y)
524 case *adt.UnaryExpr:
525 return isSelfContained(x.X)
526 case *adt.BoundExpr:
527 return isSelfContained(x.Expr)
528 case adt.Value:
529 return true
530 }
531 return false
532 }
533
View as plain text