1 |
|
2 | (function() {
|
3 | var ActiveVisitor, DisabledVisitor, DummyBuilder, ExprBuilder, Scope, VarUsage, Visitor, config, directive, kit, policy, ref,
|
4 | slice = [].slice;
|
5 |
|
6 | config = require("./config");
|
7 |
|
8 | Scope = require("./scope").Scope;
|
9 |
|
10 | ref = require("./visitor"), Visitor = ref.Visitor, ActiveVisitor = ref.ActiveVisitor, DisabledVisitor = ref.DisabledVisitor;
|
11 |
|
12 | kit = require("./kit");
|
13 |
|
14 | policy = require("./policy");
|
15 |
|
16 | directive = require("./directives");
|
17 |
|
18 | VarUsage = require("./builder").VarUsage;
|
19 |
|
20 | require("./graph");
|
21 |
|
22 | require("./expr");
|
23 |
|
24 | ExprBuilder = (function() {
|
25 | function ExprBuilder(expr1, ctx1) {
|
26 | this.expr = expr1;
|
27 | this.ctx = ctx1;
|
28 | this.init();
|
29 | this.cur = this.ctx.policy.opts.bind ? this.ctx.effValNode(this.expr) : this.ctx.exprNode(this.expr);
|
30 | }
|
31 |
|
32 | ExprBuilder.prototype.init = function() {
|
33 | return this.deps = [];
|
34 | };
|
35 |
|
36 | ExprBuilder.prototype.add = function(s, par, x, opts) {
|
37 | var r;
|
38 | r = this.ctx.expr(s, opts);
|
39 | if ((r.pureExpr != null) && !r.vdeps.mod) {
|
40 | par[x] = r.pureExpr;
|
41 | this.cur.vdeps.addInnerDeep(r.vdeps);
|
42 | return;
|
43 | }
|
44 | r.setPosition([par, x]);
|
45 | this.deps.push(r);
|
46 | };
|
47 |
|
48 | ExprBuilder.prototype.result = function() {
|
49 | var res, vdeps;
|
50 | res = this.cur;
|
51 | vdeps = res.vdeps;
|
52 | if (this.deps.length) {
|
53 | res = this.ctx.bindNode(res, this.deps);
|
54 | }
|
55 | if (this.orig === false) {
|
56 | res.origExpr = false;
|
57 | }
|
58 | this.init();
|
59 | return this.cur = res;
|
60 | };
|
61 |
|
62 | return ExprBuilder;
|
63 |
|
64 | })();
|
65 |
|
66 | DummyBuilder = (function() {
|
67 | function DummyBuilder(expr1, ctx1) {
|
68 | this.expr = expr1;
|
69 | this.ctx = ctx1;
|
70 | }
|
71 |
|
72 | DummyBuilder.prototype.add = function(s, par, x, opts) {
|
73 | var r;
|
74 | r = this.ctx.expr(s, opts);
|
75 | if (r.pureExpr != null) {
|
76 | par[x] = r.pureExpr;
|
77 | return;
|
78 | }
|
79 | throw new Error("INTERNAL: not expected effectful expression");
|
80 | };
|
81 |
|
82 | DummyBuilder.prototype.result = function() {
|
83 | return this.ctx.pureExprNode(this.expr);
|
84 | };
|
85 |
|
86 | return DummyBuilder;
|
87 |
|
88 | })();
|
89 |
|
90 | Visitor.prototype.CallExpression = function(e) {
|
91 | var a, args, builder, callee, dir, i, idn, j, len, n, opts, res, x;
|
92 | opts = this.policy.opts;
|
93 | callee = e.callee, args = e["arguments"];
|
94 | if (callee.type === "Identifier") {
|
95 | n = callee.name;
|
96 | if (n === "require" && args.length === 1) {
|
97 | a = args[0];
|
98 | if (a.type === "Literal" && a.value === config.packageName) {
|
99 | this.ctx.policy._libRequire();
|
100 | return this.ctx.pureExprNode(e);
|
101 | }
|
102 | }
|
103 | }
|
104 | dir = (function() {
|
105 | var dn, obj, prop;
|
106 | if (n === config.packageVar) {
|
107 | return directive.$packVar;
|
108 | }
|
109 | if (callee.type !== "MemberExpression") {
|
110 | return;
|
111 | }
|
112 | obj = callee.object;
|
113 | if (!(obj.type === "Identifier" && obj.name === config.packageVar)) {
|
114 | return;
|
115 | }
|
116 | prop = callee.property;
|
117 | if (prop.type === "Identifier") {
|
118 | dn = prop.name;
|
119 | } else if (callee.computed && prop.type === "Literal" && prop.value.substr) {
|
120 | dn = prop.value;
|
121 | } else {
|
122 | return;
|
123 | }
|
124 | return directive[dn];
|
125 | })();
|
126 | if (dir != null) {
|
127 | res = kit.errorPos(e, (function(_this) {
|
128 | return function() {
|
129 | return dir.call.apply(dir, [_this.ctx, e].concat(slice.call(e["arguments"])));
|
130 | };
|
131 | })(this));
|
132 | if (res == null) {
|
133 | return this.ctx.emptyNode();
|
134 | }
|
135 | return res;
|
136 | }
|
137 | idn = opts.identity;
|
138 | if ((idn != null) && idn !== false) {
|
139 | if (idn === true) {
|
140 | idn = 0;
|
141 | }
|
142 | return this.ctx.expr(e["arguments"][idn]);
|
143 | }
|
144 | builder = this.getExprBuilder(e);
|
145 | callee = e.callee, args = e["arguments"];
|
146 | builder.add(callee, e, "callee");
|
147 | if (opts.subScope !== false && callee.$dm$eff === true) {
|
148 | opts.bind = true;
|
149 | }
|
150 | for (x = j = 0, len = args.length; j < len; x = ++j) {
|
151 | i = args[x];
|
152 | builder.add(i, args, x);
|
153 | }
|
154 | return builder.result();
|
155 | };
|
156 |
|
157 | directive.$packVar = function(e, arg) {
|
158 | var bnd;
|
159 | bnd = this.policy.opts.bind;
|
160 | e = this.expr(arg);
|
161 | if (bnd && e.pureExpr) {
|
162 | return this.effValNode(e.pureExpr).morphInit(e);
|
163 | }
|
164 | return e;
|
165 | };
|
166 |
|
167 | directive.reflect = function(e, arg) {
|
168 | var bnd, expr;
|
169 | bnd = this.policy.opts.bind;
|
170 | expr = kit.call(kit.packId("reflect"), [arg]);
|
171 | return this.bindNode(this.effValNode(expr), [this.expr(arg).setPosition([expr["arguments"], 0])]);
|
172 | };
|
173 |
|
174 | directive.reify = function(e, arg) {
|
175 | return this.reifyNode().setBody(this.expr(arg)).setIsThunk(arg.type === "FunctionExpression");
|
176 | };
|
177 |
|
178 | directive.p = directive.p = function(e, arg) {
|
179 | return this.pureExprNode(arg);
|
180 | };
|
181 |
|
182 | Visitor.prototype.FunctionExpression = function(e) {
|
183 | var ctx, i, j, len, ref1, ref2, res, v, vars;
|
184 | ctx = this.ctx.subScope(e);
|
185 | if (e.params != null) {
|
186 | ref1 = e.params;
|
187 | for (j = 0, len = ref1.length; j < len; j++) {
|
188 | i = ref1[j];
|
189 | if (i.name) {
|
190 | ctx.vars[i.name] = true;
|
191 | }
|
192 | }
|
193 | }
|
194 | if (ctx == null) {
|
195 | return this.ctx.pureExprNode(e);
|
196 | }
|
197 | e.body = ctx.prog(e.body);
|
198 | if (ctx.eff) {
|
199 | e.$dm$eff = true;
|
200 | }
|
201 | res = this.ctx.exprNode(e);
|
202 | vars = ctx.vars;
|
203 | ref2 = ctx.upds;
|
204 | for (i in ref2) {
|
205 | v = ref2[i];
|
206 | if (v && !ctx.vars[i]) {
|
207 | this.ctx.refs[i] = true;
|
208 | }
|
209 | }
|
210 | if (e.generator) {
|
211 | e.generator = false;
|
212 | }
|
213 | return res;
|
214 | };
|
215 |
|
216 | ActiveVisitor.prototype.ThisExpression = function(e) {
|
217 | var base;
|
218 | if ((base = this.ctx).thisVar == null) {
|
219 | base.thisVar = this.ctx.uniqId("_this");
|
220 | }
|
221 | return this.ctx.exprNode(this.ctx.thisVar);
|
222 | };
|
223 |
|
224 | Visitor.prototype.AssignmentExpression = function(e) {
|
225 | var deps, left, lv, res, right, rv;
|
226 | left = e.left, right = e.right;
|
227 | deps = [];
|
228 | res = this.ctx.exprNode(e);
|
229 | this.policy.nameDetails(left, e.operator);
|
230 | if (left.type === "Identifier") {
|
231 | if (e.operator === "=") {
|
232 | res.vdeps.addAssign(left.name);
|
233 | } else {
|
234 | res.vdeps.addUpd(left.name);
|
235 | }
|
236 | if (!this.ctx.vars[left.name]) {
|
237 | this.ctx.upds[left.name] = true;
|
238 | }
|
239 | } else {
|
240 | lv = this.ctx.expr(left);
|
241 | if (lv.pureExpr != null) {
|
242 | res.vdeps.addInnerDeep(lv.vdeps);
|
243 | e.left = lv.pureExpr;
|
244 | } else {
|
245 | deps.push(lv.setPosition([e, "left"]));
|
246 | }
|
247 | }
|
248 | rv = this.ctx.expr(right);
|
249 | if (rv.pureExpr != null) {
|
250 | res.vdeps.addInnerDeep(rv.vdeps);
|
251 | e.right = rv.pureExpr;
|
252 | } else {
|
253 | deps.push(rv.setPosition([e, "right"]));
|
254 | }
|
255 | if (deps.length) {
|
256 | res = this.ctx.bindNode(res, deps);
|
257 | }
|
258 | return res;
|
259 | };
|
260 |
|
261 | ActiveVisitor.prototype.UpdateExpression = function(e) {
|
262 | var a, av, res;
|
263 | res = this.ctx.exprNode(e);
|
264 | a = e.argument;
|
265 | if (a.type === "Identifier") {
|
266 | if (!this.ctx.vars[a.name]) {
|
267 | this.ctx.upds[a.name] = true;
|
268 | }
|
269 | res.vdeps.addUpd(a.name);
|
270 | } else {
|
271 | av = this.ctx.expr(a);
|
272 | if (av.pureExpr) {
|
273 | e.argument = av.pureExpr;
|
274 | } else {
|
275 | res = this.ctx.bindNode(res, [av.setPosition([e, "argument"])]);
|
276 | }
|
277 | }
|
278 | return res;
|
279 | };
|
280 |
|
281 | directive.$ = function(e, arg) {
|
282 | return this.placeholderNode(arg);
|
283 | };
|
284 |
|
285 | ActiveVisitor.prototype.MemberExpression = function(e) {
|
286 | var builder, object, property;
|
287 | object = e.object, property = e.property;
|
288 | if (object.type === "Identifier" && object.name === config.packageVar && property.type === "Identifier" && property.name === "$") {
|
289 | return this.ctx.placeholderNode();
|
290 | }
|
291 | builder = this.getExprBuilder(e);
|
292 | builder.add(object, e, "object");
|
293 | if (e.computed) {
|
294 | builder.add(property, e, "property");
|
295 | }
|
296 | return builder.result();
|
297 | };
|
298 |
|
299 | ActiveVisitor.prototype.Identifier = function(e) {
|
300 | var res;
|
301 | res = this.ctx.exprNode(e);
|
302 | res.vdeps.uses[e.name] = true;
|
303 | if (!e.$dm$orig) {
|
304 | this.ctx.ids[e.name] = true;
|
305 | }
|
306 | return res;
|
307 | };
|
308 |
|
309 | Visitor.prototype.getExprBuilder = function(e) {
|
310 | return new DummyBuilder(e, this.ctx);
|
311 | };
|
312 |
|
313 | ActiveVisitor.prototype.getExprBuilder = function(e) {
|
314 | return new ExprBuilder(e, this.ctx);
|
315 | };
|
316 |
|
317 | ActiveVisitor.prototype.LogicalExpression = function(e) {
|
318 | var b, builder, cexpr, l, lexpr, r, res, rexpr;
|
319 | if (this.policy.opts.expr === "par") {
|
320 | builder = this.getExprBuilder(e);
|
321 | builder.add(e.left, e, "left");
|
322 | builder.add(e.right, e, "right");
|
323 | return builder.result();
|
324 | }
|
325 | cexpr = {
|
326 | type: "ConditionalExpression"
|
327 | };
|
328 | l = this.ctx.expr(e.left);
|
329 | r = this.ctx.expr(e.right);
|
330 | if (!(l.eff || r.eff)) {
|
331 | return this.ctx.exprNode(e);
|
332 | }
|
333 | rexpr = r.getBuilder().setOpts(this.policy.opts).toExpr();
|
334 | b = r.eff ? this.ctx.effValNode(cexpr) : this.ctx.pureExprNode(cexpr);
|
335 | res = this.ctx.sharedNode(l, b);
|
336 | lexpr = cexpr.test = res._ref;
|
337 | if (this.policy.opts.coerce === "none" && r.eff) {
|
338 | lexpr = kit.pure(lexpr);
|
339 | }
|
340 | if (e.operator === "||") {
|
341 | cexpr.consequent = lexpr;
|
342 | cexpr.alternate = rexpr;
|
343 | } else {
|
344 | cexpr.consequent = rexpr;
|
345 | cexpr.alternate = lexpr;
|
346 | }
|
347 | return res;
|
348 | };
|
349 |
|
350 | ActiveVisitor.prototype.ConditionalExpression = function(e) {
|
351 | var a, builder, c, n;
|
352 | if (this.policy.opts.expr === "par") {
|
353 | builder = this.getExprBuilder(e);
|
354 | builder.add(e.test, e, "test");
|
355 | builder.add(e.consequent, e, "consequent");
|
356 | builder.add(e.alternate, e, "alternate");
|
357 | return builder.result();
|
358 | }
|
359 | c = this.ctx.expr(e.consequent);
|
360 | a = this.ctx.expr(e.alternate);
|
361 | if (c.eff || a.eff) {
|
362 | e.consequent = c.getFullExpr(true);
|
363 | e.alternate = a.getFullExpr(true);
|
364 | n = this.ctx.effValNode(e);
|
365 | } else {
|
366 | n = this.ctx.pureExprNode(e);
|
367 | }
|
368 | return this.ctx.bindNode(n, [this.ctx.expr(e.test).setPosition([e, "test"])]);
|
369 | };
|
370 |
|
371 | directive.answer = directive["yield"] = function(s, arg) {
|
372 | var e;
|
373 | if (arg != null) {
|
374 | e = this.expr(arg);
|
375 | }
|
376 | return this.root.yieldNode(e);
|
377 | };
|
378 |
|
379 | ActiveVisitor.prototype.YieldExpression = function(e) {
|
380 | if (this.ctx.policy.opts.mopt === false) {
|
381 | if (e.delegate) {
|
382 | return directive.$packVar.call(this.ctx, e, e.argument);
|
383 | }
|
384 | return directive.reflect.call(this.ctx, e, e.argument);
|
385 | }
|
386 | return this.ctx.root.yieldNode(this.ctx.expr(e.argument));
|
387 | };
|
388 |
|
389 | ActiveVisitor.prototype.BinaryExpression = function(e) {
|
390 | var builder;
|
391 | builder = this.getExprBuilder(e);
|
392 | builder.add(e.left, e, "left");
|
393 | builder.add(e.right, e, "right");
|
394 | return builder.result();
|
395 | };
|
396 |
|
397 | ActiveVisitor.prototype.UnaryExpression = function(e) {
|
398 | var builder;
|
399 | builder = this.getExprBuilder(e);
|
400 | builder.add(e.argument, e, "argument");
|
401 | return builder.result();
|
402 | };
|
403 |
|
404 | ActiveVisitor.prototype.NewExpression = function(e) {
|
405 | var args, builder, i, j, len, x;
|
406 | builder = this.getExprBuilder(e);
|
407 | args = e["arguments"];
|
408 | for (x = j = 0, len = args.length; j < len; x = ++j) {
|
409 | i = args[x];
|
410 | builder.add(i, args, x);
|
411 | }
|
412 | return builder.result();
|
413 | };
|
414 |
|
415 | ActiveVisitor.prototype.SequenceExpression = function(e) {
|
416 | var args, builder, i, j, len, x;
|
417 | builder = this.getExprBuilder(e);
|
418 | args = e.expressions;
|
419 | for (x = j = 0, len = args.length; j < len; x = ++j) {
|
420 | i = args[x];
|
421 | builder.add(i, args, x);
|
422 | }
|
423 | return builder.result();
|
424 | };
|
425 |
|
426 | ActiveVisitor.prototype.ArrayExpression = function(e) {
|
427 | var args, builder, i, j, len, x;
|
428 | builder = this.getExprBuilder(e);
|
429 | args = e.elements;
|
430 | for (x = j = 0, len = args.length; j < len; x = ++j) {
|
431 | i = args[x];
|
432 | if (i) {
|
433 | builder.add(i, args, x);
|
434 | }
|
435 | }
|
436 | return builder.result();
|
437 | };
|
438 |
|
439 | ActiveVisitor.prototype.ObjectExpression = function(e) {
|
440 | var builder, i, j, len, ref1;
|
441 | builder = this.getExprBuilder(e);
|
442 | ref1 = e.properties;
|
443 | for (j = 0, len = ref1.length; j < len; j++) {
|
444 | i = ref1[j];
|
445 | builder.add(i.value, i, "value");
|
446 | }
|
447 | return builder.result();
|
448 | };
|
449 |
|
450 | module.exports = {};
|
451 |
|
452 | }).call(this);
|