1 |
|
2 | (function() {
|
3 | var ActiveScope, ActiveVisitor, DisabledVisitor, Scope, Visitor, assert, commonForIter, commonWhile, isLoop, kit, policy, ref, ref1, rewriteForIter, wrapP;
|
4 |
|
5 | kit = require("./kit");
|
6 |
|
7 | ref = require("./scope"), Scope = ref.Scope, ActiveScope = ref.ActiveScope;
|
8 |
|
9 | policy = require("./policy");
|
10 |
|
11 | require("./graph");
|
12 |
|
13 | require("./expr");
|
14 |
|
15 | assert = require("assert");
|
16 |
|
17 | ref1 = require("./visitor"), Visitor = ref1.Visitor, ActiveVisitor = ref1.ActiveVisitor, DisabledVisitor = ref1.DisabledVisitor;
|
18 |
|
19 | isLoop = function(stmt) {
|
20 | return stmt.type === "ForStatement";
|
21 | };
|
22 |
|
23 | ActiveVisitor.prototype.LabeledStatement = function(stmt) {
|
24 | var block, name, nlab, old, res;
|
25 | name = stmt.label.name;
|
26 | if (isLoop(stmt.body)) {
|
27 | res = this.ctx.stmt(stmt.body, name);
|
28 | res.orig = stmt;
|
29 | return res;
|
30 | }
|
31 | old = this.ctx.lab;
|
32 | block = this.ctx.controlNode();
|
33 | this.ctx.lab = nlab = Object.create(old);
|
34 | block.labname = name;
|
35 | nlab[name] = {
|
36 | brk: block
|
37 | };
|
38 | block.setLabel("" + name).setBody(this.ctx.stmt(stmt.body, name));
|
39 | this.ctx.lab = old;
|
40 | return block;
|
41 | };
|
42 |
|
43 | ActiveVisitor.prototype.ContinueStatement = function(stmt) {
|
44 | var l, name;
|
45 | name = stmt.label != null ? stmt.label.name : "#";
|
46 | l = this.ctx.lab[name];
|
47 | if (!((l != null) && (l.cnt != null))) {
|
48 | throw new Error("no such label " + name);
|
49 | }
|
50 | return l.cnt.breakNode();
|
51 | };
|
52 |
|
53 | ActiveVisitor.prototype.BreakStatement = function(stmt) {
|
54 | var l, name;
|
55 | name = stmt.label != null ? stmt.label.name : "#";
|
56 | l = this.ctx.lab[name];
|
57 | if (!((l != null) && (l.brk != null))) {
|
58 | throw new Error("no such label " + name);
|
59 | }
|
60 | return l.brk.breakNode();
|
61 | };
|
62 |
|
63 | ActiveVisitor.prototype.BlockStatement = function(stmt) {
|
64 | return this.ctx.stmts(stmt.body);
|
65 | };
|
66 |
|
67 | ActiveVisitor.prototype.EmptyStatement = function(stmt) {
|
68 | return this.ctx.pureNode([stmt]);
|
69 | };
|
70 |
|
71 | Visitor.prototype.ExpressionStatement = function(stmt) {
|
72 | return this.ctx.expr(stmt.expression).ignoreResult().setOrig(false);
|
73 | };
|
74 |
|
75 | ActiveVisitor.prototype.IfStatement = function(stmt) {
|
76 | var e, i, res, t;
|
77 | i = stmt.test, t = stmt.consequent, e = stmt.alternate;
|
78 | res = this.ctx.branchedNode(function(t, e) {
|
79 | stmt.consequent = t;
|
80 | stmt.alternate = e;
|
81 | return stmt;
|
82 | }, stmt).setOrig(stmt).setDeps(this.ctx.stmt(t), e != null ? this.ctx.stmt(e) : this.ctx.emptyNode());
|
83 | return this.ctx.bindNode(res, [this.ctx.expr(i).setPosition([stmt, "test"])]);
|
84 | };
|
85 |
|
86 | ActiveVisitor.prototype.SwitchStatement = function(stmt) {
|
87 | var block, i, j, len, nlab, old, ref2, res, s, x;
|
88 | old = this.ctx.lab;
|
89 | this.ctx.lab = nlab = Object.create(old);
|
90 | res = this.ctx.controlNode();
|
91 | nlab["#"] = {
|
92 | brk: res
|
93 | };
|
94 | block = this.ctx.blockNode();
|
95 | s = this.ctx.sharedNode(this.ctx.expr(stmt.discriminant), block);
|
96 | res.setBody(s);
|
97 | ref2 = stmt.cases;
|
98 | for (x = j = 0, len = ref2.length; j < len; x = ++j) {
|
99 | i = ref2[x];
|
100 | if (i.test != null) {
|
101 | block.append(this.IfStatement(kit.ifte(kit.eq(s._ref, i.test), i.consequent)));
|
102 | } else {
|
103 | block.append(this.ctx.stmts(i.consequent));
|
104 | }
|
105 | }
|
106 | return res;
|
107 | };
|
108 |
|
109 | ActiveVisitor.prototype.ReturnStatement = function(s) {
|
110 | var a;
|
111 | a = s.argument;
|
112 | if (a == null) {
|
113 | return this.ctx.root.breakNode();
|
114 | }
|
115 | return this.ctx.root.breakNode(this.ctx.expr(a));
|
116 | };
|
117 |
|
118 | Visitor.prototype.postDecl = function(stmt) {
|
119 | return this.ctx.pureNode([stmt]);
|
120 | };
|
121 |
|
122 | ActiveVisitor.prototype.postDecl = function(stmt) {
|
123 | this.ctx.glob.decls.push(stmt);
|
124 | return this.ctx.emptyNode();
|
125 | };
|
126 |
|
127 | Visitor.prototype.FunctionDeclaration = function(stmt) {
|
128 | var ctx, i, j, len, ref2, ref3, v;
|
129 | ctx = this.ctx.subScope(stmt);
|
130 | if (stmt.params != null) {
|
131 | ref2 = stmt.params;
|
132 | for (j = 0, len = ref2.length; j < len; j++) {
|
133 | i = ref2[j];
|
134 | if (i.name) {
|
135 | ctx.vars[i.name] = true;
|
136 | }
|
137 | }
|
138 | }
|
139 | if (ctx == null) {
|
140 | return this.ctx.pureNode([stmt]);
|
141 | }
|
142 | ctx.policy = this.policy;
|
143 | stmt.body = ctx.prog(stmt.body);
|
144 | if (stmt.generator) {
|
145 | stmt.generator = false;
|
146 | }
|
147 | ref3 = ctx.upds;
|
148 | for (i in ref3) {
|
149 | v = ref3[i];
|
150 | if (v && !ctx.vars[i]) {
|
151 | this.ctx.refs[i] = true;
|
152 | }
|
153 | }
|
154 | return this.postDecl(stmt);
|
155 | };
|
156 |
|
157 | Visitor.prototype.VariableDeclaration = function(stmt) {
|
158 | var en, i, j, len, ref2;
|
159 | ref2 = stmt.declarations;
|
160 | for (j = 0, len = ref2.length; j < len; j++) {
|
161 | i = ref2[j];
|
162 | if (!i.init) {
|
163 | continue;
|
164 | }
|
165 | this.policy.nameDetails(i.id, "=");
|
166 | en = this.ctx.expr(i.init);
|
167 | assert.ok(en.pureExpr != null);
|
168 | i.init = en.pureExpr;
|
169 | }
|
170 | return this.ctx.pureNode([stmt]);
|
171 | };
|
172 |
|
173 | ActiveVisitor.prototype.VariableDeclaration = function(stmt) {
|
174 | var asgn, cur, declarations, e, i, j, len, orig, ref2;
|
175 | cur = this.ctx.emptyNode();
|
176 | declarations = [];
|
177 | orig = [];
|
178 | ref2 = stmt.declarations;
|
179 | for (j = 0, len = ref2.length; j < len; j++) {
|
180 | i = ref2[j];
|
181 | this.ctx.vars[i.id.name] = true;
|
182 | if (!i.id.$dm$orig) {
|
183 | this.ctx.ids[i.id.name] = true;
|
184 | }
|
185 | declarations.push({
|
186 | type: "VariableDeclarator",
|
187 | id: i.id
|
188 | });
|
189 | if (this.policy.opts.varCapt === false) {
|
190 | this.ctx.refs[i.id.name] = true;
|
191 | }
|
192 | if (i.init != null) {
|
193 | asgn = kit.assign(i.id, i.init);
|
194 | e = this.ctx.stmt(kit.exprStmt(asgn));
|
195 | cur = cur.append(e);
|
196 | orig.push(asgn);
|
197 | }
|
198 | }
|
199 | this.ctx.glob.decls.push({
|
200 | type: "VariableDeclaration",
|
201 | declarations: declarations,
|
202 | kind: "var"
|
203 | });
|
204 | if (cur.pureBlock != null) {
|
205 | cur.setOrig(kit.block(cur.pureBlock()));
|
206 | } else {
|
207 | cur.setOrig(kit.exprStmt(kit.seqExpr.apply(kit, orig)));
|
208 | }
|
209 | return cur;
|
210 | };
|
211 |
|
212 | ActiveVisitor.prototype.ForStatement = function(stmt, label) {
|
213 | var body, exprs, i, init, j, len, lexpr, ref2, test, update, wbody;
|
214 | wbody = [];
|
215 | init = stmt.init, test = stmt.test, update = stmt.update, body = stmt.body;
|
216 | if (test == null) {
|
217 | test = kit.lit(true);
|
218 | }
|
219 | if (init != null) {
|
220 | if (init.type === "VariableDeclaration") {
|
221 | wbody.push(init);
|
222 | exprs = [];
|
223 | ref2 = init.declarations;
|
224 | for (j = 0, len = ref2.length; j < len; j++) {
|
225 | i = ref2[j];
|
226 | if (i.init) {
|
227 | exprs.push(kit.assign(i.id, i.init));
|
228 | }
|
229 | }
|
230 | stmt.init = kit.seqExpr.apply(kit, exprs);
|
231 | } else {
|
232 | wbody.push(kit.exprStmt(init));
|
233 | }
|
234 | }
|
235 | lexpr = {
|
236 | type: "WhileStatement",
|
237 | test: test,
|
238 | body: body,
|
239 | $dm$update: update
|
240 | };
|
241 | if (label != null) {
|
242 | lexpr = {
|
243 | type: "LabeledStatement",
|
244 | body: lexpr,
|
245 | label: kit.id(label)
|
246 | };
|
247 | }
|
248 | wbody.push(lexpr);
|
249 | return this.ctx.stmts(wbody);
|
250 | };
|
251 |
|
252 | wrapP = function(nowrap, v) {
|
253 | if (nowrap) {
|
254 | return v;
|
255 | } else {
|
256 | return kit.call(kit.packId("p"), [v]);
|
257 | }
|
258 | };
|
259 |
|
260 | rewriteForIter = function(itername, stmt, label, nowrap) {
|
261 | var body, init, iterCtr, iterDecl, iterName, left, pat, resDecls, right, update;
|
262 | left = stmt.left, right = stmt.right, body = stmt.body;
|
263 | iterName = this.ctx.uniqId("iter");
|
264 | iterCtr = kit.call(kit.packId(itername), [right]);
|
265 | init = wrapP(nowrap, iterCtr);
|
266 | iterDecl = {
|
267 | type: "VariableDeclarator",
|
268 | id: iterName,
|
269 | init: init
|
270 | };
|
271 | resDecls = [iterDecl];
|
272 | init = {
|
273 | type: "VariableDeclaration",
|
274 | kind: "var",
|
275 | declarations: resDecls
|
276 | };
|
277 | if (left.type === "VariableDeclaration") {
|
278 | if (left.declarations.length !== 1) {
|
279 | throw new Error("NOT IMPLEMENTED");
|
280 | }
|
281 | stmt.left = pat = left.declarations[0].id;
|
282 | this.ctx.glob.decls.push(left);
|
283 | } else {
|
284 | pat = left;
|
285 | }
|
286 | body = kit.flatBlock(kit.exprStmt(kit.assign(pat, kit.mem(iterName, kit.id("value")))), body);
|
287 | update = kit.assign(iterName, wrapP(nowrap, kit.call(iterName, [])));
|
288 | return [
|
289 | {
|
290 | type: "ForStatement",
|
291 | init: init,
|
292 | test: iterName,
|
293 | update: update,
|
294 | body: body
|
295 | }, iterCtr
|
296 | ];
|
297 | };
|
298 |
|
299 | commonForIter = function(itername, stmt, label) {
|
300 | var b, bn, iterCtr, ref2;
|
301 | ref2 = rewriteForIter.call(this, itername, stmt, label), b = ref2[0], iterCtr = ref2[1];
|
302 | bn = this.ForStatement(b, label);
|
303 | return this.ctx.bindNode(bn, [this.ctx.expr(stmt.right).setPosition([iterCtr["arguments"], 0])]);
|
304 | };
|
305 |
|
306 | ActiveVisitor.prototype.ForInStatement = function(stmt, label) {
|
307 | return commonForIter.call(this, "forInIterator", stmt, label);
|
308 | };
|
309 |
|
310 | ActiveVisitor.prototype.ForOfStatement = function(stmt, label) {
|
311 | var b, name, orig;
|
312 | name = this.policy.opts.varCapt === false ? "iterator" : "iteratorBuf";
|
313 | b = commonForIter.call(this, name, stmt, label);
|
314 | if (!this.policy.opts.keepForOf) {
|
315 | orig = rewriteForIter.call(this, "iterator", stmt, label, true)[0];
|
316 | b.setOrig(orig);
|
317 | }
|
318 | return b;
|
319 | };
|
320 |
|
321 | commonWhile = function(pre) {
|
322 | return function(stmt, label) {
|
323 | var bexpr, body, bodyNode, bodyv, brkControl, cntControl, inner, labDef, loopBranch, nlab, old, test, testNode, upd, update;
|
324 | test = stmt.test, body = stmt.body;
|
325 | bexpr = kit.ifte(test, [], []);
|
326 | loopBranch = this.ctx.branchedNode(function(c, a) {
|
327 | bexpr.consequent = kit.flatBlock(c);
|
328 | if (a != null) {
|
329 | bexpr.alternate = kit.flatBlock(a);
|
330 | }
|
331 | return bexpr;
|
332 | }, bexpr);
|
333 | update = stmt.$dm$update;
|
334 | if (update != null) {
|
335 | upd = this.ctx.expr(update).ignoreResult();
|
336 | }
|
337 | brkControl = this.ctx.loopNode();
|
338 | cntControl = this.ctx.controlNode();
|
339 | if (label != null) {
|
340 | brkControl.setLabel(label + "Brk");
|
341 | cntControl.setLabel(label + "Cont");
|
342 | } else {
|
343 | brkControl.setLabel("brk");
|
344 | cntControl.setLabel("cont");
|
345 | }
|
346 | old = this.ctx.lab;
|
347 | this.ctx.lab = nlab = Object.create(old);
|
348 | labDef = {
|
349 | brk: brkControl,
|
350 | cnt: cntControl
|
351 | };
|
352 | nlab["#"] = labDef;
|
353 | if (label != null) {
|
354 | nlab[label] = labDef;
|
355 | }
|
356 | bodyNode = this.ctx.stmtNode(body);
|
357 | bodyv = pre ? (testNode = this.ctx.expr(test).setPosition([bexpr, "test"]), this.ctx.bindNode(loopBranch.setDeps(bodyNode, brkControl.breakNode()), [testNode])) : (bexpr.test = test = kit.not(test), testNode = this.ctx.expr(test).setPosition([bexpr, "test"]), this.ctx.blockNode().append(bodyNode, this.ctx.bindNode(loopBranch.setDeps(brkControl.breakNode(), this.ctx.emptyNode()), [testNode])));
|
358 | this.ctx.lab = old;
|
359 | if (label != null) {
|
360 | if (bodyv.name == null) {
|
361 | bodyv.name = this.ctx.uniqId("{label}Loop");
|
362 | }
|
363 | }
|
364 | inner = cntControl.setBody(bodyv);
|
365 | if (upd != null) {
|
366 | inner = inner.append(upd);
|
367 | }
|
368 | brkControl.test = testNode;
|
369 | brkControl.inner = bodyNode;
|
370 | brkControl.update = upd != null ? upd : this.ctx.emptyNode();
|
371 | brkControl.pre = pre;
|
372 | brkControl.cont = cntControl;
|
373 | return brkControl.setBody(this.ctx.repeatNode(inner));
|
374 | };
|
375 | };
|
376 |
|
377 | ActiveVisitor.prototype.WhileStatement = commonWhile(true);
|
378 |
|
379 | ActiveVisitor.prototype.DoWhileStatement = commonWhile();
|
380 |
|
381 | ActiveVisitor.prototype.ThrowStatement = function(stmt) {
|
382 | var e, ea;
|
383 | e = stmt.argument;
|
384 | ea = this.ctx.expr(e);
|
385 | return this.ctx.throwNode(ea);
|
386 | };
|
387 |
|
388 | ActiveVisitor.prototype.TryStatement = function(stmt) {
|
389 | var block, finalizer, handler, res;
|
390 | block = stmt.block, handler = stmt.handler, finalizer = stmt.finalizer;
|
391 | res = this.ctx.tryCatchNode().setBody(this.ctx.stmt(block));
|
392 | if (finalizer != null) {
|
393 | res.setFin(this.ctx.stmt(finalizer));
|
394 | }
|
395 | if (handler != null) {
|
396 | res.setHandler(handler.param, this.ctx.stmt(handler.body));
|
397 | }
|
398 | return res;
|
399 | };
|
400 |
|
401 | ActiveVisitor.prototype.WithStatement = function(stmt) {
|
402 | var res;
|
403 | res = this.ctx.branchedNode(function(b) {
|
404 | stmt.body = b;
|
405 | return stmt;
|
406 | }, stmt).setOrig(stmt).setDeps(this.ctx.stmt(stmt.body));
|
407 | return this.ctx.bindNode(res, [this.ctx.expr(stmt.object).setPosition([stmt, "object"])]);
|
408 | };
|
409 |
|
410 | Visitor.prototype.defaultStmt = function(stmt) {
|
411 | return this.ctx.pureNode([stmt]);
|
412 | };
|
413 |
|
414 | }).call(this);
|