aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr
diff options
context:
space:
mode:
authorBen Burdette <bburdette@protonmail.com>2022-04-29 10:02:17 -0600
committerBen Burdette <bburdette@protonmail.com>2022-04-29 10:02:17 -0600
commit2a5632c70dcb686a7764c23a5f330fcb9a33c8a1 (patch)
tree95f4d9390881356c12270f6b23a8853e6ef585f7 /src/libexpr
parent6e19947993119dec3c9fb9581150d1184948bae9 (diff)
incorporate PosIdx changes, symbol changes.
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval-inline.hh6
-rw-r--r--src/libexpr/eval.cc199
-rw-r--r--src/libexpr/eval.hh67
-rw-r--r--src/libexpr/nixexpr.cc6
-rw-r--r--src/libexpr/nixexpr.hh9
-rw-r--r--src/libexpr/primops.cc10
6 files changed, 188 insertions, 109 deletions
diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh
index 4e0826101..f2f4ba725 100644
--- a/src/libexpr/eval-inline.hh
+++ b/src/libexpr/eval-inline.hh
@@ -103,7 +103,7 @@ void EvalState::forceValue(Value & v, Callable getPos)
else if (v.isApp())
callFunction(*v.app.left, *v.app.right, v, noPos);
else if (v.isBlackhole())
- throwEvalError(getPos(), "infinite recursion encountered", *this);
+ throwEvalError(getPos(), "infinite recursion encountered");
}
@@ -120,7 +120,7 @@ inline void EvalState::forceAttrs(Value & v, Callable getPos)
{
forceValue(v, getPos);
if (v.type() != nAttrs)
- throwTypeError(getPos(), "value is %1% while a set was expected", v, *this);
+ throwTypeError(getPos(), "value is %1% while a set was expected", v);
}
@@ -129,7 +129,7 @@ inline void EvalState::forceList(Value & v, const PosIdx pos)
{
forceValue(v, pos);
if (!v.isList())
- throwTypeError(pos, "value is %1% while a list was expected", v, *this);
+ throwTypeError(pos, "value is %1% while a list was expected", v);
}
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 896242e0c..7058d117f 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -714,19 +714,19 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
// just for the current level of StaticEnv, not the whole chain.
-void printStaticEnvBindings(const StaticEnv &se)
+void printStaticEnvBindings(const SymbolTable &st, const StaticEnv &se)
{
std::cout << ANSI_MAGENTA;
for (auto i = se.vars.begin(); i != se.vars.end(); ++i)
{
- std::cout << i->first << " ";
+ std::cout << st[i->first] << " ";
}
std::cout << ANSI_NORMAL;
std::cout << std::endl;
}
// just for the current level of Env, not the whole chain.
-void printWithBindings(const Env &env)
+void printWithBindings(const SymbolTable &st, const Env &env)
{
if (env.type == Env::HasWithAttrs)
{
@@ -734,7 +734,7 @@ void printWithBindings(const Env &env)
std::cout << ANSI_MAGENTA;
Bindings::iterator j = env.values[0]->attrs->begin();
while (j != env.values[0]->attrs->end()) {
- std::cout << j->name << " ";
+ std::cout << st[j->name] << " ";
++j;
}
std::cout << ANSI_NORMAL;
@@ -742,16 +742,16 @@ void printWithBindings(const Env &env)
}
}
-void printEnvBindings(const StaticEnv &se, const Env &env, int lvl)
+void printEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env, int lvl)
{
std::cout << "Env level " << lvl << std::endl;
if (se.up && env.up) {
std::cout << "static: ";
- printStaticEnvBindings(se);
- printWithBindings(env);
+ printStaticEnvBindings(st, se);
+ printWithBindings(st, env);
std::cout << std::endl;
- printEnvBindings(*se.up, *env.up, ++lvl);
+ printEnvBindings(st, *se.up, *env.up, ++lvl);
}
else
{
@@ -759,41 +759,41 @@ void printEnvBindings(const StaticEnv &se, const Env &env, int lvl)
// for the top level, don't print the double underscore ones; they are in builtins.
for (auto i = se.vars.begin(); i != se.vars.end(); ++i)
{
- if (((std::string)i->first).substr(0,2) != "__")
- std::cout << i->first << " ";
+ if (((std::string)st[i->first]).substr(0,2) != "__")
+ std::cout << st[i->first] << " ";
}
std::cout << ANSI_NORMAL;
std::cout << std::endl;
- printWithBindings(env); // probably nothing there for the top level.
+ printWithBindings(st, env); // probably nothing there for the top level.
std::cout << std::endl;
}
}
// TODO: add accompanying env for With stuff.
-void printEnvBindings(const Expr &expr, const Env &env)
+void printEnvBindings(const SymbolTable &st, const Expr &expr, const Env &env)
{
// just print the names for now
if (expr.staticenv)
{
- printEnvBindings(*expr.staticenv.get(), env, 0);
+ printEnvBindings(st, *expr.staticenv.get(), env, 0);
}
}
-void mapStaticEnvBindings(const StaticEnv &se, const Env &env, valmap & vm)
+void mapStaticEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env, valmap & vm)
{
// add bindings for the next level up first, so that the bindings for this level
// override the higher levels.
// The top level bindings (builtins) are skipped since they are added for us by initEnv()
if (env.up && se.up) {
- mapStaticEnvBindings(*se.up, *env.up, vm);
+ mapStaticEnvBindings(st, *se.up, *env.up, vm);
if (env.type == Env::HasWithAttrs)
{
// add 'with' bindings.
Bindings::iterator j = env.values[0]->attrs->begin();
while (j != env.values[0]->attrs->end()) {
- vm[j->name] = j->value;
+ vm[st[j->name]] = j->value;
++j;
}
}
@@ -802,51 +802,54 @@ void mapStaticEnvBindings(const StaticEnv &se, const Env &env, valmap & vm)
// iterate through staticenv bindings and add them.
for (auto iter = se.vars.begin(); iter != se.vars.end(); ++iter)
{
- vm[iter->first] = env.values[iter->second];
+ vm[st[iter->first]] = env.values[iter->second];
}
}
}
}
-valmap * mapStaticEnvBindings(const StaticEnv &se, const Env &env)
+valmap * mapStaticEnvBindings(const SymbolTable &st,const StaticEnv &se, const Env &env)
{
auto vm = new valmap();
- mapStaticEnvBindings(se, env, *vm);
+ mapStaticEnvBindings(st, se, env, *vm);
return vm;
}
+void EvalState::debugLastTrace(Error & e) const {
+ // call this in the situation where Expr and Env are inaccessible. The debugger will start in the last context
+ // that's in the DebugTrace stack.
+ if (debuggerHook && !debugTraces.empty()) {
+ const DebugTrace &last = debugTraces.front();
+ debuggerHook(&e, last.env, last.expr);
+ }
+}
+
/* Every "format" object (even temporary) takes up a few hundred bytes
of stack space, which is a real killer in the recursive
evaluator. So here are some helper functions for throwing
exceptions. */
-
-void EvalState::throwEvalError(const PosIdx pos, const char * s) const
+void EvalState::throwEvalError(const PosIdx pos, const char * s, Env & env, Expr &expr) const
{
auto error = EvalError({
.msg = hintfmt(s),
.errPos = positions[pos]
});
- if (debuggerHook && !debugTraces.empty()) {
- DebugTrace &last = debugTraces.front();
- debuggerHook(&error, last.env, last.expr);
- }
+ if (debuggerHook)
+ debuggerHook(&error, env, expr);
throw error;
}
-void EvalState::throwTypeError(const PosIdx pos, const char * s, const Value & v) const
+void EvalState::throwEvalError(const PosIdx pos, const char * s) const
{
- auto error = TypeError({
- .msg = hintfmt(s, showType(v)),
+ auto error = EvalError({
+ .msg = hintfmt(s),
.errPos = positions[pos]
});
- if (debuggerHook && !debugTraces.empty()) {
- DebugTrace &last = debugTraces.front();
- debuggerHook(&error, last.env, last.expr);
- }
+ debugLastTrace(error);
throw error;
}
@@ -855,23 +858,11 @@ void EvalState::throwEvalError(const char * s, const std::string & s2) const
{
auto error = EvalError(s, s2);
- if (debuggerHook && !debugTraces.empty()) {
- DebugTrace &last = debugTraces.front();
- debuggerHook(&error, last.env, last.expr);
- }
+ debugLastTrace(error);
throw error;
}
-void EvalState::debugLastTrace(Error & e) {
- // call this in the situation where Expr and Env are inaccessible. The debugger will start in the last context
- // that's in the DebugTrace stack.
- if (debuggerHook && !debugTraces.empty()) {
- DebugTrace &last = debugTraces.front();
- debuggerHook(&e, last.env, last.expr);
- }
-}
-
void EvalState::throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s,
const std::string & s2, Env & env, Expr &expr) const
{
@@ -899,16 +890,43 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri
throw error;
}
-void EvalState::throwEvalError(const char * s, const std::string & s2, const std::string & s3, Env & env, Expr &expr) const
+void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::string & s2, Env & env, Expr &expr) const
{
auto error = EvalError({
- .msg = hintfmt(s),
- .errPos = pos
+ .msg = hintfmt(s, s2),
+ .errPos = positions[pos]
});
if (debuggerHook)
debuggerHook(&error, env, expr);
+
+ throw error;
+}
+
+void EvalState::throwEvalError(const char * s, const std::string & s2,
+ const std::string & s3) const
+{
+ auto error = EvalError({
+ .msg = hintfmt(s, s2),
+ .errPos = positions[noPos]
+ });
+
+ debugLastTrace(error);
+
+ throw error;
+}
+
+void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::string & s2,
+ const std::string & s3) const
+{
+ auto error = EvalError({
+ .msg = hintfmt(s, s2),
+ .errPos = positions[pos]
+ });
+
+ debugLastTrace(error);
+
throw error;
}
@@ -917,7 +935,7 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri
{
auto error = EvalError({
.msg = hintfmt(s, s2),
- .errPos = pos
+ .errPos = positions[pos]
});
if (debuggerHook)
@@ -966,6 +984,31 @@ void EvalState::throwEvalError(const PosIdx p1, const char * s, const Symbol sym
throw error;
}
+void EvalState::throwTypeError(const PosIdx pos, const char * s, const Value & v) const
+{
+ auto error = TypeError({
+ .msg = hintfmt(s, showType(v)),
+ .errPos = positions[pos]
+ });
+
+ debugLastTrace(error);
+
+ throw error;
+}
+
+void EvalState::throwTypeError(const PosIdx pos, const char * s, const Value & v, Env & env, Expr &expr) const
+{
+ auto error = TypeError({
+ .msg = hintfmt(s, showType(v)),
+ .errPos = positions[pos]
+ });
+
+ if (debuggerHook)
+ debuggerHook(&error, env, expr);
+
+ throw error;
+}
+
void EvalState::throwTypeError(const PosIdx pos, const char * s) const
{
auto error = TypeError({
@@ -973,7 +1016,7 @@ void EvalState::throwTypeError(const PosIdx pos, const char * s) const
.errPos = positions[pos]
});
- evalState.debugLastTrace(error);
+ debugLastTrace(error);
throw error;
}
@@ -1010,9 +1053,8 @@ void EvalState::throwTypeError(const PosIdx pos, const Suggestions & suggestions
void EvalState::throwTypeError(const char * s, const Value & v, Env & env, Expr &expr) const
{
auto error = TypeError({
- .msg = hintfmt(s, fun.showNamePos(), s2),
- .errPos = pos,
- .suggestions = suggestions,
+ .msg = hintfmt(s, showType(v)),
+ .errPos = positions[expr.getPos()],
});
if (debuggerHook)
@@ -1070,8 +1112,8 @@ void EvalState::addErrorTrace(Error & e, const PosIdx pos, const char * s, const
e.addTrace(positions[pos], s, s2);
}
-LocalNoInline(std::unique_ptr<DebugTraceStacker>
- makeDebugTraceStacker(EvalState &state, Expr &expr, Env &env, std::optional<ErrPos> pos, const char * s, const std::string & s2))
+std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(EvalState &state, Expr &expr, Env &env,
+ std::optional<ErrPos> pos, const char * s, const std::string & s2)
{
return std::unique_ptr<DebugTraceStacker>(
new DebugTraceStacker(
@@ -1150,7 +1192,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
return j->value;
}
if (!env->prevWith)
- throwUndefinedVarError(var.pos, "undefined variable '%1%'", symbols[var.name], *env, var);
+ throwUndefinedVarError(var.pos, "undefined variable '%1%'", symbols[var.name], *env, const_cast<ExprVar&>(var));
for (size_t l = env->prevWith; l; --l, env = env->up) ;
}
}
@@ -1293,7 +1335,7 @@ void EvalState::cacheFile(
*this,
*e,
this->baseEnv,
- (e->getPos() ? std::optional(ErrPos(*e->getPos())) : std::nullopt),
+ (e->getPos() ? std::optional(ErrPos(positions[e->getPos()])) : std::nullopt),
"while evaluating the file '%1%':", resolvedPath)
: nullptr;
@@ -1528,7 +1570,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
state,
*this,
env,
- *pos2,
+ state.positions[pos2],
"while evaluating the attribute '%1%'",
showAttrPath(state, env, attrPath))
: nullptr;
@@ -1694,10 +1736,10 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
try {
auto dts =
debuggerHook ?
- makeDebugTraceStacker(*this, *lambda.body, env2, lambda.pos,
+ makeDebugTraceStacker(*this, *lambda.body, env2, positions[lambda.pos],
"while evaluating %s",
- (lambda.name.set()
- ? "'" + (std::string) lambda.name + "'"
+ (lambda.name
+ ? concatStrings("'", symbols[lambda.name], "'")
: "anonymous lambda"))
: nullptr;
@@ -1786,7 +1828,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
}
else
- throwTypeError(pos, "attempt to call something which is not a function but %1%", vCur, *this);
+ throwTypeError(pos, "attempt to call something which is not a function but %1%", vCur);
}
vRes = vCur;
@@ -1855,7 +1897,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
Nix attempted to evaluate a function as a top level expression; in
this case it must have its arguments supplied either by default
values, or passed explicitly with '--arg' or '--argstr'. See
-https://nixos.org/manual/nix/stable/#ss-functions.)", symbols[i.name],,
+https://nixos.org/manual/nix/stable/#ss-functions.)", symbols[i.name],
*fun.lambda.env, *fun.lambda.fun);
}
}
@@ -2092,7 +2134,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
v.mkFloat(nf);
else if (firstType == nPath) {
if (!context.empty())
- state.throwEvalError(pos, "a string that refers to a store path cannot be appended to a path", env, *this););
+ state.throwEvalError(pos, "a string that refers to a store path cannot be appended to a path", env, *this);
v.mkPath(canonPath(str()));
} else
v.mkStringMove(c_str(), context);
@@ -2124,8 +2166,8 @@ void EvalState::forceValueDeep(Value & v)
debuggerHook ?
// if the value is a thunk, we're evaling. otherwise no trace necessary.
(i.value->isThunk() ?
- makeDebugTraceStacker(*this, *v.thunk.expr, *v.thunk.env, *i.pos,
- "while evaluating the attribute '%1%'", i.name)
+ makeDebugTraceStacker(*this, *v.thunk.expr, *v.thunk.env, positions[i.pos],
+ "while evaluating the attribute '%1%'", symbols[i.name])
: nullptr)
: nullptr;
@@ -2150,7 +2192,7 @@ NixInt EvalState::forceInt(Value & v, const PosIdx pos)
{
forceValue(v, pos);
if (v.type() != nInt)
- throwTypeError(pos, "value is %1% while an integer was expected", v, *this);
+ throwTypeError(pos, "value is %1% while an integer was expected", v);
return v.integer;
}
@@ -2162,7 +2204,7 @@ NixFloat EvalState::forceFloat(Value & v, const PosIdx pos)
if (v.type() == nInt)
return v.integer;
else if (v.type() != nFloat)
- throwTypeError(pos, "value is %1% while a float was expected", v, *this);
+ throwTypeError(pos, "value is %1% while a float was expected", v);
return v.fpoint;
}
@@ -2171,7 +2213,7 @@ bool EvalState::forceBool(Value & v, const PosIdx pos)
{
forceValue(v, pos);
if (v.type() != nBool)
- throwTypeError(pos, "value is %1% while a Boolean was expected", v, *this);
+ throwTypeError(pos, "value is %1% while a Boolean was expected", v);
return v.boolean;
}
@@ -2186,7 +2228,7 @@ void EvalState::forceFunction(Value & v, const PosIdx pos)
{
forceValue(v, pos);
if (v.type() != nFunction && !isFunctor(v))
- throwTypeError(pos, "value is %1% while a function was expected", v, *this);
+ throwTypeError(pos, "value is %1% while a function was expected", v);
}
@@ -2194,7 +2236,7 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos)
{
forceValue(v, pos);
if (v.type() != nString) {
- throwTypeError(pos, "value is %1% while a string was expected", v, *this);
+ throwTypeError(pos, "value is %1% while a string was expected", v);
}
return v.string.s;
}
@@ -2254,10 +2296,10 @@ std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos)
if (v.string.context) {
if (pos)
throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')",
- v.string.s, v.string.context[0], *this);
+ v.string.s, v.string.context[0]);
else
throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
- v.string.s, v.string.context[0], *this);
+ v.string.s, v.string.context[0]);
}
return s;
}
@@ -2312,7 +2354,7 @@ BackedStringView EvalState::coerceToString(const PosIdx pos, Value & v, PathSet
return std::move(*maybeString);
auto i = v.attrs->find(sOutPath);
if (i == v.attrs->end())
- throwTypeError(pos, "cannot coerce a set to a string", *this);
+ throwTypeError(pos, "cannot coerce a set to a string");
return coerceToString(pos, *i->value, context, coerceMore, copyToStore);
}
@@ -2341,14 +2383,14 @@ BackedStringView EvalState::coerceToString(const PosIdx pos, Value & v, PathSet
}
}
- throwTypeError(pos, "cannot coerce %1% to a string", v, *this);
+ throwTypeError(pos, "cannot coerce %1% to a string", v);
}
std::string EvalState::copyPathToStore(PathSet & context, const Path & path)
{
if (nix::isDerivation(path))
- throwEvalError("file names are not allowed to end in '%1%'", drvExtension, *this);
+ throwEvalError("file names are not allowed to end in '%1%'", drvExtension);
Path dstPath;
auto i = srcToStore.find(path);
@@ -2373,7 +2415,7 @@ Path EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & context)
{
auto path = coerceToString(pos, v, context, false, false).toOwned();
if (path == "" || path[0] != '/')
- throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path, *this);
+ throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path);
return path;
}
@@ -2466,8 +2508,7 @@ bool EvalState::eqValues(Value & v1, Value & v2)
default:
throwEvalError("cannot compare %1% with %2%",
showType(v1),
- showType(v2),
- *this);
+ showType(v2));
}
}
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 76bd63ca6..2e7df13fc 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -25,8 +25,8 @@ enum RepairFlag : bool;
typedef void (* PrimOpFun) (EvalState & state, const PosIdx pos, Value * * args, Value & v);
-void printEnvBindings(const Expr &expr, const Env &env);
-void printEnvBindings(const StaticEnv &se, const Env &env, int lvl = 0);
+void printEnvBindings(const SymbolTable &st, const Expr &expr, const Env &env);
+void printEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env, int lvl = 0);
struct PrimOp
{
@@ -47,7 +47,7 @@ struct Env
Value * values[0];
};
-valmap * mapStaticEnvBindings(const StaticEnv &se, const Env &env);
+valmap * mapStaticEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env);
void copyContext(const Value & v, PathSet & context);
@@ -123,7 +123,7 @@ public:
bool debugStop;
bool debugQuit;
std::list<DebugTrace> debugTraces;
- void debugLastTrace(Error & e);
+ void debugLastTrace(Error & e) const;
private:
SrcToStore srcToStore;
@@ -273,35 +273,66 @@ public:
[[gnu::noinline, gnu::noreturn]]
void throwEvalError(const PosIdx pos, const char * s) const;
[[gnu::noinline, gnu::noreturn]]
- void throwTypeError(const PosIdx pos, const char * s, const Value & v) const;
+ void throwEvalError(const PosIdx pos, const char * s,
+ Env & env, Expr & expr) const;
[[gnu::noinline, gnu::noreturn]]
void throwEvalError(const char * s, const std::string & s2) const;
[[gnu::noinline, gnu::noreturn]]
- void throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s,
- const std::string & s2) const;
- [[gnu::noinline, gnu::noreturn]]
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2) const;
[[gnu::noinline, gnu::noreturn]]
- void throwEvalError(const char * s, const std::string & s2, const std::string & s3) const;
+ void throwEvalError(const char * s, const std::string & s2,
+ Env & env, Expr & expr) const;
+ [[gnu::noinline, gnu::noreturn]]
+ void throwEvalError(const PosIdx pos, const char * s, const std::string & s2,
+ Env & env, Expr & expr) const;
+ [[gnu::noinline, gnu::noreturn]]
+ void throwEvalError(const char * s, const std::string & s2, const std::string & s3,
+ Env & env, Expr & expr) const;
+ [[gnu::noinline, gnu::noreturn]]
+ void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3,
+ Env & env, Expr & expr) const;
[[gnu::noinline, gnu::noreturn]]
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3) const;
[[gnu::noinline, gnu::noreturn]]
- void throwEvalError(const PosIdx p1, const char * s, const Symbol sym, const PosIdx p2) const;
+ void throwEvalError(const char * s, const std::string & s2, const std::string & s3) const;
+ [[gnu::noinline, gnu::noreturn]]
+ void throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s, const std::string & s2,
+ Env & env, Expr &expr) const;
+ [[gnu::noinline, gnu::noreturn]]
+ void throwEvalError(const PosIdx p1, const char * s, const Symbol sym, const PosIdx p2,
+ Env & env, Expr & expr) const;
+
+ [[gnu::noinline, gnu::noreturn]]
+ void throwTypeError(const PosIdx pos, const char * s, const Value & v) const;
+ [[gnu::noinline, gnu::noreturn]]
+ void throwTypeError(const PosIdx pos, const char * s, const Value & v,
+ Env & env, Expr & expr) const;
[[gnu::noinline, gnu::noreturn]]
void throwTypeError(const PosIdx pos, const char * s) const;
[[gnu::noinline, gnu::noreturn]]
- void throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun, const Symbol s2) const;
+ void throwTypeError(const PosIdx pos, const char * s,
+ Env & env, Expr & expr) const;
[[gnu::noinline, gnu::noreturn]]
- void throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s,
- const ExprLambda & fun, const Symbol s2) const;
+ void throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun, const Symbol s2,
+ Env & env, Expr & expr) const;
[[gnu::noinline, gnu::noreturn]]
- void throwTypeError(const char * s, const Value & v) const;
+ void throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s, const ExprLambda & fun, const Symbol s2,
+ Env & env, Expr & expr) const;
[[gnu::noinline, gnu::noreturn]]
- void throwAssertionError(const PosIdx pos, const char * s, const std::string & s1) const;
+ void throwTypeError(const char * s, const Value & v,
+ Env & env, Expr & expr) const;
+
+ [[gnu::noinline, gnu::noreturn]]
+ void throwAssertionError(const PosIdx pos, const char * s, const std::string & s1,
+ Env & env, Expr & expr) const;
+
[[gnu::noinline, gnu::noreturn]]
- void throwUndefinedVarError(const PosIdx pos, const char * s, const std::string & s1) const;
+ void throwUndefinedVarError(const PosIdx pos, const char * s, const std::string & s1,
+ Env & env, Expr & expr) const;
+
[[gnu::noinline, gnu::noreturn]]
- void throwMissingArgumentError(const PosIdx pos, const char * s, const std::string & s1) const;
+ void throwMissingArgumentError(const PosIdx pos, const char * s, const std::string & s1,
+ Env & env, Expr & expr) const;
[[gnu::noinline]]
void addErrorTrace(Error & e, const char * s, const std::string & s2) const;
@@ -480,7 +511,7 @@ private:
class DebugTraceStacker {
public:
DebugTraceStacker(EvalState &evalState, DebugTrace t);
- ~DebugTraceStacker()
+ ~DebugTraceStacker()
{
// assert(evalState.debugTraces.front() == trace);
evalState.debugTraces.pop_front();
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index efaeba7c6..c6e545729 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -437,11 +437,11 @@ void ExprLambda::bindVars(const EvalState & es, const std::shared_ptr<const Stat
new StaticEnv(
false, env.get(),
(hasFormals() ? formals->formals.size() : 0) +
- (!arg ? 0 : 1));
+ (!arg ? 0 : 1)));
Displacement displ = 0;
- if (arg) newEnv.vars.emplace_back(arg, displ++);
+ if (arg) newEnv->vars.emplace_back(arg, displ++);
if (hasFormals()) {
for (auto & i : formals->formals)
@@ -506,7 +506,7 @@ void ExprWith::bindVars(const EvalState & es, const std::shared_ptr<const Static
staticenv = env;
attrs->bindVars(es, env);
- StaticEnv newEnv(true, &env);
+ auto newEnv = std::shared_ptr<StaticEnv>(new StaticEnv(true, env.get()));
body->bindVars(es, newEnv);
}
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index d275a51e9..82fff6dcf 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -278,7 +278,12 @@ struct ExprList : Expr
{
std::vector<Expr *> elems;
ExprList() { };
- const PosIdx getPos() const { return pos; }
+ const PosIdx getPos() const
+ { if (elems.empty())
+ return noPos;
+ else
+ return elems.front()->getPos();
+ }
COMMON_METHODS
};
@@ -389,7 +394,7 @@ struct ExprOpNot : Expr
{
Expr * e;
ExprOpNot(Expr * e) : e(e) { };
- const Pos* getPos() const { return 0; }
+ const PosIdx getPos() const { return noPos; }
COMMON_METHODS
};
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 212ce3de9..e2267d154 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -774,12 +774,14 @@ static RegisterPrimOp primop_break({
.doc = R"(
In debug mode, pause Nix expression evaluation and enter the repl.
)",
- .fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
+ .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
+ PathSet context;
+ auto s = state.coerceToString(pos, *args[0], context).toOwned();
auto error = Error(ErrorInfo{
.level = lvlInfo,
- .msg = hintfmt("breakpoint reached; value was %1%", *args[0]),
- .errPos = pos,
+ .msg = hintfmt("breakpoint reached; value was %1%", s),
+ .errPos = state.positions[pos],
});
if (debuggerHook && !state.debugTraces.empty())
{
@@ -791,7 +793,7 @@ static RegisterPrimOp primop_break({
throw Error(ErrorInfo{
.level = lvlInfo,
.msg = hintfmt("quit from debugger"),
- .errPos = noPos,
+ .errPos = state.positions[noPos],
});
}