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.

45 lines
1.6 KiB
JavaScript

"use strict";
const unreachable = require("@joepie91/unreachable");
const assert = require("assert");
const splitFilter = require("split-filter");
const _nixTypes = require("./util/nix-types");
function isValidBodyAttribute(binding) {
assert(binding.attrpath.type === "NixAttributePath");
assert(binding.attrpath.attr.length > 0);
assert(binding.attrpath.attr[0].type === "NixAttributeIdentifier");
if (binding.attrpath.attr[0].name === "body") {
if (binding.attrpath.attr.length > 1) {
throw unreachable("attribute paths should have been desugared");
} else {
return true;
}
} else {
return false;
}
}
module.exports = {
name: "desugar-let-attribute-set",
visitors: {
NixLetAttributeSet: (node) => {
// We save a bunch of complexity here by directly translating to a recursive attribute set instead of `let..in`; our JS representation of `let..in` is *functionally* identical to how a LetAttributeSet works. We just use a different attribute name to represent the returned evaluation.
let [ bodyBindings, actualBindings ] = splitFilter(node.bind, (binding) => isValidBodyAttribute(binding));
if (bodyBindings.length === 0) {
// TODO: Display source code position + snippet
// FIXME: It's possible to specify the `body` with a dynamic key; this means that we can't actually do a compile-time check here, at least not reliably, and we need to insert a runtime guard if the compile-time check fails and dynamic attributes are specified
throw new Error(`Missing required 'body' attribute in LetAttributeSet`);
} else {
return _nixTypes.JSNixLet(
actualBindings,
bodyBindings[0].expression
);
}
}
}
};