1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package adt
16
17 import "fmt"
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 func (n *nodeContext) scheduleConjunct(c Conjunct, id CloseInfo) {
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 switch cc := c.CloseInfo.cc; {
61 case cc == nil || cc.src != n.node:
62
63
64
65 if id.cc == nil {
66 id.cc = n.node.rootCloseContext()
67 }
68 if id.cc == cc {
69 panic("inconsistent state")
70 }
71 var t closeNodeType
72 if c.CloseInfo.FromDef {
73 t |= closeDef
74 }
75 if c.CloseInfo.FromEmbed {
76 t |= closeEmbed
77 }
78 if t != 0 {
79 id, _ = id.spawnCloseContext(t)
80 }
81 if !id.cc.done {
82 id.cc.incDependent(DEFER, nil)
83 defer id.cc.decDependent(n.ctx, DEFER, nil)
84 }
85
86 if id.cc.src != n.node {
87 panic("inconsistent state")
88 }
89 default:
90
91
92
93
94 id.cc = cc
95
96
97
98 id.CycleInfo = c.CloseInfo.CycleInfo
99 }
100
101 if id.cc.needsCloseInSchedule != nil {
102 dep := id.cc.needsCloseInSchedule
103 id.cc.needsCloseInSchedule = nil
104 defer id.cc.decDependent(n.ctx, EVAL, dep)
105 }
106
107 env := c.Env
108
109 if id.cc.isDef {
110 n.node.Closed = true
111 }
112
113 switch x := c.Elem().(type) {
114 case *ConjunctGroup:
115 for _, c := range *x {
116
117
118 cc := c.CloseInfo.cc
119 if cc.src == n.node && cc.needsCloseInSchedule != nil {
120
121
122
123
124
125 dep := cc.needsCloseInSchedule
126 cc.needsCloseInSchedule = nil
127 defer cc.decDependent(n.ctx, EVAL, dep)
128 }
129 }
130 for _, c := range *x {
131 n.scheduleConjunct(c, id)
132 }
133
134 case *Vertex:
135 if x.IsData() {
136 n.insertValueConjunct(env, x, id)
137 } else {
138 n.scheduleVertexConjuncts(c, x, id)
139 }
140
141 case Value:
142 n.insertValueConjunct(env, x, id)
143
144 case *BinaryExpr:
145 if x.Op == AndOp {
146 n.scheduleConjunct(MakeConjunct(env, x.X, id), id)
147 n.scheduleConjunct(MakeConjunct(env, x.Y, id), id)
148 return
149 }
150
151
152
153 n.scheduleTask(handleExpr, env, x, id)
154
155 case *StructLit:
156 n.scheduleStruct(env, x, id)
157
158 case *ListLit:
159 env := &Environment{
160 Up: env,
161 Vertex: n.node,
162 }
163 n.scheduleTask(handleListLit, env, x, id)
164
165 case *DisjunctionExpr:
166 panic("unimplemented")
167
168
169 case *Comprehension:
170
171 n.insertComprehension(env, x, id)
172
173 case Resolver:
174 n.scheduleTask(handleResolver, env, x, id)
175
176 case Evaluator:
177
178 n.scheduleTask(handleExpr, env, x, id)
179
180 default:
181 panic("unreachable")
182 }
183
184 n.ctx.stats.Conjuncts++
185 }
186
187
188
189
190 func (n *nodeContext) scheduleStruct(env *Environment,
191 s *StructLit,
192 ci CloseInfo) {
193 n.updateCyclicStatus(ci)
194
195
196
197
198
199
200 childEnv := &Environment{
201 Up: env,
202 Vertex: n.node,
203 }
204
205 hasEmbed := false
206 hasEllipsis := false
207
208
209
210
211
212 parent := n.node.AddStruct(s, childEnv, ci)
213 parent.Disable = true
214 ci.IsClosed = false
215
216
217 loop1:
218 for _, d := range s.Decls {
219 switch d.(type) {
220 case *Ellipsis:
221 hasEllipsis = true
222 break loop1
223 }
224 }
225
226
227 loop2:
228 for _, d := range s.Decls {
229 switch d.(type) {
230 case *Comprehension, Expr:
231
232
233 ci, _ = ci.spawnCloseContext(0)
234
235
236 hasEmbed = true
237 break loop2
238 }
239 }
240
241
242 for _, d := range s.Decls {
243 switch x := d.(type) {
244 case *Field:
245 if x.Label.IsString() && x.ArcType == ArcMember {
246 n.aStruct = s
247 n.aStructID = ci
248 }
249 fc := MakeConjunct(childEnv, x, ci)
250
251 n.insertArc(x.Label, x.ArcType, fc, ci, true)
252
253 case *LetField:
254 lc := MakeConjunct(childEnv, x, ci)
255 n.insertArc(x.Label, ArcMember, lc, ci, true)
256
257 case *Comprehension:
258 ci, cc := ci.spawnCloseContext(closeEmbed)
259 cc.incDependent(DEFER, nil)
260 defer cc.decDependent(n.ctx, DEFER, nil)
261 n.insertComprehension(childEnv, x, ci)
262 hasEmbed = true
263
264 case *Ellipsis:
265
266 ci.cc.isDef = false
267 ci.cc.isClosed = false
268
269 case *DynamicField:
270 if x.ArcType == ArcMember {
271 n.aStruct = s
272 n.aStructID = ci
273 }
274 n.scheduleTask(handleDynamic, childEnv, x, ci)
275
276 case *BulkOptionalField:
277
278
279 n.scheduleTask(handlePatternConstraint, childEnv, x, ci)
280
281 case Expr:
282
283 ci, cc := ci.spawnCloseContext(closeEmbed)
284
285
286 cc.incDependent(DEFER, nil)
287 defer cc.decDependent(n.ctx, DEFER, nil)
288
289 ec := MakeConjunct(childEnv, x, ci)
290 n.scheduleConjunct(ec, ci)
291 hasEmbed = true
292 }
293 }
294 if hasEllipsis {
295 ci.cc.hasEllipsis = true
296 }
297 if !hasEmbed {
298 n.aStruct = s
299 n.aStructID = ci
300 ci.cc.hasNonTop = true
301 }
302
303
304 parent.Disable = false
305 }
306
307
308
309 func (n *nodeContext) scheduleVertexConjuncts(c Conjunct, arc *Vertex, closeInfo CloseInfo) {
310
311 if n.node == arc {
312 return
313 }
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334 ciKey := closeInfo
335 ciKey.Refs = nil
336 ciKey.Inline = false
337 key := arcKey{arc, ciKey}
338 for _, k := range n.arcMap {
339 if key == k {
340 return
341 }
342 }
343 n.arcMap = append(n.arcMap, key)
344
345 if IsDef(c.Expr()) {
346
347 ci, dc := closeInfo.spawnCloseContext(closeDef)
348 closeInfo = ci
349
350 dc.incDependent(DEFER, nil)
351 defer dc.decDependent(n.ctx, DEFER, nil)
352 }
353
354 if state := arc.getState(n.ctx); state != nil {
355 state.addNotify2(n.node, closeInfo)
356 }
357
358 for i := 0; i < len(arc.Conjuncts); i++ {
359 c := arc.Conjuncts[i]
360
361
362
363
364
365
366
367
368 n.scheduleConjunct(c, closeInfo)
369 }
370 }
371
372 func (n *nodeContext) addNotify2(v *Vertex, c CloseInfo) []receiver {
373 n.completeNodeTasks()
374
375
376 old := n.notify
377 if n.meets(allAncestorsProcessed) {
378 return old
379 }
380
381
382
383
384
385
386
387 root := n.node.rootCloseContext()
388 if root.isDecremented {
389 return old
390 }
391
392 for _, r := range n.notify {
393 if r.v == v && r.cc == c.cc {
394 return old
395 }
396 }
397
398 cc := c.cc
399
400 if root.linkNotify(v, cc, c.CycleInfo) {
401 n.notify = append(n.notify, receiver{v, cc})
402 n.completeNodeTasks()
403 }
404
405 return old
406 }
407
408
409
410 func (n *nodeContext) insertValueConjunct(env *Environment, v Value, id CloseInfo) {
411 n.updateCyclicStatus(id)
412
413 ctx := n.ctx
414
415 switch x := v.(type) {
416 case *Vertex:
417 if m, ok := x.BaseValue.(*StructMarker); ok {
418 n.aStruct = x
419 n.aStructID = id
420 if m.NeedClose {
421
422
423
424 id.IsClosed = true
425 if ctx.isDevVersion() {
426 var cc *closeContext
427 id, cc = id.spawnCloseContext(0)
428 cc.isClosedOnce = true
429 }
430 }
431 }
432
433 if !x.IsData() {
434 c := MakeConjunct(env, x, id)
435 n.scheduleVertexConjuncts(c, x, id)
436 return
437 }
438
439
440 switch v := x.BaseValue.(type) {
441 default:
442 panic(fmt.Sprintf("invalid type %T", x.BaseValue))
443
444 case *ListMarker:
445
446 n.scheduleTask(handleListVertex, env, x, id)
447
448 return
449
450 case *StructMarker:
451 for _, a := range x.Arcs {
452 if a.ArcType != ArcMember {
453 continue
454 }
455
456 c := MakeConjunct(nil, a, id)
457 n.insertArc(a.Label, a.ArcType, c, id, true)
458 }
459
460 case Value:
461 n.insertValueConjunct(env, v, id)
462 }
463
464 return
465
466 case *Bottom:
467 id.cc.hasNonTop = true
468 n.addBottom(x)
469 return
470
471 case *Builtin:
472 id.cc.hasNonTop = true
473 if v := x.BareValidator(); v != nil {
474 n.insertValueConjunct(env, v, id)
475 return
476 }
477 }
478
479 if !n.updateNodeType(v.Kind(), v, id) {
480 return
481 }
482
483 switch x := v.(type) {
484 case *Disjunction:
485 n.addDisjunctionValue(env, x, id)
486
487 case *Conjunction:
488 for _, x := range x.Values {
489 n.insertValueConjunct(env, x, id)
490 }
491
492 case *Top:
493 n.hasTop = true
494 id.cc.hasTop = true
495
496 case *BasicType:
497 id.cc.hasNonTop = true
498
499 case *BoundValue:
500 id.cc.hasNonTop = true
501 switch x.Op {
502 case LessThanOp, LessEqualOp:
503 if y := n.upperBound; y != nil {
504 n.upperBound = nil
505 v := SimplifyBounds(ctx, n.kind, x, y)
506 if err := valueError(v); err != nil {
507 err.AddPosition(v)
508 err.AddPosition(n.upperBound)
509 err.AddClosedPositions(id)
510 }
511 n.insertValueConjunct(env, v, id)
512 return
513 }
514 n.upperBound = x
515
516 case GreaterThanOp, GreaterEqualOp:
517 if y := n.lowerBound; y != nil {
518 n.lowerBound = nil
519 v := SimplifyBounds(ctx, n.kind, x, y)
520 if err := valueError(v); err != nil {
521 err.AddPosition(v)
522 err.AddPosition(n.lowerBound)
523 err.AddClosedPositions(id)
524 }
525 n.insertValueConjunct(env, v, id)
526 return
527 }
528 n.lowerBound = x
529
530 case EqualOp, NotEqualOp, MatchOp, NotMatchOp:
531
532 k := 0
533 match := false
534 for _, c := range n.checks {
535 if y, ok := c.(*BoundValue); ok {
536 switch z := SimplifyBounds(ctx, n.kind, x, y); {
537 case z == y:
538 match = true
539 case z == x:
540 continue
541 }
542 }
543 n.checks[k] = c
544 k++
545 }
546 n.checks = n.checks[:k]
547 if !match {
548 n.checks = append(n.checks, x)
549 }
550 return
551 }
552
553 case Validator:
554
555 for i, y := range n.checks {
556 if b := SimplifyValidator(ctx, x, y); b != nil {
557 n.checks[i] = b
558 return
559 }
560 }
561 n.updateNodeType(x.Kind(), x, id)
562 n.checks = append(n.checks, x)
563
564 case *Vertex:
565
566
567 case Value:
568 if y := n.scalar; y != nil {
569 if b, ok := BinOp(ctx, EqualOp, x, y).(*Bool); !ok || !b.B {
570 n.reportConflict(x, y, x.Kind(), y.Kind(), n.scalarID, id)
571 }
572 break
573 }
574 n.scalar = x
575 n.scalarID = id
576 n.signal(scalarKnown)
577
578 default:
579 panic(fmt.Sprintf("unknown value type %T", x))
580 }
581
582 if n.lowerBound != nil && n.upperBound != nil {
583 if u := SimplifyBounds(ctx, n.kind, n.lowerBound, n.upperBound); u != nil {
584 if err := valueError(u); err != nil {
585 err.AddPosition(n.lowerBound)
586 err.AddPosition(n.upperBound)
587 err.AddClosedPositions(id)
588 }
589 n.lowerBound = nil
590 n.upperBound = nil
591 n.insertValueConjunct(env, u, id)
592 }
593 }
594 }
595
View as plain text