From fbaee9b8fbb554a4b3c747173226f63c7f260558 Mon Sep 17 00:00:00 2001 From: regnat Date: Fri, 4 Jun 2021 16:45:22 +0200 Subject: [PATCH] =?UTF-8?q?Add=20a=20=E2=80=9Ccached=20thunk=E2=80=9D=20va?= =?UTF-8?q?lue=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libexpr/eval-inline.hh | 4 ++++ src/libexpr/eval.cc | 9 +++++++-- src/libexpr/value.hh | 25 ++++++++++++++++++++----- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index 655408cd3..4d8d07397 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -46,6 +46,10 @@ void EvalState::forceValue(Value & v, const Pos & pos) } else if (v.isApp()) callFunction(*v.app.left, *v.app.right, v, noPos); + else if (v.isCachedThunk()) { + v.mkThunk(v.cachedThunk.thunk->env, v.cachedThunk.thunk->expr); + forceValue(v, pos); + } else if (v.isBlackhole()) throwEvalError(pos, "infinite recursion encountered"); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 32be044f3..d38917ab7 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -124,6 +124,7 @@ void printValue(std::ostream & str, std::set & active, const Valu str << "]"; break; case tThunk: + case tCachedThunk: case tApp: str << ""; break; @@ -195,7 +196,7 @@ string showType(const Value & v) case tPrimOpApp: return fmt("the partially applied built-in function '%s'", string(getPrimOp(v)->primOp->name)); case tExternal: return v.external->showType(); - case tThunk: return "a thunk"; + case tThunk: case tCachedThunk: return "a thunk"; case tApp: return "a function application"; case tBlackhole: return "a black hole"; default: @@ -218,7 +219,7 @@ bool Value::isTrivial() const return internalType != tApp && internalType != tPrimOpApp - && (internalType != tThunk + && ((internalType != tThunk && internalType != tCachedThunk) || (dynamic_cast(thunk.expr) && ((ExprAttrs *) thunk.expr)->dynamicAttrs.empty()) || dynamic_cast(thunk.expr) @@ -1818,6 +1819,8 @@ ValueCache & Value::getEvalCache() { if (internalType == tAttrs) { return attrs->eval_cache; + } else if (internalType == tCachedThunk) { + return *cachedThunk.cache; } else { return ValueCache::empty; } @@ -1897,6 +1900,8 @@ void Value::setEvalCache(ValueCache & newCache) { if (internalType == tAttrs) { attrs->eval_cache = newCache; + } else if (internalType == tCachedThunk) { + cachedThunk.cache = &newCache; } } diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 53a2e2cdd..70926c1e2 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -23,6 +23,7 @@ typedef enum { tApp, tLambda, tBlackhole, + tCachedThunk, tPrimOp, tPrimOpApp, tExternal, @@ -56,7 +57,6 @@ struct Pos; class EvalState; class XMLWriter; class JSONPlaceholder; - class ValueCache; @@ -105,6 +105,10 @@ class ExternalValueBase std::ostream & operator << (std::ostream & str, const ExternalValueBase & v); +struct Thunk { + Env * env; + Expr * expr; +}; struct Value { @@ -124,6 +128,7 @@ public: inline bool isThunk() const { return internalType == tThunk; }; inline bool isApp() const { return internalType == tApp; }; inline bool isBlackhole() const { return internalType == tBlackhole; }; + inline bool isCachedThunk() const { return internalType == tCachedThunk; }; // type() == nFunction inline bool isLambda() const { return internalType == tLambda; }; @@ -167,10 +172,13 @@ public: Value * * elems; } bigList; Value * smallList[2]; + Thunk thunk; struct { - Env * env; - Expr * expr; - } thunk; + Thunk * thunk; + // This is a pointer only to prevent a recursive import as + // `EvalCache` is already a pointer so would fit very nicely here. + ValueCache * cache; + } cachedThunk; struct { Value * left, * right; } app; @@ -201,7 +209,7 @@ public: case tLambda: case tPrimOp: case tPrimOpApp: return nFunction; case tExternal: return nExternal; case tFloat: return nFloat; - case tThunk: case tApp: case tBlackhole: return nThunk; + case tThunk: case tApp: case tBlackhole: case tCachedThunk: return nThunk; } abort(); } @@ -274,6 +282,13 @@ public: thunk.expr = ex; } + inline void mkCachedThunk(Thunk * t, ValueCache * cache) + { + internalType = tCachedThunk; + cachedThunk.thunk = t; + cachedThunk.cache = cache; + } + inline void mkApp(Value * l, Value * r) { internalType = tApp;