forked from lix-project/lix
Update primops/fromTOML.cc to use toml11
This commit is contained in:
parent
c3f68b5db7
commit
10a8b5d3ae
|
@ -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
|
|
||||||
visit(v2, i.second);
|
|
||||||
}
|
}
|
||||||
|
break;;
|
||||||
|
case toml::value_t::array:
|
||||||
|
{
|
||||||
|
auto array = toml::get<std::vector<toml::value>>(t);
|
||||||
|
|
||||||
v.attrs->sort();
|
size_t size = array.size();
|
||||||
}
|
|
||||||
|
|
||||||
else if (auto t2 = t->as_array()) {
|
|
||||||
size_t size = t2->get().size();
|
|
||||||
|
|
||||||
state.mkList(v, size);
|
state.mkList(v, size);
|
||||||
|
|
||||||
for (size_t i = 0; i < size; ++i)
|
for (size_t i = 0; i < size; ++i)
|
||||||
visit(*(v.listElems()[i] = state.allocValue()), t2->get()[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;;
|
||||||
|
|
||||||
// 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
|
||||||
|
|
Loading…
Reference in a new issue