add support for all completion record types when exploding an expression to statements

This commit is contained in:
Sebastian McKenzie 2015-05-20 09:56:45 +01:00
parent 7a59575d1e
commit e280a810c3

View File

@ -754,20 +754,22 @@ export default class TraversalPath {
* Description * Description
*/ */
getLastStatements(): Array<TraversalPath> { getCompletionRecords(): Array<TraversalPath> {
var paths = []; var paths = [];
var add = function (path) { var add = function (path) {
if (path) paths = paths.concat(path.getLastStatements()); if (path) paths = paths.concat(path.getCompletionRecords());
}; };
if (this.isIfStatement()) { if (this.isIfStatement()) {
add(this.get("consequent")); add(this.get("consequent"));
add(this.get("alternate")); add(this.get("alternate"));
} else if (this.isDoExpression()) { } else if (this.isDoExpression() || this.isFor() || this.isWhile()) {
add(this.get("body")); add(this.get("body"));
} else if (this.isProgram() || this.isBlockStatement()) { } else if (this.isProgram() || this.isBlockStatement()) {
add(this.get("body").pop()); add(this.get("body").pop());
} else if (this.isFunction()) {
return this.get("body").getCompletionRecords();
} else { } else {
paths.push(this); paths.push(this);
} }
@ -788,19 +790,27 @@ export default class TraversalPath {
var container = t.functionExpression(null, [], t.blockStatement(nodes)); var container = t.functionExpression(null, [], t.blockStatement(nodes));
container.shadow = true; container.shadow = true;
this.replaceWith(t.callExpression(container, []));
this.traverse(hoistVariablesVisitor);
// add implicit returns to all ending expression statements // add implicit returns to all ending expression statements
var last = this.getLastStatements(); var last = this.get("callee").getCompletionRecords();
for (var i = 0; i < last.length; i++) { for (var i = 0; i < last.length; i++) {
var lastNode = last[i]; var lastNode = last[i];
if (lastNode.isExpressionStatement()) { if (lastNode.isExpressionStatement()) {
lastNode.replaceWith(t.returnStatement(lastNode.node.expression)); var loop = lastNode.findParent((node, path) => path.isLoop());
if (loop) {
var uid = this.get("callee").scope.generateDeclaredUidIdentifier("ret");
this.get("callee.body").pushContainer("body", t.returnStatement(uid));
lastNode.get("expression").replaceWith(
t.assignmentExpression("=", uid, lastNode.node.expression)
);
} else {
lastNode.replaceWith(t.returnStatement(lastNode.node.expression));
}
} }
} }
this.replaceWith(t.callExpression(container, []));
this.traverse(hoistVariablesVisitor);
return this.node; return this.node;
} }
} }