Example script that turns for and do-while loops into while loops.

This commit is contained in:
Ben Newman 2012-12-16 13:36:04 -08:00
parent 230cd020e8
commit 552af994ee
2 changed files with 92 additions and 0 deletions

68
example/to-while Executable file
View file

@ -0,0 +1,68 @@
#!/usr/bin/env node
// This script converts for and do-while loops into equivalent while loops.
// Note that for-in statements are left unmodified, as they do not have a
// simple analogy to while loops. Also note that labeled continue statements
// are not correctly handled at this point, and will trigger an assertion
// failure if encountered.
var assert = require("assert"),
Syntax = require("recast").Syntax,
Visitor = require("recast").Visitor,
builder = require("recast").builder;
require("recast").run(function(ast, callback) {
callback(new ToWhile().visit(ast));
});
var ToWhile = Visitor.extend({
visitForStatement: function(fst) {
return builder.blockStatement([
fst.init,
builder.whileStatement(
fst.test,
insertBeforeLoopback(fst, fst.update))]);
},
visitDoWhileStatement: function(dwst) {
return builder.whileStatement(
builder.literal(true),
insertBeforeLoopback(
dwst,
builder.ifStatement(
dwst.test,
builder.breakStatement())));
}
});
function insertBeforeLoopback(loop, toInsert) {
var body = loop.body;
if (body.type === Syntax.BlockStatement) {
body.body.push(toInsert);
} else {
body = builder.blockStatement([body, toInsert]);
loop.body = body;
}
new BeforeContinue(toInsert).visit(body);
return body;
}
var BeforeContinue = Visitor.extend({
init: function(before) {
this.before = before;
},
visitContinueStatement: function(cst) {
assert.equal(cst.label, null, "Labeled continue statements are not yet supported.");
return builder.blockStatement([this.before, cst]);
},
// Do not descend into nested loops.
visitWhileStatement: function() {},
visitForStatement: function() {},
visitForInStatement: function() {},
visitDoWhileStatement: function() {}
});

View file

@ -71,3 +71,27 @@ exports.blockStatement = function(body) {
body: body
};
};
exports.whileStatement = function(test, body) {
return {
type: Syntax.WhileStatement,
test: test,
body: body
};
};
exports.breakStatement = function(label) {
return {
type: Syntax.BreakStatement,
label: label
};
};
exports.ifStatement = function(test, cons, alt) {
return {
type: Syntax.IfStatement,
test: test,
consequent: cons,
alternate: alt
};
}