* Simulate conventional laziness a bit better still by "allocating"
all local variables when entering a new scope. I.e., don't do implicit let-floating.
This commit is contained in:
parent
981afe821c
commit
74ce938e18
|
@ -478,7 +478,7 @@ LocalNoInline(Expr evalCall(EvalState & state, Expr fun, Expr arg))
|
|||
else if (matchFunction(fun, formals, body, pos)) {
|
||||
arg = evalExpr(state, arg);
|
||||
try {
|
||||
return evalExpr(state, substArgs(state, body, formals, arg));
|
||||
return evalExpr(state, substArgs(state, allocCells(body), formals, arg));
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the function at %1%:\n",
|
||||
showPos(pos));
|
||||
|
@ -491,7 +491,7 @@ LocalNoInline(Expr evalCall(EvalState & state, Expr fun, Expr arg))
|
|||
arg = speculativeEval(state, arg);
|
||||
ATermMap subs(1);
|
||||
subs.set(name, allocCell(arg));
|
||||
return evalExpr(state, substitute(Substitution(0, &subs), body));
|
||||
return evalExpr(state, substitute(Substitution(0, &subs), allocCells(body)));
|
||||
} catch (Error & e) {
|
||||
addErrorPrefix(e, "while evaluating the function at %1%:\n",
|
||||
showPos(pos));
|
||||
|
|
|
@ -201,6 +201,48 @@ Expr substitute(const Substitution & subs, Expr e)
|
|||
}
|
||||
|
||||
|
||||
Expr allocCells(Expr e)
|
||||
{
|
||||
checkInterrupt();
|
||||
|
||||
ATerm e2;
|
||||
if (matchClosed(e, e2)) return e;
|
||||
|
||||
int i;
|
||||
if (matchCell(e, i, e2))
|
||||
return allocCell(allocCells(e2));
|
||||
|
||||
if (ATgetType(e) == AT_APPL) {
|
||||
AFun fun = ATgetAFun(e);
|
||||
int arity = ATgetArity(fun);
|
||||
ATerm args[arity];
|
||||
bool changed = false;
|
||||
|
||||
for (int i = 0; i < arity; ++i) {
|
||||
ATerm arg = ATgetArgument(e, i);
|
||||
args[i] = allocCells(arg);
|
||||
if (args[i] != arg) changed = true;
|
||||
}
|
||||
|
||||
return changed ? (ATerm) ATmakeApplArray(fun, args) : e;
|
||||
}
|
||||
|
||||
if (ATgetType(e) == AT_LIST) {
|
||||
unsigned int len = ATgetLength((ATermList) e);
|
||||
ATerm es[len];
|
||||
ATermIterator i((ATermList) e);
|
||||
for (unsigned int j = 0; i; ++i, ++j)
|
||||
es[j] = allocCells(*i);
|
||||
ATermList out = ATempty;
|
||||
for (unsigned int j = len; j; --j)
|
||||
out = ATinsert(out, es[j - 1]);
|
||||
return (ATerm) out;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
/* We use memoisation to prevent exponential complexity on heavily
|
||||
shared ATerms (remember, an ATerm is a graph, not a tree!). Note
|
||||
that using an STL set is fine here wrt to ATerm garbage collection
|
||||
|
|
|
@ -119,6 +119,8 @@ string showValue(Expr e);
|
|||
|
||||
Expr allocCell(Expr e); // make an updateable cell (for simulating conventional laziness)
|
||||
|
||||
Expr allocCells(Expr e); // re-allocate all cells in e
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -564,12 +564,12 @@ static Expr prim_derivationLazy(EvalState & state, const ATermVector & args)
|
|||
attrs.set(toATerm("type"),
|
||||
makeAttrRHS(makeStr("derivation"), makeNoPos()));
|
||||
|
||||
Expr drvStrict = makeCall(makeVar(toATerm("derivation!")), eAttrs);
|
||||
Expr drvStrict = allocCell(makeCall(makeVar(toATerm("derivation!")), eAttrs));
|
||||
|
||||
attrs.set(toATerm("outPath"),
|
||||
makeAttrRHS(allocCell(makeSelect(drvStrict, toATerm("outPath"))), makeNoPos()));
|
||||
makeAttrRHS(makeSelect(drvStrict, toATerm("outPath")), makeNoPos()));
|
||||
attrs.set(toATerm("drvPath"),
|
||||
makeAttrRHS(allocCell(makeSelect(drvStrict, toATerm("drvPath"))), makeNoPos()));
|
||||
makeAttrRHS(makeSelect(drvStrict, toATerm("drvPath")), makeNoPos()));
|
||||
|
||||
return makeAttrs(attrs);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue