cuelang.org/go@v0.13.0/internal/core/export/expr.go (about) 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 export 16 17 import ( 18 "cmp" 19 "fmt" 20 "slices" 21 22 "cuelang.org/go/cue/ast" 23 "cuelang.org/go/cue/token" 24 "cuelang.org/go/internal" 25 "cuelang.org/go/internal/core/adt" 26 ) 27 28 // Modes: 29 // raw: as is 30 // def: merge structs, print reset as is. 31 // 32 // Possible simplifications in def mode: 33 // - merge contents of multiple _literal_ structs. 34 // - this is not possible if some of the elements are bulk optional 35 // (or is it?). 36 // - still do not ever resolve references. 37 // - to do this, fields must be pre-linked to their destinations. 38 // - use astutil.Sanitize to resolve shadowing and imports. 39 // 40 // 41 // Categories of printing: 42 // - concrete 43 // - optionals 44 // - references 45 // - constraints 46 // 47 // Mixed mode is also not supported in the old implementation (at least not 48 // correctly). It requires references to resolve properly, backtracking to 49 // a common root and prefixing that to the reference. This is now possible 50 // with the Environment construct and could be done later. 51 52 var empty *adt.Vertex 53 54 func init() { 55 // TODO: Consider setting a non-nil BaseValue. 56 empty = &adt.Vertex{} 57 empty.ForceDone() 58 } 59 60 // innerExpr is like expr, but prohibits inlining in certain cases. 61 func (e *exporter) innerExpr(env *adt.Environment, v adt.Elem) (result ast.Expr) { 62 e.inExpression++ 63 r := e.expr(env, v) 64 e.inExpression-- 65 return r 66 } 67 68 // expr converts an ADT expression to an AST expression. 69 // The env is used for resolution and does not need to be given if v is known 70 // to not contain any references. 71 func (e *exporter) expr(env *adt.Environment, v adt.Elem) (result ast.Expr) { 72 switch x := v.(type) { 73 case nil: 74 return nil 75 76 case *adt.Vertex: 77 if x.IsData() { 78 // Treat as literal value. 79 return e.value(x) 80 } // Should this be the arcs label? 81 82 a := []conjunct{} 83 x.VisitLeafConjuncts(func(c adt.Conjunct) bool { 84 if c, ok := c.Elem().(*adt.Comprehension); ok && !c.DidResolve() { 85 return true 86 } 87 a = append(a, conjunct{c, 0}) 88 return true 89 }) 90 91 return e.mergeValues(adt.InvalidLabel, x, a, x.Conjuncts...) 92 93 case *adt.StructLit: 94 c := adt.MakeRootConjunct(env, x) 95 return e.mergeValues(adt.InvalidLabel, nil, []conjunct{{c: c, up: 0}}, c) 96 97 case adt.Value: 98 return e.value(x) // Use conjuncts. 99 100 default: 101 return e.adt(env, v) 102 } 103 } 104 105 // Piece out values: 106 107 // For a struct, piece out conjuncts that are already values. Those can be 108 // unified. All other conjuncts are added verbatim. 109 110 func (x *exporter) mergeValues(label adt.Feature, src *adt.Vertex, a []conjunct, orig ...adt.Conjunct) (expr ast.Expr) { 111 112 e := conjuncts{ 113 exporter: x, 114 values: &adt.Vertex{}, 115 fields: map[adt.Feature]field{}, 116 attrs: []*ast.Attribute{}, 117 } 118 119 s, saved := e.pushFrame(src, orig) 120 defer e.popFrame(saved) 121 122 // Handle value aliases and lets 123 var valueAlias *ast.Alias 124 for _, c := range a { 125 if f, ok := c.c.Field().Source().(*ast.Field); ok { 126 if a, ok := f.Value.(*ast.Alias); ok { 127 if valueAlias == nil { 128 if e.valueAlias == nil { 129 e.valueAlias = map[*ast.Alias]*ast.Alias{} 130 } 131 name := a.Ident.Name 132 name = e.uniqueAlias(name) 133 valueAlias = &ast.Alias{Ident: ast.NewIdent(name)} 134 } 135 e.valueAlias[a] = valueAlias 136 } 137 } 138 x.markLets(c.c.Expr().Source(), s) 139 } 140 141 defer filterUnusedLets(s) 142 143 defer func() { 144 if valueAlias != nil { 145 valueAlias.Expr = expr 146 expr = valueAlias 147 } 148 }() 149 150 hasAlias := len(s.Elts) > 0 151 152 for _, c := range a { 153 e.top().upCount = c.up 154 x := c.c.Elem() 155 e.addExpr(c.c.Env, src, x, false) 156 } 157 158 if src != nil { 159 for _, a := range src.Arcs { 160 if x, ok := e.fields[a.Label]; ok { 161 x.arc = a 162 x.arcType = a.ArcType 163 e.fields[a.Label] = x 164 } 165 } 166 } 167 168 for _, a := range e.attrs { 169 s.Elts = append(s.Elts, a) 170 } 171 172 // Unify values only for one level. 173 if e.values.HasConjuncts() { 174 e.values.Finalize(e.ctx) 175 e.embed = append(e.embed, e.value(e.values, e.values.Conjuncts...)) 176 } 177 178 // Collect and order set of fields. 179 180 fields := []adt.Feature{} 181 for f := range e.fields { 182 fields = append(fields, f) 183 } 184 185 // Sort fields in case features lists are missing to ensure 186 // predictability. Also sort in reverse order, so that bugs 187 // are more likely exposed. 188 slices.SortFunc(fields, func(f1, f2 adt.Feature) int { 189 return -cmp.Compare(f1, f2) 190 }) 191 192 m := sortArcs(extractFeatures(e.structs)) 193 slices.SortStableFunc(fields, func(f1, f2 adt.Feature) int { 194 if m[f2] == 0 { 195 if m[f1] == 0 { 196 return +1 197 } 198 return -1 199 } 200 return -cmp.Compare(m[f1], m[f2]) 201 }) 202 203 if len(e.fields) == 0 && !e.hasEllipsis { 204 switch len(e.embed) + len(e.conjuncts) { 205 case 0: 206 if len(e.attrs) > 0 { 207 break 208 } 209 if len(e.structs) > 0 || e.isData { 210 return e.wrapCloseIfNecessary(s, src) 211 } 212 return ast.NewIdent("_") 213 case 1: 214 var x ast.Expr 215 if len(e.conjuncts) == 1 { 216 x = e.conjuncts[0] 217 } else { 218 x = e.embed[0] 219 } 220 if len(e.attrs) == 0 && !hasAlias { 221 return x 222 } 223 if st, ok := x.(*ast.StructLit); ok { 224 s.Elts = append(s.Elts, st.Elts...) 225 return e.wrapCloseIfNecessary(s, src) 226 } 227 } 228 } 229 230 for _, x := range e.embed { 231 s.Elts = append(s.Elts, &ast.EmbedDecl{Expr: x}) 232 } 233 234 for _, f := range fields { 235 if f.IsLet() { 236 continue 237 } 238 field := e.getField(f) 239 c := field.conjuncts 240 241 label := e.stringLabel(f) 242 243 if f.IsDef() { 244 x.inDefinition++ 245 } 246 247 a := []adt.Conjunct{} 248 for _, cc := range c { 249 a = append(a, cc.c) 250 } 251 252 d := &ast.Field{Label: label} 253 254 top := e.frame(0) 255 if fr, ok := top.fields[f]; ok && fr.alias != "" { 256 setFieldAlias(d, fr.alias) 257 fr.node = d 258 top.fields[f] = fr 259 } 260 261 d.Value = e.mergeValues(f, field.arc, c, a...) 262 263 e.linkField(field.arc, d) 264 265 if f.IsDef() { 266 x.inDefinition-- 267 } 268 269 internal.SetConstraint(d, field.arcType.Token()) 270 if x.cfg.ShowDocs { 271 v := &adt.Vertex{Conjuncts: a} 272 docs := extractDocs(v) 273 ast.SetComments(d, docs) 274 } 275 if x.cfg.ShowAttributes { 276 for _, c := range a { 277 d.Attrs = extractFieldAttrs(d.Attrs, c.Field()) 278 } 279 } 280 s.Elts = append(s.Elts, d) 281 } 282 if e.hasEllipsis { 283 s.Elts = append(s.Elts, &ast.Ellipsis{}) 284 } 285 286 ws := e.wrapCloseIfNecessary(s, src) 287 switch { 288 case len(e.conjuncts) == 0: 289 return ws 290 291 case len(e.structs) > 0, len(s.Elts) > 0: 292 e.conjuncts = append(e.conjuncts, ws) 293 } 294 295 return ast.NewBinExpr(token.AND, e.conjuncts...) 296 } 297 298 func (e *conjuncts) wrapCloseIfNecessary(s *ast.StructLit, v *adt.Vertex) ast.Expr { 299 if !e.hasEllipsis && v != nil { 300 if v.ClosedNonRecursive { 301 // Eval V3 logic 302 return ast.NewCall(ast.NewIdent("close"), s) 303 } 304 if st, ok := v.BaseValue.(*adt.StructMarker); ok && st.NeedClose { 305 // Eval V2 logic 306 return ast.NewCall(ast.NewIdent("close"), s) 307 } 308 } 309 return s 310 } 311 312 // Conjuncts if for collecting values of a single vertex. 313 type conjuncts struct { 314 *exporter 315 // Values is used to collect non-struct values. 316 values *adt.Vertex 317 embed []ast.Expr 318 conjuncts []ast.Expr 319 structs []*adt.StructInfo 320 fields map[adt.Feature]field 321 attrs []*ast.Attribute 322 hasEllipsis bool 323 324 // A value is a struct if it has a non-zero structs slice or if isData is 325 // set to true. Data vertices may not have conjuncts associated with them. 326 isData bool 327 } 328 329 func (c *conjuncts) getField(label adt.Feature) field { 330 f, ok := c.fields[label] 331 if !ok { 332 f.arcType = adt.ArcNotPresent 333 } 334 return f 335 } 336 337 func (c *conjuncts) addValueConjunct(src *adt.Vertex, env *adt.Environment, x adt.Elem) { 338 switch b, ok := x.(adt.BaseValue); { 339 case ok && src != nil && isTop(b) && !isTop(src.BaseValue): 340 // drop top 341 default: 342 c.values.AddConjunct(adt.MakeRootConjunct(env, x)) 343 } 344 } 345 346 func (c *conjuncts) addConjunct(f adt.Feature, t adt.ArcType, env *adt.Environment, n adt.Node) { 347 x := c.getField(f) 348 if t < x.arcType { 349 x.arcType = t 350 } 351 352 v := adt.MakeRootConjunct(env, n) 353 x.conjuncts = append(x.conjuncts, conjunct{ 354 c: v, 355 up: c.top().upCount, 356 }) 357 // x.upCounts = append(x.upCounts, c.top().upCount) 358 c.fields[f] = x 359 } 360 361 type field struct { 362 arcType adt.ArcType 363 arc *adt.Vertex 364 conjuncts []conjunct 365 } 366 367 type conjunct struct { 368 c adt.Conjunct 369 up int32 370 } 371 372 func (e *conjuncts) addExpr(env *adt.Environment, src *adt.Vertex, x adt.Elem, isEmbed bool) { 373 switch x := x.(type) { 374 case *adt.StructLit: 375 e.top().upCount++ 376 377 if e.cfg.ShowAttributes { 378 e.attrs = extractDeclAttrs(e.attrs, x.Src) 379 } 380 381 // Only add if it only has no bulk fields or ellipsis. 382 if isComplexStruct(x) { 383 _, saved := e.pushFrame(src, nil) 384 e.embed = append(e.embed, e.adt(env, x)) 385 e.top().upCount-- // not necessary, but for proper form 386 e.popFrame(saved) 387 return 388 } 389 // Used for sorting. 390 e.structs = append(e.structs, &adt.StructInfo{StructLit: x, Env: env}) 391 392 env = &adt.Environment{Up: env, Vertex: e.node()} 393 394 for _, d := range x.Decls { 395 var label adt.Feature 396 t := adt.ArcNotPresent 397 switch f := d.(type) { 398 case *adt.Field: 399 label = f.Label 400 t = f.ArcType 401 // TODO: mark optional here, if needed. 402 case *adt.LetField: 403 continue 404 case *adt.Ellipsis: 405 e.hasEllipsis = true 406 continue 407 case adt.Expr: 408 e.addExpr(env, nil, f, true) 409 continue 410 411 // TODO: also handle dynamic fields 412 default: 413 panic(fmt.Sprintf("Unexpected type %T", d)) 414 } 415 e.addConjunct(label, t, env, d) 416 } 417 e.top().upCount-- 418 419 case adt.Value: // other values. 420 switch v := x.(type) { 421 case nil: 422 default: 423 e.addValueConjunct(src, env, x) 424 425 case *adt.Vertex: 426 if b := v.Bottom(); b != nil { 427 if !b.IsIncomplete() || e.cfg.Final { 428 e.addExpr(env, v, b, false) 429 return 430 } 431 } 432 433 switch { 434 default: 435 v.VisitLeafConjuncts(func(c adt.Conjunct) bool { 436 e.addExpr(c.Env, v, c.Elem(), false) 437 return true 438 }) 439 440 case v.IsData(): 441 e.structs = append(e.structs, v.Structs...) 442 e.isData = true 443 444 if y, ok := v.BaseValue.(adt.Value); ok { 445 e.addValueConjunct(src, env, y) 446 } 447 448 for _, a := range v.Arcs { 449 a.Finalize(e.ctx) // TODO: should we do this? 450 451 if !a.IsDefined(e.ctx) { 452 continue 453 } 454 455 e.addConjunct(a.Label, a.ArcType, env, a) 456 } 457 } 458 } 459 460 case *adt.BinaryExpr: 461 switch { 462 case x.Op == adt.AndOp && !isEmbed: 463 e.addExpr(env, src, x.X, false) 464 e.addExpr(env, src, x.Y, false) 465 case isSelfContained(x): 466 e.addValueConjunct(src, env, x) 467 default: 468 if isEmbed { 469 e.embed = append(e.embed, e.expr(env, x)) 470 } else { 471 e.conjuncts = append(e.conjuncts, e.expr(env, x)) 472 } 473 } 474 475 default: 476 switch { 477 case isSelfContained(x): 478 e.addValueConjunct(src, env, x) 479 case isEmbed: 480 e.embed = append(e.embed, e.expr(env, x)) 481 default: 482 if x := e.expr(env, x); x != dummyTop { 483 e.conjuncts = append(e.conjuncts, x) 484 } 485 } 486 } 487 } 488 489 func isTop(x adt.BaseValue) bool { 490 switch v := x.(type) { 491 case *adt.Top: 492 return true 493 case *adt.BasicType: 494 return v.K == adt.TopKind 495 default: 496 return false 497 } 498 } 499 500 func isComplexStruct(s *adt.StructLit) bool { 501 for _, d := range s.Decls { 502 switch x := d.(type) { 503 case *adt.Field: 504 // TODO: remove this and also handle field annotation in expr(). 505 // This allows structs to be merged. Ditto below. 506 if x.Src != nil { 507 if _, ok := x.Src.Label.(*ast.Alias); ok { 508 return ok 509 } 510 } 511 512 case *adt.LetField: 513 514 case adt.Expr: 515 516 case *adt.Ellipsis: 517 if x.Value != nil { 518 return true 519 } 520 521 default: 522 return true 523 } 524 } 525 return false 526 } 527 528 func isSelfContained(expr adt.Elem) bool { 529 switch x := expr.(type) { 530 case *adt.BinaryExpr: 531 return isSelfContained(x.X) && isSelfContained(x.Y) 532 case *adt.UnaryExpr: 533 return isSelfContained(x.X) 534 case *adt.BoundExpr: 535 return isSelfContained(x.Expr) 536 case adt.Value: 537 return true 538 } 539 return false 540 }