mirror of
https://github.com/NixOS/nix.git
synced 2025-11-16 07:22:43 +01:00
Changes:
* The divider lines are gone. These were in practice a bit confusing,
in particular with --show-trace or --keep-going, since then there
were multiple lines, suggesting a start/end which wasn't the case.
* Instead, multi-line error messages are now indented to align with
the prefix (e.g. "error: ").
* The 'description' field is gone since we weren't really using it.
* 'hint' is renamed to 'msg' since it really wasn't a hint.
* The error is now printed *before* the location info.
* The 'name' field is no longer printed since most of the time it
wasn't very useful since it was just the name of the exception (like
EvalError). Ideally in the future this would be a unique, easily
googleable error ID (like rustc).
* "trace:" is now just "…". This assumes error contexts start with
something like "while doing X".
Example before:
error: --- AssertionError ---------------------------------------------------------------------------------------- nix
at: (7:7) in file: /home/eelco/Dev/nixpkgs/pkgs/applications/misc/hello/default.nix
6|
7| x = assert false; 1;
| ^
8|
assertion 'false' failed
----------------------------------------------------- show-trace -----------------------------------------------------
trace: while evaluating the attribute 'x' of the derivation 'hello-2.10'
at: (192:11) in file: /home/eelco/Dev/nixpkgs/pkgs/stdenv/generic/make-derivation.nix
191| // (lib.optionalAttrs (!(attrs ? name) && attrs ? pname && attrs ? version)) {
192| name = "${attrs.pname}-${attrs.version}";
| ^
193| } // (lib.optionalAttrs (stdenv.hostPlatform != stdenv.buildPlatform && !dontAddHostSuffix && (attrs ? name || (attrs ? pname && attrs ? version)))) {
Example after:
error: assertion 'false' failed
at: (7:7) in file: /home/eelco/Dev/nixpkgs/pkgs/applications/misc/hello/default.nix
6|
7| x = assert false; 1;
| ^
8|
… while evaluating the attribute 'x' of the derivation 'hello-2.10'
at: (192:11) in file: /home/eelco/Dev/nixpkgs/pkgs/stdenv/generic/make-derivation.nix
191| // (lib.optionalAttrs (!(attrs ? name) && attrs ? pname && attrs ? version)) {
192| name = "${attrs.pname}-${attrs.version}";
| ^
193| } // (lib.optionalAttrs (stdenv.hostPlatform != stdenv.buildPlatform && !dontAddHostSuffix && (attrs ? name || (attrs ? pname && attrs ? version)))) {
93 lines
2.7 KiB
C++
93 lines
2.7 KiB
C++
#include "primops.hh"
|
|
#include "eval-inline.hh"
|
|
|
|
#include "../../cpptoml/cpptoml.h"
|
|
|
|
namespace nix {
|
|
|
|
static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
|
{
|
|
using namespace cpptoml;
|
|
|
|
auto toml = state.forceStringNoCtx(*args[0], pos);
|
|
|
|
std::istringstream tomlStream(toml);
|
|
|
|
std::function<void(Value &, std::shared_ptr<base>)> visit;
|
|
|
|
visit = [&](Value & v, std::shared_ptr<base> t) {
|
|
|
|
if (auto t2 = t->as_table()) {
|
|
|
|
size_t size = 0;
|
|
for (auto & i : *t2) { (void) i; size++; }
|
|
|
|
state.mkAttrs(v, size);
|
|
|
|
for (auto & i : *t2) {
|
|
auto & v2 = *state.allocAttr(v, state.symbols.create(i.first));
|
|
|
|
if (auto i2 = i.second->as_table_array()) {
|
|
size_t size2 = i2->get().size();
|
|
state.mkList(v2, size2);
|
|
for (size_t j = 0; j < size2; ++j)
|
|
visit(*(v2.listElems()[j] = state.allocValue()), i2->get()[j]);
|
|
}
|
|
else
|
|
visit(v2, i.second);
|
|
}
|
|
|
|
v.attrs->sort();
|
|
}
|
|
|
|
else if (auto t2 = t->as_array()) {
|
|
size_t size = t2->get().size();
|
|
|
|
state.mkList(v, size);
|
|
|
|
for (size_t i = 0; i < size; ++i)
|
|
visit(*(v.listElems()[i] = state.allocValue()), t2->get()[i]);
|
|
}
|
|
|
|
// Handle cases like 'a = [[{ a = true }]]', which IMHO should be
|
|
// parsed as a array containing an array containing a table,
|
|
// but instead are parsed as an array containing a table array
|
|
// containing a table.
|
|
else if (auto t2 = t->as_table_array()) {
|
|
size_t size = t2->get().size();
|
|
|
|
state.mkList(v, size);
|
|
|
|
for (size_t j = 0; j < size; ++j)
|
|
visit(*(v.listElems()[j] = state.allocValue()), t2->get()[j]);
|
|
}
|
|
|
|
else if (t->is_value()) {
|
|
if (auto val = t->as<int64_t>())
|
|
mkInt(v, val->get());
|
|
else if (auto val = t->as<NixFloat>())
|
|
mkFloat(v, val->get());
|
|
else if (auto val = t->as<bool>())
|
|
mkBool(v, val->get());
|
|
else if (auto val = t->as<std::string>())
|
|
mkString(v, val->get());
|
|
else
|
|
throw EvalError("unsupported value type in TOML");
|
|
}
|
|
|
|
else abort();
|
|
};
|
|
|
|
try {
|
|
visit(v, parser(tomlStream).parse());
|
|
} catch (std::runtime_error & e) {
|
|
throw EvalError({
|
|
.msg = hintfmt("while parsing a TOML string: %s", e.what()),
|
|
.errPos = pos
|
|
});
|
|
}
|
|
}
|
|
|
|
static RegisterPrimOp primop_fromTOML("fromTOML", 1, prim_fromTOML);
|
|
|
|
}
|