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