1 | var assert = require('assert');
|
2 | var syntax = require('./syntax');
|
3 | var traverse = require('./traverse');
|
4 |
|
5 | var continuationIdentifier = exports.continuationIdentifier = '_$cont';
|
6 | exports.errName = '_$err';
|
7 | exports.contName = 'cont';
|
8 | exports.obtainName = 'obtain';
|
9 |
|
10 | exports.__defineGetter__('continuationStatement', function () {
|
11 | return new syntax.ExpressionStatement(new syntax.CallExpression(new syntax.Identifier(continuationIdentifier)));
|
12 | });
|
13 |
|
14 | exports.extractVariableDeclarations = function (block) {
|
15 | var decMap = {};
|
16 |
|
17 | traverse(block, {currentScope: true}, function (node) {
|
18 | if (node.type === 'VariableDeclaration') {
|
19 | var assignments = [];
|
20 | node.declarations.forEach(function (dec) {
|
21 | decMap[dec.id.name] = dec;
|
22 | if (dec.init !== null) {
|
23 |
|
24 | assignments.push(new syntax.ExpressionStatement(new syntax.AssignmentExpression('=', dec.id, dec.init)));
|
25 | dec.init = null;
|
26 | } else if (node.forIn) {
|
27 | assignments = dec.id;
|
28 | }
|
29 | });
|
30 | node = assignments;
|
31 | }
|
32 | return node;
|
33 | });
|
34 |
|
35 | var declarations = [];
|
36 | Object.keys(decMap).forEach(function (name) {
|
37 | var dec = decMap[name];
|
38 | dec.init = null;
|
39 | declarations.push(dec);
|
40 | });
|
41 |
|
42 | return new syntax.VariableDeclaration(declarations, 'var');
|
43 | };
|
44 |
|
45 | function findContinuation(args) {
|
46 |
|
47 | for (var i = 0; i < args.length; i++) {
|
48 | var arg = args[i];
|
49 | if (arg.type === 'CallExpression' && arg.callee.name === 'continuation') {
|
50 | return i;
|
51 | }
|
52 | }
|
53 | return -1;
|
54 | }
|
55 |
|
56 | exports.makeCPS = function (innerPlace, nextPlace) {
|
57 | return new syntax.ExpressionStatement(new syntax.CallExpression(
|
58 | new syntax.FunctionExpression(
|
59 | null,
|
60 | [new syntax.Identifier(continuationIdentifier)],
|
61 | new syntax.BlockStatement(innerPlace)
|
62 | ),
|
63 | [new syntax.FunctionExpression(
|
64 | null,
|
65 | [],
|
66 | new syntax.BlockStatement(nextPlace)
|
67 | )]
|
68 | ));
|
69 | };
|
70 |
|
71 | var loopCount = 0;
|
72 | exports.getLoopFunctionName = function () {
|
73 | var name = '_$loop_' + loopCount;
|
74 | loopCount ++;
|
75 | return name;
|
76 | };
|
77 |
|
78 | exports.reset = function () {
|
79 | loopCount = 0;
|
80 | };
|
81 |
|
82 | exports.isContinuationStatement = function (statement) {
|
83 | return statement.type === 'ExpressionStatement' &&
|
84 | statement.expression.type === 'CallExpression' &&
|
85 | statement.expression.callee.name === continuationIdentifier;
|
86 | };
|