mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-22 14:06:16 +02:00
Connect AbstractPos with Pos
This commit is contained in:
parent
9e9170a92e
commit
72dffd6c6c
13 changed files with 95 additions and 119 deletions
|
@ -215,9 +215,8 @@ static std::ostream & showDebugTrace(std::ostream & out, const PosTable & positi
|
|||
: (std::shared_ptr<AbstractPos>) positions[dt.expr.getPos() ? dt.expr.getPos() : noPos];
|
||||
|
||||
if (pos) {
|
||||
pos->print(out);
|
||||
|
||||
if (auto loc = pos->getCodeLines()) {;
|
||||
out << pos;
|
||||
if (auto loc = pos->getCodeLines()) {
|
||||
out << "\n";
|
||||
printCodeLines(out, "", *pos, *loc);
|
||||
out << "\n";
|
||||
|
@ -584,7 +583,9 @@ bool NixRepl::processLine(std::string line)
|
|||
return {filename, 0};
|
||||
} else if (v.isLambda()) {
|
||||
auto pos = state->positions[v.lambda.fun->pos];
|
||||
return {pos.file, pos.line};
|
||||
// FIXME
|
||||
abort();
|
||||
//return {pos.file, pos.line};
|
||||
} else {
|
||||
// assume it's a derivation
|
||||
return findPackageFilename(*state, v, arg);
|
||||
|
|
|
@ -1081,9 +1081,9 @@ void EvalState::mkThunk_(Value & v, Expr * expr)
|
|||
void EvalState::mkPos(Value & v, PosIdx p)
|
||||
{
|
||||
auto pos = positions[p];
|
||||
if (!pos.file.empty()) {
|
||||
if (auto path = std::get_if<SourcePath>(&pos.origin)) {
|
||||
auto attrs = buildBindings(3);
|
||||
attrs.alloc(sFile).mkString(pos.file);
|
||||
attrs.alloc(sFile).mkString(path->path.abs());
|
||||
attrs.alloc(sLine).mkInt(pos.line);
|
||||
attrs.alloc(sColumn).mkInt(pos.column);
|
||||
v.mkAttrs(attrs);
|
||||
|
@ -1450,7 +1450,8 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
|||
|
||||
} catch (Error & e) {
|
||||
auto pos2r = state.positions[pos2];
|
||||
if (pos2 && pos2r.file != state.derivationNixPath)
|
||||
// FIXME: use MemoryAccessor
|
||||
if (pos2 /* && pos2r.origin != Pos(state.derivationNixPath) */)
|
||||
state.addErrorTrace(e, pos2, "while evaluating the attribute '%1%'",
|
||||
showAttrPath(state, env, attrPath));
|
||||
throw;
|
||||
|
@ -2465,7 +2466,8 @@ void EvalState::printStats()
|
|||
else
|
||||
obj.attr("name", nullptr);
|
||||
if (auto pos = positions[i.first->pos]) {
|
||||
obj.attr("file", (const std::string &) pos.file);
|
||||
// FIXME
|
||||
//obj.attr("file", (const std::string &) pos.file);
|
||||
obj.attr("line", pos.line);
|
||||
obj.attr("column", pos.column);
|
||||
}
|
||||
|
@ -2477,7 +2479,8 @@ void EvalState::printStats()
|
|||
for (auto & i : attrSelects) {
|
||||
auto obj = list.object();
|
||||
if (auto pos = positions[i.first]) {
|
||||
obj.attr("file", (const std::string &) pos.file);
|
||||
// FIXME
|
||||
//obj.attr("file", (const std::string &) pos.file);
|
||||
obj.attr("line", pos.line);
|
||||
obj.attr("column", pos.column);
|
||||
}
|
||||
|
|
|
@ -453,8 +453,7 @@ private:
|
|||
Expr * parse(
|
||||
char * text,
|
||||
size_t length,
|
||||
FileOrigin origin,
|
||||
const PathView path,
|
||||
Pos::Origin origin,
|
||||
const SourcePath & basePath,
|
||||
std::shared_ptr<StaticEnv> & staticEnv);
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ static Flake readFlake(
|
|||
Value vInfo;
|
||||
state.evalFile(flakePath, vInfo, true);
|
||||
|
||||
expectType(state, nAttrs, vInfo, state.positions.add({flakePath.to_string(), foFile}, 0, 0));
|
||||
expectType(state, nAttrs, vInfo, state.positions.add(Pos::Origin(rootDir), 1, 1));
|
||||
|
||||
Flake flake {
|
||||
.originalRef = originalRef,
|
||||
|
|
|
@ -10,16 +10,27 @@ namespace nix {
|
|||
|
||||
struct SourcePathAdapter : AbstractPos
|
||||
{
|
||||
std::string file;
|
||||
SourcePath path;
|
||||
ref<InputAccessor> hack; // FIXME: remove
|
||||
|
||||
SourcePathAdapter(SourcePath path)
|
||||
: path(std::move(path))
|
||||
, hack(path.accessor.shared_from_this())
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<std::string> getSource() const override
|
||||
{
|
||||
return std::nullopt;
|
||||
try {
|
||||
return path.readFile();
|
||||
} catch (Error &) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
void print(std::ostream & out) const override
|
||||
{
|
||||
out << fmt(ANSI_BLUE "at " ANSI_WARNING "%s:%s" ANSI_NORMAL ":", file, showErrPos());
|
||||
out << path;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -27,7 +38,7 @@ struct StringPosAdapter : AbstractPos
|
|||
{
|
||||
void print(std::ostream & out) const override
|
||||
{
|
||||
out << fmt(ANSI_BLUE "at " ANSI_WARNING "«string»:%s" ANSI_NORMAL ":", showErrPos());
|
||||
out << "«string»";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -35,35 +46,27 @@ struct StdinPosAdapter : AbstractPos
|
|||
{
|
||||
void print(std::ostream & out) const override
|
||||
{
|
||||
out << fmt(ANSI_BLUE "at " ANSI_WARNING "«stdin»:%s" ANSI_NORMAL ":", showErrPos());
|
||||
out << "«stdin»";
|
||||
}
|
||||
};
|
||||
|
||||
Pos::operator std::shared_ptr<AbstractPos>() const
|
||||
{
|
||||
if (!line) return nullptr;
|
||||
std::shared_ptr<AbstractPos> pos;
|
||||
|
||||
switch (origin) {
|
||||
case foFile: {
|
||||
auto pos = std::make_shared<SourcePathAdapter>();
|
||||
if (auto path = std::get_if<SourcePath>(&origin))
|
||||
pos = std::make_shared<SourcePathAdapter>(*path);
|
||||
else if (std::get_if<stdin_tag>(&origin))
|
||||
pos = std::make_shared<StdinPosAdapter>();
|
||||
else if (std::get_if<string_tag>(&origin))
|
||||
pos = std::make_shared<StringPosAdapter>();
|
||||
|
||||
if (pos) {
|
||||
pos->line = line;
|
||||
pos->column = column;
|
||||
pos->file = file;
|
||||
return pos;
|
||||
}
|
||||
case foStdin: {
|
||||
auto pos = std::make_shared<StdinPosAdapter>();
|
||||
pos->line = line;
|
||||
pos->column = column;
|
||||
return pos;
|
||||
}
|
||||
case foString:
|
||||
auto pos = std::make_shared<StringPosAdapter>();
|
||||
pos->line = line;
|
||||
pos->column = column;
|
||||
return pos;
|
||||
}
|
||||
assert(false);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/* Displaying abstract syntax trees. */
|
||||
|
@ -306,24 +309,10 @@ void ExprPos::show(const SymbolTable & symbols, std::ostream & str) const
|
|||
|
||||
std::ostream & operator << (std::ostream & str, const Pos & pos)
|
||||
{
|
||||
if (!pos)
|
||||
if (auto pos2 = (std::shared_ptr<AbstractPos>) pos) {
|
||||
str << *pos2;
|
||||
} else
|
||||
str << "undefined position";
|
||||
else
|
||||
{
|
||||
auto f = format(ANSI_BOLD "%1%" ANSI_NORMAL ":%2%:%3%");
|
||||
switch (pos.origin) {
|
||||
case foFile:
|
||||
f % (const std::string &) pos.file;
|
||||
break;
|
||||
case foStdin:
|
||||
case foString:
|
||||
f % "(string)";
|
||||
break;
|
||||
default:
|
||||
throw Error("unhandled Pos origin!");
|
||||
}
|
||||
str << (f % pos.line % pos.column).str();
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
|
@ -21,21 +21,20 @@ MakeError(TypeError, EvalError);
|
|||
MakeError(UndefinedVarError, Error);
|
||||
MakeError(MissingArgumentError, EvalError);
|
||||
|
||||
// FIXME: change this into a variant?
|
||||
typedef enum {
|
||||
foFile,
|
||||
foStdin,
|
||||
foString
|
||||
} FileOrigin;
|
||||
|
||||
/* Position objects. */
|
||||
struct Pos
|
||||
{
|
||||
std::string file;
|
||||
FileOrigin origin;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
|
||||
struct no_pos_tag {};
|
||||
struct stdin_tag {};
|
||||
struct string_tag {};
|
||||
|
||||
typedef std::variant<no_pos_tag, stdin_tag, string_tag, SourcePath> Origin;
|
||||
|
||||
Origin origin;
|
||||
|
||||
explicit operator bool() const { return line > 0; }
|
||||
|
||||
operator std::shared_ptr<AbstractPos>() const;
|
||||
|
@ -68,13 +67,12 @@ public:
|
|||
// current origins.back() can be reused or not.
|
||||
mutable uint32_t idx = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
explicit Origin(uint32_t idx): idx(idx), file{}, origin{} {}
|
||||
explicit Origin(uint32_t idx): idx(idx), origin{Pos::no_pos_tag()} {}
|
||||
|
||||
public:
|
||||
const std::string file;
|
||||
const FileOrigin origin;
|
||||
const Pos::Origin origin;
|
||||
|
||||
Origin(std::string file, FileOrigin origin): file(std::move(file)), origin(origin) {}
|
||||
Origin(Pos::Origin origin): origin(origin) {}
|
||||
};
|
||||
|
||||
struct Offset {
|
||||
|
@ -114,7 +112,7 @@ public:
|
|||
[] (const auto & a, const auto & b) { return a.idx < b.idx; });
|
||||
const auto origin = *std::prev(pastOrigin);
|
||||
const auto offset = offsets[idx];
|
||||
return {origin.file, origin.origin, offset.line, offset.column};
|
||||
return {offset.line, offset.column, origin.origin};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -648,30 +648,16 @@ namespace nix {
|
|||
Expr * EvalState::parse(
|
||||
char * text,
|
||||
size_t length,
|
||||
FileOrigin origin,
|
||||
const PathView path,
|
||||
Pos::Origin origin,
|
||||
const SourcePath & basePath,
|
||||
std::shared_ptr<StaticEnv> & staticEnv)
|
||||
{
|
||||
yyscan_t scanner;
|
||||
std::string file;
|
||||
switch (origin) {
|
||||
case foFile:
|
||||
// FIXME: change this to a SourcePath.
|
||||
file = path;
|
||||
break;
|
||||
case foStdin:
|
||||
case foString:
|
||||
file = text;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
ParseData data {
|
||||
.state = *this,
|
||||
.symbols = symbols,
|
||||
.basePath = basePath,
|
||||
.origin = {file, origin},
|
||||
.origin = {origin},
|
||||
};
|
||||
|
||||
yylex_init(&scanner);
|
||||
|
@ -713,14 +699,14 @@ Expr * EvalState::parseExprFromFile(const SourcePath & path, std::shared_ptr<Sta
|
|||
// readFile hopefully have left some extra space for terminators
|
||||
buffer.append("\0\0", 2);
|
||||
// FIXME: pass SourcePaths
|
||||
return parse(buffer.data(), buffer.size(), foFile, path.path.abs(), path.parent(), staticEnv);
|
||||
return parse(buffer.data(), buffer.size(), Pos::Origin(path), path.parent(), staticEnv);
|
||||
}
|
||||
|
||||
|
||||
Expr * EvalState::parseExprFromString(std::string s, const SourcePath & basePath, std::shared_ptr<StaticEnv> & staticEnv)
|
||||
{
|
||||
s.append("\0\0", 2);
|
||||
return parse(s.data(), s.size(), foString, "", basePath, staticEnv);
|
||||
return parse(s.data(), s.size(), Pos::string_tag(), basePath, staticEnv);
|
||||
}
|
||||
|
||||
|
||||
|
@ -736,7 +722,7 @@ Expr * EvalState::parseStdin()
|
|||
auto buffer = drainFD(0);
|
||||
// drainFD should have left some extra space for terminators
|
||||
buffer.append("\0\0", 2);
|
||||
return parse(buffer.data(), buffer.size(), foStdin, "", rootPath(absPath(".")), staticBaseEnv);
|
||||
return parse(buffer.data(), buffer.size(), Pos::stdin_tag(), rootPath(absPath(".")), staticBaseEnv);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -368,8 +368,8 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
|||
auto output = runProgram(program, true, commandArgs);
|
||||
Expr * parsed;
|
||||
try {
|
||||
auto base = state.positions[pos];
|
||||
parsed = state.parseExprFromString(std::move(output), state.rootPath(base.file));
|
||||
//auto base = state.positions[pos];
|
||||
parsed = state.parseExprFromString(std::move(output), state.rootPath("/"));
|
||||
} catch (Error & e) {
|
||||
e.addTrace(state.positions[pos], "While parsing the output from '%1%'", program);
|
||||
throw;
|
||||
|
@ -3979,6 +3979,7 @@ void EvalState::createBaseEnv()
|
|||
|
||||
/* Add a wrapper around the derivation primop that computes the
|
||||
`drvPath' and `outPath' attributes lazily. */
|
||||
// FIXME: use corepkgsFS.
|
||||
sDerivationNix = symbols.create(derivationNixPath);
|
||||
auto vDerivation = allocValue();
|
||||
addConstant("derivation", vDerivation);
|
||||
|
@ -3996,7 +3997,7 @@ void EvalState::createBaseEnv()
|
|||
// the parser needs two NUL bytes as terminators; one of them
|
||||
// is implied by being a C string.
|
||||
"\0";
|
||||
eval(parse(code, sizeof(code), foFile, derivationNixPath, rootPath("/"), staticBaseEnv), *vDerivation);
|
||||
eval(parse(code, sizeof(code), Pos::string_tag(), rootPath("/"), staticBaseEnv), *vDerivation);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,8 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
|||
|
||||
static void posToXML(EvalState & state, XMLAttrs & xmlAttrs, const Pos & pos)
|
||||
{
|
||||
xmlAttrs["path"] = pos.file;
|
||||
// FIXME
|
||||
//xmlAttrs["path"] = pos.file;
|
||||
xmlAttrs["line"] = (format("%1%") % pos.line).str();
|
||||
xmlAttrs["column"] = (format("%1%") % pos.column).str();
|
||||
}
|
||||
|
|
|
@ -35,13 +35,13 @@ std::ostream & operator<<(std::ostream & os, const hintformat & hf)
|
|||
return os << hf.str();
|
||||
}
|
||||
|
||||
std::string AbstractPos::showErrPos() const
|
||||
std::ostream & operator << (std::ostream & str, const AbstractPos & pos)
|
||||
{
|
||||
if (column > 0) {
|
||||
return fmt("%d:%d", line, column);
|
||||
} else {
|
||||
return fmt("%d", line);
|
||||
}
|
||||
pos.print(str);
|
||||
str << ":" << pos.line;
|
||||
if (pos.column > 0)
|
||||
str << ":" << pos.column;
|
||||
return str;
|
||||
}
|
||||
|
||||
std::optional<LinesOfCode> AbstractPos::getCodeLines() const
|
||||
|
@ -202,8 +202,7 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
|||
auto noSource = ANSI_ITALIC " (source not available)" ANSI_NORMAL "\n";
|
||||
|
||||
if (einfo.errPos) {
|
||||
oss << "\n";
|
||||
einfo.errPos->print(oss);
|
||||
oss << "\n" << ANSI_BLUE << "at " ANSI_WARNING << *einfo.errPos << ANSI_NORMAL << ":";
|
||||
|
||||
if (auto loc = einfo.errPos->getCodeLines()) {
|
||||
oss << "\n";
|
||||
|
@ -226,8 +225,7 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
|||
oss << "\n" << "… " << iter->hint.str() << "\n";
|
||||
|
||||
if (iter->pos) {
|
||||
oss << "\n";
|
||||
iter->pos->print(oss);
|
||||
oss << "\n" << ANSI_BLUE << "at " ANSI_WARNING << *iter->pos << ANSI_NORMAL << ":";
|
||||
|
||||
if (auto loc = iter->pos->getCodeLines()) {
|
||||
oss << "\n";
|
||||
|
|
|
@ -73,11 +73,11 @@ struct AbstractPos
|
|||
|
||||
virtual void print(std::ostream & out) const = 0;
|
||||
|
||||
std::string showErrPos() const;
|
||||
|
||||
std::optional<LinesOfCode> getCodeLines() const;
|
||||
};
|
||||
|
||||
std::ostream & operator << (std::ostream & str, const AbstractPos & pos);
|
||||
|
||||
void printCodeLines(std::ostream & out,
|
||||
const std::string & prefix,
|
||||
const AbstractPos & errPos,
|
||||
|
|
|
@ -11,7 +11,7 @@ expect_trace() {
|
|||
--expr "$expr" 2>&1 \
|
||||
| grep "function-trace" \
|
||||
| sed -e 's/ [0-9]*$//'
|
||||
);
|
||||
)
|
||||
|
||||
echo -n "Tracing expression '$expr'"
|
||||
set +e
|
||||
|
@ -32,40 +32,40 @@ expect_trace() {
|
|||
|
||||
# failure inside a tryEval
|
||||
expect_trace 'builtins.tryEval (throw "example")' "
|
||||
function-trace entered (string):1:1 at
|
||||
function-trace entered (string):1:19 at
|
||||
function-trace exited (string):1:19 at
|
||||
function-trace exited (string):1:1 at
|
||||
function-trace entered «string»:1:1 at
|
||||
function-trace entered «string»:1:19 at
|
||||
function-trace exited «string»:1:19 at
|
||||
function-trace exited «string»:1:1 at
|
||||
"
|
||||
|
||||
# Missing argument to a formal function
|
||||
expect_trace '({ x }: x) { }' "
|
||||
function-trace entered (string):1:1 at
|
||||
function-trace exited (string):1:1 at
|
||||
function-trace entered «string»:1:1 at
|
||||
function-trace exited «string»:1:1 at
|
||||
"
|
||||
|
||||
# Too many arguments to a formal function
|
||||
expect_trace '({ x }: x) { x = "x"; y = "y"; }' "
|
||||
function-trace entered (string):1:1 at
|
||||
function-trace exited (string):1:1 at
|
||||
function-trace entered «string»:1:1 at
|
||||
function-trace exited «string»:1:1 at
|
||||
"
|
||||
|
||||
# Not enough arguments to a lambda
|
||||
expect_trace '(x: y: x + y) 1' "
|
||||
function-trace entered (string):1:1 at
|
||||
function-trace exited (string):1:1 at
|
||||
function-trace entered «string»:1:1 at
|
||||
function-trace exited «string»:1:1 at
|
||||
"
|
||||
|
||||
# Too many arguments to a lambda
|
||||
expect_trace '(x: x) 1 2' "
|
||||
function-trace entered (string):1:1 at
|
||||
function-trace exited (string):1:1 at
|
||||
function-trace entered «string»:1:1 at
|
||||
function-trace exited «string»:1:1 at
|
||||
"
|
||||
|
||||
# Not a function
|
||||
expect_trace '1 2' "
|
||||
function-trace entered (string):1:1 at
|
||||
function-trace exited (string):1:1 at
|
||||
function-trace entered «string»:1:1 at
|
||||
function-trace exited «string»:1:1 at
|
||||
"
|
||||
|
||||
set -e
|
||||
|
|
|
@ -17,10 +17,10 @@ nix-env -q --foo 2>&1 | grep "unknown flag"
|
|||
|
||||
# Eval Errors.
|
||||
eval_arg_res=$(nix-instantiate --eval -E 'let a = {} // a; in a.foo' 2>&1 || true)
|
||||
echo $eval_arg_res | grep "at «string»:1:15:"
|
||||
echo $eval_arg_res | grep "at «string»:1:15"
|
||||
echo $eval_arg_res | grep "infinite recursion encountered"
|
||||
|
||||
eval_stdin_res=$(echo 'let a = {} // a; in a.foo' | nix-instantiate --eval -E - 2>&1 || true)
|
||||
echo $eval_stdin_res | grep "at «stdin»:1:15:"
|
||||
echo $eval_stdin_res | grep "at «stdin»:1:15"
|
||||
echo $eval_stdin_res | grep "infinite recursion encountered"
|
||||
|
||||
|
|
Loading…
Reference in a new issue