"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 ); } } } };