this repo has no description
0
fork

Configure Feed

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

internal/core/adt: allow lookup across disjunction boundary

If we are evaluating a disjunct, allow indexing
into the disjunct. Theoretically this is not correct.
However, doing so we approximate carrying over
unresolved tasks across the disjunction boundary
so that they can be resolved once a single disjunction
has been chosen. This is something we SHOULD do,
but is rather hard. Doing this instead seems like a
good approximation.

Issue #3967

Signed-off-by: Marcel van Lohuizen <mpvl@gmail.com>
Change-Id: Ib39640f2e978a08eefbf02dd6bb97e9202010de3
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1217087
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

+53 -72
+38 -72
cue/testdata/eval/disjunctioncross.txtar
··· 103 103 } 104 104 } 105 105 -- out/evalalpha/stats -- 106 - Leaks: 291 106 + Leaks: 294 107 107 Freed: 0 108 108 Reused: 0 109 - Allocs: 291 109 + Allocs: 294 110 110 Retain: 0 111 111 112 - Unifications: 165 113 - Conjuncts: 379 114 - Disjuncts: 74 112 + Unifications: 162 113 + Conjuncts: 394 114 + Disjuncts: 80 115 115 116 - CloseIDElems: 1476 117 - NumCloseIDs: 91 116 + CloseIDElems: 1504 117 + NumCloseIDs: 94 118 118 -- diff/-out/evalalpha/stats<==>+out/eval/stats -- 119 119 diff old new 120 120 --- old ··· 132 132 - 133 133 -CloseIDElems: 0 134 134 -NumCloseIDs: 8 135 - +Leaks: 291 135 + +Leaks: 294 136 136 +Freed: 0 137 137 +Reused: 0 138 - +Allocs: 291 138 + +Allocs: 294 139 139 +Retain: 0 140 140 + 141 - +Unifications: 165 142 - +Conjuncts: 379 143 - +Disjuncts: 74 141 + +Unifications: 162 142 + +Conjuncts: 394 143 + +Disjuncts: 80 144 144 + 145 - +CloseIDElems: 1476 146 - +NumCloseIDs: 91 145 + +CloseIDElems: 1504 146 + +NumCloseIDs: 94 147 147 -- out/eval/stats -- 148 148 Leaks: 16 149 149 Freed: 292 ··· 205 205 }) } 206 206 } 207 207 #Application: (#struct){ 208 - oneOrTwo: (#struct){ |((#struct){ 208 + oneOrTwo: (#struct){ |(*(#struct){ 209 + kind: (string){ "two" } 210 + two: (#struct){ 211 + optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 212 + } 213 + }, (#struct){ 209 214 kind: (string){ "one" } 210 215 one: (#struct){ 211 216 oneField: (string){ "value" } ··· 255 260 fieldDiscriminator: (struct){ 256 261 crossing: (struct){ 257 262 out: (#struct){ 258 - oneOrTwo: (#struct){ 259 - two: (#struct){ 260 - optional?: (string){ string } 261 - } 262 - kind: (string){ "two" } 263 - } 263 + oneOrTwo: (#struct){ |(*(#struct){ 264 + two: (#struct){ 265 + optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 266 + } 267 + kind: (string){ "two" } 268 + }, (#struct){ 269 + two: (#struct){ 270 + optional?: (string){ string } 271 + } 272 + kind: (string){ "two" } 273 + }) } 264 274 } 265 275 #Application: (#struct){ 266 - oneOrTwo: (#struct){ |((#struct){ 276 + oneOrTwo: (#struct){ |(*(#struct){ 277 + kind: (string){ "two" } 278 + two: (#struct){ 279 + optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 280 + } 281 + }, (#struct){ 267 282 kind: (string){ "one" } 268 283 one: (#struct){ 269 284 oneField: (string){ "value" } ··· 365 380 diff old new 366 381 --- old 367 382 +++ new 368 - @@ -45,12 +45,7 @@ 369 - }) } 370 - } 371 - #Application: (#struct){ 372 - - oneOrTwo: (#struct){ |(*(#struct){ 373 - - kind: (string){ "two" } 374 - - two: (#struct){ 375 - - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 376 - - } 377 - - }, (#struct){ 378 - + oneOrTwo: (#struct){ |((#struct){ 379 - kind: (string){ "one" } 380 - one: (#struct){ 381 - oneField: (string){ "value" } 382 - @@ -100,25 +95,15 @@ 383 - fieldDiscriminator: (struct){ 384 - crossing: (struct){ 385 - out: (#struct){ 386 - - oneOrTwo: (#struct){ |(*(#struct){ 387 - - two: (#struct){ 388 - - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 389 - - } 390 - - kind: (string){ "two" } 391 - - }, (#struct){ 392 - - two: (#struct){ 393 - - optional?: (string){ string } 394 - - } 395 - - kind: (string){ "two" } 396 - - }) } 397 - - } 398 - - #Application: (#struct){ 399 - - oneOrTwo: (#struct){ |(*(#struct){ 400 - - kind: (string){ "two" } 401 - - two: (#struct){ 402 - - optional: (string){ |(*(string){ "optional set" }, (string){ string }) } 403 - - } 404 - - }, (#struct){ 405 - + oneOrTwo: (#struct){ 406 - + two: (#struct){ 407 - + optional?: (string){ string } 408 - + } 409 - + kind: (string){ "two" } 410 - + } 411 - + } 412 - + #Application: (#struct){ 413 - + oneOrTwo: (#struct){ |((#struct){ 414 - kind: (string){ "one" } 415 - one: (#struct){ 416 - oneField: (string){ "value" } 417 - @@ -168,45 +153,48 @@ 383 + @@ -168,45 +168,48 @@ 418 384 issue3967: (struct){ 419 385 error: (struct){ 420 386 nested: (struct){
+15
internal/core/adt/disjunct2.go
··· 506 506 507 507 // TODO(perf): do not set to nil, but rather maintain an index to unwind 508 508 // to avoid allocting new arrays. 509 + // TODO: ideally, we move unresolved tasks to the original vertex for 510 + // disambiguated disjuncts. 509 511 saved := n.ctx.blocking 510 512 n.ctx.blocking = nil 511 513 defer func() { n.ctx.blocking = saved }() 512 514 515 + // We forward the original base value to the disjunct. This allows for 516 + // lookups with the disjunct to the original value. 517 + var savedBase BaseValue 518 + if !orig.IsDisjunct { 519 + savedBase = orig.BaseValue 520 + defer func() { orig.BaseValue = savedBase }() 521 + } 522 + 513 523 d := oc.cloneRoot(n) 524 + 525 + // This mechanism only works if the original is not a disjunct. 526 + if !orig.IsDisjunct { 527 + orig.BaseValue = d.node 528 + } 514 529 515 530 n.ctx.pushOverlay(n.node, oc.vertexMap) 516 531 defer n.ctx.popOverlay()