UNPKG

41.1 kBJavaScriptView Raw
1// Generated by CoffeeScript 1.10.0
2(function() {
3 var BindNode, BlockNode, BranchedNode, BreakNode, ControlNode, DynNode, EffValNode, EffectfulNode, EmptyNode, JumpNode, LoopNode, Node, PlaceholderNode, PureExprNode, PureNode, ReifyNode, RepeatNode, Scope, SharedNode, ThrowNode, TryCatchNode, VarUsage, WrapNode, YieldNode, assert, builder, config, getBuilderFun, id, isSimpleExpr, kit, lookupPlaceholderTarget, regNodeType, root, simpleExpressions,
4 slice = [].slice,
5 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; },
6 hasProp = {}.hasOwnProperty;
7
8 kit = require("./kit");
9
10 Scope = require("./scope").Scope;
11
12 builder = require("./builder");
13
14 assert = require("assert");
15
16 config = require("./config");
17
18 VarUsage = builder.VarUsage;
19
20 module.exports = root = {};
21
22 root.regNodeType = regNodeType = function(n, ctr) {
23 root["" + (n[0].toUpperCase()) + (n.substr(1))] = ctr;
24 return Scope.prototype[n] = function() {
25 var args, nctr, res;
26 args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
27 args.unshift(null);
28 nctr = Function.prototype.bind.apply(ctr, args);
29 nctr.name = ctr.name;
30 res = (new nctr()).init(this);
31 return res;
32 };
33 };
34
35 id = 0;
36
37 Node = (function() {
38 function Node() {
39 this.unwindBy = {};
40 this.id = id++;
41 this.vdeps = new VarUsage();
42 }
43
44 Node.prototype.morphInit = function(other) {
45 this.setOrig(other.orig);
46 this.vdeps = other.vdeps;
47 return this;
48 };
49
50 Node.prototype.init = function(ctx) {
51 this.opts = kit.merge({}, ctx.policy.opts);
52 this.ctx = ctx;
53 this.vdeps.vars = ctx.vars;
54 this.vdeps.refs = ctx.refs;
55 return this;
56 };
57
58 Node.prototype.setOrig = function(orig) {
59 if (this.orig == null) {
60 this.orig = orig;
61 }
62 return this;
63 };
64
65 Node.prototype.setParent = function(parent) {
66 this.parent = parent;
67 return this;
68 };
69
70 Node.prototype.getFullBlock = function(eff) {
71 eff = eff && this.opts.coerce === "none";
72 return this.getBuilder().toBlock(eff);
73 };
74
75 Node.prototype.getFullExpr = function(eff) {
76 eff = eff && this.opts.coerce === "none";
77 return this.getBuilder().toExpr(eff);
78 };
79
80 Node.prototype.fwdPass = function(use) {
81 if (!this._fwdPassDone) {
82 this._fwdPassDone = true;
83 this.vdeps.setBefore(use);
84 this._fwdPass(use);
85 kit.extend(use, this.vdeps.uses);
86 }
87 if (this.parent != null) {
88 this.parent.vdeps.addInner(this.vdeps);
89 }
90 return this;
91 };
92
93 Node.prototype._fwdPass = function(use) {};
94
95 Node.prototype.backPass = function(use) {
96 if (this.eff) {
97 this.propagateEff();
98 }
99 kit.extend(this.vdeps.after, use);
100 this._backPass(use);
101 kit.extend(use, this.vdeps.uses);
102 return this;
103 };
104
105 Node.prototype._backPass = function() {};
106
107 Node.prototype.propagateEff = function() {
108 if (this._propagateEffDone) {
109 return this;
110 }
111 return this._propagateEff();
112 };
113
114 Node.prototype._propagateEff = function() {
115 this._propagateEffDone = true;
116 this.eff = true;
117 this.ctx.eff = true;
118 return this;
119 };
120
121 Node.prototype.getBuilder = function() {
122 var b;
123 b = (function(_this) {
124 return function() {
125 if (_this.isEmpty()) {
126 return builder.empty();
127 }
128 if (!_this.eff) {
129 if (_this.orig) {
130 return builder.pure(kit.blockStmts(_this.orig));
131 }
132 }
133 return _this._getBuilder();
134 };
135 })(this)();
136 return b.setOpts(this.opts).mergeEnv(this.vdeps);
137 };
138
139 Node.prototype.ignoreResult = function() {
140 this.ignoreResult = true;
141 return this;
142 };
143
144 return Node;
145
146 })();
147
148 root.Node = Node;
149
150 EffectfulNode = (function(superClass) {
151 extend(EffectfulNode, superClass);
152
153 function EffectfulNode() {
154 EffectfulNode.__super__.constructor.call(this);
155 }
156
157 EffectfulNode.prototype.eff = true;
158
159 return EffectfulNode;
160
161 })(Node);
162
163 PureNode = (function(superClass) {
164 extend(PureNode, superClass);
165
166 function PureNode(block1) {
167 this.block = block1;
168 PureNode.__super__.constructor.call(this);
169 if (this.block == null) {
170 this.block = [];
171 }
172 }
173
174 PureNode.prototype.eff = false;
175
176 PureNode.prototype._getBuilder = function() {
177 return builder.pure(this.block);
178 };
179
180 PureNode.prototype.pureBlock = function() {
181 return this.block;
182 };
183
184 return PureNode;
185
186 })(Node);
187
188 PureExprNode = (function(superClass) {
189 extend(PureExprNode, superClass);
190
191 function PureExprNode(pureExpr) {
192 this.pureExpr = pureExpr;
193 PureExprNode.__super__.constructor.call(this, [kit.ret(this.pureExpr)]);
194 }
195
196 PureExprNode.prototype.setExpr = function(pureExpr) {
197 this.pureExpr = pureExpr;
198 this.block = [kit.ret(this.pureExpr)];
199 return this;
200 };
201
202 PureExprNode.prototype._getBuilder = function() {
203 return builder.exprPure(this.pureExpr);
204 };
205
206 PureExprNode.prototype.ignoreResult = function() {
207 return this.ctx.pureNode([kit.exprStmt(this.pureExpr)]).morphInit(this);
208 };
209
210 return PureExprNode;
211
212 })(PureNode);
213
214 regNodeType("pureNode", PureNode);
215
216 regNodeType("pureExprNode", PureExprNode);
217
218 Scope.prototype.exprNode = function(e) {
219 return (this.policy.opts.bind ? new EffValNode(e) : new PureExprNode(e)).init(this);
220 };
221
222 Scope.prototype.pureExprNode = function(e) {
223 return new PureExprNode(e).init(this);
224 };
225
226 EmptyNode = (function(superClass) {
227 extend(EmptyNode, superClass);
228
229 function EmptyNode() {
230 EmptyNode.__super__.constructor.call(this, []);
231 this.orig = {
232 type: "EmptyStatement"
233 };
234 }
235
236 EmptyNode.prototype.setOrig = function() {
237 return this;
238 };
239
240 EmptyNode.prototype.getBuilder = function() {
241 return builder.empty().setOpts(this.opts).mergeEnv(this.vdeps);
242 };
243
244 return EmptyNode;
245
246 })(PureNode);
247
248 regNodeType("emptyNode", EmptyNode);
249
250 DynNode = (function(superClass) {
251 extend(DynNode, superClass);
252
253 function DynNode() {
254 DynNode.__super__.constructor.call(this);
255 }
256
257 DynNode.prototype._propagateEff = function() {
258 DynNode.__super__._propagateEff.call(this);
259 if (this.parent != null) {
260 this.parent.propagateEff();
261 }
262 return this;
263 };
264
265 return DynNode;
266
267 })(Node);
268
269 ReifyNode = (function(superClass) {
270 extend(ReifyNode, superClass);
271
272 function ReifyNode() {
273 ReifyNode.__super__.constructor.call(this);
274 }
275
276 ReifyNode.prototype.eff = false;
277
278 ReifyNode.prototype.setBody = function(body1) {
279 this.body = body1;
280 this.body.setParent(this);
281 return this;
282 };
283
284 ReifyNode.prototype.setIsThunk = function(isThunk) {
285 this.isThunk = isThunk;
286 return this;
287 };
288
289 ReifyNode.prototype.setVar = function(_var) {
290 this["var"] = _var;
291 return this;
292 };
293
294 ReifyNode.prototype._backPass = function(use) {
295 return this.body.backPass(use);
296 };
297
298 ReifyNode.prototype._fwdPass = function(use) {
299 return this.body.fwdPass(use);
300 };
301
302 ReifyNode.prototype._propagateEff = function() {
303 return this;
304 };
305
306 ReifyNode.prototype.getBuilder = function() {
307 var e, expr;
308 e = this.isThunk ? this.body.getBuilder().toExpr(true) : kit.fun([], this.body.getBuilder().toBlock(true));
309 expr = kit.call(kit.packId("reify"), [e]);
310 if (this["var"]) {
311 return builder.pure([kit.varDecl(this["var"], expr)]).mergeEnv(this.vdeps);
312 }
313 return builder.exprPure(expr).mergeEnv(this.vdeps);
314 };
315
316 return ReifyNode;
317
318 })(Node);
319
320 regNodeType("reifyNode", ReifyNode);
321
322 BlockNode = (function(superClass) {
323 extend(BlockNode, superClass);
324
325 function BlockNode() {
326 BlockNode.__super__.constructor.call(this);
327 this.block = [];
328 this.placeholders = [];
329 }
330
331 BlockNode.prototype.append = function() {
332 var c, i, len, m, x;
333 c = 1 <= arguments.length ? slice.call(arguments, 0) : [];
334 for (x = m = 0, len = c.length; m < len; x = ++m) {
335 i = c[x];
336 if (!((i != null) && !i.isEmpty())) {
337 continue;
338 }
339 i.setParent(this);
340 if (i.eff) {
341 this.eff = true;
342 }
343 this.block.push(i);
344 }
345 return this;
346 };
347
348 BlockNode.prototype._getBuilder = function() {
349 var block, cur, i, len, m, x;
350 cur = builder.empty();
351 block = this.block;
352 for (x = m = 0, len = block.length; m < len; x = ++m) {
353 i = block[x];
354 cur = cur.append(i.getBuilder());
355 }
356 return cur;
357 };
358
359 BlockNode.prototype.addPlaceholder = function(e, p) {
360 var base, x;
361 x = this.block.indexOf(e);
362 assert.ok(x >= 0);
363 return ((base = this.placeholders)[x] != null ? base[x] : base[x] = []).push(p);
364 };
365
366 BlockNode.prototype._fwdPass = function(use) {
367 var b, c, i, j, len, len1, m, n, nb, o, ouse, q, ref, ref1, s, x;
368 this.placeholders = [];
369 ouse = kit.extend({}, use);
370 ref = this.block;
371 for (x = m = 0, len = ref.length; m < len; x = ++m) {
372 i = ref[x];
373 i.fwdPass(use);
374 }
375 if (this.placeholders.length) {
376 c = this;
377 ref1 = this.placeholders;
378 for (x = o = ref1.length - 1; o >= 0; x = o += -1) {
379 i = ref1[x];
380 if (!(i)) {
381 continue;
382 }
383 b = c.block;
384 n = b.splice(0, x);
385 nb = (function() {
386 var ref2;
387 switch (n.length) {
388 case 0:
389 return this.ctx.emptyNode();
390 case 1:
391 return n[0];
392 default:
393 return c = (ref2 = this.ctx.blockNode()).append.apply(ref2, n).fwdPass(ouse);
394 }
395 }).call(this);
396 s = {};
397 for (q = 0, len1 = i.length; q < len1; q++) {
398 j = i[q];
399 j.setBlock(nb, b, s);
400 }
401 }
402 }
403 return delete this.placeholders;
404 };
405
406 BlockNode.prototype._backPass = function(use) {
407 var eff, f, i, len, m, o, ref, ref1;
408 eff = this.eff;
409 if (!eff) {
410 ref = this.block;
411 for (m = 0, len = ref.length; m < len; m++) {
412 f = ref[m];
413 if (f.eff) {
414 eff = true;
415 break;
416 }
417 }
418 }
419 ref1 = this.block;
420 for (o = ref1.length - 1; o >= 0; o += -1) {
421 i = ref1[o];
422 i.backPass(use);
423 }
424 if (eff) {
425 this._propagateEff();
426 }
427 return this;
428 };
429
430 BlockNode.prototype.last = function() {
431 return this.block[this.block.length - 1];
432 };
433
434 return BlockNode;
435
436 })(DynNode);
437
438 regNodeType("blockNode", BlockNode);
439
440 Node.prototype.getTail = function() {
441 return this;
442 };
443
444 Scope.prototype.nodes = function() {
445 var arr, i, len, m, ref, res, walk;
446 arr = 1 <= arguments.length ? slice.call(arguments, 0) : [];
447 if (arr.length === 1) {
448 return arr[0];
449 }
450 res = [];
451 walk = function(n) {
452 var i, len, m, ref, results;
453 if (n instanceof BlockNode) {
454 ref = n.block;
455 results = [];
456 for (m = 0, len = ref.length; m < len; m++) {
457 i = ref[m];
458 results.push(walk(i));
459 }
460 return results;
461 } else {
462 return res.push(n);
463 }
464 };
465 for (m = 0, len = arr.length; m < len; m++) {
466 i = arr[m];
467 walk(i);
468 }
469 if (!res.length) {
470 return this.emptyNode();
471 }
472 if (res.length === 1) {
473 return res[0];
474 }
475 return (ref = this.blockNode()).append.apply(ref, arr);
476 };
477
478 Node.prototype.append = function() {
479 var args, ref;
480 args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
481 return (ref = this.ctx).nodes.apply(ref, [this].concat(slice.call(args)));
482 };
483
484 EmptyNode.prototype.append = function() {
485 var f, nxt;
486 f = arguments[0], nxt = 2 <= arguments.length ? slice.call(arguments, 1) : [];
487 if (nxt.length) {
488 return f.append.apply(f, nxt);
489 }
490 return f;
491 };
492
493 PureNode.prototype.append = function() {
494 var f, nxt, ref;
495 f = arguments[0], nxt = 2 <= arguments.length ? slice.call(arguments, 1) : [];
496 if (f.pureBlock != null) {
497 (ref = this.block).push.apply(ref, f.pureBlock());
498 if (nxt.length) {
499 return this.append.apply(this, nxt);
500 }
501 return this;
502 }
503 return PureNode.__super__.append.apply(this, [f].concat(slice.call(nxt)));
504 };
505
506 Node.prototype.fullDeps = function() {};
507
508 Node.prototype.setPosition = function(exprPos) {
509 this.exprPos = exprPos;
510 return this;
511 };
512
513 Node.prototype.fullDeps = function(pos, deps) {
514 if (this.exprPos) {
515 pos.push(this.exprPos);
516 return deps.push(this);
517 }
518 };
519
520 PureNode.prototype.fullDeps = function() {
521 var p, px, ref;
522 if (this.exprPos) {
523 ref = this.exprPos, p = ref[0], px = ref[1];
524 return p[px] = kit.lit(null);
525 }
526 };
527
528 PureExprNode.prototype.fullDeps = function(pos, deps) {
529 var p, px, ref;
530 if (this.exprPos) {
531 if (this.vdeps.mod) {
532 pos.push(this.exprPos);
533 return deps.push(this);
534 } else {
535 ref = this.exprPos, p = ref[0], px = ref[1];
536 return p[px] = this.pureExpr;
537 }
538 }
539 };
540
541 EffValNode = (function(superClass) {
542 extend(EffValNode, superClass);
543
544 function EffValNode(val1) {
545 this.val = val1;
546 EffValNode.__super__.constructor.call(this);
547 }
548
549 EffValNode.prototype.ignoreResult = function() {
550 this.noRes = true;
551 return this;
552 };
553
554 EffValNode.prototype._getBuilder = function() {
555 return builder.exprEffCoerce(this.val);
556 };
557
558 return EffValNode;
559
560 })(EffectfulNode);
561
562 regNodeType("effValNode", EffValNode);
563
564 lookupPlaceholderTarget = function() {
565 var i, p;
566 i = this;
567 while (true) {
568 p = i.parent;
569 if (p == null) {
570 break;
571 }
572 if (p.addPlaceholder != null) {
573 p.addPlaceholder(i, this);
574 break;
575 }
576 i = p;
577 }
578 return this;
579 };
580
581 PlaceholderNode = (function(superClass) {
582 extend(PlaceholderNode, superClass);
583
584 function PlaceholderNode(arg) {
585 this.arg = arg;
586 PlaceholderNode.__super__.constructor.call(this);
587 }
588
589 PlaceholderNode.prototype.setExpr = function(expr) {
590 if (!this.arg) {
591 return PlaceholderNode.__super__.setExpr.call(this, expr);
592 }
593 return PlaceholderNode.__super__.setExpr.call(this, kit.mapply([expr], kit.fun([], [kit.ret(this.arg)])));
594 };
595
596 PlaceholderNode.prototype.setBlock = function(n, b, s) {
597 var i, vn;
598 vn = s.vn;
599 this.depBlock = n;
600 if (s.vn == null) {
601 this.prim = true;
602 s.vn = vn = this.ctx.uniqId("n");
603 b.unshift(this.ctx.reifyNode().setBody(n).setVar(vn).setParent(this));
604 for (i in n.vdeps.mods) {
605 this.ctx.refs[i] = true;
606 }
607 }
608 return this.setExpr(vn);
609 };
610
611 PlaceholderNode.prototype._fwdPass = function(use) {
612 return lookupPlaceholderTarget.call(this);
613 };
614
615 return PlaceholderNode;
616
617 })(PureExprNode);
618
619 Node.prototype.fillPlaceholder = function(p) {
620 return this.parent.fillPlaceholder(p, this);
621 };
622
623 BlockNode.prototype.fillPlaceholder = function(p) {
624 var block, x;
625 block = this.block;
626 x = block.indexOf(n);
627 return assert.ok(x >= 0);
628 };
629
630 regNodeType("placeholderNode", PlaceholderNode);
631
632 Node.prototype.setExprPos = function(exprPos) {
633 this.exprPos = exprPos;
634 return this;
635 };
636
637 BindNode = (function(superClass) {
638 extend(BindNode, superClass);
639
640 function BindNode(body, deps) {
641 BindNode.__super__.constructor.call(this);
642 this.setDeps(deps);
643 this.setBody(body);
644 }
645
646 BindNode.prototype.bindNode = true;
647
648 BindNode.prototype.setBody = function(body) {
649 if (body != null) {
650 body.setParent(this);
651 }
652 this.body = body;
653 return this;
654 };
655
656 BindNode.prototype.setDeps = function(deps) {
657 var i, len, m;
658 for (m = 0, len = deps.length; m < len; m++) {
659 i = deps[m];
660 i.setParent(this);
661 }
662 this.deps = deps;
663 return this;
664 };
665
666 BindNode.prototype._fullDeps = function(pos, deps) {
667 var i, len, m, ref, x;
668 this.body.fullDeps(pos, deps);
669 ref = this.deps;
670 for (x = m = 0, len = ref.length; m < len; x = ++m) {
671 i = ref[x];
672 i.fullDeps(pos, deps);
673 }
674 };
675
676 BindNode.prototype.fullDeps = function(pos, deps) {
677 if (this.body.eff) {
678 return BindNode.__super__.fullDeps.call(this, pos, deps);
679 } else {
680 return this._fullDeps(pos, deps);
681 }
682 };
683
684 BindNode.prototype.assemblePar = function(deps, cur) {
685 return builder.par(deps, cur);
686 };
687
688 BindNode.prototype._getBuilder = function() {
689 var b, commit, cur, deps, e, eargs, eb, m, nxt, p, pos, px, ref, shallow, x;
690 pos = [];
691 eargs = [];
692 this._fullDeps(pos, eargs);
693 deps = [];
694 cur = this.body.getBuilder();
695 shallow = true;
696 commit = (function(_this) {
697 return function() {
698 switch (deps.length) {
699 case 0:
700 return cur;
701 case 1:
702 cur = deps[0].append(cur);
703 break;
704 default:
705 cur = _this.assemblePar(deps, cur);
706 }
707 deps = [];
708 return cur;
709 };
710 })(this);
711 for (x = m = pos.length - 1; m >= 0; x = m += -1) {
712 ref = pos[x], p = ref[0], px = ref[1];
713 e = eargs[x];
714 if (!e.eff) {
715 if (!e.vdeps.mod) {
716 eb = e.getBuilder().toExprBuilder();
717 cur.pushEnv(eb.env);
718 p[px] = eb.expr;
719 continue;
720 }
721 if (shallow) {
722 eb = e.getBuilder().toExprBuilder();
723 p[px] = eb.expr;
724 nxt = commit();
725 cur = builder.pure([]).pushEnv(eb.env).setOpts(this.opts).append(nxt);
726 continue;
727 }
728 }
729 b = e.getBuilder().setBindVar(p[px] = this.ctx.uniqId("b"));
730 if (e.vdeps.mod) {
731 cur = b.append(commit());
732 } else {
733 deps.unshift(b);
734 }
735 shallow = false;
736 }
737 return commit();
738 };
739
740 BindNode.prototype.ignoreResult = function() {
741 BindNode.__super__.ignoreResult.call(this);
742 this.setBody(this.body.ignoreResult());
743 return this;
744 };
745
746 BindNode.prototype._backPass = function(use) {
747 var eff, i, len, m, o, ref, ref1;
748 this.body.backPass(use);
749 ref = this.deps;
750 for (m = ref.length - 1; m >= 0; m += -1) {
751 i = ref[m];
752 i.backPass(use);
753 }
754 ref1 = this.deps;
755 for (o = 0, len = ref1.length; o < len; o++) {
756 i = ref1[o];
757 eff = eff || i.eff;
758 }
759 eff || (eff = this.eff || this.body.eff);
760 if (eff) {
761 this.propagateEff();
762 }
763 return this;
764 };
765
766 BindNode.prototype._fwdPass = function(use) {
767 var block, i, len, m, ref;
768 block = this.block;
769 ref = this.deps;
770 for (m = 0, len = ref.length; m < len; m++) {
771 i = ref[m];
772 i.fwdPass(use);
773 }
774 return this.body.fwdPass(use);
775 };
776
777 return BindNode;
778
779 })(DynNode);
780
781 regNodeType("bindNode", BindNode);
782
783 simpleExpressions = {
784 Literal: true,
785 Identifier: true
786 };
787
788 isSimpleExpr = function(e) {
789 return simpleExpressions[e.type];
790 };
791
792 SharedNode = (function(superClass) {
793 extend(SharedNode, superClass);
794
795 function SharedNode(def, body) {
796 SharedNode.__super__.constructor.call(this);
797 this.setDef(def);
798 this.setBody(body);
799 this.refs = [];
800 }
801
802 SharedNode.prototype.setDef = function(def1) {
803 this.def = def1;
804 if (this.def) {
805 this.def.setParent(this);
806 if (this.def.eff) {
807 this.eff = true;
808 }
809 }
810 return this;
811 };
812
813 SharedNode.prototype.setBody = function(body1) {
814 this.body = body1;
815 if (this.body) {
816 this.body.setParent(this);
817 if (this.body.eff) {
818 this.eff = true;
819 }
820 }
821 return this;
822 };
823
824 SharedNode.prototype.init = function(ctx) {
825 if (this.def.pureExpr && isSimpleExpr(this.def.pureExpr)) {
826 this._ref = this.def.pureExpr;
827 this._simplExpr = true;
828 } else {
829 this._ref = this.name = ctx.uniqId("s");
830 }
831 return SharedNode.__super__.init.call(this, ctx);
832 };
833
834 SharedNode.prototype._getBuilder = function() {
835 if (this._simplExpr) {
836 return this.body.getBuilder();
837 }
838 if (this.def.pureExpr != null) {
839 return builder.pure([kit.varDecl(this.name, this.def.pureExpr)]).mergeEnv(this.def.vdeps).append(this.body.getBuilder());
840 } else {
841 return builder.par([this.def.getBuilder().setBindVar(this.name)], this.body.getBuilder());
842 }
843 };
844
845 SharedNode.prototype.ignoreResult = function() {
846 SharedNode.__super__.ignoreResult.call(this);
847 this.setBody(this.body.ignoreResult());
848 return this;
849 };
850
851 SharedNode.prototype._backPass = function(use) {
852 var eff;
853 this.body.backPass(use);
854 this.def.backPass(use);
855 eff = this.eff || this.body.eff || this.def.eff;
856 if (eff) {
857 this.propagateEff();
858 }
859 return this;
860 };
861
862 SharedNode.prototype._fwdPass = function(use) {
863 var block;
864 block = this.block;
865 this.def.fwdPass(use);
866 return this.body.fwdPass(use);
867 };
868
869 return SharedNode;
870
871 })(DynNode);
872
873 regNodeType("sharedNode", SharedNode);
874
875 JumpNode = (function(superClass) {
876 extend(JumpNode, superClass);
877
878 function JumpNode(dst1, kind) {
879 this.dst = dst1;
880 this.kind = kind;
881 JumpNode.__super__.constructor.call(this);
882 this.vdeps.skipMods();
883 }
884
885 JumpNode.prototype.setDst = function(dst1) {
886 this.dst = dst1;
887 return this;
888 };
889
890 JumpNode.prototype._fwdPass = function(use) {
891 var i;
892 if (this.val) {
893 this.val.fwdPass(use);
894 }
895 i = this;
896 while (true) {
897 i = i.parent;
898 if ((i == null) || i === this.dst) {
899 break;
900 }
901 i.unwindBy[this.id] = this;
902 }
903 };
904
905 return JumpNode;
906
907 })(DynNode);
908
909 BreakNode = (function(superClass) {
910 extend(BreakNode, superClass);
911
912 function BreakNode(dst, val, name) {
913 BreakNode.__super__.constructor.call(this, dst, name != null ? name : "brk");
914 this.setVal(val);
915 }
916
917 BreakNode.prototype.setVal = function(val1) {
918 this.val = val1;
919 if (this.val) {
920 this.val.setParent(this);
921 }
922 return this;
923 };
924
925 BreakNode.prototype._getBuilder = function() {
926 var expr, lab, thread, vexpr;
927 if (this.ret) {
928 if (this.val) {
929 return this.val.getBuilder();
930 }
931 return builder.empty();
932 }
933 lab = this.dst.getLabel();
934 if (this.val) {
935 if (this.val != null) {
936 vexpr = this.val.getBuilder().coerceObj().toExpr();
937 }
938 expr = this.val.eff ? kit.mbind([vexpr], lab) : kit.call(lab, [vexpr]);
939 } else {
940 thread = this.dst.thread;
941 if (thread.length > 1) {
942 thread = [kit.arr(thread)];
943 }
944 expr = kit.call(lab, thread);
945 }
946 return builder.exprEff(expr).noCapture().setBrk(true);
947 };
948
949 BreakNode.prototype._backPass = function(use) {
950 var eff;
951 eff = this.eff;
952 if (this.val) {
953 this.val.backPass(use);
954 eff || (eff = this.val.eff);
955 }
956 if (eff) {
957 this.propagateEff();
958 }
959 return this;
960 };
961
962 return BreakNode;
963
964 })(JumpNode);
965
966 YieldNode = (function(superClass) {
967 extend(YieldNode, superClass);
968
969 function YieldNode(dst, val) {
970 YieldNode.__super__.constructor.call(this, dst, val);
971 this.eff = true;
972 }
973
974 YieldNode.prototype.ignoreResult = function() {
975 return this;
976 };
977
978 YieldNode.prototype.setBlock = function(block1) {
979 this.block = block1;
980 return this;
981 };
982
983 YieldNode.prototype._getBuilder = function() {
984 var b;
985 b = this.block.getBuilder().append(YieldNode.__super__._getBuilder.call(this)).setOpts(this.opts).mergeEnv(this.vdeps).toExprBuilder();
986 return builder.exprEff(kit.call(kit.mem(b.expr, kit.id("mopt")), [])).morph(b);
987 };
988
989 YieldNode.prototype._fwdPass = function(use) {
990 this.dst.opts.keepScope = true;
991 return lookupPlaceholderTarget.call(this);
992 };
993
994 YieldNode.prototype._backPass = function(use) {
995 this.propagateEff();
996 return this.block.backPass(use);
997 };
998
999 return YieldNode;
1000
1001 })(BreakNode);
1002
1003 regNodeType("breakNode", BreakNode);
1004
1005 regNodeType("yieldNode", YieldNode);
1006
1007 BranchedNode = (function(superClass) {
1008 extend(BranchedNode, superClass);
1009
1010 function BranchedNode(fun1, template) {
1011 this.fun = fun1;
1012 this.template = template;
1013 BranchedNode.__super__.constructor.call(this);
1014 this.deps = [];
1015 }
1016
1017 BranchedNode.prototype.setDeps = function() {
1018 var cur, deps, i, len, m;
1019 deps = 1 <= arguments.length ? slice.call(arguments, 0) : [];
1020 cur = this.deps;
1021 cur.length = 0;
1022 if (deps != null) {
1023 for (m = 0, len = deps.length; m < len; m++) {
1024 i = deps[m];
1025 i.setParent(this);
1026 cur.push(i);
1027 }
1028 }
1029 return this;
1030 };
1031
1032 BranchedNode.prototype._getItemBuilder = function(i) {
1033 return i.getBuilder();
1034 };
1035
1036 BranchedNode.prototype._getBuilder = function() {
1037 var block, blocks, bn, cb, eff, i, j, len, len1, m, needCoerce, nenv, o, ref, ref1, ref2, threadOut, v, w;
1038 eff = this.eff;
1039 threadOut = {};
1040 nenv = {};
1041 ref = this.deps;
1042 for (m = 0, len = ref.length; m < len; m++) {
1043 i = ref[m];
1044 i.vdeps.threadOutMap(threadOut);
1045 }
1046 blocks = [];
1047 needCoerce = false;
1048 ref1 = this.deps;
1049 for (o = 0, len1 = ref1.length; o < len1; o++) {
1050 i = ref1[o];
1051 cb = this._getItemBuilder(i);
1052 cb = cb.addThread(threadOut);
1053 bn = cb.capture().toBlockBuilder(eff);
1054 needCoerce || (needCoerce = bn._needCoerce === true);
1055 ref2 = bn.env;
1056 for (j in ref2) {
1057 v = ref2[j];
1058 w = nenv[j] != null ? nenv[j] : nenv[j] = {};
1059 if (v.use) {
1060 w.use = true;
1061 }
1062 if (v.set) {
1063 w.set = true;
1064 }
1065 if (v.mod) {
1066 w.mod = true;
1067 }
1068 if (threadOut[j]) {
1069 w.thread = true;
1070 }
1071 }
1072 blocks.push(kit.flatBlock(bn.block));
1073 }
1074 block = builder.block(eff, [this.fun.apply(this, blocks)]).pushEnv(nenv).noCapture().needCoerce(needCoerce != null ? needCoerce : false);
1075 return block;
1076 };
1077
1078 BranchedNode.prototype._propagateEff = function() {
1079 var deps, i, len, m, x;
1080 BranchedNode.__super__._propagateEff.call(this);
1081 deps = this.deps;
1082 for (x = m = 0, len = deps.length; m < len; x = ++m) {
1083 i = deps[x];
1084 deps[x] = i.propagateEff();
1085 }
1086 return this;
1087 };
1088
1089 BranchedNode.prototype._backPass = function(use) {
1090 var i, len, len1, len2, m, o, q, ref, ref1, ref2;
1091 if (!this.eff) {
1092 ref = this.deps;
1093 for (m = 0, len = ref.length; m < len; m++) {
1094 i = ref[m];
1095 if (!i.eff) {
1096 continue;
1097 }
1098 this.eff = true;
1099 break;
1100 }
1101 }
1102 if (this.eff) {
1103 this._propagateEff();
1104 }
1105 ref1 = this.deps;
1106 for (o = 0, len1 = ref1.length; o < len1; o++) {
1107 i = ref1[o];
1108 i.backPass(kit.extend({}, use));
1109 }
1110 ref2 = this.deps;
1111 for (q = 0, len2 = ref2.length; q < len2; q++) {
1112 i = ref2[q];
1113 kit.extend(use, i.vdeps.uses);
1114 }
1115 return this;
1116 };
1117
1118 BranchedNode.prototype._fwdPass = function(use) {
1119 var i, len, m, ref;
1120 ref = this.deps;
1121 for (m = 0, len = ref.length; m < len; m++) {
1122 i = ref[m];
1123 i.fwdPass(kit.extend({}, use));
1124 }
1125 };
1126
1127 return BranchedNode;
1128
1129 })(DynNode);
1130
1131 regNodeType("branchedNode", BranchedNode);
1132
1133 WrapNode = (function(superClass) {
1134 extend(WrapNode, superClass);
1135
1136 function WrapNode(body) {
1137 WrapNode.__super__.constructor.call(this);
1138 this.setBody(body);
1139 }
1140
1141 WrapNode.prototype.setBody = function(body1) {
1142 this.body = body1;
1143 if (this.body != null) {
1144 this.body.setParent(this);
1145 }
1146 return this;
1147 };
1148
1149 WrapNode.prototype._backPass = function(use) {
1150 if (this.eff || this.body.eff) {
1151 this._propagateEff();
1152 }
1153 this.body.backPass(use);
1154 return this;
1155 };
1156
1157 WrapNode.prototype._fwdPass = function(use) {
1158 return this.body.fwdPass(use);
1159 };
1160
1161 return WrapNode;
1162
1163 })(DynNode);
1164
1165 getBuilderFun = function(node, ctx) {
1166 var b, fun, i, thread, vars;
1167 thread = node.vdeps.threadOutMap();
1168 b = node.getBuilder();
1169 if (thread != null) {
1170 b.addThread(thread);
1171 }
1172 b = b.capture().toBlockBuilder();
1173 for (i in b.env) {
1174 if (i.thread) {
1175 thread[i] = true;
1176 }
1177 }
1178 vars = ((function() {
1179 var results;
1180 results = [];
1181 for (i in thread) {
1182 results.push(i);
1183 }
1184 return results;
1185 })()).sort().map(kit.id);
1186 fun = kit.spreadFun(vars, kit.fun(vars, b.block));
1187 return [fun, vars, b, thread];
1188 };
1189
1190 RepeatNode = (function(superClass) {
1191 extend(RepeatNode, superClass);
1192
1193 function RepeatNode(body) {
1194 RepeatNode.__super__.constructor.call(this, body);
1195 }
1196
1197 RepeatNode.prototype._getBuilder = function() {
1198 var b, expr, fun, ref, vars;
1199 ref = getBuilderFun(this.body, this.ctx), fun = ref[0], vars = ref[1], b = ref[2];
1200 if (vars.length > 1) {
1201 vars = [kit.arr(vars)];
1202 }
1203 expr = kit.call(kit.packId("repeat"), [fun].concat(slice.call(vars)));
1204 return builder.exprEff(expr).morph(b).mergeEnv(this.vdeps).noCapture();
1205 };
1206
1207 RepeatNode.prototype._fwdPass = function(use) {
1208 return this.body.fwdPass({});
1209 };
1210
1211 RepeatNode.prototype._backPass = function(use) {
1212 var i;
1213 for (i in this.body.vdeps.uses) {
1214 use[i] = true;
1215 }
1216 return RepeatNode.__super__._backPass.call(this, use);
1217 };
1218
1219 return RepeatNode;
1220
1221 })(WrapNode);
1222
1223 regNodeType("repeatNode", RepeatNode);
1224
1225 ControlNode = (function(superClass) {
1226 extend(ControlNode, superClass);
1227
1228 function ControlNode(kind) {
1229 this.kind = kind;
1230 this.exits = [];
1231 if (this.kind == null) {
1232 this.kind = "block";
1233 }
1234 this.labCount = 0;
1235 this.thread = [];
1236 ControlNode.__super__.constructor.call(this);
1237 }
1238
1239 ControlNode.prototype.setLabel = function(lab) {
1240 if (lab == null) {
1241 lab = "l";
1242 }
1243 this.label = this.ctx.uniqId(lab);
1244 return this;
1245 };
1246
1247 ControlNode.prototype.getLabel = function() {
1248 if (this.label != null) {
1249 return this.label;
1250 }
1251 return this.label = this.ctx.uniqId("l");
1252 };
1253
1254 ControlNode.prototype.breakNode = function(v) {
1255 var res;
1256 res = this.ctx.breakNode(this, v);
1257 this.exits.push(res);
1258 return res;
1259 };
1260
1261 ControlNode.prototype.yieldNode = function(v) {
1262 var res;
1263 res = this.ctx.yieldNode(this, v);
1264 this.exits.push(res);
1265 return res;
1266 };
1267
1268 ControlNode.prototype.trimExits = function(loopBody) {
1269 var i, j, k, x;
1270 if (!this.opts.keepScope) {
1271 if (this.exits.length === 1) {
1272 i = j = this.exits[0];
1273 while (true) {
1274 k = i;
1275 i = i.parent;
1276 if (i === this || i === loopBody) {
1277 j.ret = true;
1278 this.exits.length = 0;
1279 break;
1280 }
1281 if (i instanceof BlockNode) {
1282 x = i.block.indexOf(k);
1283 if (x < 0) {
1284 return this;
1285 }
1286 i.block.splice(x + 1, i.block.length);
1287 continue;
1288 }
1289 if (!(i instanceof BindNode)) {
1290 return;
1291 }
1292 }
1293 }
1294 }
1295 };
1296
1297 ControlNode.prototype._getBuilder = function() {
1298 var b, bodyBlock, i, thread;
1299 this.trimExits();
1300 if (!(this.exits.length && this.eff)) {
1301 return this.body.getBuilder();
1302 }
1303 if (this.kind !== "scope") {
1304 thread = this.body.vdeps.threadOutMap();
1305 this.thread = ((function() {
1306 var results;
1307 results = [];
1308 for (i in thread) {
1309 results.push(i);
1310 }
1311 return results;
1312 })()).sort().map(kit.id);
1313 } else {
1314 this.thread = [];
1315 }
1316 b = this.body.getBuilder();
1317 b = b.capture().toBlockBuilder();
1318 bodyBlock = b.block;
1319 return builder.exprEff(kit.call(kit.packId(this.kind), [kit.fun([this.getLabel()], bodyBlock)])).morph(b).mergeEnv(this.vdeps).noCapture();
1320 };
1321
1322 ControlNode.prototype._propagateEff = function() {
1323 var i, len, m, ref;
1324 ControlNode.__super__._propagateEff.call(this);
1325 ref = this.exits;
1326 for (m = 0, len = ref.length; m < len; m++) {
1327 i = ref[m];
1328 i.propagateEff();
1329 }
1330 return this;
1331 };
1332
1333 ControlNode.prototype._backPass = function(use) {
1334 var i, j, len, m, ref, ref1, v;
1335 this.body.backPass(use);
1336 if (this.kind !== "scope") {
1337 ref = this.exits;
1338 for (m = 0, len = ref.length; m < len; m++) {
1339 i = ref[m];
1340 ref1 = this.vdeps.after;
1341 for (j in ref1) {
1342 v = ref1[j];
1343 if (v) {
1344 i.vdeps.after[j] = true;
1345 }
1346 }
1347 }
1348 }
1349 };
1350
1351 return ControlNode;
1352
1353 })(WrapNode);
1354
1355 regNodeType("controlNode", ControlNode);
1356
1357 LoopNode = (function(superClass) {
1358 extend(LoopNode, superClass);
1359
1360 function LoopNode() {
1361 LoopNode.__super__.constructor.call(this);
1362 }
1363
1364 LoopNode.prototype.simpleLoop = function() {
1365 var b, bb, body, i, ref, ref1, ref2, tb, test, thread, updVars, update, v;
1366 if (!this.pre) {
1367 return;
1368 }
1369 if (this.opts.loop === "seq") {
1370 return;
1371 }
1372 this.cont.trimExits();
1373 if (this.cont.exits.length) {
1374 return;
1375 }
1376 if ((this.update != null) && this.update.eff) {
1377 return;
1378 }
1379 if (this.test.eff || this.test.vdeps.upd) {
1380 return;
1381 }
1382 if (this.inner.vdeps.upd) {
1383 return;
1384 }
1385 ref = this.inner.unwindBy;
1386 for (i in ref) {
1387 v = ref[i];
1388 if (v.dst !== this && v.dst !== this.cont) {
1389 return;
1390 }
1391 }
1392 this.trimExits(this.inner.parent);
1393 if (this.exits.length) {
1394 return;
1395 }
1396 ref1 = getBuilderFun(this.update, this.ctx), update = ref1[0], updVars = ref1[1], b = ref1[2], thread = ref1[3];
1397 tb = this.test.getBuilder().toBlockBuilder().capture();
1398 test = kit.spreadFun(updVars, kit.fun(updVars, tb.block));
1399 bb = this.inner.getBuilder();
1400 bb = bb.capture().toBlockBuilder();
1401 body = kit.spreadFun(updVars, kit.fun(updVars, bb.block));
1402 ref2 = b.env;
1403 for (i in ref2) {
1404 v = ref2[i];
1405 if (v.mod) {
1406 v.mod = false;
1407 }
1408 }
1409 if (updVars.length > 1) {
1410 updVars = [kit.arr(updVars)];
1411 }
1412 return builder.exprEff(kit.call(kit.packId("forPar"), [test, body, update].concat(slice.call(updVars)))).morph(b).mergeEnv(this.vdeps).noCapture();
1413 };
1414
1415 LoopNode.prototype._getBuilder = function() {
1416 var res;
1417 res = this.simpleLoop();
1418 if (res != null) {
1419 return res;
1420 }
1421 return LoopNode.__super__._getBuilder.call(this);
1422 };
1423
1424 return LoopNode;
1425
1426 })(ControlNode);
1427
1428 regNodeType("loopNode", LoopNode);
1429
1430 TryCatchNode = (function(superClass) {
1431 extend(TryCatchNode, superClass);
1432
1433 function TryCatchNode() {
1434 TryCatchNode.__super__.constructor.call(this);
1435 this.throws = [];
1436 }
1437
1438 TryCatchNode.prototype.setBody = function(b) {
1439 this.body = b;
1440 if (b != null) {
1441 b.setParent(this);
1442 }
1443 return this;
1444 };
1445
1446 TryCatchNode.prototype.setHandler = function(hvar, h) {
1447 this.hvar = hvar;
1448 this.handler = h;
1449 if (h != null) {
1450 h.setParent(this);
1451 }
1452 return this;
1453 };
1454
1455 TryCatchNode.prototype.setFin = function(f) {
1456 this.fin = f;
1457 if (f != null) {
1458 f.setParent(this);
1459 }
1460 return this;
1461 };
1462
1463 TryCatchNode.prototype._getBuilder = function() {
1464 var bb, e, fb, hb, res;
1465 if (!((this.handler != null) || (this.fin != null))) {
1466 return this.body.getBuilder();
1467 }
1468 bb = this.body.getBuilder().coerceTry().toExprBuilder(true);
1469 e = bb.expr;
1470 if (this.handler != null) {
1471 hb = this.handler.getBuilder().toBlockBuilder(true);
1472 e = kit["catch"](bb.expr, this.hvar, hb.block);
1473 }
1474 if (this.fin != null) {
1475 fb = this.fin.getBuilder().toBlockBuilder(true);
1476 e = kit["finally"](e, fb.block);
1477 }
1478 res = builder.exprEff(e).pushEnv(bb.env);
1479 if (hb != null) {
1480 res.pushEnv(hb.env);
1481 }
1482 if (fb != null) {
1483 res.pushEnv(fb.env);
1484 }
1485 return res;
1486 };
1487
1488 TryCatchNode.prototype._fwdPass = function(use) {
1489 var fdeps, hdeps, i;
1490 this.body.fwdPass(use);
1491 if (this.handler) {
1492 this.handler.fwdPass(use);
1493 hdeps = this.handler.vdeps.uses;
1494 } else {
1495 hdeps = {};
1496 }
1497 if (this.fin) {
1498 this.fin.fwdPass(use);
1499 fdeps = this.fin.vdeps.uses;
1500 } else {
1501 fdeps = {};
1502 }
1503 for (i in this.body.vdeps.mods) {
1504 if (fdeps[i] || hdeps[i]) {
1505 this.ctx.refs[i] = true;
1506 }
1507 }
1508 };
1509
1510 TryCatchNode.prototype._propagateEff = function() {
1511 var i, len, m, ref;
1512 TryCatchNode.__super__._propagateEff.call(this);
1513 ref = this.throws;
1514 for (m = 0, len = ref.length; m < len; m++) {
1515 i = ref[m];
1516 i.propagateEff();
1517 }
1518 return this;
1519 };
1520
1521 TryCatchNode.prototype._backPass = function(use) {
1522 if (!this.eff) {
1523 this.eff = this.body.eff || (this.handler != null) && this.handler.eff || this.fin && this.fin.eff;
1524 }
1525 if (this.eff) {
1526 this._propagateEff();
1527 }
1528 if (this.fin != null) {
1529 this.fin.backPass(use);
1530 }
1531 if (this.handler != null) {
1532 this.handler.backPass(use);
1533 }
1534 return this.body.backPass(use);
1535 };
1536
1537 return TryCatchNode;
1538
1539 })(DynNode);
1540
1541 regNodeType("tryCatchNode", TryCatchNode);
1542
1543 ThrowNode = (function(superClass) {
1544 extend(ThrowNode, superClass);
1545
1546 function ThrowNode(val) {
1547 ThrowNode.__super__.constructor.call(this);
1548 this.setVal(val);
1549 }
1550
1551 ThrowNode.prototype.setVal = function(val) {
1552 this.val = val.setParent(this);
1553 return this;
1554 };
1555
1556 ThrowNode.prototype._backPass = function(use) {
1557 ThrowNode.__super__._backPass.call(this);
1558 if (!this.eff) {
1559 this.eff = this.val.eff;
1560 }
1561 if (this.eff) {
1562 this._propagateEff();
1563 }
1564 this.val.backPass(use);
1565 return this;
1566 };
1567
1568 ThrowNode.prototype._fwdPass = function(use) {
1569 var l, p;
1570 p = this.parent;
1571 l = this;
1572 while (true) {
1573 if ((p.throws != null) && p.body === l) {
1574 this.dst = p;
1575 break;
1576 }
1577 l = p;
1578 p = p.parent;
1579 }
1580 this.dst.throws.push(this);
1581 this.val.fwdPass(use);
1582 return this;
1583 };
1584
1585 ThrowNode.prototype._getBuilder = function() {
1586 var v;
1587 assert.ok(this.eff);
1588 v = this.ctx.uniqId("e");
1589 if (this.val.pureExpr) {
1590 return builder.exprEff(kit.call(kit.packId("raise"), [this.val.pureExpr]));
1591 }
1592 return this.val.getBuilder().setBindVar(v).setOpts(this.opts).append(builder.exprEff(kit.call(kit.packId("raise"), [v])).setOpts(this.opts));
1593 };
1594
1595 return ThrowNode;
1596
1597 })(DynNode);
1598
1599 regNodeType("throwNode", ThrowNode);
1600
1601 Node.prototype.tryCatch = function(hv, h, f) {
1602 return this.ctx.tryCatchNode().setBody(this).setHandler(hv, h).setFin(f);
1603 };
1604
1605 Scope.prototype.stmtNode = function(s) {
1606 var sv;
1607 if (s == null) {
1608 return EmptyNode();
1609 }
1610 sv = this.stmt(s);
1611 if (sv != null) {
1612 return sv;
1613 }
1614 return PureNode([s]);
1615 };
1616
1617 Node.prototype.isEmpty = function() {
1618 return false;
1619 };
1620
1621 BlockNode.prototype.isEmpty = function() {
1622 return !this.block.length;
1623 };
1624
1625 EmptyNode.prototype.isEmpty = function() {
1626 return true;
1627 };
1628
1629}).call(this);