1 | var BlockStatement = require('./BlockStatement');
|
2 | var CallExpression = require('./CallExpression');
|
3 | var ExpressionStatement = require('./ExpressionStatement');
|
4 | var FunctionDeclaration = require('./FunctionDeclaration');
|
5 | var Identifier = require('./Identifier');
|
6 | var ReturnStatement = require('./ReturnStatement');
|
7 | var helpers = require('../helpers');
|
8 | var traverse = require('../traverse');
|
9 |
|
10 | var SwitchStatement = module.exports = function(discriminant, cases) {
|
11 | this.type = 'SwitchStatement';
|
12 | this.discriminant = discriminant;
|
13 | this.cases = cases;
|
14 | };
|
15 |
|
16 | SwitchStatement.prototype.normalize = function (body) {
|
17 | if (this.cases) {
|
18 | this.cases.forEach(function (sCase) {
|
19 | var block = new BlockStatement(sCase.consequent);
|
20 | block.normalize();
|
21 | sCase.consequent = block.body;
|
22 | });
|
23 | }
|
24 | body.push(this);
|
25 | };
|
26 |
|
27 | SwitchStatement.prototype.transform = function (place) {
|
28 | var innerPlace = [];
|
29 | var caseFunctions = [];
|
30 | var casePlaces = [];
|
31 | var async = false;
|
32 |
|
33 | if (this.cases) {
|
34 | this.cases.forEach(function (sCase, index) {
|
35 | var name = 'case_' + index;
|
36 | var func = new FunctionDeclaration(
|
37 | new Identifier(name),
|
38 | [new Identifier(helpers.continuationIdentifier)],
|
39 | new BlockStatement(sCase.consequent)
|
40 | );
|
41 |
|
42 | var place = func.body.transform();
|
43 | async = async || func.body.async;
|
44 | casePlaces.push(place);
|
45 | caseFunctions.push(func);
|
46 | innerPlace.push(func);
|
47 | });
|
48 | }
|
49 |
|
50 | if (!async) {
|
51 |
|
52 | place.push(this);
|
53 | return place;
|
54 | }
|
55 | this.async = true;
|
56 |
|
57 |
|
58 | this.cases.forEach(function (sCase, index) {
|
59 | var name = 'case_' + index;
|
60 | var continuationExpression = new CallExpression(new Identifier(name), [new Identifier(helpers.continuationIdentifier)]);
|
61 | sCase.consequent = [
|
62 | new ReturnStatement(continuationExpression),
|
63 | ];
|
64 | });
|
65 |
|
66 | caseFunctions.forEach(function (func, index) {
|
67 | var nextFunc = null;
|
68 | if (index !== caseFunctions.length - 1) {
|
69 | nextFunc = caseFunctions[index + 1];
|
70 | }
|
71 | var place = casePlaces[index];
|
72 | place.forEach(function (statement, i) {
|
73 |
|
74 | if (statement.type === 'BreakStatement') {
|
75 | place[i] = helpers.continuationStatement;
|
76 | }
|
77 | });
|
78 | if (place.length === 0 || !helpers.isContinuationStatement(place[place.length - 1])) {
|
79 |
|
80 | if (nextFunc !== null) {
|
81 | place.push(new ExpressionStatement(new CallExpression(nextFunc.id, [new Identifier(helpers.continuationIdentifier)])));
|
82 | } else {
|
83 | place.push(helpers.continuationStatement);
|
84 | }
|
85 | }
|
86 |
|
87 | traverse(func.body, function (statement) {
|
88 | if (statement.type === 'BreakStatement') {
|
89 | statement = new ReturnStatement(helpers.continuationStatement.expression);
|
90 | }
|
91 | return statement;
|
92 | });
|
93 | });
|
94 |
|
95 |
|
96 | innerPlace.push(this);
|
97 |
|
98 | var nextPlace = [];
|
99 | place.push(helpers.makeCPS(innerPlace, nextPlace));
|
100 |
|
101 | return nextPlace;
|
102 | };
|