Skip to content

Commit

Permalink
switch statement
Browse files Browse the repository at this point in the history
  • Loading branch information
alongubkin committed Nov 15, 2014
1 parent 38b9656 commit f325358
Show file tree
Hide file tree
Showing 6 changed files with 1,416 additions and 647 deletions.
4 changes: 3 additions & 1 deletion lib/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ module.exports = {
DebuggerStatement: require('./ast/statements/DebuggerStatement').DebuggerStatement,
UseStatement: require('./ast/statements/UseStatement').UseStatement,
TryStatement: require('./ast/statements/TryStatement').TryStatement,
SwitchStatement: require('./ast/statements/SwitchStatement').SwitchStatement,
BooleanLiteral: require('./ast/literals/BooleanLiteral').BooleanLiteral,
NumberLiteral: require('./ast/literals/NumberLiteral').NumberLiteral,
StringLiteral: require('./ast/literals/StringLiteral').StringLiteral,
Expand All @@ -49,5 +50,6 @@ module.exports = {
Property: require('./ast/Property').Property,
Range: require('./ast/Range').Range,
Parameter: require('./ast/Parameter').Parameter,
CatchClause: require('./ast/CatchClause').CatchClause
CatchClause: require('./ast/CatchClause').CatchClause,
CaseClause: require('./ast/CaseClause').CaseClause
};
109 changes: 109 additions & 0 deletions lib/ast/CaseClause.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
var Node = require('./Node').Node;

exports.CaseClause = function (tests, body) {
var self = this;
Node.call(this);

self.type = 'CaseClause';

self.tests = tests;
if (self.tests) {
self.tests.forEach(function (test) {
test.parent = self;
});
}

self.body = body;
self.body.parent = self;
};

exports.CaseClause.prototype = Object.create(Node);

exports.CaseClause.prototype.codegen = function () {
var self = this;

if (!Node.prototype.codegen.call(self)) {
return;
}

if (!self.tests) {
return self.body.codegen();
}

self.type = "IfStatement";

var rangeError = false;
self.tests.forEach(function (test) {
var equalsToDiscriminant;

if (test.type === "Range") {
var fromCheck;
if (test.from) {
fromCheck = {
"type": "BinaryExpression",
"operator": ">=",
"left": self.parent.discriminant,
"right": test.from
};
}

var toCheck;
if (test.to) {
toCheck = {
"type": "BinaryExpression",
"operator": "<" + (test.operator === ".." ? "=": ""),
"left": self.parent.discriminant,
"right": test.to
};
}

if (fromCheck && toCheck) {
equalsToDiscriminant = {
"type": "LogicalExpression",
"operator": "&&",
"left": fromCheck,
"right": toCheck
};
} else if (fromCheck || toCheck) {
equalsToDiscriminant = fromCheck || toCheck;
} else {
rangeError = test;
return false;
}
} else {
equalsToDiscriminant = {
"type": "BinaryExpression",
"operator": "===",
"left": self.parent.discriminant,
"right": test.codegen()
};
}


if (!self.test) {
self.test = equalsToDiscriminant;
} else {
self.test = {
"type": "LogicalExpression",
"operator": "||",
"left": self.test,
"right": equalsToDiscriminant
};
}
});

if (rangeError) {
Node.getErrorManager().error({
type: "EmptyRange",
message: "empty range in case clause is disallowed.",
loc: rangeError.loc
});

return false;
}

self.consequent = self.body.codegen();
self.alternate = null;

return self;
};
68 changes: 68 additions & 0 deletions lib/ast/statements/SwitchStatement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
var Node = require('../Node').Node;

exports.SwitchStatement = function (discriminant, cases) {
var self = this;
Node.call(this);

self.type = 'SwitchStatement';

self.discriminant = discriminant;
self.discriminant.parent = this;

self.cases = cases;
self.cases.forEach(function (caseClause) {
caseClause.parent = self;
});
};

exports.SwitchStatement.prototype = Object.create(Node);

exports.SwitchStatement.prototype.codegen = function () {
var self = this;

if (!Node.prototype.codegen.call(self)) {
return;
}

self.discriminant = self.discriminant.codegen();

var firstCase, currentCase, defaultCase;
self.cases.forEach(function (caseClause) {
if (!caseClause.tests) {
defaultCase = caseClause;
return;
}

if (!firstCase) {
firstCase = caseClause.codegen();
currentCase = firstCase;
} else {
currentCase.alternate = caseClause.codegen();
currentCase = currentCase.alternate;
}
});

if (defaultCase) {
if (!firstCase) {
Node.getErrorManager().error({
type: "SingleDefaultClause",
message: "default clause without other case clauses is disallowed.",
loc: defaultCase.loc
});
} else {
currentCase.alternate = defaultCase.codegen();
}
}

if (!firstCase) {
self.type = "ExpressionStatement";
self.expression = self.discriminant;
} else {
self.type = firstCase.type;
self.test = firstCase.test;
self.consequent = firstCase.consequent;
self.alternate = firstCase.alternate;
}

return self;
};
Loading

0 comments on commit f325358

Please sign in to comment.