libexpr: migrate Expr::eval to return a Value, take 2

This is a rebase of CL 1626 after the performance problems that blocked
that change are no longer an issue.

Change-Id: I4a17f7606c5fdc9a924933a860eb401f6a6a6964
This commit is contained in:
skye
2026-02-23 18:11:47 -05:00
parent 62a2663436
commit 1ef7ccfc72
6 changed files with 136 additions and 160 deletions
+5 -9
View File
@@ -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<Expr> & 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<std::unique_ptr<Expr>, 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;
}
+89 -110
View File
@@ -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<AssertionError>("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<BackedStringView> 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<InfiniteRecursionError>("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;
}
}
+1 -1
View File
@@ -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;
+3 -4
View File
@@ -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<Value> 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(
+29 -27
View File
@@ -128,7 +128,7 @@ public:
virtual JSON toJSON(const SymbolTable & symbols) const;
virtual void accept(ExprVisitor & ev, std::unique_ptr<Expr> & 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<Expr> & 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<Expr> & 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<Expr> & 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
@@ -309,7 +309,7 @@ struct ExprSelect : Expr
ExprSelect(const PosIdx & pos, std::unique_ptr<Expr> e, AttrPath attrPath, std::unique_ptr<Expr> def) : Expr(pos), e(std::move(e)), def(std::move(def)), attrPath(std::move(attrPath)) { };
ExprSelect(const PosIdx & pos, std::unique_ptr<Expr> 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<Expr> & ptr) override { ev.visit(*this, ptr); }
private:
@@ -322,7 +322,7 @@ struct ExprOpHasAttr : Expr
AttrPath attrPath;
ExprOpHasAttr(const PosIdx & pos, std::unique_ptr<Expr> 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<Expr> & 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
@@ -410,7 +410,7 @@ struct ExprList : Expr
std::vector<std::unique_ptr<Expr>> 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<Expr> & 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<Expr> & 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
@@ -548,7 +548,7 @@ struct ExprLet : Expr, ExprAttrs
{
std::unique_ptr<Expr> 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
@@ -559,7 +559,7 @@ struct ExprWith : Expr
ExprWith * parentWith;
ExprWith(const PosIdx & pos, std::unique_ptr<Expr> attrs, std::unique_ptr<Expr> 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
@@ -568,7 +568,7 @@ struct ExprIf : Expr
std::unique_ptr<Expr> cond, then, else_;
ExprIf(const PosIdx & pos, std::unique_ptr<Expr> cond, std::unique_ptr<Expr> then, std::unique_ptr<Expr> 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
@@ -577,7 +577,7 @@ struct ExprAssert : Expr
std::unique_ptr<Expr> cond, body;
ExprAssert(const PosIdx & pos, std::unique_ptr<Expr> cond, std::unique_ptr<Expr> 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
@@ -586,7 +586,7 @@ struct ExprOpNot : Expr
std::unique_ptr<Expr> e;
ExprOpNot(const PosIdx & pos, std::unique_ptr<Expr> 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
@@ -595,17 +595,19 @@ struct ExprOpNot : Expr
{ \
std::unique_ptr<Expr> e1, e2; \
name(std::unique_ptr<Expr> e1, std::unique_ptr<Expr> e2) : e1(std::move(e1)), e2(std::move(e2)) {}; \
name(const PosIdx & pos, std::unique_ptr<Expr> e1, std::unique_ptr<Expr> e2) : Expr(pos), e1(std::move(e1)), e2(std::move(e2)) { }; \
name(const PosIdx & pos, std::unique_ptr<Expr> e1, std::unique_ptr<Expr> 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)} \
};\
return {{"_type", #name}, {"e1", e1->toJSON(symbols)}, {"e2", e2->toJSON(symbols)}}; \
} \
void accept(ExprVisitor & ev, std::unique_ptr<Expr> & ptr) override { ev.visit(*this, ptr); } \
void eval(EvalState & state, Env & env, Value & v) override; \
void accept(ExprVisitor & ev, std::unique_ptr<Expr> & 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<std::pair<PosIdx, std::unique_ptr<Expr>>> 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<Expr> & 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<Expr> & 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<Expr> & ptr) override { ev.visit(*this, ptr); }
};
+1 -1
View File
@@ -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);
}
}
}