1 |
|
2 | (function() {
|
3 | var ParBlockNode, ParBranchedNode, Scope, SeqBindNode, assert, blockSortAlgs, builder, config, graph, kit, mkGroup, usedOnLeftOrder, usedOrder,
|
4 | extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
5 | hasProp = {}.hasOwnProperty;
|
6 |
|
7 | kit = require("./kit");
|
8 |
|
9 | Scope = require("./scope").Scope;
|
10 |
|
11 | builder = require("./builder");
|
12 |
|
13 | assert = require("assert");
|
14 |
|
15 | config = require("./config");
|
16 |
|
17 | graph = require("./graph");
|
18 |
|
19 | ParBlockNode = (function(superClass) {
|
20 | extend(ParBlockNode, superClass);
|
21 |
|
22 | function ParBlockNode(sort) {
|
23 | this.sort = sort;
|
24 | this.reorder = this.sort.reorder;
|
25 | ParBlockNode.__super__.constructor.call(this);
|
26 | }
|
27 |
|
28 | ParBlockNode.prototype._getBuilder = function() {
|
29 | var b, block, cur, eff, i, j, k, l, last, len, len1, len2, m, pure, reorder;
|
30 | if (!this.block.length) {
|
31 | return builder.empty();
|
32 | }
|
33 | block = this.sort(this.block);
|
34 | cur = builder.empty();
|
35 | reorder = this.reorder;
|
36 | for (k = 0, len = block.length; k < len; k++) {
|
37 | i = block[k];
|
38 | if (i.length === 1) {
|
39 | cur = cur.append(i[0].getBuilder());
|
40 | continue;
|
41 | }
|
42 | pure = [];
|
43 | eff = [];
|
44 | if (reorder) {
|
45 | for (l = 0, len1 = i.length; l < len1; l++) {
|
46 | j = i[l];
|
47 | b = j.getBuilder();
|
48 | if (j.eff) {
|
49 | eff.push(b.toExpr());
|
50 | } else {
|
51 | pure.push.apply(pure, b.toBlock());
|
52 | }
|
53 | }
|
54 | cur = cur.append(builder.purePrefix(builder.pure(pure), builder.exprEff(kit.seq.apply(kit, eff))));
|
55 | } else {
|
56 | last = builder.empty();
|
57 | for (m = 0, len2 = i.length; m < len2; m++) {
|
58 | j = i[m];
|
59 | b = j.getBuilder();
|
60 | if (j.eff) {
|
61 | eff.push((last = b).toExpr());
|
62 | } else {
|
63 | last.append(b);
|
64 | }
|
65 | }
|
66 | cur = cur.append(builder.exprEff(kit.seq.apply(kit, eff)));
|
67 | }
|
68 | }
|
69 | return cur;
|
70 | };
|
71 |
|
72 | return ParBlockNode;
|
73 |
|
74 | })(graph.BlockNode);
|
75 |
|
76 | graph.regNodeType("parBlockNode", ParBlockNode);
|
77 |
|
78 | Scope.prototype.seqBlockNode = Scope.prototype.blockNode;
|
79 |
|
80 | Scope.prototype.blockNode = function() {
|
81 | var alg, b, p;
|
82 | b = this.policy.opts.block;
|
83 | if (b != null) {
|
84 | p = b.par;
|
85 | }
|
86 | if (p === true) {
|
87 | p = "byUsage";
|
88 | }
|
89 | alg = blockSortAlgs[p];
|
90 | if (alg == null) {
|
91 | return this.seqBlockNode();
|
92 | }
|
93 | return this.parBlockNode(alg);
|
94 | };
|
95 |
|
96 | mkGroup = function(reorder, order) {
|
97 | return function(b) {
|
98 | var c, d, deps, i, ix, j, jx, k, l, len, len1, len2, len3, level, lx, m, n, o, q, ref, ref1, removed, res, x;
|
99 | deps = [];
|
100 | for (x = k = 0, len = b.length; k < len; x = ++k) {
|
101 | i = b[x];
|
102 | deps.push([i, n = []]);
|
103 | ref = b.slice(0, x);
|
104 | for (l = 0, len1 = ref.length; l < len1; l++) {
|
105 | j = ref[l];
|
106 | if (order(j, i)) {
|
107 | n.push(j);
|
108 | }
|
109 | }
|
110 | }
|
111 | removed = {};
|
112 | res = [];
|
113 | while (true) {
|
114 | lx = [];
|
115 | level = [];
|
116 | for (ix = m = 0, len2 = deps.length; m < len2; ix = ++m) {
|
117 | ref1 = deps[ix], c = ref1[0], d = ref1[1];
|
118 | jx = 0;
|
119 | while (true) {
|
120 | if (jx === d.length) {
|
121 | break;
|
122 | }
|
123 | j = d[jx];
|
124 | if (removed[j.id]) {
|
125 | d.splice(jx, 1);
|
126 | } else {
|
127 | ++jx;
|
128 | }
|
129 | }
|
130 | if (d.length) {
|
131 | if (!reorder) {
|
132 | break;
|
133 | }
|
134 | } else {
|
135 | lx.push(ix);
|
136 | level.push(c);
|
137 | }
|
138 | }
|
139 | assert.ok(level.length);
|
140 | for (o = lx.length - 1; o >= 0; o += -1) {
|
141 | ix = lx[o];
|
142 | deps.splice(ix, 1);
|
143 | }
|
144 | for (q = 0, len3 = level.length; q < len3; q++) {
|
145 | c = level[q];
|
146 | removed[c.id] = true;
|
147 | }
|
148 | res.push(level);
|
149 | if (!deps.length) {
|
150 | break;
|
151 | }
|
152 | }
|
153 | return res;
|
154 | };
|
155 | };
|
156 |
|
157 | usedOnLeftOrder = function(a, b) {
|
158 | var i, uses;
|
159 | uses = a.vdeps.uses;
|
160 | for (i in b.vdeps.mods) {
|
161 | if (uses[i]) {
|
162 | return true;
|
163 | }
|
164 | }
|
165 | return false;
|
166 | };
|
167 |
|
168 | usedOrder = function(a, b) {
|
169 | var i, mods, ref, uses;
|
170 | ref = a.vdeps, uses = ref.uses, mods = ref.mods;
|
171 | for (i in b.vdeps.mods) {
|
172 | if (uses[i] || mods[i]) {
|
173 | return true;
|
174 | }
|
175 | }
|
176 | return false;
|
177 | };
|
178 |
|
179 | blockSortAlgs = {
|
180 | all: function(b) {
|
181 | return [b];
|
182 | },
|
183 | reorderByUsage: mkGroup(true, usedOrder),
|
184 | reorderByLhsUsage: mkGroup(true, usedOnLeftOrder),
|
185 | byUsage: mkGroup(false, usedOrder),
|
186 | byLhsUsage: mkGroup(false, usedOnLeftOrder)
|
187 | };
|
188 |
|
189 | blockSortAlgs.reorderByUsage.reorder = true;
|
190 |
|
191 | blockSortAlgs.reorderByLhsUsage.reorder = true;
|
192 |
|
193 | blockSortAlgs.reorderByLhsUsage.all = true;
|
194 |
|
195 | SeqBindNode = (function(superClass) {
|
196 | extend(SeqBindNode, superClass);
|
197 |
|
198 | function SeqBindNode(body, deps) {
|
199 | SeqBindNode.__super__.constructor.call(this, body, deps);
|
200 | }
|
201 |
|
202 | SeqBindNode.prototype.assemblePar = function(deps, cur) {
|
203 | var i, k, x;
|
204 | for (x = k = deps.length - 1; k >= 0; x = k += -1) {
|
205 | i = deps[x];
|
206 | cur = i.append(cur);
|
207 | }
|
208 | return cur;
|
209 | };
|
210 |
|
211 | return SeqBindNode;
|
212 |
|
213 | })(graph.BindNode);
|
214 |
|
215 | graph.regNodeType("seqBindNode", SeqBindNode);
|
216 |
|
217 | Scope.prototype.defaultBindNode = Scope.prototype.bindNode;
|
218 |
|
219 | Scope.prototype.bindNode = function(body, deps) {
|
220 | switch (this.policy.opts.expr) {
|
221 | case "seq":
|
222 | return this.seqBindNode(body, deps);
|
223 | default:
|
224 | return this.defaultBindNode(body, deps);
|
225 | }
|
226 | };
|
227 |
|
228 | ParBranchedNode = (function(superClass) {
|
229 | extend(ParBranchedNode, superClass);
|
230 |
|
231 | function ParBranchedNode(fun, template) {
|
232 | ParBranchedNode.__super__.constructor.call(this, fun, template);
|
233 | }
|
234 |
|
235 | ParBranchedNode.prototype._getBuilder = function() {
|
236 | return ParBranchedNode.__super__._getBuilder.call(this);
|
237 | };
|
238 |
|
239 | return ParBranchedNode;
|
240 |
|
241 | })(graph.BranchedNode);
|
242 |
|
243 | Scope.prototype.seqBranchedNode = Scope.prototype.branchedNode;
|
244 |
|
245 | graph.regNodeType("parBranchedNode", ParBranchedNode);
|
246 |
|
247 | Scope.prototype.branchedNode = function(body, deps) {
|
248 | switch (this.policy.opts.branch) {
|
249 | case "par":
|
250 | return this.parBranchedNode(body, deps);
|
251 | default:
|
252 | return this.seqBranchedNode(body, deps);
|
253 | }
|
254 | };
|
255 |
|
256 | }).call(this);
|