@effectful/transducers
Version:
JS syntax transformation framework for @effectful/js
120 lines (119 loc) • 3.86 kB
JavaScript
;
exports.__esModule = true;
exports.default = void 0;
var _core = require("../core");
var Kit = require("../kit");
var T = require("@babel/types");
const SpecVars = (0, _core.symbol)("SpecVars", "ctrl");
const specNames = {
arguments: true
};
var _default = exports.default = Kit.pipe(Kit.wrap("eager-generators-transform", function* transform(s) {
function* make(i) {
i.value.node.generator = false;
const lab = s.label();
yield* s.peelTo(_core.Tag.body);
yield* s.peelTo(_core.Tag.body);
const specVars = {};
yield s.tok(_core.Tag.push, SpecVars, {
node: specVars
});
yield s.enter(_core.Tag.push, _core.Tag.ReturnStatement);
yield s.enter(_core.Tag.argument, _core.Tag.CallExpression);
yield s.tok(_core.Tag.callee, T.identifier("e$y$make"));
yield s.enter(_core.Tag.arguments, _core.Tag.Array);
yield s.enter(_core.Tag.push, _core.Tag.ArrowFunctionExpression, {
node: {
id: {
type: "Identifier",
name: i.value.node.id != null ? `${i.value.node.id.name}Impl` : "EagerGen"
},
params: [{
type: "Identifier",
name: "e$y$buf"
}]
}
});
yield s.enter(_core.Tag.body, _core.Tag.BlockStatement);
yield s.enter(_core.Tag.body, _core.Tag.Array);
yield* walk(specVars);
yield* lab();
}
function* walk(specVars) {
for (const i of s.sub()) {
switch (i.type) {
case _core.Tag.YieldExpression:
if (i.enter) {
const lab = s.label();
yield s.enter(i.pos, _core.Tag.CallExpression);
yield s.tok(_core.Tag.callee, T.identifier(i.value.node.delegate ? "e$y$star" : "e$y"));
yield s.enter(_core.Tag.arguments, _core.Tag.Array);
yield s.tok(_core.Tag.push, T.identifier("e$y$buf"));
yield s.enter(_core.Tag.push, Kit.Subst);
yield* walk(specVars);
yield* lab();
}
continue;
case _core.Tag.Identifier:
if (specVars != null && specNames[i.value.node.name]) {
specVars[i.value.node.name] = true;
if (i.enter)
//TODO: unique names
yield s.tok(i.pos, T.identifier(`e$y$${i.value.node.name}`));
continue;
}
case _core.Tag.FunctionExpression:
case _core.Tag.ArrowFunctionExpression:
case _core.Tag.FunctionDeclaration:
if (i.enter && i.value.node.generator) {
yield i;
yield* make(i);
continue;
}
}
yield i;
}
}
for (const i of s) {
yield i;
switch (i.type) {
case _core.Tag.Class:
case _core.Tag.ClassBody:
case _core.Tag.ClassMethod:
case _core.Tag.FunctionExpression:
case _core.Tag.ArrowFunctionExpression:
case _core.Tag.FunctionDeclaration:
if (i.enter) {
if (!i.value.node.generator) break;
if (Kit.hasAnnot(i.value.node, "@LAZY")) {
yield* s.sub();
break;
}
yield* make(i);
}
}
}
}), Array.from, function* completeSpecVars(si) {
const s = Kit.auto(si);
for (const i of s) {
if (i.type === SpecVars) {
const lab = s.label();
const k = Object.keys(i.value.node);
if (k.length) {
yield s.enter(i.pos, _core.Tag.VariableDeclaration, {
node: {
kind: "var"
}
});
yield s.enter(_core.Tag.declarations, _core.Tag.Array);
for (const j of k) {
yield s.enter(_core.Tag.push, _core.Tag.VariableDeclarator);
yield s.tok(_core.Tag.id, T.identifier(`e$y$${j}`));
yield s.tok(_core.Tag.init, T.identifier(j));
yield* s.leave();
}
yield* lab();
}
} else yield i;
}
}, Kit.completeSubst);