Skip to content

Commit

Permalink
cfg: fix branching
Browse files Browse the repository at this point in the history
  • Loading branch information
indutny committed Sep 25, 2012
1 parent 77407e0 commit a7e6b41
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 30 deletions.
1 change: 1 addition & 0 deletions lib/spoon.js
Expand Up @@ -9,3 +9,4 @@ spoon.renderer = require('./spoon/renderer');
// Export API
spoon.construct = require('./spoon/api').construct;
spoon.render = require('./spoon/api').render;
spoon.preprocess = require('./spoon/api').preprocess;
21 changes: 11 additions & 10 deletions lib/spoon/api.js
Expand Up @@ -16,20 +16,21 @@ api.render = function render(cfg) {
return r.render();
};

api.spoon = function spoon(code, fn, options) {
api.preprocess = function preprocess(code, options, callback) {
if (!options) options = {};

var ast = esprima.parse('function main() {\n' +
code +
'\n}',
options.esprima),
cfg = spoon.construct(ast);
var ast = esprima.parse(code, options.esprima),
cfg = api.spoon.construct(ast);

cfg.asyncify(fn);
ast = spoon.render(cfg);
if (callback) callback(cfg);

// Leave only function's body
ast[1] = ast[1][0][1][3];
ast = api.spoon.render(cfg);

return uglify.uglify.gen_code(ast, options.uglify);
};

api.spoon = function spoon(code, fn, options) {
return api.preprocess(function(cfg) {
cfg.asyncify(fn);
});
};
43 changes: 24 additions & 19 deletions lib/spoon/cfg.js
Expand Up @@ -58,6 +58,14 @@ Cfg.prototype.add = function add(type, args) {
return this.current.add(type, args);
};

Cfg.prototype.goto = function branch(target) {
return this.current.goto(target);
}

Cfg.prototype.branch = function branch(type, args, tblock, fblock) {
return this.current.branch(type, args, tblock, fblock);
};

Cfg.prototype.translate = function translate(ast) {
this.rootQueue.push({
instr: null,
Expand Down Expand Up @@ -599,7 +607,7 @@ Cfg.prototype.visitLogical = function visitLogical(ast) {
move1,
move2;

this.current.branch('logical', [ left ], tblock, fblock);
this.branch('logical', [ left ], tblock, fblock);

if (ast.operator === '||') {
this.setCurrentBlock(tblock);
Expand Down Expand Up @@ -661,10 +669,10 @@ Cfg.prototype.visitIf = function visitIf(ast) {
fblock = ast.alternate && this.createBlock(),
join = this.createBlock();

this.current.branch('if',
[ this.visit(ast.test) ],
tblock,
ast.alternate ? fblock : join);
this.branch('if',
[ this.visit(ast.test) ],
tblock,
ast.alternate ? fblock : join);

// True branch
this.setCurrentBlock(tblock);
Expand Down Expand Up @@ -779,7 +787,7 @@ Cfg.prototype.visitWhile = function visitWhile(ast) {
var start = this.current,
body = this.createBlock();

this.current.branch('while', [this.visit(ast.test)], body, end);
this.branch('while', [this.visit(ast.test)], body, end);

this.setCurrentBlock(body);
this.visit(ast.body);
Expand All @@ -791,7 +799,7 @@ Cfg.prototype.visitDoWhile = function visitDoWhile(ast) {
var start = this.current,
body = this.createBlock();

this.current.branch('while', [
this.branch('while', [
this.visit({ type: 'Identifier', name: 'true' })
], body, end);

Expand Down Expand Up @@ -822,10 +830,10 @@ Cfg.prototype.visitConditional = function visitConditional(ast) {
fblock = this.createBlock(),
join = this.createBlock();

this.current.branch('ternary',
[this.visit(ast.test), tblock, fblock],
tblock,
ast.alternate ? fblock : join);
this.branch('ternary',
[this.visit(ast.test), tblock, fblock],
tblock,
ast.alternate ? fblock : join);

// True branch
this.setCurrentBlock(tblock);
Expand Down Expand Up @@ -887,7 +895,7 @@ Cfg.prototype.visitFor = function visitFor(ast) {
body = this.createBlock();

this.breakInfo.update = ast.update;
this.current.branch('while', [this.visit(ast.test)], body, end);
this.branch('while', [this.visit(ast.test)], body, end);

this.setCurrentBlock(body);
this.visit(ast.body);
Expand All @@ -907,10 +915,7 @@ Cfg.prototype.visitForIn = function visitFor(ast) {
var start = this.current,
body = this.createBlock();

this.current.branch('forin',
[this.visit(left), this.visit(ast.right)],
body,
end);
this.branch('forin', [this.visit(left), this.visit(ast.right)], body, end);
start.end();

this.setCurrentBlock(body);
Expand All @@ -923,18 +928,18 @@ Cfg.prototype.visitTry = function visitTry(ast) {
caught = this.createBlock(),
join = this.createBlock();

var instr = this.current.branch('try', [], body, caught);
var instr = this.branch('try', [], body, caught);

this.setCurrentBlock(body);
this.visit(ast.block);
this.current.goto(join);
this.goto(join);

this.setCurrentBlock(caught);
ast.handlers.forEach(function(handler) {
instr.catchParam = handler.param.name;
this.visit(handler.body);
}, this);
this.current.goto(join);
this.goto(join);

this.setCurrentBlock(join);
if (ast.finalizer) throw TypeError('Finally is not supported yet');
Expand Down
1 change: 0 additions & 1 deletion test/asyncify-test.js
Expand Up @@ -13,7 +13,6 @@ describe('Spoon', function() {

var out = spoon.render(cfg);
var code = uglify.uglify.gen_code(out, { beautify: true });
console.log(code);

var res,
once = false;
Expand Down
9 changes: 9 additions & 0 deletions test/cfg-test.js
Expand Up @@ -137,6 +137,15 @@ describe('Spoon', function() {
test('new Object()', {});
});

it('should work with regr#1', function() {
test('var x, y;\n' +
'if (!(typeof x === "undefined" || !y) === false) {\n' +
' "true"\n' +
'} else {\n' +
' "false"\n' +
'}', "true");
})

// XXX Implement switch
return;
it('should work with switch', function() {
Expand Down

0 comments on commit a7e6b41

Please sign in to comment.