-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
74 lines (68 loc) · 2.38 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import * as horchata from "horchata";
import * as parserPlugin from "./horchata/parser";
import * as lexerPlugin from "./horchata/lexer";
horchata.registerPluginModule("logical-assign", parserPlugin, lexerPlugin);
// helpers required:
// cache value
// find nearest statement location
// TODO: document comal-traverse (and babel-traverse) thoroughly
export default function ({types: t}) {
return {
visitor: {
ExpressionStatement(path) {
const node = path.node.expression;
if (t.isAssignmentExpression(node)) {
const {left, right, operator: op, extra} = node;
if (op === "&&=" || op === "||=") {
if (extra == null || !extra.parenthesized) {
let test = op === "&&=" ? left : t.unaryExpression("!", left, true);
path.replaceWith(t.ifStatement(test, t.expressionStatement(t.assignmentExpression('=', left, right))));
}
}
}
},
AssignmentExpression(path) {
const node = path.node;
const op = node.operator;
if (op === "&&=" || op === "||=") {
const {left, right} = path.node;
path.replaceWith(t.logicalExpression(op.slice(0, -1), left, t.assignmentExpression('=', left, right)));
// TODO: also cache accessor, e.g.
// a.b.c ||= d
// =>
// const a_b = a.b
// (a_b.c || (a_b.c = d));
}
}
},
manipulateOptions(opts, parserOpts, transformation) {
const parser = transformation.parser;
if (parser && parser.name === "horchata") {
parserOpts.plugins["logical-assign"] = true;
}
}
};
}
export function transpose({types: t}) {
return {
visitor: {
LogicalExpression(path) {
const {node} = path;
if (node.operator !== "&&" && node.operator !== "||") return;
// TODO: create a "node equals" for comal-types
if (t.isAssignmentExpression(node.right)) {
const outerLeft = node.left;
const innerLeft = node.right.left;
// TODO: generic case, not just identifier
if (
t.isIdentifier(outerLeft) && t.isIdentifier(innerLeft) &&
outerLeft.name === innerLeft.name
) {
path.replaceWith(t.assignmentExpression(node.operator + "=", node.left, node.right.right));
}
}
}
},
};
}
export * as tacotruck from "./tacotruck";