Use heap-of-vars for rec attrsets, fix lazy function args

master
Sven Slootweg 2 years ago
parent c87f70e40a
commit 40db79aea0

@ -0,0 +1 @@
rec { a = 1; b = rec { c = d.foo; }; d = { foo = a; }; }.b.c

@ -5,6 +5,7 @@ const types = require("@babel/types");
const template = require("@babel/template").default;
const unpackExpression = require("./_unpack-expression");
const NoChange = require("../astformer/actions/no-change");
const printAst = require("../print-ast");
// FIXME: Add expression parens!
let tmplCallLazy = template(`
@ -23,9 +24,23 @@ let tmplExtend = template(`(
$$jsNix$extend(this ?? {}, %%object%%)
)`);
let tmplScopeWrapper = template(`(
(() => {
%%bindings%%;
return %%object%%;
})()
)`);
// FIXME: Verify that this always works, and that we don't need `var` for hoisting!
let tmplRecursiveBinding = template(`
const %%name%% = %%expression%%;
`);
function lazyEvaluationWrapper(args) {
let { recursive, ... rest } = args;
// printAst(rest.expression);
let wrapper = (recursive)
? tmplLazyWrapperRecursive
: tmplLazyWrapper;
@ -68,23 +83,41 @@ module.exports = {
let isRecursive = node.recursive;
let hasDynamicBindings = node.bind.some((binding) => isDynamicBinding(binding));
let bindings = node.bind.map((binding) => {
assert(binding.attrpath.attr.length === 1); // Nested attributes should have been desugared by this point
return {
name: binding.attrpath.attr[0].name,
expression: lazyEvaluationWrapper({ recursive: isRecursive, expression: binding.expression })
};
});
if (hasDynamicBindings) {
throw new Error(`UNIMPLEMENTED: Dynamic bindings are not supported yet`);
} else if (isRecursive) {
return unpackExpression(tmplScopeWrapper({
bindings: bindings.map(({ name, expression }) => {
return tmplRecursiveBinding({
name: name,
expression: expression
});
}),
object: types.objectExpression(bindings.map(({ name }) => {
return types.objectProperty(
types.stringLiteral(name),
types.identifier(name)
);
}))
}));
} else {
let object = types.objectExpression(node.bind.map((binding) => {
assert(binding.attrpath.attr.length === 1); // Nested attributes should have been desugared by this point
let name = binding.attrpath.attr[0].name;
let expression = binding.expression;
let object = types.objectExpression(bindings.map(({ name, expression }) => {
return types.objectProperty(
types.stringLiteral(name),
lazyEvaluationWrapper({ recursive: isRecursive, expression: expression })
// TODO: Remove the isRecursive distinction here once heap-of-vars works
expression
);
}));
// FIXME/MARKER: This is currently broken!
console.log({context: getContext("attributeSets_inRecursiveSet")});
// Only do prototypal inheritance for `this` if we're dealing with nested recursive attribute sets
if (isRecursive && getContext("attributeSets_inRecursiveSet") === true) {
return unpackExpression(tmplExtend({

@ -32,6 +32,11 @@ let tmplFunctionCall = template(`
(%%function%%(%%arg%%))
`);
// NOTE: Duplicated from `attribute-sets` for now
let tmplLazyWrapper = template(`(
() => %%expression%%
)`);
function functionDefinition({ universal, formals, body }) {
let convertedFormals = asExpression(() => {
if (formals != null) {
@ -101,7 +106,7 @@ module.exports = {
return unpackExpression(
tmplFunctionCall({
function: node.function,
arg: node.argument
arg: unpackExpression(tmplLazyWrapper({ expression: node.argument }))
})
);
});

@ -47,7 +47,7 @@ let tmplObjectDynamicEntry = template(`
`);
let tmplIdentifierReference = template(`(
(this?.%%name%% ?? %%name%%)()
%%name%%()
)`);
function generateDynamicObject(bindings, recursive) {

Loading…
Cancel
Save