You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.7 KiB
JavaScript
103 lines
2.7 KiB
JavaScript
"use strict";
|
|
|
|
const assert = require("assert");
|
|
const types = require("@babel/types");
|
|
const template = require("@babel/template").default;
|
|
const unreachable = require("@joepie91/unreachable")("jsnix");
|
|
|
|
const NoChange = require("../astformer/actions/no-change");
|
|
const ConsumeNode = require("../astformer/actions/consume-node");
|
|
const RemoveNode = require("../astformer/actions/remove-node");
|
|
|
|
const asExpression = require("as-expression");
|
|
const unpackExpression = require("./_unpack-expression");
|
|
const printAst = require("../print-ast");
|
|
|
|
|
|
|
|
// FIXME: Make strict mode! Otherwise objects will inherit from `global`
|
|
let tmplModule = template(`
|
|
module.exports = function({ builtins, $$jsNix$memoize }) {
|
|
return %%contents%%;
|
|
};
|
|
`);
|
|
|
|
let tmplObjectDynamic = template(`
|
|
(() => {
|
|
let $$nixJS_object = {};
|
|
|
|
%%entries%%
|
|
|
|
return $$nixJS_object;
|
|
})()
|
|
`);
|
|
|
|
let tmplObjectDynamicEntry = template(`
|
|
if ($$nixJS_object[%%key%%] !== undefined) { throw new Error(\`Duplicate key '\${%%key%%}' in attribute set\`); }
|
|
$$nixJS_object[%%key%%] = %%wrappedExpression%%;
|
|
`);
|
|
|
|
let tmplIdentifierReference = template(`(
|
|
%%name%%()
|
|
)`);
|
|
|
|
function generateDynamicObject(bindings, recursive) {
|
|
let generatedBindings = bindings.map((binding) => {
|
|
let wrapper = (recursive)
|
|
? tmplLazyWrapperRecursive
|
|
: tmplLazyWrapper;
|
|
|
|
let key = isDynamicBinding(binding)
|
|
? binding.attrpath.attr[0]
|
|
: binding.attrpath.attr[0].name;
|
|
|
|
return tmplObjectDynamicEntry({
|
|
key: key,
|
|
wrappedExpression: wrapper({ expression: binding.expression })
|
|
});
|
|
});
|
|
|
|
return tmplObjectDynamic({ entries: generatedBindings.flat() })
|
|
}
|
|
|
|
let trivial = {
|
|
name: "trivial-transforms",
|
|
visitors: {
|
|
// Trivial transforms
|
|
NixParenthesizedExpression: (node) => node.expression,
|
|
Program: (_node, { setContext, defer }) => {
|
|
setContext(null, "identifierType", "reference");
|
|
|
|
return defer((node) => {
|
|
assert(node.body.length === 1);
|
|
return tmplModule({ contents: node.body[0] });
|
|
});
|
|
},
|
|
NixIdentifier: (node, { getContext }) => {
|
|
// FIXME: Mangle reserved keywords like `const`
|
|
if (getContext("identifierType") === "define") {
|
|
return types.identifier(node.name);
|
|
} else { // reference
|
|
return unpackExpression(tmplIdentifierReference({ name: node.name }));
|
|
}
|
|
},
|
|
NixBinaryOperation: (_node, { defer }) => {
|
|
return defer((node) => {
|
|
// FIXME: Verify that all the 'operator' values match between Nix and JS!
|
|
return types.binaryExpression(node.operator, node.left, node.right);
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = [
|
|
require("./desugar-inherits"),
|
|
require("./mangle-identifiers"),
|
|
require("./let-in"),
|
|
require("./desugar-attrsets"),
|
|
require("./literals"),
|
|
require("./functions"),
|
|
require("./attribute-sets"),
|
|
trivial,
|
|
];
|