51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
import { types as t } from "@babel/core";
|
|
|
|
const topicReferenceReplacementVisitor = {
|
|
TopicReference(path) {
|
|
path.replaceWith(t.cloneNode(this.topicVariable));
|
|
},
|
|
};
|
|
|
|
// This visitor traverses `BinaryExpression`
|
|
// and replaces any that use `|>`
|
|
// with sequence expressions containing assignment expressions
|
|
// with automatically generated variables,
|
|
// from inside to outside, from left to right.
|
|
export default {
|
|
BinaryExpression: {
|
|
exit(path) {
|
|
const { scope, node } = path;
|
|
|
|
if (node.operator !== "|>") {
|
|
// The path node is a binary expression,
|
|
// but it is not a pipe expression.
|
|
return;
|
|
}
|
|
|
|
const topicVariable = scope.generateUidIdentifierBasedOnNode(node);
|
|
const pipeBodyPath = path.get("right");
|
|
|
|
scope.push({ id: topicVariable });
|
|
|
|
if (pipeBodyPath.node.type === "TopicReference") {
|
|
// If the pipe body is itself a lone topic reference,
|
|
// then replace it with the topic variable.
|
|
pipeBodyPath.replaceWith(t.cloneNode(topicVariable));
|
|
} else {
|
|
// Replace topic references with the topic variable.
|
|
pipeBodyPath.traverse(topicReferenceReplacementVisitor, {
|
|
topicVariable,
|
|
});
|
|
}
|
|
|
|
// Replace the pipe expression itself with an assignment expression.
|
|
path.replaceWith(
|
|
t.sequenceExpression([
|
|
t.assignmentExpression("=", t.cloneNode(topicVariable), node.left),
|
|
node.right,
|
|
]),
|
|
);
|
|
},
|
|
},
|
|
};
|