init
This commit is contained in:
commit
0e5218513e
4 changed files with 128 additions and 0 deletions
52
scope.cc
Normal file
52
scope.cc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include <nix/expr/primops.hh>
|
||||
#include <nix/expr/eval.hh>
|
||||
#include <nix/expr/eval-inline.hh>
|
||||
#include <nix/expr/nixexpr.hh>
|
||||
#include <nix/expr/attr-set.hh>
|
||||
|
||||
using namespace nix;
|
||||
|
||||
static void prim_scope(EvalState & state, const PosIdx pos, Value ** args, Value & v)
|
||||
{
|
||||
std::vector<Symbol> path;
|
||||
|
||||
state.forceStringNoCtx(*args[0], pos, "'scope' path argument");
|
||||
auto s = std::string(args[0]->string_view());
|
||||
if (s.empty())
|
||||
state.error<TypeError>("'scope' requires a non-empty path")
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
size_t start = 0;
|
||||
while (start < s.size()) {
|
||||
auto dot = s.find('.', start);
|
||||
if (dot == std::string::npos) {
|
||||
path.push_back(state.symbols.create(s.substr(start)));
|
||||
break;
|
||||
}
|
||||
path.push_back(state.symbols.create(s.substr(start, dot - start)));
|
||||
start = dot + 1;
|
||||
}
|
||||
|
||||
// Build nested attrset from inside out
|
||||
// Given path [a, b, c] and value v: { a = { b = { c = v; }; }; }
|
||||
Value * inner = args[1];
|
||||
for (auto it = path.rbegin(); it != path.rend(); ++it) {
|
||||
auto attrs = state.buildBindings(1);
|
||||
attrs.insert(*it, inner);
|
||||
Value * wrapper = state.allocValue();
|
||||
wrapper->mkAttrs(attrs.finish());
|
||||
inner = wrapper;
|
||||
}
|
||||
v = *inner;
|
||||
}
|
||||
|
||||
static RegisterPrimOp rp({
|
||||
.name = "scope",
|
||||
.args = {"path", "value"},
|
||||
.doc = R"(
|
||||
Construct a nested attribute set from a dotted string path and a value.
|
||||
|
||||
Example: `scope "a.b.c" 42` evaluates to `{ a = { b = { c = 42; }; }; }`.
|
||||
)",
|
||||
.fun = prim_scope,
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue