From 5d50971b948be376666cc324fa85fc64c059c01b Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Fri, 4 Dec 2020 00:19:29 +0100 Subject: [PATCH] More position info --- src/libexpr/eval-inline.hh | 11 ++++++---- src/libexpr/eval.cc | 41 +++++++++++++++++++++++++++++--------- src/libexpr/nixexpr.hh | 11 ++++++++++ src/libexpr/value.hh | 5 ++++- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index e1cfa5fea86..014b80562f1 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -37,8 +37,8 @@ void EvalState::forceValue(Value & v, const Pos & pos) v.lazyBinOp->expr->evalLazyBinOp(*this, *v.lazyBinOp->env, v); } else if (v.type == tValue) { v.type = tBlackhole; - forceValue(*v.value, pos); - v = *v.value; + forceValue(*v.value.value, pos != noPos ? pos : *v.value.pos); + v = *v.value.value; } } @@ -84,8 +84,11 @@ Attr * EvalState::evalValueAttr(Value & v, const Symbol & name, const Pos & pos) } else if (v.type == tLazyBinOp) { return v.lazyBinOp->expr->evalLazyBinOpAttr(*this, *v.lazyBinOp->env, name, v); } else if (v.type == tValue) { - return evalValueAttr(*v.value, name, pos); - // TODO: Set v to v.value if it's in WHNF, for efficiency + Attr * result = evalValueAttr(*v.value.value, name, pos != noPos ? pos : *v.value.pos); + if (v.value.value->type != tLazyBinOp) { + v = *v.value.value; + } + return result; } else { return nullptr; } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 5b8162e42ff..79ac5954cd3 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -960,7 +960,12 @@ void Expr::evalMinimal(EvalState & state, Env & env, Value & v) void Expr::eval(EvalState & state, Env & env, Value & v) { evalMinimal(state, env, v); - state.forceValue(v, noPos); + state.forceValue(v, getPos()); +} + +Pos Expr::getPos() +{ + return noPos; } @@ -1107,8 +1112,9 @@ void ExprList::evalMinimal(EvalState & state, Env & env, Value & v) void ExprVar::evalMinimal(EvalState & state, Env & env, Value & v) { v.type = tValue; - v.value = state.lookupVar(&env, *this, false); - state.evalValueMinimal(*v.value, pos); + v.value.value = state.lookupVar(&env, *this, false); + v.value.pos = &pos; + state.evalValueMinimal(*v.value.value, pos); } static string showAttrPath(EvalState & state, Env & env, const AttrPath & attrPath) @@ -1170,8 +1176,9 @@ void ExprSelect::evalMinimal(EvalState & state, Env & env, Value & v) } v.type = tValue; - v.value = vAttrs; - state.evalValueMinimal(*vAttrs, ( pos2 != NULL ? *pos2 : this->pos )); + v.value.value = vAttrs; + v.value.pos = pos2 != NULL ? pos2 : &pos; + state.evalValueMinimal(*vAttrs, *v.value.pos); } @@ -1517,7 +1524,11 @@ void ExprOpUpdate::evalMinimal(EvalState & state, Env & env, Value & v) void ExprOpUpdate::evalLazyBinOp(EvalState & state, Env & env, Value & v) { if (v.lazyBinOp->rightBlackhole) { - throwEvalError(pos, "infinite recursion encountered while recursing into the right side of a lazy binop (evalLazyBinOp)"); + Pos pos2 = e2->getPos(); + if (pos2 == noPos) { + pos2 = pos; + } + throwEvalError(pos2, "infinite recursion encountered while recursing into the right side of a lazy binop (evalLazyBinOp)"); } v.lazyBinOp->rightBlackhole = true; state.forceAttrs(*v.lazyBinOp->right); @@ -1525,7 +1536,11 @@ void ExprOpUpdate::evalLazyBinOp(EvalState & state, Env & env, Value & v) if (v.lazyBinOp->leftBlackhole) { - throwEvalError(pos, "infinite recursion encountered while recursing into the left side of a lazy binop (evalLazyBinOp)"); + Pos pos2 = e1->getPos(); + if (pos2 == noPos) { + pos2 = pos; + } + throwEvalError(pos2, "infinite recursion encountered while recursing into the left side of a lazy binop (evalLazyBinOp)"); } v.lazyBinOp->leftBlackhole = true; state.forceAttrs(*v.lazyBinOp->left); @@ -1545,7 +1560,11 @@ Attr * ExprOpUpdate::evalLazyBinOpAttr(EvalState & state, Env & env, const Symbo */ if (v.lazyBinOp->rightBlackhole) { - throwEvalError(pos, "infinite recursion encountered while recursing into the right side of a lazy binop"); + Pos pos2 = e2->getPos(); + if (pos2 == noPos) { + pos2 = pos; + } + throwEvalError(pos2, "infinite recursion encountered while recursing into the right side of a lazy binop"); } v.lazyBinOp->rightBlackhole = true; Attr * onRight = state.evalValueAttr(*v.lazyBinOp->right, name, pos); @@ -1555,7 +1574,11 @@ Attr * ExprOpUpdate::evalLazyBinOpAttr(EvalState & state, Env & env, const Symbo }; if (v.lazyBinOp->leftBlackhole) { - throwEvalError(pos, "infinite recursion encountered while recursing into the left side of a lazy binop"); + Pos pos2 = e1->getPos(); + if (pos2 == noPos) { + pos2 = pos; + } + throwEvalError(pos2, "infinite recursion encountered while recursing into the left side of a lazy binop"); } v.lazyBinOp->leftBlackhole = true; Attr * onLeft = state.evalValueAttr(*v.lazyBinOp->left, name, pos); diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 24efa81fb3f..79785658402 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -78,6 +78,7 @@ string showAttrPath(const AttrPath & attrPath); struct Expr { virtual ~Expr() { }; + virtual Pos getPos(); virtual void show(std::ostream & str) const; virtual void bindVars(const StaticEnv & env); virtual void evalMinimal(EvalState & state, Env & env, Value & v); @@ -178,6 +179,7 @@ struct ExprVar : Expr ExprVar(const Symbol & name) : name(name) { }; ExprVar(const Pos & pos, const Symbol & name) : pos(pos), name(name) { }; COMMON_METHODS + Pos getPos() { return pos; } Value * noAllocationValue(EvalState & state, Env & env); }; @@ -188,6 +190,7 @@ struct ExprSelect : Expr AttrPath attrPath; ExprSelect(const Pos & pos, Expr * e, const AttrPath & attrPath, Expr * def) : pos(pos), e(e), def(def), attrPath(attrPath) { }; ExprSelect(const Pos & pos, Expr * e, const Symbol & name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); }; + Pos getPos() { return pos; } COMMON_METHODS }; @@ -267,6 +270,7 @@ struct ExprLambda : Expr }; void setName(Symbol & name); string showNamePos() const; + Pos getPos() { return pos; } COMMON_METHODS }; @@ -284,6 +288,7 @@ struct ExprWith : Expr Expr * attrs, * body; size_t prevWith; ExprWith(const Pos & pos, Expr * attrs, Expr * body) : pos(pos), attrs(attrs), body(body) { }; + Pos getPos() { return pos; } COMMON_METHODS }; @@ -292,6 +297,7 @@ struct ExprIf : Expr Pos pos; Expr * cond, * then, * else_; ExprIf(const Pos & pos, Expr * cond, Expr * then, Expr * else_) : pos(pos), cond(cond), then(then), else_(else_) { }; + Pos getPos() { return pos; } COMMON_METHODS }; @@ -300,6 +306,7 @@ struct ExprAssert : Expr Pos pos; Expr * cond, * body; ExprAssert(const Pos & pos, Expr * cond, Expr * body) : pos(pos), cond(cond), body(body) { }; + Pos getPos() { return pos; } COMMON_METHODS }; @@ -326,6 +333,7 @@ struct ExprOpNot : Expr e1->bindVars(env); e2->bindVars(env); \ } \ void evalMinimal(EvalState & state, Env & env, Value & v); \ + Pos getPos() { return pos; } \ }; MakeBinOp(ExprApp, "") @@ -360,6 +368,7 @@ struct ExprOpUpdate : ExprLazyBinOp Attr * evalLazyBinOpAttr(EvalState & state, Env & env, const Symbol & name, Value & v); void updateAttrs(EvalState & state, const Value & v1, const Value & v2, Value & v); + Pos getPos() { return pos; } }; struct ExprConcatStrings : Expr @@ -369,6 +378,7 @@ struct ExprConcatStrings : Expr vector * es; ExprConcatStrings(const Pos & pos, bool forceString, vector * es) : pos(pos), forceString(forceString), es(es) { }; + Pos getPos() { return pos; } COMMON_METHODS }; @@ -376,6 +386,7 @@ struct ExprPos : Expr { Pos pos; ExprPos(const Pos & pos) : pos(pos) { }; + Pos getPos() { return pos; } COMMON_METHODS }; diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index 96e3eb8f261..bab40175275 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -160,7 +160,10 @@ struct Value } primOpApp; ExternalValueBase * external; NixFloat fpoint; - Value * value; + struct { + Value * value; + const Pos * pos; + } value; }; bool isList() const