better helpers for assignment operators

This commit is contained in:
Sebastian McKenzie 2015-01-18 00:37:51 +11:00
parent b54800234f
commit 67029ac8e8
7 changed files with 123 additions and 64 deletions

View File

@ -0,0 +1,43 @@
var explode = require("./explode-assignable-expression");
var t = require("../../types");
module.exports = function (exports, opts) {
var isAssignment = function (node) {
return node.operator === opts.operator + "=";
};
var buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
exports.ExpressionStatement = function (node, parent, scope, context, file) {
var expr = node.expression;
if (!isAssignment(expr)) return;
var nodes = [];
var exploded = explode(expr.left, nodes, file, scope);
nodes.push(t.expressionStatement(
buildAssignment(exploded.ref, opts.build(exploded.uid, expr.right))
));
return nodes;
};
exports.AssignmentExpression = function (node, parent, scope, context, file) {
if (t.isExpressionStatement(parent)) return;
if (!isAssignment(node)) return;
var nodes = [];
var exploded = explode(node.left, nodes, file, scope);
nodes.push(opts.build(exploded.uid, node.right));
nodes.push(exploded.ref);
return t.toSequenceExpression(nodes, scope);
};
exports.BinaryExpression = function (node) {
if (node.operator !== opts.operator) return;
return opts.build(node.left, node.right);
};
};

View File

@ -1,53 +1,22 @@
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 explode = require("./explode-assignable-expression");
var t = require("../../types");
module.exports = function (exports, opts) {
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;
if (!opts.is(expr, file)) return;
var nodes = [];
var left = buildAbsoluteRef(expr.left, nodes, file, scope);
var exploded = explode(expr.left, nodes, file, scope);
nodes.push(t.ifStatement(
opts.build(left, file),
t.expressionStatement(buildAssignment(left, expr.right))
opts.build(exploded.uid, file),
t.expressionStatement(buildAssignment(exploded.ref, expr.right))
));
return nodes;
@ -55,21 +24,19 @@ module.exports = function (opts) {
exports.AssignmentExpression = function (node, parent, scope, context, file) {
if (t.isExpressionStatement(parent)) return;
if (!opts.is(node)) return;
if (!opts.is(node, file)) return;
var nodes = [];
var left = buildAbsoluteRef(node.left, nodes, file, scope);
var nodes = [];
var exploded = explode(node.left, nodes, file, scope);
nodes.push(t.logicalExpression(
"&&",
opts.build(left, file),
buildAssignment(left, node.right)
opts.build(exploded.uid, file),
buildAssignment(exploded.ref, node.right)
));
nodes.push(left);
nodes.push(exploded.ref);
return t.toSequenceExpression(nodes, scope);
};
return exports;
};

View File

@ -0,0 +1,49 @@
var t = require("../../types");
var getObjRef = function (node, nodes, file, scope) {
var ref;
if (t.isIdentifier(node)) {
ref = node;
} else if (t.isMemberExpression(node)) {
ref = node.object;
} else {
throw new Error("We can't explode this node type " + node.type);
}
var temp = scope.generateUidBasedOnNode(ref, file);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, ref)
]));
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;
};
module.exports = function (node, nodes, file, scope) {
var obj = getObjRef(node, nodes, file, scope);
var ref, uid;
if (t.isIdentifier(node)) {
ref = node;
uid = obj;
} else {
var prop = getPropRef(node, nodes, file, scope);
var computed = node.computed || t.isLiteral(prop);
uid = ref = t.memberExpression(obj, prop, computed);
}
return {
uid: uid,
ref: ref
};
};

View File

@ -2,17 +2,15 @@
exports.experimental = true;
var t = require("../../types");
var pow = t.memberExpression(t.identifier("Math"), t.identifier("pow"));
var build = require("../helpers/build-binary-assignment-operator-transformer");
var t = require("../../types");
exports.AssignmentExpression = function (node) {
if (node.operator !== "**=") return;
node.operator = "=";
node.right = t.callExpression(pow, [node.left, node.right]);
};
var MATH_POW = t.memberExpression(t.identifier("Math"), t.identifier("pow"));
exports.BinaryExpression = function (node) {
if (node.operator !== "**") return;
build(exports, {
operator: "**",
return t.callExpression(pow, [node.left, node.right]);
};
build: function (left, right) {
return t.callExpression(MATH_POW, [left, right]);
}
});

View File

@ -1,12 +1,13 @@
var t = require("../../types");
var build = require("../helpers/build-conditional-assignment-operator-transformer");
var t = require("../../types");
module.exports = require("../helpers/build-conditional-assignment-operator-transformer")({
is: function (node) {
build(exports, {
is: function (node, file) {
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");
throw file.errorWithNode(left, "Expected type MemeberExpression or Identifier");
}
return true;
}

View File

@ -1,6 +1,7 @@
var t = require("../../types");
var build = require("../helpers/build-conditional-assignment-operator-transformer");
var t = require("../../types");
module.exports = require("../helpers/build-conditional-assignment-operator-transformer")({
build(exports, {
is: function (node) {
var is = t.isAssignmentExpression(node) && node.operator === "?=";
if (is) t.assertMemberExpression(node.left);