diff options
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 219 |
1 files changed, 102 insertions, 117 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 10dba69e7..ca0eec6e3 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -466,7 +466,7 @@ EvalState::EvalState( , env1AllocCache(std::make_shared<void *>(nullptr)) #endif , baseEnv(allocEnv(128)) - , staticBaseEnv(new StaticEnv(false, 0)) + , staticBaseEnv{std::make_shared<StaticEnv>(false, nullptr)} { countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0"; @@ -524,7 +524,7 @@ void EvalState::allowPath(const StorePath & storePath) allowedPaths->insert(store->toRealPath(storePath)); } -void EvalState::allowAndSetStorePathString(const StorePath &storePath, Value & v) +void EvalState::allowAndSetStorePathString(const StorePath & storePath, Value & v) { allowPath(storePath); @@ -714,22 +714,19 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v) // just for the current level of StaticEnv, not the whole chain. -void printStaticEnvBindings(const SymbolTable &st, 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 << st[i->first] << " "; - } + for (auto & i : se.vars) + 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 SymbolTable &st, const Env &env) +void printWithBindings(const SymbolTable & st, const Env & env) { - if (env.type == Env::HasWithAttrs) - { + if (env.type == Env::HasWithAttrs) { std::cout << "with: "; std::cout << ANSI_MAGENTA; Bindings::iterator j = env.values[0]->attrs->begin(); @@ -742,7 +739,7 @@ void printWithBindings(const SymbolTable &st, const Env &env) } } -void printEnvBindings(const SymbolTable &st, 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; @@ -752,16 +749,13 @@ void printEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env printWithBindings(st, env); std::cout << std::endl; printEnvBindings(st, *se.up, *env.up, ++lvl); - } - else - { + } else { std::cout << ANSI_MAGENTA; - // 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)st[i->first]).substr(0,2) != "__") - std::cout << st[i->first] << " "; - } + // for the top level, don't print the double underscore ones; + // they are in builtins. + for (auto & i : se.vars) + if (!hasPrefix(st[i.first], "__")) + std::cout << st[i.first] << " "; std::cout << ANSI_NORMAL; std::cout << std::endl; printWithBindings(st, env); // probably nothing there for the top level. @@ -771,56 +765,50 @@ void printEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env } // TODO: add accompanying env for With stuff. -void printEnvBindings(const SymbolTable &st, 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(st, *expr.staticenv.get(), env, 0); + if (expr.staticEnv) + printEnvBindings(st, *expr.staticEnv.get(), env, 0); +} + +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(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[st[j->name]] = j->value; + ++j; + } + } else { + // iterate through staticenv bindings and add them. + for (auto & i : se.vars) + vm[st[i.first]] = env.values[i.second]; + } } } -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(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[st[j->name]] = j->value; - ++j; - } - } - else - { - // iterate through staticenv bindings and add them. - for (auto iter = se.vars.begin(); iter != se.vars.end(); ++iter) - { - vm[st[iter->first]] = env.values[iter->second]; - } - } - } -} - -valmap * mapStaticEnvBindings(const SymbolTable &st,const StaticEnv &se, const Env &env) -{ - auto vm = new valmap(); +std::unique_ptr<valmap> mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env) +{ + auto vm = std::make_unique<valmap>(); 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. +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(); + const DebugTrace & last = debugTraces.front(); debuggerHook(&e, last.env, last.expr); } } @@ -829,7 +817,7 @@ void EvalState::debugLastTrace(Error & e) const { 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, Env & env, Expr &expr) const +void EvalState::throwEvalError(const PosIdx pos, const char * s, Env & env, Expr & expr) const { auto error = EvalError({ .msg = hintfmt(s), @@ -864,7 +852,7 @@ void EvalState::throwEvalError(const char * s, const std::string & s2) const } void EvalState::throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s, - const std::string & s2, Env & env, Expr &expr) const + const std::string & s2, Env & env, Expr & expr) const { auto error = EvalError(ErrorInfo{ .msg = hintfmt(s, s2), @@ -890,7 +878,7 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri throw error; } -void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::string & s2, 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, s2), @@ -900,7 +888,6 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri if (debuggerHook) debuggerHook(&error, env, expr); - throw error; } @@ -931,7 +918,7 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri } void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::string & s2, - const std::string & s3, Env & env, Expr &expr) const + const std::string & s3, Env & env, Expr & expr) const { auto error = EvalError({ .msg = hintfmt(s, s2), @@ -944,7 +931,7 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri throw error; } -void EvalState::throwEvalError(const PosIdx p1, const char * s, const Symbol sym, const PosIdx p2, Env & env, Expr &expr) const +void EvalState::throwEvalError(const PosIdx p1, const char * s, const Symbol sym, const PosIdx p2, Env & env, Expr & expr) const { // p1 is where the error occurred; p2 is a position mentioned in the message. auto error = EvalError({ @@ -970,7 +957,7 @@ void EvalState::throwTypeError(const PosIdx pos, const char * s, const Value & v throw error; } -void EvalState::throwTypeError(const PosIdx pos, const char * s, const Value & v, Env & env, Expr &expr) const +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)), @@ -1086,27 +1073,31 @@ void EvalState::addErrorTrace(Error & e, const PosIdx pos, const char * s, const e.addTrace(positions[pos], s, s2); } -std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(EvalState &state, Expr &expr, Env &env, - std::optional<ErrPos> pos, const char * s, const std::string & s2) +static 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( - state, - DebugTrace - {.pos = pos, - .expr = expr, - .env = env, - .hint = hintfmt(s, s2), - .is_error = false - })); + return std::make_unique<DebugTraceStacker>(state, + DebugTrace { + .pos = pos, + .expr = expr, + .env = env, + .hint = hintfmt(s, s2), + .isError = false + }); } -DebugTraceStacker::DebugTraceStacker(EvalState &evalState, DebugTrace t) -:evalState(evalState), trace(t) +DebugTraceStacker::DebugTraceStacker(EvalState & evalState, DebugTrace t) + : evalState(evalState) + , trace(std::move(t)) { - evalState.debugTraces.push_front(t); + evalState.debugTraces.push_front(trace); if (evalState.debugStop && debuggerHook) - debuggerHook(0, t.env, t.expr); + debuggerHook(nullptr, trace.env, trace.expr); } void Value::mkString(std::string_view s) @@ -1303,15 +1294,14 @@ void EvalState::cacheFile( fileParseCache[resolvedPath] = e; try { - auto dts = - debuggerHook ? - makeDebugTraceStacker( - *this, - *e, - this->baseEnv, - (e->getPos() ? std::optional(ErrPos(positions[e->getPos()])) : std::nullopt), - "while evaluating the file '%1%':", resolvedPath) - : nullptr; + auto dts = debuggerHook + ? makeDebugTraceStacker( + *this, + *e, + this->baseEnv, + e->getPos() ? std::optional(ErrPos(positions[e->getPos()])) : std::nullopt, + "while evaluating the file '%1%':", resolvedPath) + : nullptr; // Enforce that 'flake.nix' is a direct attrset, not a // computation. @@ -1538,15 +1528,14 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) e->eval(state, env, vTmp); try { - auto dts = - debuggerHook ? - makeDebugTraceStacker( - state, - *this, - env, - state.positions[pos2], - "while evaluating the attribute '%1%'", - showAttrPath(state, env, attrPath)) + auto dts = debuggerHook + ? makeDebugTraceStacker( + state, + *this, + env, + state.positions[pos2], + "while evaluating the attribute '%1%'", + showAttrPath(state, env, attrPath)) : nullptr; for (auto & i : attrPath) { @@ -1708,14 +1697,14 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & /* Evaluate the body. */ try { - auto dts = - debuggerHook ? - makeDebugTraceStacker(*this, *lambda.body, env2, positions[lambda.pos], - "while evaluating %s", - (lambda.name - ? concatStrings("'", symbols[lambda.name], "'") - : "anonymous lambda")) - : nullptr; + auto dts = debuggerHook + ? makeDebugTraceStacker( + *this, *lambda.body, env2, positions[lambda.pos], + "while evaluating %s", + lambda.name + ? concatStrings("'", symbols[lambda.name], "'") + : "anonymous lambda") + : nullptr; lambda.body->eval(*this, env2, vCur); } catch (Error & e) { @@ -2135,14 +2124,10 @@ void EvalState::forceValueDeep(Value & v) if (v.type() == nAttrs) { for (auto & i : *v.attrs) try { - - auto dts = - 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, positions[i.pos], - "while evaluating the attribute '%1%'", symbols[i.name]) - : nullptr) + // If the value is a thunk, we're evaling. Otherwise no trace necessary. + auto dts = debuggerHook && i.value->isThunk() + ? makeDebugTraceStacker(*this, *v.thunk.expr, *v.thunk.env, positions[i.pos], + "while evaluating the attribute '%1%'", symbols[i.name]) : nullptr; recurse(*i.value); |