From 981afe821cf519aab622f0de47255e2d96fe2347 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 11 Oct 2007 21:58:37 +0000 Subject: [PATCH] * Some hacks to simulate conventional laziness. --- src/libexpr/eval.cc | 24 ++++++++++++++++++++---- src/libexpr/eval.hh | 4 +++- src/libexpr/nixexpr-ast.def | 2 ++ src/libexpr/nixexpr.cc | 14 ++++++++++++++ src/libexpr/nixexpr.hh | 3 +++ src/libexpr/parser.y | 4 ++-- src/libexpr/primops.cc | 6 +++--- 7 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 6c0ef1940..84bd9ff54 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1,3 +1,5 @@ +#include + #include "eval.hh" #include "parser.hh" #include "hash.hh" @@ -13,6 +15,9 @@ namespace nix { + + +int cacheTerms; EvalState::EvalState() @@ -24,7 +29,7 @@ EvalState::EvalState() addPrimOps(); - cacheTerms = getEnv("NIX_TERM_CACHE", "1") == "1"; + if (!string2Int(getEnv("NIX_TERM_CACHE"), cacheTerms)) cacheTerms = 1; strictMode = getEnv("NIX_STRICT", "0") == "1"; } @@ -405,7 +410,7 @@ Expr autoCallFunction(Expr e, const ATermMap & args) Expr name, def, value; ATerm values, def2; if (!matchFormal(*i, name, values, def2)) abort(); if ((value = args.get(name))) - actualArgs.set(name, makeAttrRHS(value, makeNoPos())); + actualArgs.set(name, makeAttrRHS(allocCell(value), makeNoPos())); else if (!matchDefaultValue(def2, def)) throw TypeError(format("cannot auto-call a function that has an argument without a default value (`%1%')") % aterm2String(name)); @@ -485,7 +490,7 @@ LocalNoInline(Expr evalCall(EvalState & state, Expr fun, Expr arg)) try { arg = speculativeEval(state, arg); ATermMap subs(1); - subs.set(name, arg); + subs.set(name, allocCell(arg)); return evalExpr(state, substitute(Substitution(0, &subs), body)); } catch (Error & e) { addErrorPrefix(e, "while evaluating the function at %1%:\n", @@ -641,6 +646,10 @@ Expr evalExpr2(EvalState & state, Expr e) Expr e1, e2, e3; ATerm name, pos; + + int bla; + if (matchCell(e, bla, e1)) e = e1; + AFun sym = ATgetAFun(e); /* Normal forms. */ @@ -732,6 +741,7 @@ Expr evalExpr2(EvalState & state, Expr e) if (matchOpConcat(e, e1, e2)) return evalOpConcat(state, e1, e2); /* Barf. */ + //printMsg(lvlError, format("%1%") % e); abort(); } @@ -747,7 +757,13 @@ Expr evalExpr(EvalState & state, Expr e) state.nrEvaluated++; - if (!state.cacheTerms) return evalExpr2(state, e); + if (cacheTerms == 0) return evalExpr2(state, e); + + if (cacheTerms == 2) { + int pseudoAddr; + Expr e2; + if (!matchCell(e, pseudoAddr, e2)) return evalExpr2(state, e); + } /* Consult the memo table to quickly get the normal form of previously evaluated expressions. */ diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 4692bfd27..d4960d1ac 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -27,6 +27,9 @@ struct EvalState; typedef Expr (* PrimOp) (EvalState &, const ATermVector & args); +extern int cacheTerms; // 0 = don't, 1 = do, 2 = "cell" terms only + + struct EvalState { ATermMap normalForms; @@ -38,7 +41,6 @@ struct EvalState unsigned int nrEvaluated; unsigned int nrCached; - bool cacheTerms; bool strictMode; ATermMap parsings; /* path -> expr mapping */ diff --git a/src/libexpr/nixexpr-ast.def b/src/libexpr/nixexpr-ast.def index c7029e927..d6f75169b 100644 --- a/src/libexpr/nixexpr-ast.def +++ b/src/libexpr/nixexpr-ast.def @@ -73,6 +73,8 @@ Inherit | Expr ATermList Pos | ATerm | Scope | | Expr | +Cell | int Expr | Expr | + Formal | string ValidValues DefaultValue | ATerm | ValidValues | ATermList | ValidValues | diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index 123513594..f2eacaf11 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -2,6 +2,7 @@ #include "derivations.hh" #include "util.hh" #include "aterm.hh" +#include "eval.hh" // !!! urgh #include "nixexpr-ast.hh" #include "nixexpr-ast.cc" @@ -399,5 +400,18 @@ string showValue(Expr e) return ""; } + +static unsigned int cellCount = 0; + + +Expr allocCell(Expr e) +{ + if (cacheTerms != 2) return e; + int i; + Expr e2; + if (matchCell(e, i, e2)) return e; + return makeCell(cellCount++, e); +} + } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index dabbaa323..8ccd36bd4 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -116,6 +116,9 @@ string showType(Expr e); string showValue(Expr e); + +Expr allocCell(Expr e); // make an updateable cell (for simulating conventional laziness) + } diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index b1284b4b0..e943bdc97 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -57,7 +57,7 @@ static Expr fixAttrs(int recursive, ATermList as) bool fromScope = matchScope(src); for (ATermIterator j(names); j; ++j) { Expr rhs = fromScope ? makeVar(*j) : makeSelect(src, *j); - *is = ATinsert(*is, makeBind(*j, rhs, pos)); + *is = ATinsert(*is, makeBind(*j, allocCell(rhs), pos)); } } else bs = ATinsert(bs, *i); } @@ -226,7 +226,7 @@ binds bind : ID '=' expr ';' - { $$ = makeBind($1, $3, CUR_POS); } + { $$ = makeBind($1, allocCell($3), CUR_POS); } | INHERIT inheritsrc ids ';' { $$ = makeInherit($2, $3, CUR_POS); } ; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 129b9e2e5..75275ed1b 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -567,9 +567,9 @@ static Expr prim_derivationLazy(EvalState & state, const ATermVector & args) Expr drvStrict = makeCall(makeVar(toATerm("derivation!")), eAttrs); attrs.set(toATerm("outPath"), - makeAttrRHS(makeSelect(drvStrict, toATerm("outPath")), makeNoPos())); + makeAttrRHS(allocCell(makeSelect(drvStrict, toATerm("outPath"))), makeNoPos())); attrs.set(toATerm("drvPath"), - makeAttrRHS(makeSelect(drvStrict, toATerm("drvPath")), makeNoPos())); + makeAttrRHS(allocCell(makeSelect(drvStrict, toATerm("drvPath"))), makeNoPos())); return makeAttrs(attrs); } @@ -773,7 +773,7 @@ static Expr prim_listToAttrs(EvalState & state, const ATermVector & args) Expr e = evalExpr(state, makeSelect(evaledExpr, toATerm("name"))); string attr = evalStringNoCtx(state,e); Expr r = makeSelect(evaledExpr, toATerm("value")); - res.set(toATerm(attr), makeAttrRHS(r, makeNoPos())); + res.set(toATerm(attr), makeAttrRHS(allocCell(r), makeNoPos())); } else throw TypeError(format("list element in `listToAttrs' is %s, expected a set { name = \"\"; value = ; }")