Update primops/fromTOML.cc to use toml11

This commit is contained in:
Nicolas Mattia 2021-12-17 22:03:48 +01:00
parent c3f68b5db7
commit 10a8b5d3ae

View file

@ -1,86 +1,79 @@
#include "primops.hh" #include "primops.hh"
#include "eval-inline.hh" #include "eval-inline.hh"
#include "../../cpptoml/cpptoml.h" #include "../../toml11/toml.hpp"
namespace nix { namespace nix {
static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Value & v) static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Value & val)
{ {
using namespace cpptoml;
auto toml = state.forceStringNoCtx(*args[0], pos); auto toml = state.forceStringNoCtx(*args[0], pos);
std::istringstream tomlStream(toml); std::istringstream tomlStream(toml);
std::function<void(Value &, std::shared_ptr<base>)> visit; std::function<void(Value &, toml::value)> visit;
visit = [&](Value & v, std::shared_ptr<base> t) { visit = [&](Value & v, toml::value t) {
if (auto t2 = t->as_table()) { switch(t.type())
{
case toml::value_t::table:
{
auto table = toml::get<toml::table>(t);
size_t size = 0; size_t size = 0;
for (auto & i : *t2) { (void) i; size++; } for (auto & i : table) { (void) i; size++; }
state.mkAttrs(v, size); state.mkAttrs(v, size);
for (auto & i : *t2) { for(auto & elem: table) {
auto & v2 = *state.allocAttr(v, state.symbols.create(i.first));
if (auto i2 = i.second->as_table_array()) { auto & v2 = *state.allocAttr(v, state.symbols.create(elem.first));
size_t size2 = i2->get().size();
state.mkList(v2, size2); // TODO: note about creating children here in old code
for (size_t j = 0; j < size2; ++j) visit(v2, elem.second);
visit(*(v2.listElems()[j] = state.allocValue()), i2->get()[j]); }
} }
else break;;
visit(v2, i.second); case toml::value_t::array:
} {
auto array = toml::get<std::vector<toml::value>>(t);
size_t size = array.size();
state.mkList(v, size);
for (size_t i = 0; i < size; ++i)
visit(*(v.listElems()[i] = state.allocValue()), array[i]);
}
break;;
case toml::value_t::boolean:
mkBool(v, toml::get<bool>(t));
break;;
case toml::value_t::integer:
mkInt(v, toml::get<int>(t));
break;;
case toml::value_t::floating:
mkFloat(v, toml::get<double>(t));
break;;
case toml::value_t::string:
mkString(v, toml::get<std::string>(t));
break;;
case toml::value_t::local_datetime:
case toml::value_t::offset_datetime:
case toml::value_t::local_date:
case toml::value_t::local_time:
// TODO: convert to string?
throw std::runtime_error("Dates and times are not supported");
break;;
case toml::value_t::empty:
mkNull(v);
break;;
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 { try {
visit(v, parser(tomlStream).parse()); visit(val, toml::parse(tomlStream)); // TODO give filename
} catch (std::runtime_error & e) { } catch (std::exception & e) { // TODO: toml::syntax_error
throw EvalError({ throw EvalError({
.msg = hintfmt("while parsing a TOML string: %s", e.what()), .msg = hintfmt("while parsing a TOML string: %s", e.what()),
.errPos = pos .errPos = pos