Merge pull request #516 from jridgewell/mallot

Playground Proposal: Mallet operator
This commit is contained in:
Sebastian McKenzie 2015-01-17 21:59:23 +11:00
commit ecd85f53b4
5 changed files with 223 additions and 0 deletions

View File

@ -46,6 +46,7 @@ _.each({
specSetters: require("./transformers/spec-setters"),
// playground
malletOperator: require("./transformers/playground-mallet-operator"),
methodBinding: require("./transformers/playground-method-binding"),
memoizationOperator: require("./transformers/playground-memoization-operator"),
objectGetterMemoization: require("./transformers/playground-object-getter-memoization"),

View File

@ -0,0 +1,86 @@
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");
}
return 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

@ -0,0 +1,17 @@
obj ||= {};
obj.x ||= 2;
console.log(obj.x ||= 2);
obj.x.x ||= 2;
console.log(obj.x.x ||= 2);
obj[x()] ||= 2;
console.log(obj[x()] ||= 2);
obj[y()][x()] ||= 2;
console.log(obj[y()][x()] ||= 2);

View File

@ -0,0 +1,90 @@
var obj = {};
obj.x ||= 2;
assert.equal(obj.x, 2);
obj = {};
assert.equal(obj.x ||= 2, 2);
obj = { x: 1 };
obj.x ||= 2;
assert.equal(obj.x, 1);
obj = { x: 1 };
assert.equal(obj.x ||= 2, 1);
obj = { x: undefined }
obj.x ||= 2;
assert.equal(obj.x, 2);
obj = { x: undefined }
assert.equal(obj.x ||= 2, 2);
obj = { x: null }
obj.x ||= 2;
assert.equal(obj.x, 2);
obj = { x: null }
assert.equal(obj.x ||= 2, 2);
obj = { x: false }
obj.x ||= 2;
assert.equal(obj.x, 2);
obj = { x: false }
assert.equal(obj.x ||= 2, 2);
obj = { x: '' }
obj.x ||= 2;
assert.equal(obj.x, 2);
obj = { x: '' }
assert.equal(obj.x ||= 2, 2);
obj = { x: 0 }
obj.x ||= 2;
assert.equal(obj.x, 2);
obj = { x: 0 }
assert.equal(obj.x ||= 2, 2);
obj = undefined;
obj ||= 2;
assert.equal(obj, 2);
obj = undefined;
assert.equal(obj ||= 2 , 2);
obj = 1;
obj ||= 2;
assert.equal(obj, 1);
obj = 1;
assert.equal(obj ||= 2 , 1);
obj = null;
obj ||= 2;
assert.equal(obj, 2);
obj = null;
assert.equal(obj ||= 2 , 2);
obj = false;
obj ||= 2;
assert.equal(obj, 2);
obj = false;
assert.equal(obj ||= 2 , 2);
obj = '';
obj ||= 2;
assert.equal(obj, 2);
obj = '';
assert.equal(obj ||= 2 , 2);
obj = 0;
obj ||= 2;
assert.equal(obj, 2);
obj = 0;
assert.equal(obj ||= 2 , 2);

View File

@ -0,0 +1,29 @@
"use strict";
var _obj$x2, _x2, _obj$y2, _x4;
if (!obj) obj = {};
if (!obj.x) obj.x = 2;
console.log((!obj.x && (obj.x = 2), obj.x));
var _obj$x = obj.x;
if (!_obj$x.x) _obj$x.x = 2;
console.log((_obj$x2 = obj.x, !_obj$x2.x && (_obj$x2.x = 2), _obj$x2.x));
var _x = x();
if (!obj[_x]) obj[_x] = 2;
console.log((_x2 = x(), !obj[_x2] && (obj[_x2] = 2), obj[_x2]));
var _obj$y = obj[y()];
var _x3 = x();
if (!_obj$y[_x3]) _obj$y[_x3] = 2;
console.log((_obj$y2 = obj[y()], _x4 = x(), !_obj$y2[_x4] && (_obj$y2[_x4] = 2), _obj$y2[_x4]));