UNPKG

3.37 kBJavaScriptView Raw
1var util = require('util');
2var helpers = require('../helpers');
3var AssignmentExpression = require('./AssignmentExpression');
4var BlockStatement = require('./BlockStatement');
5var ExpressionStatement = require('./ExpressionStatement');
6var FunctionExpression = require('./FunctionExpression');
7var Identifier = require('./Identifier');
8var IfStatement = require('./IfStatement');
9var Literal = require('./Literal');
10var MemberExpression = require('./MemberExpression');
11var ThrowStatement = require('./ThrowStatement');
12var VariableDeclaration = require('./VariableDeclaration');
13var VariableDeclarator = require('./VariableDeclarator');
14
15var CallExpression = module.exports = function(callee, args) {
16 this.type = 'CallExpression';
17 this.callee = callee;
18 this.arguments = args;
19 if (!this.arguments) {
20 this.arguments = [];
21 }
22 if (!util.isArray(this.arguments)) {
23 this.arguments = [this.arguments];
24 }
25};
26
27CallExpression.prototype.normalize = function (place) {
28 var self = this;
29 this.callee.normalize();
30 for (var i = 0; i < this.arguments.length; i++) {
31 this.arguments[i].normalize();
32 }
33
34 findContinuation(this.arguments, function (contExpr, contPos, options) {
35 if (options.obtain) {
36 //Support obtain statement
37 contExpr.arguments.unshift(new Identifier(helpers.errName));
38 }
39
40 contExpr.arguments.forEach(function (argument, index) {
41 //Declare argument variable if not defined
42 if (argument.type === 'MemberExpression') {
43 argument = argument.object;
44 }
45 place.push(new VariableDeclaration(
46 new VariableDeclarator(
47 argument
48 )
49 ));
50 });
51 });
52};
53
54CallExpression.prototype.transform = function (place) {
55 var self = this;
56
57 this.callee.transform();
58 if (this.callee.async) {
59 this.async = true;
60 }
61
62 this.arguments.forEach(function (expression) {
63 expression.transform();
64 if (expression.async) {
65 this.async = true;
66 }
67 });
68
69 var newPlace;
70 findContinuation(this.arguments, function (contExpr, contPos, options) {
71 //Function call with cont
72 var callbackPlace = [];
73 contExpr.arguments.forEach(function (argument, index) {
74 callbackPlace.push(new ExpressionStatement(
75 new AssignmentExpression(
76 '=',
77 argument,
78 new MemberExpression(new Identifier('arguments'), new Literal(index))
79 )
80 ));
81 });
82
83 if (options.obtain) {
84 //Check and throw error
85 var errIdentifier = new Identifier(helpers.errName);
86 callbackPlace.push(new IfStatement(
87 errIdentifier,
88 new ThrowStatement(errIdentifier)
89 ));
90 }
91
92 //Replace cont with a callback function
93 self.arguments[contPos] = new FunctionExpression(
94 null,
95 [],
96 new BlockStatement(callbackPlace)
97 );
98 self.async = true;
99 newPlace = callbackPlace;
100 });
101 if (newPlace) {
102 return newPlace;
103 }
104
105 return place;
106};
107
108var findContinuation = function (args, callback) {
109 //Todo check multiple cont && obtain
110 for (var i = 0; i < args.length; i++) {
111 var arg = args[i];
112 if (arg.type === 'CallExpression') {
113 if (arg.callee.name === helpers.contName) {
114 return callback(arg, i, {});
115 } else if (arg.callee.name === helpers.obtainName) {
116 return callback(arg, i, {obtain: true});
117 }
118 }
119 }
120 return -1;
121};