1 | kit = require "./kit"
|
2 | {Scope} = require "./scope"
|
3 | builder = require "./builder"
|
4 | assert = require "assert"
|
5 | config = require "./config"
|
6 | graph = require "./graph"
|
7 |
|
8 | class ParBlockNode extends graph.BlockNode
|
9 | constructor: (@sort) ->
|
10 | @reorder = @sort.reorder
|
11 | super()
|
12 | _getBuilder: ->
|
13 | return builder.empty() unless @block.length
|
14 | block = @sort @block
|
15 | cur = builder.empty()
|
16 | {reorder} = @
|
17 | for i in block
|
18 | if i.length is 1
|
19 | cur = cur.append(i[0].getBuilder())
|
20 | continue
|
21 | pure = []
|
22 | eff = []
|
23 | if reorder
|
24 | for j in i
|
25 | b = j.getBuilder()
|
26 | if j.eff
|
27 | eff.push b.toExpr()
|
28 | else
|
29 | pure.push(b.toBlock()...)
|
30 | cur = cur.append(
|
31 | builder.purePrefix(builder.pure(pure),
|
32 | builder.exprEff(kit.seq(eff...))))
|
33 | else
|
34 | last = builder.empty()
|
35 | for j in i
|
36 | b = j.getBuilder()
|
37 | if j.eff
|
38 | eff.push((last = b).toExpr())
|
39 | else
|
40 | last.append(b)
|
41 | cur = cur.append(builder.exprEff(kit.seq(eff...)))
|
42 | cur
|
43 |
|
44 | graph.regNodeType "parBlockNode", ParBlockNode
|
45 |
|
46 | Scope::seqBlockNode = Scope::blockNode
|
47 |
|
48 | Scope::blockNode = ->
|
49 | b = @policy.opts.block
|
50 | p = b.par if b?
|
51 | p = "byUsage" if p is true
|
52 | alg = blockSortAlgs[p]
|
53 | return @seqBlockNode() unless alg?
|
54 | @parBlockNode(alg)
|
55 |
|
56 | mkGroup = (reorder,order) ->
|
57 | (b) ->
|
58 | deps = []
|
59 | for i, x in b
|
60 | deps.push [i, n = []]
|
61 | for j in b[...x]
|
62 | if order(j, i)
|
63 | n.push j
|
64 | removed = {}
|
65 | res = []
|
66 | loop
|
67 | lx = []
|
68 | level = []
|
69 | for [c,d], ix in deps
|
70 | jx = 0
|
71 | loop
|
72 | break if jx is d.length
|
73 | j = d[jx]
|
74 | if removed[j.id]
|
75 | d.splice(jx, 1)
|
76 | else
|
77 | ++jx
|
78 | if d.length
|
79 | break unless reorder
|
80 | else
|
81 | lx.push ix
|
82 | level.push c
|
83 | assert.ok(level.length)
|
84 | deps.splice(ix,1) for ix in lx by -1
|
85 | removed[c.id] = true for c in level
|
86 | res.push level
|
87 | break unless deps.length
|
88 | res
|
89 |
|
90 | usedOnLeftOrder = (a,b) ->
|
91 | {uses} = a.vdeps
|
92 | for i of b.vdeps.mods
|
93 | return true if uses[i]
|
94 | return false
|
95 | usedOrder = (a,b) ->
|
96 | {uses,mods} = a.vdeps
|
97 | for i of b.vdeps.mods
|
98 | return true if uses[i] or mods[i]
|
99 | return false
|
100 |
|
101 | blockSortAlgs =
|
102 | all: (b) -> [b]
|
103 | reorderByUsage: mkGroup(true, usedOrder)
|
104 | reorderByLhsUsage: mkGroup(true, usedOnLeftOrder)
|
105 | byUsage: mkGroup(false, usedOrder)
|
106 | byLhsUsage: mkGroup(false, usedOnLeftOrder)
|
107 |
|
108 | blockSortAlgs.reorderByUsage.reorder = true
|
109 | blockSortAlgs.reorderByLhsUsage.reorder = true
|
110 | blockSortAlgs.reorderByLhsUsage.all = true
|
111 |
|
112 | class SeqBindNode extends graph.BindNode
|
113 | constructor: (body, deps) ->
|
114 | super(body, deps)
|
115 | assemblePar: (deps, cur) ->
|
116 | for i, x in deps by -1
|
117 | cur = i.append(cur)
|
118 | cur
|
119 |
|
120 | graph.regNodeType "seqBindNode", SeqBindNode
|
121 |
|
122 | Scope::defaultBindNode = Scope::bindNode
|
123 |
|
124 | Scope::bindNode = (body, deps) ->
|
125 | switch @policy.opts.expr
|
126 | when "seq" then @seqBindNode(body, deps)
|
127 | else @defaultBindNode(body, deps)
|
128 |
|
129 |
|
130 | class ParBranchedNode extends graph.BranchedNode
|
131 | constructor: (fun, template) ->
|
132 | super(fun,template)
|
133 | _getBuilder: ->
|
134 | super()
|
135 |
|
136 | Scope::seqBranchedNode = Scope::branchedNode
|
137 |
|
138 | graph.regNodeType "parBranchedNode", ParBranchedNode
|
139 |
|
140 | Scope::branchedNode = (body, deps) ->
|
141 | switch @policy.opts.branch
|
142 | when "par" then @parBranchedNode(body, deps)
|
143 | else @seqBranchedNode(body, deps)
|
144 |
|
145 |
|