libexpr: Track position information in all expressions

Change-Id: Ied79381a917a715cdd8816d6f9df527289217dfb
This commit is contained in:
piegames
2025-01-27 20:49:25 +01:00
parent d0361e9467
commit f324574265
5 changed files with 65 additions and 93 deletions
+26 -55
View File
@@ -49,12 +49,14 @@ struct Expr
protected:
Expr(Expr &&) = default;
Expr & operator=(Expr &&) = default;
Expr(const PosIdx pos) : pos(pos) {};
public:
struct AstSymbols {
Symbol sub, lessThan, mul, div, or_, findFile, nixPath, body, overrides;
};
PosIdx pos;
Expr() = default;
Expr(const Expr &) = delete;
@@ -66,7 +68,7 @@ public:
virtual void eval(EvalState & state, Env & env, Value & v);
virtual Value * maybeThunk(EvalState & state, Env & env);
virtual void setName(Symbol name);
virtual PosIdx getPos() const { return noPos; }
PosIdx getPos() const { return pos; }
};
#define COMMON_METHODS \
@@ -78,11 +80,12 @@ struct ExprLiteral : Expr
{
protected:
Value v;
ExprLiteral() = default;
ExprLiteral(const PosIdx pos) : Expr(pos) {};
public:
ExprLiteral(NewValueAs::integer_t, NixInt n) { v.mkInt(n); };
ExprLiteral(NewValueAs::integer_t, NixInt::Inner n) { v.mkInt(n); };
ExprLiteral(NewValueAs::floating_t, NixFloat nf) { v.mkFloat(nf); };
ExprLiteral(const PosIdx pos, NewValueAs::integer_t, NixInt n) : Expr(pos) { v.mkInt(n); };
ExprLiteral(const PosIdx pos, NewValueAs::integer_t, NixInt::Inner n) : Expr(pos) { v.mkInt(n); };
ExprLiteral(const PosIdx pos, NewValueAs::floating_t, NixFloat nf) : Expr(pos) { v.mkFloat(nf); };
Value * maybeThunk(EvalState & state, Env & env) override;
COMMON_METHODS
};
@@ -90,13 +93,13 @@ public:
struct ExprString : ExprLiteral
{
std::string s;
ExprString(std::string &&s) : s(std::move(s)) { v.mkString(this->s.data()); };
ExprString(const PosIdx pos, std::string &&s) : ExprLiteral(pos), s(std::move(s)) { v.mkString(this->s.data()); };
};
struct ExprPath : ExprLiteral
{
std::string s;
ExprPath(std::string s) : s(std::move(s)) { v.mkPath(this->s.c_str()); };
ExprPath(const PosIdx pos, std::string s) : ExprLiteral(pos), s(std::move(s)) { v.mkPath(this->s.c_str()); };
};
typedef uint32_t Level;
@@ -104,7 +107,6 @@ typedef uint32_t Displacement;
struct ExprVar : Expr
{
PosIdx pos;
Symbol name;
/* Whether the variable comes from an environment (e.g. a rec, let
@@ -130,9 +132,8 @@ struct ExprVar : Expr
bool needsRoot;
ExprVar(Symbol name) : name(name), needsRoot(false) { };
ExprVar(const PosIdx & pos, Symbol name, bool needsRoot = false) : pos(pos), name(name), needsRoot(needsRoot) { };
ExprVar(const PosIdx & pos, Symbol name, bool needsRoot = false) : Expr(pos), name(name), needsRoot(needsRoot) { };
Value * maybeThunk(EvalState & state, Env & env) override;
PosIdx getPos() const override { return pos; }
COMMON_METHODS
};
@@ -159,8 +160,6 @@ struct ExprInheritFrom : ExprVar
struct ExprSelect : Expr
{
PosIdx pos;
/** The expression attributes are being selected on. e.g. `foo` in `foo.bar.baz`. */
std::unique_ptr<Expr> e;
@@ -172,9 +171,8 @@ struct ExprSelect : Expr
/** The path of attributes being selected. e.g. `bar.baz` in `foo.bar.baz.` */
AttrPath attrPath;
ExprSelect(const PosIdx & pos, std::unique_ptr<Expr> e, AttrPath attrPath, std::unique_ptr<Expr> def) : pos(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) : pos(pos), e(std::move(e)) { attrPath.push_back(AttrName(namePos, name)); };
PosIdx getPos() const override { return pos; }
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)); };
COMMON_METHODS
};
@@ -182,8 +180,7 @@ struct ExprOpHasAttr : Expr
{
std::unique_ptr<Expr> e;
AttrPath attrPath;
ExprOpHasAttr(std::unique_ptr<Expr> e, AttrPath attrPath) : e(std::move(e)), attrPath(std::move(attrPath)) { };
PosIdx getPos() const override { return e->getPos(); }
ExprOpHasAttr(const PosIdx & pos, std::unique_ptr<Expr> e, AttrPath attrPath) : Expr(pos), e(std::move(e)), attrPath(std::move(attrPath)) { };
COMMON_METHODS
};
@@ -248,26 +245,19 @@ struct ExprAttrs
};
struct ExprSet : Expr, ExprAttrs {
PosIdx pos;
bool recursive = false;
ExprSet(const PosIdx &pos, bool recursive = false) : pos(pos), recursive(recursive) { };
ExprSet(const PosIdx &pos, bool recursive = false) : Expr(pos), recursive(recursive) { };
ExprSet() { };
PosIdx getPos() const override { return pos; }
COMMON_METHODS
};
struct ExprList : Expr
{
std::vector<std::unique_ptr<Expr>> elems;
ExprList() { };
ExprList(PosIdx pos) : Expr(pos) { };
COMMON_METHODS
Value * maybeThunk(EvalState & state, Env & env) override;
PosIdx getPos() const override
{
return elems.empty() ? noPos : elems.front()->getPos();
}
};
struct Formal
@@ -305,9 +295,6 @@ struct Formals
struct ExprLambda : Expr
{
/** Where the lambda is defined in Nix code. May be falsey if the
* position is not known. */
PosIdx pos;
/** Name of the lambda. This is set if the lambda is defined in a
* let-expression or an attribute set, such that there is a name.
* Lambdas may have a falsey symbol as the name if they are anonymous */
@@ -320,17 +307,16 @@ struct ExprLambda : Expr
std::unique_ptr<Formals> formals;
std::unique_ptr<Expr> body;
ExprLambda(PosIdx pos, Symbol arg, std::unique_ptr<Formals> formals, std::unique_ptr<Expr> body)
: pos(pos), arg(arg), formals(std::move(formals)), body(std::move(body))
: Expr(pos), arg(arg), formals(std::move(formals)), body(std::move(body))
{
};
ExprLambda(PosIdx pos, std::unique_ptr<Formals> formals, std::unique_ptr<Expr> body)
: pos(pos), formals(std::move(formals)), body(std::move(body))
: Expr(pos), formals(std::move(formals)), body(std::move(body))
{
}
void setName(Symbol name) override;
std::string showNamePos(const EvalState & state) const;
inline bool hasFormals() const { return formals != nullptr; }
PosIdx getPos() const override { return pos; }
/** Returns the name of the lambda,
* or "anonymous lambda" if it doesn't have one.
@@ -363,11 +349,9 @@ struct ExprCall : Expr
{
std::unique_ptr<Expr> fun;
std::vector<std::unique_ptr<Expr>> args;
PosIdx pos;
ExprCall(const PosIdx & pos, std::unique_ptr<Expr> fun, std::vector<std::unique_ptr<Expr>> && args)
: fun(std::move(fun)), args(std::move(args)), pos(pos)
: Expr(pos), fun(std::move(fun)), args(std::move(args))
{ }
PosIdx getPos() const override { return pos; }
COMMON_METHODS
};
@@ -379,48 +363,40 @@ struct ExprLet : Expr, ExprAttrs
struct ExprWith : Expr
{
PosIdx pos;
std::unique_ptr<Expr> attrs, body;
size_t prevWith;
ExprWith * parentWith;
ExprWith(const PosIdx & pos, std::unique_ptr<Expr> attrs, std::unique_ptr<Expr> body) : pos(pos), attrs(std::move(attrs)), body(std::move(body)) { };
PosIdx getPos() const override { return pos; }
ExprWith(const PosIdx & pos, std::unique_ptr<Expr> attrs, std::unique_ptr<Expr> body) : Expr(pos), attrs(std::move(attrs)), body(std::move(body)) { };
COMMON_METHODS
};
struct ExprIf : Expr
{
PosIdx pos;
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_) : pos(pos), cond(std::move(cond)), then(std::move(then)), else_(std::move(else_)) { };
PosIdx getPos() const override { return pos; }
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_)) { };
COMMON_METHODS
};
struct ExprAssert : Expr
{
PosIdx pos;
std::unique_ptr<Expr> cond, body;
ExprAssert(const PosIdx & pos, std::unique_ptr<Expr> cond, std::unique_ptr<Expr> body) : pos(pos), cond(std::move(cond)), body(std::move(body)) { };
PosIdx getPos() const override { return pos; }
ExprAssert(const PosIdx & pos, std::unique_ptr<Expr> cond, std::unique_ptr<Expr> body) : Expr(pos), cond(std::move(cond)), body(std::move(body)) { };
COMMON_METHODS
};
struct ExprOpNot : Expr
{
std::unique_ptr<Expr> e;
ExprOpNot(std::unique_ptr<Expr> e) : e(std::move(e)) { };
PosIdx getPos() const override { return e->getPos(); }
ExprOpNot(const PosIdx & pos, std::unique_ptr<Expr> e) : Expr(pos), e(std::move(e)) { };
COMMON_METHODS
};
#define MakeBinOp(name, s) \
struct name : Expr \
{ \
PosIdx pos; \
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) : pos(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)) { }; \
nlohmann::json toJSON(const SymbolTable & symbols) const override \
{ \
return { \
@@ -434,7 +410,6 @@ struct ExprOpNot : Expr
e1->bindVars(es, env); e2->bindVars(es, env); \
} \
void eval(EvalState & state, Env & env, Value & v) override; \
PosIdx getPos() const override { return pos; } \
};
MakeBinOp(ExprOpEq, "==")
@@ -447,20 +422,16 @@ MakeBinOp(ExprOpConcatLists, "++")
struct ExprConcatStrings : Expr
{
PosIdx pos;
bool forceString;
std::vector<std::pair<PosIdx, std::unique_ptr<Expr>>> es;
ExprConcatStrings(const PosIdx & pos, bool forceString, std::vector<std::pair<PosIdx, std::unique_ptr<Expr>>> es)
: pos(pos), forceString(forceString), es(std::move(es)) { };
PosIdx getPos() const override { return pos; }
: Expr(pos), forceString(forceString), es(std::move(es)) { };
COMMON_METHODS
};
struct ExprPos : Expr
{
PosIdx pos;
ExprPos(const PosIdx & pos) : pos(pos) { };
PosIdx getPos() const override { return pos; }
ExprPos(const PosIdx & pos) : Expr(pos) { };
COMMON_METHODS
};
+31 -30
View File
@@ -79,8 +79,8 @@ struct ExprState
}
template<typename Op, typename... Args>
std::unique_ptr<Expr> applyUnary(Args &&... args) {
return std::make_unique<Op>(popExprOnly(), std::forward<Args>(args)...);
std::unique_ptr<Expr> applyUnary(PosIdx pos, Args &&... args) {
return std::make_unique<Op>(pos, popExprOnly(), std::forward<Args>(args)...);
}
template<typename Op>
@@ -136,7 +136,7 @@ struct ExprState
std::unique_ptr<Expr> negate(PosIdx pos, State & state)
{
std::vector<std::unique_ptr<Expr>> args(2);
args[0] = std::make_unique<ExprLiteral>(NewValueAs::integer, 0);
args[0] = std::make_unique<ExprLiteral>(pos, NewValueAs::integer, 0);
args[1] = popExprOnly();
return std::make_unique<ExprCall>(pos, state.mkInternalVar(pos, state.s.sub), std::move(args));
}
@@ -144,8 +144,8 @@ struct ExprState
void applyOp(PosIdx pos, auto & op, State & state) {
using Op = grammar::v1::op;
auto not_ = [] (auto e) {
return std::make_unique<ExprOpNot>(std::move(e));
auto not_ = [&] (auto e) {
return std::make_unique<ExprOpNot>(pos, std::move(e));
};
auto expr = (overloaded {
@@ -159,13 +159,13 @@ struct ExprState
[&] (Op::greater) { return order(pos, false, state); },
[&] (Op::less_eq) { return not_(order(pos, false, state)); },
[&] (Op::update) { return applyBinary<ExprOpUpdate>(pos); },
[&] (Op::not_) { return applyUnary<ExprOpNot>(); },
[&] (Op::not_) { return applyUnary<ExprOpNot>(pos); },
[&] (Op::plus) { return concatStrings(pos); },
[&] (Op::minus) { return call(pos, state, state.s.sub); },
[&] (Op::mul) { return call(pos, state, state.s.mul); },
[&] (Op::div) { return call(pos, state, state.s.div); },
[&] (Op::concat) { return applyBinary<ExprOpConcatLists>(pos); },
[&] (has_attr & a) { return applyUnary<ExprOpHasAttr>(std::move(a.path)); },
[&] (has_attr & a) { return applyUnary<ExprOpHasAttr>(pos, std::move(a.path)); },
[&] (Op::unary_minus) { return negate(pos, state); },
[&] (Op::pipe_right) { return pipe(pos, state, true); },
[&] (Op::pipe_left) { return pipe(pos, state); },
@@ -186,7 +186,7 @@ struct ExprState
template<typename ExprT, typename... Args>
inline ExprT & emplaceExpr(PosIdx pos, Args && ... args)
{
auto p = std::make_unique<ExprT>(std::forward<Args>(args)...);
auto p = std::make_unique<ExprT>(pos, std::forward<Args>(args)...);
auto & result = *p;
pushExpr(pos, std::move(p));
return result;
@@ -403,9 +403,9 @@ template<> struct BuildAST<grammar::v1::binding> {
template<> struct BuildAST<grammar::v1::expr::id> {
static void apply(const auto & in, ExprState & s, State & ps) {
if (in.string_view() == "__curPos")
s.emplaceExpr<ExprPos>(ps.at(in), ps.at(in));
s.emplaceExpr<ExprPos>(ps.at(in));
else
s.emplaceExpr<ExprVar>(ps.at(in), ps.at(in), ps.symbols.create(in.string_view()));
s.emplaceExpr<ExprVar>(ps.at(in), ps.symbols.create(in.string_view()));
}
};
@@ -418,7 +418,7 @@ template<> struct BuildAST<grammar::v1::expr::int_> {
.pos = ps.positions[ps.at(in)],
});
}
s.emplaceExpr<ExprLiteral>(noPos, NewValueAs::integer, v);
s.emplaceExpr<ExprLiteral>(ps.at(in), NewValueAs::integer, v);
}
};
@@ -453,7 +453,7 @@ template<> struct BuildAST<grammar::v1::expr::float_> {
});
}
}();
s.emplaceExpr<ExprLiteral>(noPos, NewValueAs::floating, v);
s.emplaceExpr<ExprLiteral>(ps.at(in), NewValueAs::floating, v);
}
};
@@ -502,7 +502,7 @@ struct StringState : SubexprState {
{
if (!currentLiteral.empty()) {
unescapeStr(currentLiteral);
parts.emplace_back(currentPos, std::make_unique<ExprString>(std::move(currentLiteral)));
parts.emplace_back(currentPos, std::make_unique<ExprString>(currentPos, std::move(currentLiteral)));
}
}
@@ -510,7 +510,7 @@ struct StringState : SubexprState {
{
if (parts.empty()) {
unescapeStr(currentLiteral);
return std::make_unique<ExprString>(std::move(currentLiteral));
return std::make_unique<ExprString>(currentPos, std::move(currentLiteral));
} else {
endLiteral();
auto pos = parts[0].first;
@@ -614,7 +614,7 @@ template<> struct BuildAST<grammar::v1::path::anchor> {
/* add back in the trailing '/' to the first segment */
if (in.string_view().ends_with('/') && in.size() > 1)
path += "/";
s.parts.emplace_back(ps.at(in), new ExprPath(std::move(path)));
s.parts.emplace_back(ps.at(in), new ExprPath(ps.at(in), std::move(path)));
}
};
@@ -623,7 +623,7 @@ template<> struct BuildAST<grammar::v1::path::home_anchor> {
if (evalSettings.pureEval)
throw Error("the path '%s' can not be resolved in pure mode", in.string_view());
Path path(getHome() + in.string_view().substr(1));
s.parts.emplace_back(ps.at(in), new ExprPath(std::move(path)));
s.parts.emplace_back(ps.at(in), new ExprPath(ps.at(in), std::move(path)));
}
};
@@ -636,7 +636,7 @@ template<> struct BuildAST<grammar::v1::path::searched_path> {
* (TODO: Provide a better and officially supported and documented mechanism for doing this)
*/
args[0] = std::make_unique<ExprVar>(pos, ps.s.nixPath);
args[1] = std::make_unique<ExprString>(in.string());
args[1] = std::make_unique<ExprString>(pos, in.string());
s.parts.emplace_back(
pos,
std::make_unique<ExprCall>(
@@ -670,7 +670,7 @@ template<> struct BuildAST<grammar::v1::path> : change_head<StringState> {
if (s.parts.size() == 1) {
e.pushExpr(noPos, std::move(s.parts.back().second));
} else {
e.emplaceExpr<ExprConcatStrings>(ps.at(in), ps.at(in), false, std::move(s.parts));
e.emplaceExpr<ExprConcatStrings>(ps.at(in), false, std::move(s.parts));
}
}
};
@@ -706,21 +706,21 @@ template<> struct BuildAST<grammar::v1::expr::ancient_let> : change_head<Binding
auto pos = ps.at(in);
b.set.pos = pos;
s.emplaceExpr<ExprSelect>(pos, pos, std::make_unique<ExprSet>(std::move(b.set)), pos, ps.s.body);
s.emplaceExpr<ExprSelect>(pos, std::make_unique<ExprSet>(std::move(b.set)), pos, ps.s.body);
}
};
template<> struct BuildAST<grammar::v1::expr::rec_set> : change_head<BindingsStateRecSet> {
static void success(const auto & in, BindingsStateRecSet & b, ExprState & s, State & ps) {
b.set.pos = ps.at(in);
s.emplaceExpr<ExprSet>(ps.at(in), std::move(b.set));
s.pushExpr(ps.at(in), std::make_unique<ExprSet>(std::move(b.set)));
}
};
template<> struct BuildAST<grammar::v1::expr::set> : change_head<BindingsStateSet> {
static void success(const auto & in, BindingsStateSet & b, ExprState & s, State & ps) {
b.set.pos = ps.at(in);
s.emplaceExpr<ExprSet>(ps.at(in), std::move(b.set));
s.pushExpr(ps.at(in), std::make_unique<ExprSet>(std::move(b.set)));
}
};
@@ -728,7 +728,7 @@ using ListState = std::vector<std::unique_ptr<Expr>>;
template<> struct BuildAST<grammar::v1::expr::list> : change_head<ListState> {
static void success(const auto & in, ListState & ls, ExprState & s, State & ps) {
auto e = std::make_unique<ExprList>();
auto e = std::make_unique<ExprList>(ps.at(in));
e->elems = std::move(ls);
s.pushExpr(ps.at(in), std::move(e));
}
@@ -755,7 +755,7 @@ template<> struct BuildAST<grammar::v1::expr::select::head> {
template<> struct BuildAST<grammar::v1::expr::select::attr> : change_head<AttrState> {
static void success0(AttrState & a, SelectState & s, State &) {
s.e = &s->emplaceExpr<ExprSelect>(s.pos, s.pos, s->popExprOnly(), std::move(a.attrs), nullptr);
s.e = &s->emplaceExpr<ExprSelect>(s.pos, s->popExprOnly(), std::move(a.attrs), nullptr);
}
};
@@ -769,7 +769,7 @@ template<> struct BuildAST<grammar::v1::expr::select::as_app_or> {
static void apply(const auto & in, SelectState & s, State & ps) {
std::vector<std::unique_ptr<Expr>> args(1);
args[0] = std::make_unique<ExprVar>(ps.at(in), ps.s.or_);
s->emplaceExpr<ExprCall>(s.pos, s.pos, s->popExprOnly(), std::move(args));
s->emplaceExpr<ExprCall>(s.pos, s->popExprOnly(), std::move(args));
}
};
@@ -803,7 +803,7 @@ template<> struct BuildAST<grammar::v1::expr::app::first_arg> {
} else {
std::vector<std::unique_ptr<Expr>> args{1};
args[0] = std::move(arg);
s.e = &s->emplaceExpr<ExprCall>(s.pos, s.pos, std::move(fn), std::move(args));
s.e = &s->emplaceExpr<ExprCall>(s.pos, std::move(fn), std::move(args));
}
}
};
@@ -839,21 +839,21 @@ template<> struct BuildAST<grammar::v1::expr::lambda> : change_head<LambdaState>
static void success(const auto & in, LambdaState & l, ExprState & s, State & ps) {
if (l.formals)
l.formals = ps.validateFormals(std::move(l.formals), ps.at(in), l.arg);
s.emplaceExpr<ExprLambda>(ps.at(in), ps.at(in), l.arg, std::move(l.formals), l->popExprOnly());
s.emplaceExpr<ExprLambda>(ps.at(in), l.arg, std::move(l.formals), l->popExprOnly());
}
};
template<> struct BuildAST<grammar::v1::expr::assert_> {
static void apply(const auto & in, ExprState & s, State & ps) {
auto body = s.popExprOnly(), cond = s.popExprOnly();
s.emplaceExpr<ExprAssert>(ps.at(in), ps.at(in), std::move(cond), std::move(body));
s.emplaceExpr<ExprAssert>(ps.at(in), std::move(cond), std::move(body));
}
};
template<> struct BuildAST<grammar::v1::expr::with> {
static void apply(const auto & in, ExprState & s, State & ps) {
auto body = s.popExprOnly(), scope = s.popExprOnly();
s.emplaceExpr<ExprWith>(ps.at(in), ps.at(in), std::move(scope), std::move(body));
s.emplaceExpr<ExprWith>(ps.at(in), std::move(scope), std::move(body));
}
};
@@ -865,14 +865,15 @@ template<> struct BuildAST<grammar::v1::expr::let> : change_head<BindingsStateLe
.pos = ps.positions[ps.at(in)]
});
b.let.body = b->popExprOnly();
s.emplaceExpr<ExprLet>(ps.at(in), std::move(b.let));
b.let.pos = ps.at(in);
s.pushExpr(ps.at(in), std::make_unique<ExprLet>(std::move(b.let)));
}
};
template<> struct BuildAST<grammar::v1::expr::if_> {
static void apply(const auto & in, ExprState & s, State & ps) {
auto else_ = s.popExprOnly(), then = s.popExprOnly(), cond = s.popExprOnly();
s.emplaceExpr<ExprIf>(ps.at(in), ps.at(in), std::move(cond), std::move(then), std::move(else_));
s.emplaceExpr<ExprIf>(ps.at(in), std::move(cond), std::move(then), std::move(else_));
}
};
+2 -2
View File
@@ -210,7 +210,7 @@ inline std::unique_ptr<Expr> State::stripIndentation(
* The rest of the code relies on the final string not being empty.
*/
if (lines.size() == 1 && lines.front().parts.empty()) {
return std::make_unique<ExprString>("");
return std::make_unique<ExprString>(pos, "");
}
/* If the last line only contains whitespace, trim it to not cause excessive whitespace.
@@ -251,7 +251,7 @@ inline std::unique_ptr<Expr> State::stripIndentation(
auto flush_merged = [&] () {
if (!merged.empty()) {
parts.emplace_back(merged_pos, std::make_unique<ExprString>(std::string(merged)));
parts.emplace_back(merged_pos, std::make_unique<ExprString>(pos, std::string(merged)));
merged.clear();
}
};
@@ -1,8 +1,8 @@
error:
… in the argument of the not operator
at /pwd/lang/eval-fail-not-throws.nix:1:4:
at /pwd/lang/eval-fail-not-throws.nix:1:1:
1| ! (throw "uh oh!")
| ^
| ^
2|
… caused by explicit throw
+4 -4
View File
@@ -90,7 +90,7 @@ TEST_F(ValuePrintingTests, tList)
TEST_F(ValuePrintingTests, vThunk)
{
Value vThunk;
ExprLiteral e(NewValueAs::integer, 0);
ExprLiteral e(noPos, NewValueAs::integer, 0);
vThunk.mkThunk(nullptr, e);
test(vThunk, "«thunk»");
@@ -113,7 +113,7 @@ TEST_F(ValuePrintingTests, vLambda)
PosTable::Origin origin = evaluator.positions.addOrigin(std::monostate(), 1);
auto posIdx = evaluator.positions.add(origin, 0);
ExprLambda eLambda(posIdx, createSymbol("a"), std::make_unique<Formals>(), std::make_unique<ExprLiteral>(NewValueAs::integer, 0));
ExprLambda eLambda(posIdx, createSymbol("a"), std::make_unique<Formals>(), std::make_unique<ExprLiteral>(noPos, NewValueAs::integer, 0));
Value vLambda;
vLambda.mkLambda(&env, &eLambda);
@@ -550,7 +550,7 @@ TEST_F(ValuePrintingTests, ansiColorsLambda)
PosTable::Origin origin = evaluator.positions.addOrigin(std::monostate(), 1);
auto posIdx = evaluator.positions.add(origin, 0);
ExprLambda eLambda(posIdx, createSymbol("a"), std::make_unique<Formals>(), std::make_unique<ExprLiteral>(NewValueAs::integer, 0));
ExprLambda eLambda(posIdx, createSymbol("a"), std::make_unique<Formals>(), std::make_unique<ExprLiteral>(noPos, NewValueAs::integer, 0));
Value vLambda;
vLambda.mkLambda(&env, &eLambda);
@@ -608,7 +608,7 @@ TEST_F(ValuePrintingTests, ansiColorsPrimOpApp)
TEST_F(ValuePrintingTests, ansiColorsThunk)
{
Value v;
ExprLiteral e(NewValueAs::integer, 0);
ExprLiteral e(noPos, NewValueAs::integer, 0);
v.mkThunk(nullptr, e);
test(v,