cuelang.org/go@v0.10.1/internal/core/compile/compile.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 compile 16 17 import ( 18 "strings" 19 20 "cuelang.org/go/cue/ast" 21 "cuelang.org/go/cue/errors" 22 "cuelang.org/go/cue/literal" 23 "cuelang.org/go/cue/token" 24 "cuelang.org/go/internal" 25 "cuelang.org/go/internal/astinternal" 26 "cuelang.org/go/internal/core/adt" 27 ) 28 29 // A Scope represents a nested scope of Vertices. 30 type Scope interface { 31 Parent() Scope 32 Vertex() *adt.Vertex 33 } 34 35 // Config configures a compilation. 36 type Config struct { 37 // Scope specifies a node in which to look up unresolved references. This 38 // is useful for evaluating expressions within an already evaluated 39 // configuration. 40 Scope Scope 41 42 // Imports allows unresolved identifiers to resolve to imports. 43 // 44 // Under normal circumstances, identifiers bind to import specifications, 45 // which get resolved to an ImportReference. Use this option to 46 // automatically resolve identifiers to imports. 47 Imports func(x *ast.Ident) (pkgPath string) 48 49 // pkgPath is used to qualify the scope of hidden fields. The default 50 // scope is "_". 51 pkgPath string 52 } 53 54 // Files compiles the given files as a single instance. It disregards 55 // the package names and it is the responsibility of the user to verify that 56 // the packages names are consistent. The pkgID must be a unique identifier 57 // for a package in a module, for instance as obtained from build.Instance.ID. 58 // 59 // Files may return a completed parse even if it has errors. 60 func Files(cfg *Config, r adt.Runtime, pkgID string, files ...*ast.File) (*adt.Vertex, errors.Error) { 61 c := newCompiler(cfg, pkgID, r) 62 63 v := c.compileFiles(files) 64 65 if c.errs != nil { 66 return v, c.errs 67 } 68 return v, nil 69 } 70 71 // Expr compiles the given expression into a conjunct. The pkgID must be a 72 // unique identifier for a package in a module, for instance as obtained from 73 // build.Instance.ID. 74 func Expr(cfg *Config, r adt.Runtime, pkgPath string, x ast.Expr) (adt.Conjunct, errors.Error) { 75 c := newCompiler(cfg, pkgPath, r) 76 77 v := c.compileExpr(x) 78 79 if c.errs != nil { 80 return v, c.errs 81 } 82 return v, nil 83 } 84 85 func newCompiler(cfg *Config, pkgPath string, r adt.Runtime) *compiler { 86 c := &compiler{ 87 index: r, 88 } 89 if cfg != nil { 90 c.Config = *cfg 91 } 92 if pkgPath == "" { 93 pkgPath = "_" 94 } 95 c.Config.pkgPath = pkgPath 96 return c 97 } 98 99 type compiler struct { 100 Config 101 upCountOffset int32 // 1 for files; 0 for expressions 102 103 index adt.StringIndexer 104 105 stack []frame 106 inSelector int 107 108 // refersToForVariable tracks whether an expression refers to a key or 109 // value produced by a for comprehension embedded within a struct. 110 // An Environment associated with such a comprehension value is collapsed 111 // onto the destination. 112 // Tracking this is necessary for let fields, which should not be unified 113 // into the destination when referring to such values. 114 // See https://cuelang.org/issue/2218. 115 // TODO(perf): use this to compute when a field can be structure shared 116 // across different iterations of the same field. 117 refersToForVariable bool 118 119 fileScope map[adt.Feature]bool 120 121 num literal.NumInfo 122 123 errs errors.Error 124 } 125 126 func (c *compiler) reset() { 127 c.fileScope = nil 128 c.stack = c.stack[:0] 129 c.errs = nil 130 } 131 132 func (c *compiler) errf(n ast.Node, format string, args ...interface{}) *adt.Bottom { 133 err := &compilerError{ 134 n: n, 135 path: c.path(), 136 Message: errors.NewMessagef(format, args...), 137 } 138 c.errs = errors.Append(c.errs, err) 139 return &adt.Bottom{Err: err} 140 } 141 142 func (c *compiler) path() []string { 143 a := []string{} 144 for _, f := range c.stack { 145 if f.label != nil { 146 a = append(a, f.label.labelString()) 147 } 148 } 149 return a 150 } 151 152 type frame struct { 153 label labeler // path name leading to this frame. 154 scope ast.Node // *ast.File or *ast.Struct 155 field ast.Decl 156 // scope map[ast.Node]bool 157 upCount int32 // 1 for field, 0 for embedding. 158 159 // isComprehensionVar indicates that this scope refers to a for clause 160 // that is part of a comprehension embedded in a struct. 161 isComprehensionVar bool 162 163 aliases map[string]aliasEntry 164 } 165 166 type aliasEntry struct { 167 label labeler 168 srcExpr ast.Expr 169 expr adt.Expr 170 source ast.Node 171 feature adt.Feature // For let declarations 172 used bool 173 } 174 175 func (c *compiler) insertAlias(id *ast.Ident, a aliasEntry) *adt.Bottom { 176 k := len(c.stack) - 1 177 m := c.stack[k].aliases 178 if m == nil { 179 m = map[string]aliasEntry{} 180 c.stack[k].aliases = m 181 } 182 183 if id == nil || !ast.IsValidIdent(id.Name) { 184 return c.errf(a.source, "invalid identifier name") 185 } 186 187 if e, ok := m[id.Name]; ok { 188 return c.errf(a.source, 189 "alias %q already declared; previous declaration at %s", 190 id.Name, e.source.Pos()) 191 } 192 if id.Name == "_" { 193 return c.errf(id, "cannot use _ as alias or let clause") 194 } 195 196 m[id.Name] = a 197 return nil 198 } 199 200 func (c *compiler) updateAlias(id *ast.Ident, expr adt.Expr) { 201 k := len(c.stack) - 1 202 m := c.stack[k].aliases 203 204 x := m[id.Name] 205 x.expr = expr 206 x.label = nil 207 x.srcExpr = nil 208 m[id.Name] = x 209 } 210 211 // lookupAlias looks up an alias with the given name at the k'th stack position. 212 func (c *compiler) lookupAlias(k int, id *ast.Ident) aliasEntry { 213 m := c.stack[k].aliases 214 name := id.Name 215 entry, ok := m[name] 216 217 if !ok { 218 err := c.errf(id, "could not find LetClause associated with identifier %q", name) 219 return aliasEntry{expr: err} 220 } 221 222 switch { 223 case entry.label != nil: 224 // TODO: allow cyclic references in let expressions once these can be 225 // encoded as a ValueReference. 226 if entry.srcExpr == nil { 227 entry.expr = c.errf(id, "cyclic references in let clause or alias") 228 break 229 } 230 231 src := entry.srcExpr 232 entry.srcExpr = nil // mark to allow detecting cycles 233 m[name] = entry 234 235 entry.expr = c.labeledExprAt(k, nil, entry.label, src) 236 entry.label = nil 237 } 238 239 entry.used = true 240 m[name] = entry 241 return entry 242 } 243 244 func (c *compiler) pushScope(n labeler, upCount int32, id ast.Node) *frame { 245 c.stack = append(c.stack, frame{ 246 label: n, 247 scope: id, 248 upCount: upCount, 249 }) 250 return &c.stack[len(c.stack)-1] 251 } 252 253 func (c *compiler) popScope() { 254 k := len(c.stack) - 1 255 f := c.stack[k] 256 for k, v := range f.aliases { 257 if !v.used { 258 c.errf(v.source, "unreferenced alias or let clause %s", k) 259 } 260 } 261 c.stack = c.stack[:k] 262 } 263 264 func (c *compiler) compileFiles(a []*ast.File) *adt.Vertex { // Or value? 265 c.fileScope = map[adt.Feature]bool{} 266 c.upCountOffset = 1 267 268 // TODO(resolve): this is also done in the runtime package, do we need both? 269 270 // Populate file scope to handle unresolved references. 271 // Excluded from cross-file resolution are: 272 // - import specs 273 // - aliases 274 // - let declarations 275 // - anything in an anonymous file 276 // 277 for _, f := range a { 278 if p := internal.GetPackageInfo(f); p.IsAnonymous() { 279 continue 280 } 281 for _, d := range f.Decls { 282 if f, ok := d.(*ast.Field); ok { 283 if id, ok := f.Label.(*ast.Ident); ok { 284 c.fileScope[c.label(id)] = true 285 } 286 } 287 } 288 } 289 290 // TODO: set doc. 291 res := &adt.Vertex{} 292 293 // env := &adt.Environment{Vertex: nil} // runtime: c.runtime 294 295 env := &adt.Environment{} 296 top := env 297 298 for p := c.Config.Scope; p != nil; p = p.Parent() { 299 top.Vertex = p.Vertex() 300 top.Up = &adt.Environment{} 301 top = top.Up 302 } 303 304 for _, file := range a { 305 c.pushScope(nil, 0, file) // File scope 306 v := &adt.StructLit{Src: file} 307 c.addDecls(v, file.Decls) 308 res.Conjuncts = append(res.Conjuncts, adt.MakeRootConjunct(env, v)) 309 c.popScope() 310 } 311 312 return res 313 } 314 315 func (c *compiler) compileExpr(x ast.Expr) adt.Conjunct { 316 expr := c.expr(x) 317 318 env := &adt.Environment{} 319 top := env 320 321 for p := c.Config.Scope; p != nil; p = p.Parent() { 322 top.Vertex = p.Vertex() 323 top.Up = &adt.Environment{} 324 top = top.Up 325 } 326 327 return adt.MakeRootConjunct(env, expr) 328 } 329 330 // resolve assumes that all existing resolutions are legal. Validation should 331 // be done in a separate step if required. 332 // 333 // TODO: collect validation pass to verify that all resolutions are 334 // legal? 335 func (c *compiler) resolve(n *ast.Ident) adt.Expr { 336 // X in import "path/X" 337 // X in import X "path" 338 if imp, ok := n.Node.(*ast.ImportSpec); ok { 339 return &adt.ImportReference{ 340 Src: n, 341 ImportPath: c.label(imp.Path), 342 Label: c.label(n), 343 } 344 } 345 346 label := c.label(n) 347 348 if label == adt.InvalidLabel { // `_` 349 return &adt.Top{Src: n} 350 } 351 352 // Unresolved field. 353 if n.Node == nil { 354 upCount := int32(0) 355 for _, c := range c.stack { 356 upCount += c.upCount 357 } 358 if c.fileScope[label] { 359 return &adt.FieldReference{ 360 Src: n, 361 UpCount: upCount, 362 Label: label, 363 } 364 } 365 upCount += c.upCountOffset 366 for p := c.Scope; p != nil; p = p.Parent() { 367 for _, a := range p.Vertex().Arcs { 368 switch { 369 case a.Label.IsLet() && a.Label.IdentString(c.index) == n.Name: 370 label = a.Label 371 case a.Label == label: 372 return &adt.FieldReference{ 373 Src: n, 374 UpCount: upCount, 375 Label: label, 376 } 377 } 378 } 379 upCount++ 380 } 381 382 if c.Config.Imports != nil { 383 if pkgPath := c.Config.Imports(n); pkgPath != "" { 384 return &adt.ImportReference{ 385 Src: n, 386 ImportPath: adt.MakeStringLabel(c.index, pkgPath), 387 Label: c.label(n), 388 } 389 } 390 } 391 392 if p := predeclared(n); p != nil { 393 return p 394 } 395 396 return c.errf(n, "reference %q not found", n.Name) 397 } 398 399 // X in [X=x]: y Scope: Field Node: Expr (x) 400 // X in X=[x]: y Scope: Field Node: Field 401 // X in x: X=y Scope: Field Node: Alias 402 if f, ok := n.Scope.(*ast.Field); ok { 403 upCount := int32(0) 404 405 k := len(c.stack) - 1 406 for ; k >= 0; k-- { 407 if c.stack[k].field == f { 408 break 409 } 410 upCount += c.stack[k].upCount 411 } 412 413 label := &adt.LabelReference{ 414 Src: n, 415 UpCount: upCount, 416 } 417 418 switch f := n.Node.(type) { 419 case *ast.Field: 420 _ = c.lookupAlias(k, f.Label.(*ast.Alias).Ident) // mark as used 421 // The expression of field Label is always done in the same 422 // Environment as pointed to by the UpCount of the DynamicReference 423 // and the evaluation of a DynamicReference assumes this. 424 // We therefore set the UpCount of the LabelReference to 0. 425 label.UpCount = 0 426 return &adt.DynamicReference{ 427 Src: n, 428 UpCount: upCount, 429 Label: label, 430 } 431 432 case *ast.Alias: 433 _ = c.lookupAlias(k, f.Ident) // mark as used 434 return &adt.ValueReference{ 435 Src: n, 436 UpCount: upCount, 437 Label: c.label(f.Ident), 438 } 439 } 440 return label 441 } 442 443 upCount := int32(0) 444 445 k := len(c.stack) - 1 446 for ; k >= 0; k-- { 447 if f := c.stack[k]; f.scope == n.Scope { 448 if f.isComprehensionVar { 449 c.refersToForVariable = true 450 } 451 break 452 } 453 upCount += c.stack[k].upCount 454 } 455 if k < 0 { 456 // This is a programmatic error and should never happen if the users 457 // just builds with the cue command or if astutil.Resolve is used 458 // correctly. 459 c.errf(n, "reference %q set to unknown node in AST; "+ 460 "this can result from incorrect API usage or a compiler bug", 461 n.Name) 462 } 463 464 if n.Scope == nil { 465 // Package. 466 // Should have been handled above. 467 return c.errf(n, "unresolved identifier %v", n.Name) 468 } 469 470 switch f := n.Node.(type) { 471 // Local expressions 472 case *ast.LetClause: 473 entry := c.lookupAlias(k, n) 474 if entry.expr == nil { 475 panic("unreachable") 476 } 477 label = entry.feature 478 479 // let x = y 480 return &adt.LetReference{ 481 Src: n, 482 UpCount: upCount, 483 Label: label, 484 X: entry.expr, // TODO: remove usage 485 } 486 487 // TODO: handle new-style aliases 488 489 case *ast.Field: 490 // X=x: y 491 // X=(x): y 492 // X="\(x)": y 493 a, ok := f.Label.(*ast.Alias) 494 if !ok { 495 return c.errf(n, "illegal reference %s", n.Name) 496 } 497 aliasInfo := c.lookupAlias(k, a.Ident) // marks alias as used. 498 lab, ok := a.Expr.(ast.Label) 499 if !ok { 500 return c.errf(a.Expr, "invalid label expression") 501 } 502 name, _, err := ast.LabelName(lab) 503 switch { 504 case errors.Is(err, ast.ErrIsExpression): 505 if aliasInfo.expr == nil { 506 panic("unreachable") 507 } 508 return &adt.DynamicReference{ 509 Src: n, 510 UpCount: upCount, 511 Label: aliasInfo.expr, 512 } 513 514 case err != nil: 515 return c.errf(n, "invalid label: %v", err) 516 517 case name != "": 518 label = c.label(lab) 519 520 default: 521 return c.errf(n, "unsupported field alias %q", name) 522 } 523 } 524 525 return &adt.FieldReference{ 526 Src: n, 527 UpCount: upCount, 528 Label: label, 529 } 530 } 531 532 func (c *compiler) addDecls(st *adt.StructLit, a []ast.Decl) { 533 for _, d := range a { 534 c.markAlias(d) 535 } 536 for _, d := range a { 537 c.addLetDecl(d) 538 } 539 for _, d := range a { 540 if x := c.decl(d); x != nil { 541 st.Decls = append(st.Decls, x) 542 } 543 } 544 } 545 546 func (c *compiler) markAlias(d ast.Decl) { 547 switch x := d.(type) { 548 case *ast.Field: 549 lab := x.Label 550 if a, ok := lab.(*ast.Alias); ok { 551 if _, ok = a.Expr.(ast.Label); !ok { 552 c.errf(a, "alias expression is not a valid label") 553 } 554 555 e := aliasEntry{source: a} 556 557 c.insertAlias(a.Ident, e) 558 } 559 560 case *ast.LetClause: 561 a := aliasEntry{ 562 label: (*letScope)(x), 563 srcExpr: x.Expr, 564 source: x, 565 feature: adt.MakeLetLabel(c.index, x.Ident.Name), 566 } 567 c.insertAlias(x.Ident, a) 568 569 case *ast.Alias: 570 c.errf(x, "old-style alias no longer supported: use let clause; use cue fix to update.") 571 } 572 } 573 574 func (c *compiler) decl(d ast.Decl) adt.Decl { 575 switch x := d.(type) { 576 case *ast.BadDecl: 577 return c.errf(d, "") 578 579 case *ast.Field: 580 lab := x.Label 581 if a, ok := lab.(*ast.Alias); ok { 582 if lab, ok = a.Expr.(ast.Label); !ok { 583 return c.errf(a, "alias expression is not a valid label") 584 } 585 } 586 587 v := x.Value 588 var value adt.Expr 589 if a, ok := v.(*ast.Alias); ok { 590 c.pushScope(nil, 0, a) 591 c.insertAlias(a.Ident, aliasEntry{source: a}) 592 value = c.labeledExpr(x, (*fieldLabel)(x), a.Expr) 593 c.popScope() 594 } else { 595 value = c.labeledExpr(x, (*fieldLabel)(x), v) 596 } 597 598 switch l := lab.(type) { 599 case *ast.Ident, *ast.BasicLit: 600 label := c.label(lab) 601 602 if label == adt.InvalidLabel { 603 return c.errf(x, "cannot use _ as label") 604 } 605 606 t, _ := internal.ConstraintToken(x) 607 608 return &adt.Field{ 609 Src: x, 610 Label: label, 611 ArcType: adt.ConstraintFromToken(t), 612 Value: value, 613 } 614 615 case *ast.ListLit: 616 if len(l.Elts) != 1 { 617 // error 618 return c.errf(x, "list label must have one element") 619 } 620 var label adt.Feature 621 elem := l.Elts[0] 622 // TODO: record alias for error handling? In principle it is okay 623 // to have duplicates, but we do want it to be used. 624 if a, ok := elem.(*ast.Alias); ok { 625 label = c.label(a.Ident) 626 elem = a.Expr 627 } 628 629 return &adt.BulkOptionalField{ 630 Src: x, 631 Filter: c.expr(elem), 632 Value: value, 633 Label: label, 634 } 635 636 case *ast.ParenExpr: 637 t, _ := internal.ConstraintToken(x) 638 639 return &adt.DynamicField{ 640 Src: x, 641 Key: c.expr(l), 642 ArcType: adt.ConstraintFromToken(t), 643 Value: value, 644 } 645 646 case *ast.Interpolation: 647 t, _ := internal.ConstraintToken(x) 648 649 return &adt.DynamicField{ 650 Src: x, 651 Key: c.expr(l), 652 ArcType: adt.ConstraintFromToken(t), 653 Value: value, 654 } 655 } 656 657 case *ast.LetClause: 658 m := c.stack[len(c.stack)-1].aliases 659 entry := m[x.Ident.Name] 660 661 // A reference to the let should, in principle, be interpreted as a 662 // value reference, not field reference: 663 // - this is syntactically consistent for the use of = 664 // - this is semantically the only valid interpretation 665 // In practice this amounts to the same thing, as let expressions cannot 666 // be addressed from outside their scope. But it will matter once 667 // expressions may refer to a let from within the let. 668 669 savedUses := c.refersToForVariable 670 c.refersToForVariable = false 671 value := c.labeledExpr(x, (*letScope)(x), x.Expr) 672 refsCompVar := c.refersToForVariable 673 c.refersToForVariable = savedUses || refsCompVar 674 675 return &adt.LetField{ 676 Src: x, 677 Label: entry.feature, 678 IsMulti: refsCompVar, 679 Value: value, 680 } 681 682 // case: *ast.Alias: // TODO(value alias) 683 684 case *ast.CommentGroup: 685 // Nothing to do for a free-floating comment group. 686 687 case *ast.Attribute: 688 // Nothing to do for now for an attribute declaration. 689 690 case *ast.Ellipsis: 691 return &adt.Ellipsis{ 692 Src: x, 693 Value: c.expr(x.Type), 694 } 695 696 case *ast.Comprehension: 697 return c.comprehension(x, false) 698 699 case *ast.EmbedDecl: // Deprecated 700 return c.expr(x.Expr) 701 702 case ast.Expr: 703 return c.expr(x) 704 } 705 return nil 706 } 707 708 func (c *compiler) addLetDecl(d ast.Decl) { 709 switch x := d.(type) { 710 case *ast.Field: 711 lab := x.Label 712 if a, ok := lab.(*ast.Alias); ok { 713 if lab, ok = a.Expr.(ast.Label); !ok { 714 // error reported elsewhere 715 return 716 } 717 718 switch lab.(type) { 719 case *ast.Ident, *ast.BasicLit, *ast.ListLit: 720 // Even though we won't need the alias, we still register it 721 // for duplicate and failed reference detection. 722 default: 723 c.updateAlias(a.Ident, c.expr(a.Expr)) 724 } 725 } 726 727 case *ast.Alias: 728 c.errf(x, "old-style alias no longer supported: use let clause; use cue fix to update.") 729 } 730 } 731 732 func (c *compiler) elem(n ast.Expr) adt.Elem { 733 switch x := n.(type) { 734 case *ast.Ellipsis: 735 return &adt.Ellipsis{ 736 Src: x, 737 Value: c.expr(x.Type), 738 } 739 740 case *ast.Comprehension: 741 return c.comprehension(x, true) 742 743 case ast.Expr: 744 return c.expr(x) 745 } 746 return nil 747 } 748 749 func (c *compiler) comprehension(x *ast.Comprehension, inList bool) adt.Elem { 750 var a []adt.Yielder 751 for _, v := range x.Clauses { 752 switch x := v.(type) { 753 case *ast.ForClause: 754 var key adt.Feature 755 if x.Key != nil { 756 key = c.label(x.Key) 757 } 758 y := &adt.ForClause{ 759 Syntax: x, 760 Key: key, 761 Value: c.label(x.Value), 762 Src: c.expr(x.Source), 763 } 764 f := c.pushScope((*forScope)(x), 1, v) 765 defer c.popScope() 766 f.isComprehensionVar = !inList 767 a = append(a, y) 768 769 case *ast.IfClause: 770 y := &adt.IfClause{ 771 Src: x, 772 Condition: c.expr(x.Condition), 773 } 774 a = append(a, y) 775 776 case *ast.LetClause: 777 // Check if any references in the expression refer to a for 778 // comprehension. 779 savedUses := c.refersToForVariable 780 c.refersToForVariable = false 781 expr := c.expr(x.Expr) 782 refsCompVar := c.refersToForVariable 783 c.refersToForVariable = savedUses || refsCompVar 784 785 y := &adt.LetClause{ 786 Src: x, 787 Label: c.label(x.Ident), 788 Expr: expr, 789 } 790 f := c.pushScope((*letScope)(x), 1, v) 791 defer c.popScope() 792 f.isComprehensionVar = !inList && refsCompVar 793 a = append(a, y) 794 } 795 796 if _, ok := a[0].(*adt.LetClause); ok { 797 return c.errf(x, 798 "first comprehension clause must be 'if' or 'for'") 799 } 800 } 801 802 // TODO: make x.Value an *ast.StructLit and this is redundant. 803 if y, ok := x.Value.(*ast.StructLit); !ok { 804 return c.errf(x.Value, 805 "comprehension value must be struct, found %T", y) 806 } 807 808 y := c.expr(x.Value) 809 810 st, ok := y.(*adt.StructLit) 811 if !ok { 812 // Error must have been generated. 813 return y 814 } 815 816 if len(a) == 0 { 817 return c.errf(x, "comprehension value without clauses") 818 } 819 820 return &adt.Comprehension{ 821 Syntax: x, 822 Clauses: a, 823 Value: st, 824 } 825 } 826 827 func (c *compiler) labeledExpr(f ast.Decl, lab labeler, expr ast.Expr) adt.Expr { 828 k := len(c.stack) - 1 829 return c.labeledExprAt(k, f, lab, expr) 830 } 831 832 func (c *compiler) labeledExprAt(k int, f ast.Decl, lab labeler, expr ast.Expr) adt.Expr { 833 saved := c.stack[k] 834 835 c.stack[k].label = lab 836 c.stack[k].field = f 837 838 value := c.expr(expr) 839 840 c.stack[k] = saved 841 return value 842 } 843 844 func (c *compiler) expr(expr ast.Expr) adt.Expr { 845 switch n := expr.(type) { 846 case nil: 847 return nil 848 case *ast.Ident: 849 return c.resolve(n) 850 851 case *ast.Func: 852 // We don't yet support function types natively in 853 // CUE. ast.Func exists only to support external 854 // interpreters. Function values (really, adt.Builtin) 855 // are only created by the runtime, or injected by 856 // external interpreters. 857 // 858 // TODO: revise this when we add function types. 859 return c.resolve(ast.NewIdent("_")) 860 861 case *ast.StructLit: 862 c.pushScope(nil, 1, n) 863 v := &adt.StructLit{Src: n} 864 c.addDecls(v, n.Elts) 865 c.popScope() 866 return v 867 868 case *ast.ListLit: 869 c.pushScope(nil, 1, n) 870 v := &adt.ListLit{Src: n} 871 elts, ellipsis := internal.ListEllipsis(n) 872 for _, d := range elts { 873 elem := c.elem(d) 874 875 switch x := elem.(type) { 876 case nil: 877 case adt.Elem: 878 v.Elems = append(v.Elems, x) 879 default: 880 c.errf(d, "type %T not allowed in ListLit", d) 881 } 882 } 883 if ellipsis != nil { 884 d := &adt.Ellipsis{ 885 Src: ellipsis, 886 Value: c.expr(ellipsis.Type), 887 } 888 v.Elems = append(v.Elems, d) 889 } 890 c.popScope() 891 return v 892 893 case *ast.SelectorExpr: 894 c.inSelector++ 895 ret := &adt.SelectorExpr{ 896 Src: n, 897 X: c.expr(n.X), 898 Sel: c.label(n.Sel)} 899 c.inSelector-- 900 return ret 901 902 case *ast.IndexExpr: 903 return &adt.IndexExpr{ 904 Src: n, 905 X: c.expr(n.X), 906 Index: c.expr(n.Index), 907 } 908 909 case *ast.SliceExpr: 910 slice := &adt.SliceExpr{Src: n, X: c.expr(n.X)} 911 if n.Low != nil { 912 slice.Lo = c.expr(n.Low) 913 } 914 if n.High != nil { 915 slice.Hi = c.expr(n.High) 916 } 917 return slice 918 919 case *ast.BottomLit: 920 return &adt.Bottom{ 921 Src: n, 922 Code: adt.UserError, 923 Err: errors.Newf(n.Pos(), "explicit error (_|_ literal) in source"), 924 } 925 926 case *ast.BadExpr: 927 return c.errf(n, "invalid expression") 928 929 case *ast.BasicLit: 930 return c.parse(n) 931 932 case *ast.Interpolation: 933 if len(n.Elts) == 0 { 934 return c.errf(n, "invalid interpolation") 935 } 936 first, ok1 := n.Elts[0].(*ast.BasicLit) 937 last, ok2 := n.Elts[len(n.Elts)-1].(*ast.BasicLit) 938 if !ok1 || !ok2 { 939 return c.errf(n, "invalid interpolation") 940 } 941 if len(n.Elts) == 1 { 942 return c.expr(n.Elts[0]) 943 } 944 lit := &adt.Interpolation{Src: n} 945 info, prefixLen, _, err := literal.ParseQuotes(first.Value, last.Value) 946 if err != nil { 947 return c.errf(n, "invalid interpolation: %v", err) 948 } 949 if info.IsDouble() { 950 lit.K = adt.StringKind 951 } else { 952 lit.K = adt.BytesKind 953 } 954 prefix := "" 955 for i := 0; i < len(n.Elts); i += 2 { 956 l, ok := n.Elts[i].(*ast.BasicLit) 957 if !ok { 958 return c.errf(n, "invalid interpolation") 959 } 960 s := l.Value 961 if !strings.HasPrefix(s, prefix) { 962 return c.errf(l, "invalid interpolation: unmatched ')'") 963 } 964 s = l.Value[prefixLen:] 965 x := parseString(c, l, info, s) 966 lit.Parts = append(lit.Parts, x) 967 if i+1 < len(n.Elts) { 968 lit.Parts = append(lit.Parts, c.expr(n.Elts[i+1])) 969 } 970 prefix = ")" 971 prefixLen = 1 972 } 973 return lit 974 975 case *ast.ParenExpr: 976 return c.expr(n.X) 977 978 case *ast.CallExpr: 979 call := &adt.CallExpr{Src: n, Fun: c.expr(n.Fun)} 980 for _, a := range n.Args { 981 call.Args = append(call.Args, c.expr(a)) 982 } 983 return call 984 985 case *ast.UnaryExpr: 986 switch n.Op { 987 case token.NOT, token.ADD, token.SUB: 988 return &adt.UnaryExpr{ 989 Src: n, 990 Op: adt.OpFromToken(n.Op), 991 X: c.expr(n.X), 992 } 993 case token.GEQ, token.GTR, token.LSS, token.LEQ, 994 token.NEQ, token.MAT, token.NMAT: 995 return &adt.BoundExpr{ 996 Src: n, 997 Op: adt.OpFromToken(n.Op), 998 Expr: c.expr(n.X), 999 } 1000 1001 case token.MUL: 1002 return c.errf(n, "preference mark not allowed at this position") 1003 default: 1004 return c.errf(n, "unsupported unary operator %q", n.Op) 1005 } 1006 1007 case *ast.BinaryExpr: 1008 switch n.Op { 1009 case token.OR: 1010 d := &adt.DisjunctionExpr{Src: n} 1011 c.addDisjunctionElem(d, n.X, false) 1012 c.addDisjunctionElem(d, n.Y, false) 1013 return d 1014 1015 default: 1016 op := adt.OpFromToken(n.Op) 1017 x := c.expr(n.X) 1018 y := c.expr(n.Y) 1019 if op != adt.AndOp { 1020 c.assertConcreteIsPossible(n.X, op, x) 1021 c.assertConcreteIsPossible(n.Y, op, y) 1022 } 1023 // return updateBin(c, 1024 return &adt.BinaryExpr{Src: n, Op: op, X: x, Y: y} // ) 1025 } 1026 1027 default: 1028 return c.errf(n, "%s values not allowed in this position", ast.Name(n)) 1029 } 1030 } 1031 1032 func (c *compiler) assertConcreteIsPossible(src ast.Node, op adt.Op, x adt.Expr) bool { 1033 if !adt.AssertConcreteIsPossible(op, x) { 1034 str := astinternal.DebugStr(src) 1035 c.errf(src, "invalid operand %s ('%s' requires concrete value)", str, op) 1036 } 1037 return false 1038 } 1039 1040 func (c *compiler) addDisjunctionElem(d *adt.DisjunctionExpr, n ast.Expr, mark bool) { 1041 switch x := n.(type) { 1042 case *ast.BinaryExpr: 1043 if x.Op == token.OR { 1044 c.addDisjunctionElem(d, x.X, mark) 1045 c.addDisjunctionElem(d, x.Y, mark) 1046 return 1047 } 1048 case *ast.UnaryExpr: 1049 if x.Op == token.MUL { 1050 d.HasDefaults = true 1051 c.addDisjunctionElem(d, x.X, true) 1052 return 1053 } 1054 } 1055 d.Values = append(d.Values, adt.Disjunct{Val: c.expr(n), Default: mark}) 1056 } 1057 1058 // TODO(perf): validate that regexps are cached at the right time. 1059 1060 func (c *compiler) parse(l *ast.BasicLit) (n adt.Expr) { 1061 s := l.Value 1062 if s == "" { 1063 return c.errf(l, "invalid literal %q", s) 1064 } 1065 switch l.Kind { 1066 case token.STRING: 1067 info, nStart, _, err := literal.ParseQuotes(s, s) 1068 if err != nil { 1069 return c.errf(l, err.Error()) 1070 } 1071 s := s[nStart:] 1072 return parseString(c, l, info, s) 1073 1074 case token.FLOAT, token.INT: 1075 err := literal.ParseNum(s, &c.num) 1076 if err != nil { 1077 return c.errf(l, "parse error: %v", err) 1078 } 1079 kind := adt.FloatKind 1080 if c.num.IsInt() { 1081 kind = adt.IntKind 1082 } 1083 n := &adt.Num{Src: l, K: kind} 1084 if err = c.num.Decimal(&n.X); err != nil { 1085 return c.errf(l, "error converting number to decimal: %v", err) 1086 } 1087 return n 1088 1089 case token.TRUE: 1090 return &adt.Bool{Src: l, B: true} 1091 1092 case token.FALSE: 1093 return &adt.Bool{Src: l, B: false} 1094 1095 case token.NULL: 1096 return &adt.Null{Src: l} 1097 1098 default: 1099 return c.errf(l, "unknown literal type") 1100 } 1101 } 1102 1103 // parseString decodes a string without the starting and ending quotes. 1104 func parseString(c *compiler, node ast.Expr, q literal.QuoteInfo, s string) (n adt.Expr) { 1105 str, err := q.Unquote(s) 1106 if err != nil { 1107 return c.errf(node, "invalid string: %v", err) 1108 } 1109 if q.IsDouble() { 1110 return &adt.String{Src: node, Str: str, RE: nil} 1111 } 1112 return &adt.Bytes{Src: node, B: []byte(str), RE: nil} 1113 }