this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

cue: closedness only applies to regular fields

Issue #40

Change-Id: I6f2cf753e84bc570dfe1fc91cda1eccb29f0582e
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/3042
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>

authored by

Marcel van Lohuizen and committed by
Marcel van Lohuizen
18637dba 1c4d5979

+101 -57
+2 -2
cue/binop.go
··· 653 653 break 654 654 } 655 655 } 656 - if !unchecked && !found && !y.allows(a.feature) { 656 + if !unchecked && !found && !y.allows(a.feature) && !a.definition { 657 657 if a.optional { 658 658 continue 659 659 } ··· 691 691 continue outer 692 692 } 693 693 } 694 - if !unchecked && !found && !x.allows(a.feature) { 694 + if !unchecked && !found && !x.allows(a.feature) && !a.definition { 695 695 if a.optional { 696 696 continue 697 697 }
+5
cue/export.go
··· 215 215 } 216 216 217 217 func (p *exporter) closeOrOpen(s *ast.StructLit, isClosed bool) ast.Expr { 218 + // Note, there is no point in printing close if we are dropping optional 219 + // fields, as by this the meaning of close will change anyway. 220 + if p.mode.omitOptional || p.mode.concrete { 221 + return s 222 + } 218 223 if isClosed && !p.inDef { 219 224 return &ast.CallExpr{ 220 225 Fun: ast.NewIdent("close"),
+89 -50
cue/export_test.go
··· 27 27 testCases := []struct { 28 28 raw bool // skip evaluation the root, fully raw 29 29 eval bool // evaluate the full export 30 + noOpt bool 30 31 in, out string 31 32 }{{ 32 33 in: `"hello"`, ··· 99 100 d: _|_ /* undefined field "d" */ 100 101 e: _|_ /* undefined field "t" */ 101 102 }`), 102 - }, { 103 - // a closed struct with template restrictions is exported as a 104 - // conjunction of two structs. 105 - in: `{ 106 - A :: { b: int } 107 - a: A & { <_>: <10 } 108 - B :: a 109 - }`, 110 - out: unindent(` 111 - { 112 - A :: { 113 - b: int 114 - } 115 - a: close({ 116 - b: <10 117 - }) & { 118 - <_>: <10 119 - } 120 - B :: { 121 - b: <10 122 - } & { 123 - <_>: <10 124 - } 125 - }`), 126 103 }, { 127 104 in: `{ 128 105 a: 5*[int] ··· 383 360 } 384 361 }`), 385 362 }, { 386 - raw: true, 387 - eval: true, 363 + raw: true, 364 + eval: true, 365 + noOpt: true, 388 366 in: `{ 389 367 reg: { foo: 1, bar: { baz: 3 } } 390 368 def :: { ··· 404 382 a: 1 405 383 sub: { 406 384 foo: 1 407 - bar: { 408 - baz: 3 409 - ... 410 - } 411 - ... 385 + bar baz: 3 412 386 } 413 387 } 414 - val: close({ 388 + val: { 415 389 a: 1 416 390 sub: { 417 391 foo: 1 418 392 bar baz: 3 419 393 } 420 - }) 394 + } 421 395 }`), 422 396 }, { 423 397 raw: true, 424 398 eval: true, 425 399 in: `{ 426 - b: [{ 427 - <X>: int 428 - f: 4 if a > 4 429 - }][a] 430 - a: int 431 - c: *1 | 2 432 - }`, 400 + b: [{ 401 + <X>: int 402 + f: 4 if a > 4 403 + }][a] 404 + a: int 405 + c: *1 | 2 406 + }`, 433 407 // reference to a must be redirected to outer a through alias 434 408 out: unindent(` 435 - { 436 - b: [{ 437 - <X>: int 438 - f: 4 if a > 4 439 - }][a] 440 - a: int 441 - c: 1 442 - }`), 409 + { 410 + b: [{ 411 + <X>: int 412 + f: 4 if a > 4 413 + }][a] 414 + a: int 415 + c: 1 416 + }`), 443 417 }} 444 418 for _, tc := range testCases { 445 419 t.Run("", func(t *testing.T) { ··· 455 429 n := root.(*structLit).arcs[0].v 456 430 v := newValueRoot(ctx, n) 457 431 458 - opts := options{raw: !tc.eval} 432 + opts := options{raw: !tc.eval, omitOptional: true} 459 433 node, _ := export(ctx, v.eval(ctx), opts) 460 434 b, err := format.Node(node, format.Simplify()) 461 435 if err != nil { ··· 595 569 } | { 596 570 c: time.Duration 597 571 }`), 572 + }, { 573 + // a closed struct unified with a struct with a template restrictions is 574 + // exported as a conjunction of two structs. 575 + eval: true, 576 + in: ` 577 + A :: { b: int } 578 + a: A & { <_>: <10 } 579 + B :: a 580 + `, 581 + out: unindent(` 582 + { 583 + A :: { 584 + b: int 585 + } 586 + a: close({ 587 + b: <10 588 + }) & { 589 + <_>: <10 590 + } 591 + B :: { 592 + b: <10 593 + } & { 594 + <_>: <10 595 + } 596 + }`), 597 + }, { 598 + eval: true, 599 + in: `{ 600 + reg: { foo: 1, bar: { baz: 3 } } 601 + def :: { 602 + a: 1 603 + 604 + sub: reg 605 + } 606 + val: def 607 + }`, 608 + out: unindent(` 609 + { 610 + reg: { 611 + foo: 1 612 + bar baz: 3 613 + } 614 + def :: { 615 + a: 1 616 + sub: { 617 + foo: 1 618 + bar: { 619 + baz: 3 620 + ... 621 + } 622 + ... 623 + } 624 + } 625 + val: close({ 626 + a: 1 627 + sub: { 628 + foo: 1 629 + bar baz: 3 630 + } 631 + }) 632 + }`), 598 633 }} 599 634 for _, tc := range testCases { 600 635 t.Run("", func(t *testing.T) { ··· 603 638 if err != nil { 604 639 t.Fatal(err) 605 640 } 606 - b, err := format.Node(inst.Value().Syntax(Raw()), format.Simplify()) 641 + opts := []Option{} 642 + if !tc.eval { 643 + opts = []Option{Raw()} 644 + } 645 + b, err := format.Node(inst.Value().Syntax(opts...), format.Simplify()) 607 646 if err != nil { 608 647 log.Fatal(err) 609 648 }
+2 -2
cue/value.go
··· 658 658 } 659 659 660 660 func (x *structLit) allows(f label) bool { 661 - return !x.isClosed 661 + return !x.isClosed || f&hidden != 0 662 662 } 663 663 664 664 func newStruct(src source) *structLit { ··· 886 886 // A label is a canonicalized feature name. 887 887 type label uint32 888 888 889 - const hidden label = 0x01 // only set iff identifier starting with $ 889 + const hidden label = 0x01 // only set iff identifier starting with _ 890 890 891 891 // An arc holds the label-value pair. 892 892 //
+3 -3
doc/ref/spec.md
··· 1122 1122 1123 1123 By default, structs are open to adding fields. 1124 1124 Instances of an open struct `p` may contain fields not defined in `p`. 1125 - A _closed struct_ `c` is a struct whose instances may not have fields 1125 + A _closed struct_ `c` is a struct whose instances may not have regular fields 1126 1126 not defined in `c`. 1127 1127 Closing a struct is equivalent to adding an optional field with value `_|_` 1128 1128 for all undefined fields. ··· 1190 1190 or as a _definition_ (using `::`). 1191 1191 Definitions are not emitted as part of the model and are never required 1192 1192 to be concrete when emitting data. 1193 - It is illegal to have a normal field and a definition with the same name 1193 + It is illegal to have a regular field and a definition with the same name 1194 1194 within the same struct. 1195 1195 Literal structs that are part of a definition's value are implicitly closed. 1196 1196 An ellipsis `...` in such literal structs keeps them open, ··· 1517 1517 All other identifiers are not exported. 1518 1518 1519 1519 An identifier that starts with the underscore "_" is not 1520 - emitted in any data output. 1520 + emitted in any data output and treated as a definition for that purpose. 1521 1521 Quoted labels that start with an underscore are emitted, however. 1522 1522 <!-- END REPLACE --> 1523 1523