clean up conditional assignment operator transformers

This commit is contained in:
Sebastian McKenzie
2015-01-17 22:56:49 +11:00
parent ecd85f53b4
commit b54800234f
10 changed files with 137 additions and 252 deletions

View File

@@ -0,0 +1,75 @@
var t = require("../../types");
module.exports = function (opts) {
var getObjRef = function (node, nodes, file, scope) {
var obj = node.object;
var temp = scope.generateUidBasedOnNode(obj, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, obj)
]));
return temp;
};
var getPropRef = function (node, nodes, file, scope) {
var prop = node.property;
var key = t.toComputedKey(node, prop);
if (t.isLiteral(key)) return key;
var temp = scope.generateUidBasedOnNode(prop, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, prop)
]));
return temp;
};
var buildAbsoluteRef = function (node, nodes, file, scope) {
if (t.isIdentifier(node)) return node;
var obj = getObjRef(node, nodes, file, scope);
var prop = getPropRef(node, nodes, file, scope);
var computed = node.computed || t.isLiteral(prop);
return t.memberExpression(obj, prop, computed);
};
var buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
var exports = {};
exports.ExpressionStatement = function (node, parent, scope, context, file) {
var expr = node.expression;
if (!opts.is(expr)) return;
var nodes = [];
var left = buildAbsoluteRef(expr.left, nodes, file, scope);
nodes.push(t.ifStatement(
opts.build(left, file),
t.expressionStatement(buildAssignment(left, expr.right))
));
return nodes;
};
exports.AssignmentExpression = function (node, parent, scope, context, file) {
if (t.isExpressionStatement(parent)) return;
if (!opts.is(node)) return;
var nodes = [];
var left = buildAbsoluteRef(node.left, nodes, file, scope);
nodes.push(t.logicalExpression(
"&&",
opts.build(left, file),
buildAssignment(left, node.right)
));
nodes.push(left);
return t.toSequenceExpression(nodes, scope);
};
return exports;
};

View File

@@ -1,86 +1,18 @@
var t = require("../../types");
var isMallet = function (node) {
var is = t.isAssignmentExpression(node) && node.operator === "||=";
if (is) {
var left = node.left;
if (!t.isMemberExpression(left) && !t.isIdentifier(left)) {
throw new Error("Expected type MemeberExpression or Identifier");
module.exports = require("../helpers/build-conditional-assignment-operator-transformer")({
is: function (node) {
var is = t.isAssignmentExpression(node) && node.operator === "||=";
if (is) {
var left = node.left;
if (!t.isMemberExpression(left) && !t.isIdentifier(left)) {
throw new Error("Expected type MemeberExpression or Identifier");
}
return true;
}
return true;
},
build: function (node) {
return t.unaryExpression("!", node, true);
}
};
var getObjRef = function (node, nodes, file, scope) {
var obj = node.object;
if (t.isIdentifier(obj)) return obj;
var temp = scope.generateUidBasedOnNode(obj, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, obj)
]));
return temp;
};
var getPropRef = function (node, nodes, file, scope) {
var prop = node.property;
var key = t.toComputedKey(node, prop);
if (t.isLiteral(key)) return key;
var temp = scope.generateUidBasedOnNode(prop, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, prop)
]));
return temp;
};
var buildAbsoluteRef = function (node, nodes, file, scope) {
if (t.isIdentifier(node)) return node;
var obj = getObjRef(node, nodes, file, scope);
var prop = getPropRef(node, nodes, file, scope);
var computed = node.computed || t.isLiteral(prop);
return t.memberExpression(obj, prop, computed);
};
var buildIsFalsey = function (node) {
return t.unaryExpression("!", node, true);
};
var buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
exports.ExpressionStatement = function (node, parent, file, scope) {
var expr = node.expression;
if (!isMallet(expr)) return;
var nodes = [];
var left = buildAbsoluteRef(expr.left, nodes, file, scope);
nodes.push(t.ifStatement(
buildIsFalsey(left),
t.expressionStatement(buildAssignment(left, expr.right))
));
return nodes;
};
exports.AssignmentExpression = function (node, parent, file, scope) {
if (t.isExpressionStatement(parent)) return;
if (!isMallet(node)) return;
var nodes = [];
var left = buildAbsoluteRef(node.left, nodes, file, scope);
nodes.push(t.logicalExpression(
"&&",
buildIsFalsey(left),
buildAssignment(left, node.right)
));
nodes.push(left);
return t.toSequenceExpression(nodes, scope);
};
});

View File

@@ -1,88 +1,20 @@
var t = require("../../types");
var isMemo = function (node) {
var is = t.isAssignmentExpression(node) && node.operator === "?=";
if (is) t.assertMemberExpression(node.left);
return is;
};
module.exports = require("../helpers/build-conditional-assignment-operator-transformer")({
is: function (node) {
var is = t.isAssignmentExpression(node) && node.operator === "?=";
if (is) t.assertMemberExpression(node.left);
return is;
},
var getPropRef = function (nodes, member, file, scope) {
var prop = member.property;
var key = t.toComputedKey(member, member.property);
if (t.isLiteral(key)) {
return key;
} else {
var temp = scope.generateUidBasedOnNode(prop, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, prop)
]));
return temp;
build: function (node, file) {
return t.unaryExpression(
"!",
t.callExpression(
t.memberExpression(file.addHelper("has-own"), t.identifier("call")),
[node.object, node.property]
),
true
);
}
};
var getObjRef = function (nodes, obj, file, scope) {
var temp = scope.generateUidBasedOnNode(obj, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, obj)
]));
return temp;
};
var buildHasOwn = function (obj, prop, file) {
return t.unaryExpression(
"!",
t.callExpression(
t.memberExpression(file.addHelper("has-own"), t.identifier("call")),
[obj, prop]
),
true
);
};
var buildAbsoluteRef = function (left, obj, prop) {
var computed = left.computed || t.isLiteral(prop);
return t.memberExpression(obj, prop, computed);
};
var buildAssignment = function (expr, obj, prop) {
return t.assignmentExpression("=", buildAbsoluteRef(expr.left, obj, prop), expr.right);
};
exports.ExpressionStatement = function (node, parent, scope, context, file) {
var expr = node.expression;
if (!isMemo(expr)) return;
var nodes = [];
var left = expr.left;
var obj = getObjRef(nodes, left.object, file, scope);
var prop = getPropRef(nodes, left, file, scope);
nodes.push(t.ifStatement(
buildHasOwn(obj, prop, file),
t.expressionStatement(buildAssignment(expr, obj, prop))
));
return nodes;
};
exports.AssignmentExpression = function (node, parent, scope, context, file) {
if (t.isExpressionStatement(parent)) return;
if (!isMemo(node)) return;
var nodes = [];
var left = node.left;
var obj = getObjRef(nodes, left.object, file, scope);
var prop = getPropRef(nodes, left, file, scope);
nodes.push(t.logicalExpression(
"&&",
buildHasOwn(obj, prop, file),
buildAssignment(node, obj, prop)
));
nodes.push(buildAbsoluteRef(left, obj, prop));
return t.toSequenceExpression(nodes, scope);
};
});