From c9b0a85b088b472eda9818dfaa0cc1a54124933c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 13 Dec 2022 16:00:44 +0100 Subject: [PATCH] Restore display of source lines for stdin/string inputs --- src/libexpr/nixexpr.cc | 73 +++++++++++++++++++----------------------- src/libexpr/nixexpr.hh | 9 +++--- src/libexpr/parser.y | 10 +++--- 3 files changed, 44 insertions(+), 48 deletions(-) diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index bdfb6457a..eb6f062b4 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -8,62 +8,55 @@ namespace nix { -struct SourcePathAdapter : AbstractPos +struct PosAdapter : AbstractPos { - Path path; + Pos::Origin origin; - SourcePathAdapter(Path path) - : path(std::move(path)) + PosAdapter(Pos::Origin origin) + : origin(std::move(origin)) { } std::optional getSource() const override { - try { - return readFile(path); - } catch (Error &) { - return std::nullopt; - } + return std::visit(overloaded { + [](const Pos::none_tag &) -> std::optional { + return std::nullopt; + }, + [](const Pos::Stdin & s) -> std::optional { + // Get rid of the null terminators added by the parser. + return std::string(s.source->c_str()); + }, + [](const Pos::String & s) -> std::optional { + // Get rid of the null terminators added by the parser. + return std::string(s.source->c_str()); + }, + [](const Path & path) -> std::optional { + try { + return readFile(path); + } catch (Error &) { + return std::nullopt; + } + } + }, origin); } void print(std::ostream & out) const override { - out << path; - } -}; - -struct StringPosAdapter : AbstractPos -{ - void print(std::ostream & out) const override - { - out << "«string»"; - } -}; - -struct StdinPosAdapter : AbstractPos -{ - void print(std::ostream & out) const override - { - out << "«stdin»"; + std::visit(overloaded { + [&](const Pos::none_tag &) { out << "«none»"; }, + [&](const Pos::Stdin &) { out << "«stdin»"; }, + [&](const Pos::String & s) { out << "«string»"; }, + [&](const Path & path) { out << path; } + }, origin); } }; Pos::operator std::shared_ptr() const { - std::shared_ptr pos; - - if (auto path = std::get_if(&origin)) - pos = std::make_shared(*path); - else if (std::get_if(&origin)) - pos = std::make_shared(); - else if (std::get_if(&origin)) - pos = std::make_shared(); - - if (pos) { - pos->line = line; - pos->column = column; - } - + auto pos = std::make_shared(origin); + pos->line = line; + pos->column = column; return pos; } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 0338a8c37..ac7ce021e 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -28,10 +28,11 @@ struct Pos uint32_t line; uint32_t column; - struct stdin_tag {}; - struct string_tag {}; + struct none_tag { }; + struct Stdin { ref source; }; + struct String { ref source; }; - typedef std::variant Origin; + typedef std::variant Origin; Origin origin; @@ -72,7 +73,7 @@ public: mutable uint32_t idx = std::numeric_limits::max(); // Used for searching in PosTable::[]. - explicit Origin(uint32_t idx): idx(idx), origin{Pos::stdin_tag()} {} + explicit Origin(uint32_t idx): idx(idx), origin{Pos::none_tag()} {} public: const Pos::Origin origin; diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index ea4e0bfb0..e07909f8e 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -713,10 +713,11 @@ Expr * EvalState::parseExprFromFile(const Path & path, std::shared_ptr & staticEnv) +Expr * EvalState::parseExprFromString(std::string s_, const Path & basePath, std::shared_ptr & staticEnv) { - s.append("\0\0", 2); - return parse(s.data(), s.size(), Pos::string_tag(), basePath, staticEnv); + auto s = make_ref(std::move(s_)); + s->append("\0\0", 2); + return parse(s->data(), s->size(), Pos::String{.source = s}, basePath, staticEnv); } @@ -732,7 +733,8 @@ 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(), Pos::stdin_tag(), absPath("."), staticBaseEnv); + auto s = make_ref(std::move(buffer)); + return parse(s->data(), s->size(), Pos::Stdin{.source = s}, absPath("."), staticBaseEnv); }