diff --git a/lix/libcmd/repl.cc b/lix/libcmd/repl.cc index ed111070f..7c12411d6 100644 --- a/lix/libcmd/repl.cc +++ b/lix/libcmd/repl.cc @@ -504,8 +504,7 @@ StringSet NixRepl::completePrefix(const std::string &prefix) auto cur2 = cur.substr(dot + 1); Expr & e = parseString(expr); - Value v; - e.eval(state, *env, v); + Value v = e.eval(state, *env); state.forceAttrs(v, noPos, "while evaluating an attrset for the purpose of completion (this error should not be displayed; file an issue?)"); for (auto & i : *v.attrs()) { @@ -656,8 +655,7 @@ ProcessLineResult NixRepl::processLine(std::string line) overloaded{ [&](ExprReplBindings & b) { for (auto & [name, e] : b.symbols) { - Value v; - e->eval(state, *env, v); + Value v = e->eval(state, *env); // NONEXTLINE(bugprone-unused-return-value): leak because of thunk // references (void) e.release(); @@ -665,8 +663,7 @@ ProcessLineResult NixRepl::processLine(std::string line) } }, [&](std::unique_ptr & e) { - Value v; - e->eval(state, *env, v); + Value v = e->eval(state, *env); // NONEXTLINE(bugprone-unused-return-value): leak because of thunk references (void) e.release(); state.forceValue(v, noPos); @@ -1590,15 +1587,14 @@ std::variant, ExprReplBindings> NixRepl::parseReplString(s void NixRepl::evalString(std::string s, Value & v) { Expr & e = parseString(s); - e.eval(state, *env, v); + v = e.eval(state, *env); state.forceValue(v, noPos); } Value NixRepl::evalFile(SourcePath & path) { auto & expr = evaluator.parseExprFromFile(evaluator.paths.checkSourcePath(path), staticEnv); - Value result; - expr.eval(state, *env, result); + Value result = expr.eval(state, *env); state.forceValue(result, noPos); return result; } diff --git a/lix/libexpr/eval-expr.cc b/lix/libexpr/eval-expr.cc index 70fc59838..ed80cde43 100644 --- a/lix/libexpr/eval-expr.cc +++ b/lix/libexpr/eval-expr.cc @@ -1,5 +1,4 @@ #include "eval.hh" -#include "eval-inline.hh" #include "primops.hh" #include "gc-small-vector.hh" @@ -47,21 +46,21 @@ Value ExprList::maybeThunk(EvalState & state, Env & env) return Expr::maybeThunk(state, env); } -void Expr::eval(EvalState & state, Env & env, Value & v) +Value Expr::eval(EvalState & state, Env & env) { abort(); } -void ExprLiteral::eval(EvalState & state, Env & env, Value & v) +Value ExprLiteral::eval(EvalState & state, Env & env) { - v = this->v; + return this->v; } -void ExprInheritFrom::eval(EvalState & state, Env & env, Value & v) +Value ExprInheritFrom::eval(EvalState & state, Env & env) { Value & v2 = env.values[displ]; state.forceValue(v2, pos); - v = v2; + return v2; } Env * ExprAttrs::buildInheritFromEnv(EvalState & state, Env & up) @@ -77,10 +76,10 @@ Env * ExprAttrs::buildInheritFromEnv(EvalState & state, Env & up) return &inheritEnv; } -void ExprSet::eval(EvalState & state, Env & env, Value & v) +Value ExprSet::eval(EvalState & state, Env & env) { Bindings::Size capacity = attrs.size() + dynamicAttrs.size(); - v = {NewValueAs::attrs, state.ctx.buildBindings(capacity).finish()}; + Value v = {NewValueAs::attrs, state.ctx.buildBindings(capacity).finish()}; auto dynamicEnv = &env; if (recursive) { @@ -167,7 +166,7 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v) { KJ_DEFER(v = vBackup); v = Value{NewValueAs::blackhole}; - i.nameExpr->eval(state, *dynamicEnv, nameVal); + nameVal = i.nameExpr->eval(state, *dynamicEnv); state.forceValue(nameVal, i.pos); if (nameVal.type() == nNull) { continue; @@ -195,9 +194,10 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v) } v.attrs()->pos = pos; + return v; } -void ExprLet::eval(EvalState & state, Env & env, Value & v) +Value ExprLet::eval(EvalState & state, Env & env) { /* Create a new environment that contains the attributes in this `let'. */ @@ -214,19 +214,20 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) env2.values[displ++] = i.second.e->maybeThunk(state, *i.second.chooseByKind(&env2, &env, inheritEnv)); } - body->eval(state, env2, v); + return body->eval(state, env2); } -void ExprList::eval(EvalState & state, Env & env, Value & v) +Value ExprList::eval(EvalState & state, Env & env) { auto result = state.ctx.mem.newList(elems.size()); - v = {NewValueAs::list, result}; + Value v = {NewValueAs::list, result}; for (auto && [n, v2] : enumerate(result->span())) { v2 = elems[n]->maybeThunk(state, env); } + return v; } -void ExprVar::eval(EvalState & state, Env & env, Value & v) +Value ExprVar::eval(EvalState & state, Env & env) { Value * v2 = state.lookupVar(&env, *this, false); try { @@ -238,123 +239,103 @@ void ExprVar::eval(EvalState & state, Env & env, Value & v) } throw; } - v = *v2; + return *v2; } -void ExprWith::eval(EvalState & state, Env & env, Value & v) +Value ExprWith::eval(EvalState & state, Env & env) { Env & env2(state.ctx.mem.allocEnv(1)); env2.up = &env; env2.values[0] = attrs->maybeThunk(state, env); - body->eval(state, env2, v); + return body->eval(state, env2); } -void ExprIf::eval(EvalState & state, Env & env, Value & v) +Value ExprIf::eval(EvalState & state, Env & env) { - Value vCond; - cond->eval(state, env, vCond); - (state.checkBool(vCond, env, *cond) ? *then : *else_).eval(state, env, v); + Value vCond = cond->eval(state, env); + return (state.checkBool(vCond, env, *cond) ? *then : *else_).eval(state, env); } -void ExprAssert::eval(EvalState & state, Env & env, Value & v) +Value ExprAssert::eval(EvalState & state, Env & env) { - Value vCond; - cond->eval(state, env, vCond); + Value vCond = cond->eval(state, env); if (!state.checkBool(vCond, env, *cond)) { state.ctx.errors.make("assertion failed") .atPos(pos) .withFrame(env, *this) .debugThrow(); } - body->eval(state, env, v); + return body->eval(state, env); } -void ExprOpNot::eval(EvalState & state, Env & env, Value & v) +Value ExprOpNot::eval(EvalState & state, Env & env) { - Value vInner; - e->eval(state, env, vInner); - v = {NewValueAs::boolean, !state.checkBool(vInner, env, *e)}; + Value vInner = e->eval(state, env); + return {NewValueAs::boolean, !state.checkBool(vInner, env, *e)}; } -void ExprOpEq::eval(EvalState & state, Env & env, Value & v) +Value ExprOpEq::eval(EvalState & state, Env & env) { - Value v1; - e1->eval(state, env, v1); - Value v2; - e2->eval(state, env, v2); - v = {NewValueAs::boolean, state.eqValues(v1, v2, pos, "while testing two values for equality")}; + Value v1 = e1->eval(state, env); + Value v2 = e2->eval(state, env); + return {NewValueAs::boolean, state.eqValues(v1, v2, pos, "while testing two values for equality")}; } -void ExprOpNEq::eval(EvalState & state, Env & env, Value & v) +Value ExprOpNEq::eval(EvalState & state, Env & env) { - Value v1; - e1->eval(state, env, v1); - Value v2; - e2->eval(state, env, v2); - v = {NewValueAs::boolean, !state.eqValues(v1, v2, pos, "while testing two values for inequality")}; + Value v1 = e1->eval(state, env); + Value v2 = e2->eval(state, env); + return {NewValueAs::boolean, !state.eqValues(v1, v2, pos, "while testing two values for inequality")}; } -void ExprOpAnd::eval(EvalState & state, Env & env, Value & v) +Value ExprOpAnd::eval(EvalState & state, Env & env) { - Value v1; - e1->eval(state, env, v1); + Value v1 = e1->eval(state, env); /* Explicitly short-circuit */ if (!state.checkBool(v1, env, *e1)) { - v = {NewValueAs::boolean, false}; - return; + return {NewValueAs::boolean, false}; } - Value v2; - e2->eval(state, env, v2); - v = {NewValueAs::boolean, state.checkBool(v2, env, *e2)}; + Value v2 = e2->eval(state, env); + return {NewValueAs::boolean, state.checkBool(v2, env, *e2)}; } -void ExprOpOr::eval(EvalState & state, Env & env, Value & v) +Value ExprOpOr::eval(EvalState & state, Env & env) { - Value v1; - e1->eval(state, env, v1); + Value v1 = e1->eval(state, env); /* Explicitly short-circuit */ if (state.checkBool(v1, env, *e1)) { - v = {NewValueAs::boolean, true}; - return; + return {NewValueAs::boolean, true}; } - Value v2; - e2->eval(state, env, v2); - v = {NewValueAs::boolean, state.checkBool(v2, env, *e2)}; + Value v2 = e2->eval(state, env); + return {NewValueAs::boolean, state.checkBool(v2, env, *e2)}; } -void ExprOpImpl::eval(EvalState & state, Env & env, Value & v) +Value ExprOpImpl::eval(EvalState & state, Env & env) { - Value v1; - e1->eval(state, env, v1); + Value v1 = e1->eval(state, env); /* Explicitly short-circuit (ex falso quodlibet) */ if (!state.checkBool(v1, env, *e1)) { - v = {NewValueAs::boolean, true}; - return; + return {NewValueAs::boolean, true}; } - Value v2; - e2->eval(state, env, v2); - v = {NewValueAs::boolean, state.checkBool(v2, env, *e2)}; + Value v2 = e2->eval(state, env); + return {NewValueAs::boolean, state.checkBool(v2, env, *e2)}; } -void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) +Value ExprOpUpdate::eval(EvalState & state, Env & env) { - Value v1; - e1->eval(state, env, v1); + Value v1 = e1->eval(state, env); state.checkAttrs(v1, env, *e1); - Value v2; - e2->eval(state, env, v2); + Value v2 = e2->eval(state, env); state.checkAttrs(v2, env, *e2); state.ctx.stats.nrOpUpdates++; if (v1.attrs()->size() == 0) { - v = v2; - return; + return v2; } if (v2.attrs()->size() == 0) { - v = v1; - return; + return v1; } auto attrs = state.ctx.buildBindings(v1.attrs()->size() + v2.attrs()->size()); @@ -383,40 +364,39 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) attrs.insert(*j++); } - v = {NewValueAs::attrs, attrs.alreadySorted()}; + Value v = {NewValueAs::attrs, attrs.alreadySorted()}; state.ctx.stats.nrOpUpdateValuesCopied += v.attrs()->size(); + return v; } -void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) +Value ExprOpConcatLists::eval(EvalState & state, Env & env) { state.ctx.stats.nrListConcats++; /* We don't call into `concatLists` as that loses the position information of the expressions. */ - Value v1; - e1->eval(state, env, v1); + Value v1 = e1->eval(state, env); state.checkList(v1, env, *e1); - Value v2; - e2->eval(state, env, v2); + Value v2 = e2->eval(state, env); state.checkList(v2, env, *e2); size_t l1 = v1.listSize(), l2 = v2.listSize(), len = l1 + l2; if (l1 == 0) { - v = v2; + return v2; } else if (l2 == 0) { - v = v1; + return v1; } else { auto list = state.ctx.mem.newList(len); - v = {NewValueAs::list, list}; auto out = list->elems; std::copy(v1.listElems(), v1.listElems() + l1, out); std::copy(v2.listElems(), v2.listElems() + l2, out + l1); + return {NewValueAs::list, list}; } } -void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) +Value ExprConcatStrings::eval(EvalState & state, Env & env) { NixStringContext context; std::vector s; @@ -454,7 +434,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) for (auto & [i_pos, i] : es) { Value & vTmp = *vTmpP++; - i->eval(state, env, vTmp); + vTmp = i->eval(state, env); /* If the first element is a path, then the result will also be a path, we don't copy anything (yet - that's done later, @@ -528,9 +508,9 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) } if (firstType == nInt) { - v = {NewValueAs::integer, n}; + return {NewValueAs::integer, n}; } else if (firstType == nFloat) { - v = {NewValueAs::floating, nf}; + return {NewValueAs::floating, nf}; } else if (firstType == nPath) { if (!context.empty()) { state.ctx.errors @@ -539,26 +519,28 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) .withFrame(env, *this) .debugThrow(); } - v = {NewValueAs::path, CanonPath(canonPath(str()))}; + return {NewValueAs::path, CanonPath(canonPath(str()))}; } else { - v = {NewValueAs::string, gcStr(), context}; + return {NewValueAs::string, gcStr(), context}; } } -void ExprPos::eval(EvalState & state, Env & env, Value & v) +Value ExprPos::eval(EvalState & state, Env & env) { + Value v; state.mkPos(v, pos); + return v; } -void ExprBlackHole::eval(EvalState & state, Env & env, Value & v) +Value ExprBlackHole::eval(EvalState & state, Env & env) { state.ctx.errors.make("infinite recursion encountered").debugThrow(); } -void ExprDebugFrame::eval(EvalState & state, Env & env, Value & v) +Value ExprDebugFrame::eval(EvalState & state, Env & env) { auto dts = makeDebugTraceStacker(state, *inner, env, state.ctx.positions[pos], message); - inner->eval(state, env, v); + return inner->eval(state, env); } /** Returns `nullptr` if we should be using a default instead. */ @@ -630,7 +612,7 @@ ExprSelect::selectSingleAttr(EvalState & state, Env & env, AttrName const & attr return attrIt; } -void ExprSelect::eval(EvalState & state, Env & env, Value & v) +Value ExprSelect::eval(EvalState & state, Env & env) { // Position for the current attrset Value in this select chain. PosIdx posCurrent; @@ -640,7 +622,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) Value baseSelectee; try { // Evaluate the original thing we're selecting on. - e->eval(state, env, baseSelectee); + baseSelectee = e->eval(state, env); } catch (Error & e) { // clang-format off e.addTrace(state.ctx.positions[getPos()], HintFmt( @@ -663,7 +645,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) if (!attr) { // Use default. try { - this->def->eval(state, env, v); + return this->def->eval(state, env); } catch (Error & err) { err.addTrace( state.ctx.positions[this->def->pos], @@ -672,7 +654,6 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) ); throw; } - return; } // The selection worked. If we have another iteration, then we use `attr->value` @@ -689,7 +670,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) state.forceValue(curSelectee.get(), posCurrent ? posCurrent : posCurrentSyntax); - v = curSelectee.get(); + return curSelectee.get(); } catch (Error & err) { auto const & lastPos = state.ctx.positions[posCurrent]; @@ -701,37 +682,33 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) } } -void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) +Value ExprOpHasAttr::eval(EvalState & state, Env & env) { - Value vTmp; + Value vTmp = e->eval(state, env); Value * vAttrs = &vTmp; - e->eval(state, env, vTmp); - for (auto & i : attrPath) { state.forceValue(*vAttrs, getPos()); const Attr * j; auto name = getName(i, state, env); if (vAttrs->type() != nAttrs || (j = vAttrs->attrs()->get(name)) == nullptr) { - v = {NewValueAs::boolean, false}; - return; + return {NewValueAs::boolean, false}; } else { vAttrs = &j->value; } } - v = {NewValueAs::boolean, true}; + return {NewValueAs::boolean, true}; } -void ExprLambda::eval(EvalState & state, Env & env, Value & v) +Value ExprLambda::eval(EvalState & state, Env & env) { - v = {NewValueAs::lambda, state.ctx.mem, env, *this}; + return {NewValueAs::lambda, state.ctx.mem, env, *this}; } -void ExprCall::eval(EvalState & state, Env & env, Value & v) +Value ExprCall::eval(EvalState & state, Env & env) { - Value vFun; - fun->eval(state, env, vFun); + Value vFun = fun->eval(state, env); // Empirical arity of Nixpkgs lambdas by regex e.g. ([a-zA-Z]+:(\s|(/\*.*\/)|(#.*\n))*){5} // 2: over 4000 @@ -745,7 +722,9 @@ void ExprCall::eval(EvalState & state, Env & env, Value & v) vArgs[i] = args[i]->maybeThunk(state, env); } + Value v; state.callFunction(vFun, vArgs, v, pos); + return v; } } diff --git a/lix/libexpr/eval-inline.hh b/lix/libexpr/eval-inline.hh index 2924ea237..3de0d6d07 100644 --- a/lix/libexpr/eval-inline.hh +++ b/lix/libexpr/eval-inline.hh @@ -203,7 +203,7 @@ void EvalState::forceValue(Value & v, const PosIdx pos) Expr & expr = *thunk.expr; thunk = Value::blackHole; try { - expr.eval(*this, *env, v); + v = expr.eval(*this, *env); thunk.resolve(v); } catch (...) { thunk = backup; diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 38181b161..ed73faa64 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -166,8 +166,7 @@ Symbol getName(const AttrName & name, EvalState & state, Env & env) if (name.symbol) { return name.symbol; } else { - Value nameValue; - name.expr->eval(state, env, nameValue); + Value nameValue = name.expr->eval(state, env); state.forceStringNoCtx(nameValue, name.expr->getPos(), "while evaluating an attribute name"); return state.ctx.symbols.create(nameValue.str()); } @@ -976,7 +975,7 @@ void EvalState::resetFileCache() void EvalState::eval(Expr & e, Value & v) { - e.eval(*this, ctx.builtins.env, v); + v = e.eval(*this, ctx.builtins.env); } std::string showAttrPath(EvalState & state, Env & env, const AttrPath & attrPath) @@ -1168,7 +1167,7 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, c /* Evaluate the body. */ try { - lambda.body->eval(*this, env2, vCur); + vCur = lambda.body->eval(*this, env2); } catch (Error & e) { if (loggerSettings.showTrace.get()) { e.addTrace( diff --git a/lix/libexpr/nixexpr.hh b/lix/libexpr/nixexpr.hh index 806dae45a..a124efed1 100644 --- a/lix/libexpr/nixexpr.hh +++ b/lix/libexpr/nixexpr.hh @@ -128,7 +128,7 @@ public: virtual JSON toJSON(const SymbolTable & symbols) const; virtual void accept(ExprVisitor & ev, std::unique_ptr & ptr) = 0; - virtual void eval(EvalState & state, Env & env, Value & v); + virtual Value eval(EvalState & state, Env & env); virtual Value maybeThunk(EvalState & state, Env & env); virtual void setName(Symbol name); PosIdx getPos() const { return pos; } @@ -167,7 +167,7 @@ struct ExprDebugFrame : Expr { return inner->toJSON(symbols); } - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -179,7 +179,7 @@ protected: public: Value maybeThunk(EvalState & state, Env & env) override; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -267,7 +267,7 @@ struct ExprVar : Expr ExprVar(const PosIdx & pos, Symbol name, bool needsRoot = false) : Expr(pos), name(name), needsRoot(needsRoot) { }; Value maybeThunk(EvalState & state, Env & env) override; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -287,7 +287,7 @@ struct ExprInheritFrom : Expr } JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -309,7 +309,7 @@ struct ExprSelect : Expr ExprSelect(const PosIdx & pos, std::unique_ptr e, AttrPath attrPath, std::unique_ptr def) : Expr(pos), e(std::move(e)), def(std::move(def)), attrPath(std::move(attrPath)) { }; ExprSelect(const PosIdx & pos, std::unique_ptr e, const PosIdx namePos, Symbol name) : Expr(pos), e(std::move(e)) { attrPath.push_back(AttrName(namePos, name)); }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } private: @@ -322,7 +322,7 @@ struct ExprOpHasAttr : Expr AttrPath attrPath; ExprOpHasAttr(const PosIdx & pos, std::unique_ptr e, AttrPath attrPath) : Expr(pos), e(std::move(e)), attrPath(std::move(attrPath)) { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -392,7 +392,7 @@ struct ExprSet : Expr, ExprAttrs { ExprSet(const PosIdx &pos, bool recursive = false) : Expr(pos), recursive(recursive) { }; ExprSet() { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -410,7 +410,7 @@ struct ExprList : Expr std::vector> elems; ExprList(PosIdx pos) : Expr(pos) { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } Value maybeThunk(EvalState & state, Env & env) override; }; @@ -528,7 +528,7 @@ struct ExprLambda : Expr } JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -540,7 +540,7 @@ struct ExprCall : Expr : Expr(pos), fun(std::move(fun)), args(std::move(args)) { } JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -548,7 +548,7 @@ struct ExprLet : Expr, ExprAttrs { std::unique_ptr body; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -559,7 +559,7 @@ struct ExprWith : Expr ExprWith * parentWith; ExprWith(const PosIdx & pos, std::unique_ptr attrs, std::unique_ptr body) : Expr(pos), attrs(std::move(attrs)), body(std::move(body)) { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -568,7 +568,7 @@ struct ExprIf : Expr std::unique_ptr cond, then, else_; ExprIf(const PosIdx & pos, std::unique_ptr cond, std::unique_ptr then, std::unique_ptr else_) : Expr(pos), cond(std::move(cond)), then(std::move(then)), else_(std::move(else_)) { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -577,7 +577,7 @@ struct ExprAssert : Expr std::unique_ptr cond, body; ExprAssert(const PosIdx & pos, std::unique_ptr cond, std::unique_ptr body) : Expr(pos), cond(std::move(cond)), body(std::move(body)) { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -586,26 +586,28 @@ struct ExprOpNot : Expr std::unique_ptr e; ExprOpNot(const PosIdx & pos, std::unique_ptr e) : Expr(pos), e(std::move(e)) { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; -#define MakeBinOp(name, s) \ - struct name : Expr \ - { \ - std::unique_ptr e1, e2; \ - name(std::unique_ptr e1, std::unique_ptr e2) : e1(std::move(e1)), e2(std::move(e2)) { }; \ - name(const PosIdx & pos, std::unique_ptr e1, std::unique_ptr e2) : Expr(pos), e1(std::move(e1)), e2(std::move(e2)) { }; \ - JSON toJSON(const SymbolTable & symbols) const override \ - { \ - return { \ - {"_type", #name}, \ - {"e1", e1->toJSON(symbols)}, \ - {"e2", e2->toJSON(symbols)} \ - };\ - } \ - void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } \ - void eval(EvalState & state, Env & env, Value & v) override; \ +#define MakeBinOp(name, s) \ + struct name : Expr \ + { \ + std::unique_ptr e1, e2; \ + name(std::unique_ptr e1, std::unique_ptr e2) : e1(std::move(e1)), e2(std::move(e2)) {}; \ + name(const PosIdx & pos, std::unique_ptr e1, std::unique_ptr e2) \ + : Expr(pos) \ + , e1(std::move(e1)) \ + , e2(std::move(e2)) {}; \ + JSON toJSON(const SymbolTable & symbols) const override \ + { \ + return {{"_type", #name}, {"e1", e1->toJSON(symbols)}, {"e2", e2->toJSON(symbols)}}; \ + } \ + void accept(ExprVisitor & ev, std::unique_ptr & ptr) override \ + { \ + ev.visit(*this, ptr); \ + } \ + Value eval(EvalState & state, Env & env) override; \ }; MakeBinOp(ExprOpEq, "==") @@ -623,7 +625,7 @@ struct ExprConcatStrings : Expr ExprConcatStrings(const PosIdx & pos, bool isInterpolation, std::vector>> es) : Expr(pos), isInterpolation(isInterpolation), es(std::move(es)) { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; @@ -631,14 +633,14 @@ struct ExprPos : Expr { ExprPos(const PosIdx & pos) : Expr(pos) { }; JSON toJSON(const SymbolTable & symbols) const override; - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; /* only used to mark thunks as black holes. */ struct ExprBlackHole : Expr { - void eval(EvalState & state, Env & env, Value & v) override; + Value eval(EvalState & state, Env & env) override; void accept(ExprVisitor & ev, std::unique_ptr & ptr) override { ev.visit(*this, ptr); } }; diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index 86bd93695..696f015f9 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -250,7 +250,7 @@ static void import(EvalState & state, Value & vPath, Value * vScope, Value & v) debug("evaluating file '%1%'", path); Expr & e = state.ctx.parseExprFromFile(state.ctx.paths.resolveExprPath(path), staticEnv); - e.eval(state, *env, v); + v = e.eval(state, *env); } } }