1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package adt
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74 type envComprehension struct {
75 comp *Comprehension
76 vertex *Vertex
77
78
79
80 err *Bottom
81
82
83
84 envs []*Environment
85 done bool
86
87
88
89 structs []*StructLit
90 }
91
92
93
94
95 type envYield struct {
96 *envComprehension
97 leaf *Comprehension
98
99
100
101
102 self bool
103
104
105 inserted bool
106
107 env *Environment
108 id CloseInfo
109 expr Node
110 }
111
112
113
114
115 type ValueClause struct {
116 Node
117
118
119 arc *Vertex
120 }
121
122 func (v *ValueClause) yield(s *compState) {
123 s.yield(s.ctx.spawn(v.arc))
124 }
125
126
127
128
129 func (n *nodeContext) insertComprehension(
130 env *Environment,
131 c *Comprehension,
132 ci CloseInfo,
133 ) {
134
135
136
137
138
139
140
141 ec := c.comp
142 if ec == nil {
143 ec = &envComprehension{
144 comp: c,
145 vertex: n.node,
146
147 err: nil,
148 envs: nil,
149 done: false,
150 }
151 }
152
153 if ec.done && len(ec.envs) == 0 {
154 return
155 }
156
157 x := c.Value
158
159 if !n.ctx.isDevVersion() {
160 ci = ci.SpawnEmbed(c)
161 ci.closeInfo.span |= ComprehensionSpan
162 }
163
164 var decls []Decl
165 switch v := ToExpr(x).(type) {
166 case *StructLit:
167 numFixed := 0
168 var fields []Decl
169 for _, d := range v.Decls {
170 switch f := d.(type) {
171 case *Field:
172 numFixed++
173
174
175 c := &Comprehension{
176 Syntax: c.Syntax,
177 Clauses: c.Clauses,
178 Value: f,
179 arcType: f.ArcType,
180
181 comp: ec,
182 parent: c,
183 arc: n.node,
184 }
185
186 conjunct := MakeConjunct(env, c, ci)
187 n.node.state.insertFieldUnchecked(f.Label, ArcPending, conjunct)
188 fields = append(fields, f)
189
190 case *LetField:
191
192
193 numFixed++
194
195
196 c := &Comprehension{
197 Syntax: c.Syntax,
198 Clauses: c.Clauses,
199 Value: f,
200
201 comp: ec,
202 parent: c,
203 arc: n.node,
204 }
205
206 conjunct := MakeConjunct(env, c, ci)
207 arc := n.node.state.insertFieldUnchecked(f.Label, ArcMember, conjunct)
208 arc.MultiLet = f.IsMulti
209
210 fields = append(fields, f)
211
212 default:
213 decls = append(decls, d)
214 }
215 }
216
217 if len(fields) > 0 {
218
219
220
221
222
223
224 st := v
225 if len(fields) < len(v.Decls) {
226 st = &StructLit{
227 Src: v.Src,
228 Decls: fields,
229 }
230 }
231 n.node.AddStruct(st, env, ci)
232 switch {
233 case !ec.done:
234 ec.structs = append(ec.structs, st)
235 case len(ec.envs) > 0:
236 st.Init()
237 }
238 }
239
240 switch numFixed {
241 case 0:
242
243
244 case len(v.Decls):
245
246 return
247
248 default:
249
250
251 x = &StructLit{Decls: decls}
252 }
253 }
254
255 if n.ctx.isDevVersion() {
256 t := n.scheduleTask(handleComprehension, env, x, ci)
257 t.comp = ec
258 t.leaf = c
259 } else {
260 n.comprehensions = append(n.comprehensions, envYield{
261 envComprehension: ec,
262 leaf: c,
263 env: env,
264 id: ci,
265 expr: x,
266 })
267 }
268 }
269
270 type compState struct {
271 ctx *OpContext
272 comp *Comprehension
273 i int
274 f YieldFunc
275 state vertexStatus
276 }
277
278
279
280 func (c *OpContext) yield(
281 node *Vertex,
282 env *Environment,
283 comp *Comprehension,
284 state combinedFlags,
285 f YieldFunc,
286 ) *Bottom {
287 s := &compState{
288 ctx: c,
289 comp: comp,
290 f: f,
291 state: state.vertexStatus(),
292 }
293 y := comp.Clauses[0]
294
295 saved := c.PushState(env, y.Source())
296 if node != nil {
297 defer c.PopArc(c.PushArc(node))
298 }
299
300 s.i++
301 y.yield(s)
302 s.i--
303
304 return c.PopState(saved)
305 }
306
307 func (s *compState) yield(env *Environment) (ok bool) {
308 c := s.ctx
309 if s.i >= len(s.comp.Clauses) {
310 s.f(env)
311 return true
312 }
313 dst := s.comp.Clauses[s.i]
314 saved := c.PushState(env, dst.Source())
315
316 s.i++
317 dst.yield(s)
318 s.i--
319
320 if b := c.PopState(saved); b != nil {
321 c.AddBottom(b)
322 return false
323 }
324 return !c.HasErr()
325 }
326
327
328
329
330 func (n *nodeContext) injectComprehensions(state vertexStatus) (progress bool) {
331 unreachableForDev(n.ctx)
332
333 workRemaining := false
334
335
336 for i := 0; i < len(n.comprehensions); i++ {
337 d := &n.comprehensions[i]
338 if d.self || d.inserted {
339 continue
340 }
341 if err := n.processComprehension(d, state); err != nil {
342
343 if err.ForCycle && err.Value == n.node {
344 n.selfComprehensions = append(n.selfComprehensions, *d)
345 progress = true
346 d.self = true
347 return
348 }
349
350 d.err = err
351 workRemaining = true
352
353 continue
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368 }
369 progress = true
370 }
371
372 if !workRemaining {
373 n.comprehensions = n.comprehensions[:0]
374 }
375
376 return progress
377 }
378
379
380
381
382 func (n *nodeContext) injectSelfComprehensions(state vertexStatus) {
383 unreachableForDev(n.ctx)
384
385
386 for i := 0; i < len(n.selfComprehensions); i++ {
387 n.processComprehension(&n.selfComprehensions[i], state)
388 }
389 n.selfComprehensions = n.selfComprehensions[:0]
390 }
391
392
393
394
395 func (n *nodeContext) processComprehension(d *envYield, state vertexStatus) *Bottom {
396 ctx := n.ctx
397
398
399 if !d.done {
400 var envs []*Environment
401 f := func(env *Environment) {
402 envs = append(envs, env)
403 }
404
405 if err := ctx.yield(d.vertex, d.env, d.comp, oldOnly(state), f); err != nil {
406 if err.IsIncomplete() {
407 return err
408 }
409
410
411 d.done = true
412 d.inserted = true
413 if d.vertex != nil {
414 d.vertex.state.addBottom(err)
415 ctx.PopArc(d.vertex)
416 }
417 return nil
418 }
419
420 d.envs = envs
421
422 if len(d.envs) > 0 {
423 for _, s := range d.structs {
424 s.Init()
425 }
426 }
427 d.structs = nil
428 d.done = true
429 }
430
431 d.inserted = true
432
433 if len(d.envs) == 0 {
434 return nil
435 }
436
437 v := n.node
438 for c := d.leaf; c.parent != nil; c = c.parent {
439 v.updateArcType(c.arcType)
440 if v.ArcType == ArcNotPresent {
441 parent := v.Parent
442 b := parent.reportFieldCycleError(ctx, d.comp.Syntax.Pos(), v.Label)
443 d.envComprehension.vertex.state.addBottom(b)
444 ctx.current().err = b
445 ctx.current().state = taskFAILED
446 return nil
447 }
448 v = c.arc
449 }
450
451 id := d.id
452
453 for _, env := range d.envs {
454 if n.node.ArcType == ArcNotPresent {
455 b := n.node.reportFieldCycleError(ctx, d.comp.Syntax.Pos(), n.node.Label)
456 ctx.current().err = b
457 n.yield()
458 return nil
459 }
460
461 env = linkChildren(env, d.leaf)
462
463 if ctx.isDevVersion() {
464 n.scheduleConjunct(Conjunct{env, d.expr, id}, id)
465 } else {
466 n.addExprConjunct(Conjunct{env, d.expr, id}, state)
467 }
468 }
469
470 return nil
471 }
472
473
474
475 func linkChildren(env *Environment, c *Comprehension) *Environment {
476 if c.parent != nil {
477 env = linkChildren(env, c.parent)
478 env = spawn(env, c.arc)
479 }
480 return env
481 }
482
View as plain text