forked from lix-project/lix
Merge pull request #5864 from edolstra/attr-sets-cleanup
Attrset improvements
This commit is contained in:
commit
6d7844695b
|
@ -7,26 +7,19 @@
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Allocate a new array of attributes for an attribute set with a specific
|
/* Allocate a new array of attributes for an attribute set with a specific
|
||||||
capacity. The space is implicitly reserved after the Bindings
|
capacity. The space is implicitly reserved after the Bindings
|
||||||
structure. */
|
structure. */
|
||||||
Bindings * EvalState::allocBindings(size_t capacity)
|
Bindings * EvalState::allocBindings(size_t capacity)
|
||||||
{
|
{
|
||||||
|
if (capacity == 0)
|
||||||
|
return &emptyBindings;
|
||||||
if (capacity > std::numeric_limits<Bindings::size_t>::max())
|
if (capacity > std::numeric_limits<Bindings::size_t>::max())
|
||||||
throw Error("attribute set of size %d is too big", capacity);
|
throw Error("attribute set of size %d is too big", capacity);
|
||||||
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void EvalState::mkAttrs(Value & v, size_t capacity)
|
|
||||||
{
|
|
||||||
if (capacity == 0) {
|
|
||||||
v = vEmptySet;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
v.mkAttrs(allocBindings(capacity));
|
|
||||||
nrAttrsets++;
|
nrAttrsets++;
|
||||||
nrAttrsInAttrsets += capacity;
|
nrAttrsInAttrsets += capacity;
|
||||||
|
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,15 +34,36 @@ Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Value * EvalState::allocAttr(Value & vAttrs, const std::string & name)
|
Value * EvalState::allocAttr(Value & vAttrs, std::string_view name)
|
||||||
{
|
{
|
||||||
return allocAttr(vAttrs, symbols.create(name));
|
return allocAttr(vAttrs, symbols.create(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value & BindingsBuilder::alloc(const Symbol & name, ptr<Pos> pos)
|
||||||
|
{
|
||||||
|
auto value = state.allocValue();
|
||||||
|
bindings->push_back(Attr(name, value, pos));
|
||||||
|
return *value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value & BindingsBuilder::alloc(std::string_view name, ptr<Pos> pos)
|
||||||
|
{
|
||||||
|
return alloc(state.symbols.create(name), pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Bindings::sort()
|
void Bindings::sort()
|
||||||
{
|
{
|
||||||
std::sort(begin(), end());
|
if (size_) std::sort(begin(), end());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value & Value::mkAttrs(BindingsBuilder & bindings)
|
||||||
|
{
|
||||||
|
mkAttrs(bindings.finish());
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -113,5 +113,45 @@ public:
|
||||||
friend class EvalState;
|
friend class EvalState;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* A wrapper around Bindings that ensures that its always in sorted
|
||||||
|
order at the end. The only way to consume a BindingsBuilder is to
|
||||||
|
call finish(), which sorts the bindings. */
|
||||||
|
class BindingsBuilder
|
||||||
|
{
|
||||||
|
Bindings * bindings;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
EvalState & state;
|
||||||
|
|
||||||
|
BindingsBuilder(EvalState & state, Bindings * bindings)
|
||||||
|
: bindings(bindings), state(state)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void insert(Symbol name, Value * value, ptr<Pos> pos = ptr(&noPos))
|
||||||
|
{
|
||||||
|
insert(Attr(name, value, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(const Attr & attr)
|
||||||
|
{
|
||||||
|
bindings->push_back(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value & alloc(const Symbol & name, ptr<Pos> pos = ptr(&noPos));
|
||||||
|
|
||||||
|
Value & alloc(std::string_view name, ptr<Pos> pos = ptr(&noPos));
|
||||||
|
|
||||||
|
Bindings * finish()
|
||||||
|
{
|
||||||
|
bindings->sort();
|
||||||
|
return bindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bindings * alreadySorted()
|
||||||
|
{
|
||||||
|
return bindings;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,17 +73,16 @@ MixEvalArgs::MixEvalArgs()
|
||||||
|
|
||||||
Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
|
||||||
{
|
{
|
||||||
Bindings * res = state.allocBindings(autoArgs.size());
|
auto res = state.buildBindings(autoArgs.size());
|
||||||
for (auto & i : autoArgs) {
|
for (auto & i : autoArgs) {
|
||||||
Value * v = state.allocValue();
|
auto v = state.allocValue();
|
||||||
if (i.second[0] == 'E')
|
if (i.second[0] == 'E')
|
||||||
state.mkThunk_(*v, state.parseExprFromString(string(i.second, 1), absPath(".")));
|
state.mkThunk_(*v, state.parseExprFromString(string(i.second, 1), absPath(".")));
|
||||||
else
|
else
|
||||||
mkString(*v, string(i.second, 1));
|
v->mkString(((std::string_view) i.second).substr(1));
|
||||||
res->push_back(Attr(state.symbols.create(i.first), v));
|
res.insert(state.symbols.create(i.first), v);
|
||||||
}
|
}
|
||||||
res->sort();
|
return res.finish();
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Path lookupFileArg(EvalState & state, string s)
|
Path lookupFileArg(EvalState & state, string s)
|
||||||
|
|
|
@ -145,7 +145,7 @@ void printValue(std::ostream & str, std::set<const Value *> & active, const Valu
|
||||||
str << v.fpoint;
|
str << v.fpoint;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw Error("invalid value");
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
active.erase(&v);
|
active.erase(&v);
|
||||||
|
@ -413,6 +413,7 @@ EvalState::EvalState(
|
||||||
, sSelf(symbols.create("self"))
|
, sSelf(symbols.create("self"))
|
||||||
, sEpsilon(symbols.create(""))
|
, sEpsilon(symbols.create(""))
|
||||||
, repair(NoRepair)
|
, repair(NoRepair)
|
||||||
|
, emptyBindings(0)
|
||||||
, store(store)
|
, store(store)
|
||||||
, buildStore(buildStore ? buildStore : store)
|
, buildStore(buildStore ? buildStore : store)
|
||||||
, regexCache(makeRegexCache())
|
, regexCache(makeRegexCache())
|
||||||
|
@ -454,8 +455,6 @@ EvalState::EvalState(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vEmptySet.mkAttrs(allocBindings(0));
|
|
||||||
|
|
||||||
createBaseEnv();
|
createBaseEnv();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,7 +612,7 @@ Value * EvalState::addPrimOp(const string & name,
|
||||||
auto vPrimOp = allocValue();
|
auto vPrimOp = allocValue();
|
||||||
vPrimOp->mkPrimOp(new PrimOp { .fun = primOp, .arity = 1, .name = sym });
|
vPrimOp->mkPrimOp(new PrimOp { .fun = primOp, .arity = 1, .name = sym });
|
||||||
Value v;
|
Value v;
|
||||||
mkApp(v, *vPrimOp, *vPrimOp);
|
v.mkApp(vPrimOp, vPrimOp);
|
||||||
return addConstant(name, v);
|
return addConstant(name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,7 +634,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
|
||||||
auto vPrimOp = allocValue();
|
auto vPrimOp = allocValue();
|
||||||
vPrimOp->mkPrimOp(new PrimOp(std::move(primOp)));
|
vPrimOp->mkPrimOp(new PrimOp(std::move(primOp)));
|
||||||
Value v;
|
Value v;
|
||||||
mkApp(v, *vPrimOp, *vPrimOp);
|
v.mkApp(vPrimOp, vPrimOp);
|
||||||
return addConstant(primOp.name, v);
|
return addConstant(primOp.name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,30 +765,29 @@ LocalNoInline(void addErrorTrace(Error & e, const Pos & pos, const char * s, con
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void mkString(Value & v, const char * s)
|
void Value::mkString(std::string_view s)
|
||||||
{
|
{
|
||||||
v.mkString(dupString(s));
|
mkString(dupStringWithLen(s.data(), s.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Value & mkString(Value & v, std::string_view s, const PathSet & context)
|
void Value::mkString(std::string_view s, const PathSet & context)
|
||||||
{
|
{
|
||||||
v.mkString(dupStringWithLen(s.data(), s.size()));
|
mkString(s);
|
||||||
if (!context.empty()) {
|
if (!context.empty()) {
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
v.string.context = (const char * *)
|
string.context = (const char * *)
|
||||||
allocBytes((context.size() + 1) * sizeof(char *));
|
allocBytes((context.size() + 1) * sizeof(char *));
|
||||||
for (auto & i : context)
|
for (auto & i : context)
|
||||||
v.string.context[n++] = dupString(i.c_str());
|
string.context[n++] = dupString(i.c_str());
|
||||||
v.string.context[n] = 0;
|
string.context[n] = 0;
|
||||||
}
|
}
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void mkPath(Value & v, const char * s)
|
void Value::mkPath(std::string_view s)
|
||||||
{
|
{
|
||||||
v.mkPath(dupString(s));
|
mkPath(dupStringWithLen(s.data(), s.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -882,13 +880,13 @@ void EvalState::mkThunk_(Value & v, Expr * expr)
|
||||||
void EvalState::mkPos(Value & v, ptr<Pos> pos)
|
void EvalState::mkPos(Value & v, ptr<Pos> pos)
|
||||||
{
|
{
|
||||||
if (pos->file.set()) {
|
if (pos->file.set()) {
|
||||||
mkAttrs(v, 3);
|
auto attrs = buildBindings(3);
|
||||||
mkString(*allocAttr(v, sFile), pos->file);
|
attrs.alloc(sFile).mkString(pos->file);
|
||||||
mkInt(*allocAttr(v, sLine), pos->line);
|
attrs.alloc(sLine).mkInt(pos->line);
|
||||||
mkInt(*allocAttr(v, sColumn), pos->column);
|
attrs.alloc(sColumn).mkInt(pos->column);
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
} else
|
} else
|
||||||
mkNull(v);
|
v.mkNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1067,8 +1065,8 @@ void ExprPath::eval(EvalState & state, Env & env, Value & v)
|
||||||
|
|
||||||
void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
state.mkAttrs(v, attrs.size() + dynamicAttrs.size());
|
v.mkAttrs(state.buildBindings(attrs.size() + dynamicAttrs.size()).finish());
|
||||||
Env *dynamicEnv = &env;
|
auto dynamicEnv = &env;
|
||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
/* Create a new environment that contains the attributes in
|
/* Create a new environment that contains the attributes in
|
||||||
|
@ -1259,14 +1257,14 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
|
||||||
if (vAttrs->type() != nAttrs ||
|
if (vAttrs->type() != nAttrs ||
|
||||||
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
||||||
{
|
{
|
||||||
mkBool(v, false);
|
v.mkBool(false);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
vAttrs = j->value;
|
vAttrs = j->value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mkBool(v, true);
|
v.mkBool(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1341,7 +1339,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
/* Nope, so show the first unexpected argument to the
|
/* Nope, so show the first unexpected argument to the
|
||||||
user. */
|
user. */
|
||||||
for (auto & i : *args[0]->attrs)
|
for (auto & i : *args[0]->attrs)
|
||||||
if (lambda.formals->argNames.find(i.name) == lambda.formals->argNames.end())
|
if (!lambda.formals->argNames.count(i.name))
|
||||||
throwTypeError(pos, "%1% called with unexpected argument '%2%'", lambda, i.name);
|
throwTypeError(pos, "%1% called with unexpected argument '%2%'", lambda, i.name);
|
||||||
abort(); // can't happen
|
abort(); // can't happen
|
||||||
}
|
}
|
||||||
|
@ -1484,22 +1482,20 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value * actualArgs = allocValue();
|
auto attrs = buildBindings(std::max(static_cast<uint32_t>(fun.lambda.fun->formals->formals.size()), args.size()));
|
||||||
mkAttrs(*actualArgs, std::max(static_cast<uint32_t>(fun.lambda.fun->formals->formals.size()), args.size()));
|
|
||||||
|
|
||||||
if (fun.lambda.fun->formals->ellipsis) {
|
if (fun.lambda.fun->formals->ellipsis) {
|
||||||
// If the formals have an ellipsis (eg the function accepts extra args) pass
|
// If the formals have an ellipsis (eg the function accepts extra args) pass
|
||||||
// all available automatic arguments (which includes arguments specified on
|
// all available automatic arguments (which includes arguments specified on
|
||||||
// the command line via --arg/--argstr)
|
// the command line via --arg/--argstr)
|
||||||
for (auto& v : args) {
|
for (auto & v : args)
|
||||||
actualArgs->attrs->push_back(v);
|
attrs.insert(v);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, only pass the arguments that the function accepts
|
// Otherwise, only pass the arguments that the function accepts
|
||||||
for (auto & i : fun.lambda.fun->formals->formals) {
|
for (auto & i : fun.lambda.fun->formals->formals) {
|
||||||
Bindings::iterator j = args.find(i.name);
|
Bindings::iterator j = args.find(i.name);
|
||||||
if (j != args.end()) {
|
if (j != args.end()) {
|
||||||
actualArgs->attrs->push_back(*j);
|
attrs.insert(*j);
|
||||||
} else if (!i.def) {
|
} else if (!i.def) {
|
||||||
throwMissingArgumentError(i.pos, R"(cannot evaluate a function that has an argument without a value ('%1%')
|
throwMissingArgumentError(i.pos, R"(cannot evaluate a function that has an argument without a value ('%1%')
|
||||||
|
|
||||||
|
@ -1512,9 +1508,7 @@ https://nixos.org/manual/nix/stable/#ss-functions.)", i.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actualArgs->attrs->sort();
|
callFunction(fun, allocValue()->mkAttrs(attrs), res, noPos);
|
||||||
|
|
||||||
callFunction(fun, *actualArgs, res, noPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1549,7 +1543,7 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v)
|
||||||
|
|
||||||
void ExprOpNot::eval(EvalState & state, Env & env, Value & v)
|
void ExprOpNot::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
mkBool(v, !state.evalBool(env, e));
|
v.mkBool(!state.evalBool(env, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1557,7 +1551,7 @@ void ExprOpEq::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
Value v1; e1->eval(state, env, v1);
|
Value v1; e1->eval(state, env, v1);
|
||||||
Value v2; e2->eval(state, env, v2);
|
Value v2; e2->eval(state, env, v2);
|
||||||
mkBool(v, state.eqValues(v1, v2));
|
v.mkBool(state.eqValues(v1, v2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1565,25 +1559,25 @@ void ExprOpNEq::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
Value v1; e1->eval(state, env, v1);
|
Value v1; e1->eval(state, env, v1);
|
||||||
Value v2; e2->eval(state, env, v2);
|
Value v2; e2->eval(state, env, v2);
|
||||||
mkBool(v, !state.eqValues(v1, v2));
|
v.mkBool(!state.eqValues(v1, v2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExprOpAnd::eval(EvalState & state, Env & env, Value & v)
|
void ExprOpAnd::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
mkBool(v, state.evalBool(env, e1, pos) && state.evalBool(env, e2, pos));
|
v.mkBool(state.evalBool(env, e1, pos) && state.evalBool(env, e2, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExprOpOr::eval(EvalState & state, Env & env, Value & v)
|
void ExprOpOr::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
mkBool(v, state.evalBool(env, e1, pos) || state.evalBool(env, e2, pos));
|
v.mkBool(state.evalBool(env, e1, pos) || state.evalBool(env, e2, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExprOpImpl::eval(EvalState & state, Env & env, Value & v)
|
void ExprOpImpl::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
mkBool(v, !state.evalBool(env, e1, pos) || state.evalBool(env, e2, pos));
|
v.mkBool(!state.evalBool(env, e1, pos) || state.evalBool(env, e2, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1598,7 +1592,7 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
|
||||||
if (v1.attrs->size() == 0) { v = v2; return; }
|
if (v1.attrs->size() == 0) { v = v2; return; }
|
||||||
if (v2.attrs->size() == 0) { v = v1; return; }
|
if (v2.attrs->size() == 0) { v = v1; return; }
|
||||||
|
|
||||||
state.mkAttrs(v, v1.attrs->size() + v2.attrs->size());
|
auto attrs = state.buildBindings(v1.attrs->size() + v2.attrs->size());
|
||||||
|
|
||||||
/* Merge the sets, preferring values from the second set. Make
|
/* Merge the sets, preferring values from the second set. Make
|
||||||
sure to keep the resulting vector in sorted order. */
|
sure to keep the resulting vector in sorted order. */
|
||||||
|
@ -1607,17 +1601,19 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
|
||||||
|
|
||||||
while (i != v1.attrs->end() && j != v2.attrs->end()) {
|
while (i != v1.attrs->end() && j != v2.attrs->end()) {
|
||||||
if (i->name == j->name) {
|
if (i->name == j->name) {
|
||||||
v.attrs->push_back(*j);
|
attrs.insert(*j);
|
||||||
++i; ++j;
|
++i; ++j;
|
||||||
}
|
}
|
||||||
else if (i->name < j->name)
|
else if (i->name < j->name)
|
||||||
v.attrs->push_back(*i++);
|
attrs.insert(*i++);
|
||||||
else
|
else
|
||||||
v.attrs->push_back(*j++);
|
attrs.insert(*j++);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i != v1.attrs->end()) v.attrs->push_back(*i++);
|
while (i != v1.attrs->end()) attrs.insert(*i++);
|
||||||
while (j != v2.attrs->end()) v.attrs->push_back(*j++);
|
while (j != v2.attrs->end()) attrs.insert(*j++);
|
||||||
|
|
||||||
|
v.mkAttrs(attrs.alreadySorted());
|
||||||
|
|
||||||
state.nrOpUpdateValuesCopied += v.attrs->size();
|
state.nrOpUpdateValuesCopied += v.attrs->size();
|
||||||
}
|
}
|
||||||
|
@ -1710,16 +1706,15 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (firstType == nInt)
|
if (firstType == nInt)
|
||||||
mkInt(v, n);
|
v.mkInt(n);
|
||||||
else if (firstType == nFloat)
|
else if (firstType == nFloat)
|
||||||
mkFloat(v, nf);
|
v.mkFloat(nf);
|
||||||
else if (firstType == nPath) {
|
else if (firstType == nPath) {
|
||||||
if (!context.empty())
|
if (!context.empty())
|
||||||
throwEvalError(pos, "a string that refers to a store path cannot be appended to a path");
|
throwEvalError(pos, "a string that refers to a store path cannot be appended to a path");
|
||||||
auto path = canonPath(s.str());
|
v.mkPath(canonPath(s.str()));
|
||||||
mkPath(v, path.c_str());
|
|
||||||
} else
|
} else
|
||||||
mkString(v, s.str(), context);
|
v.mkString(s.str(), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,6 @@ struct Env
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Value & mkString(Value & v, std::string_view s, const PathSet & context = PathSet());
|
|
||||||
|
|
||||||
void copyContext(const Value & v, PathSet & context);
|
void copyContext(const Value & v, PathSet & context);
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,7 +91,7 @@ public:
|
||||||
mode. */
|
mode. */
|
||||||
std::optional<PathSet> allowedPaths;
|
std::optional<PathSet> allowedPaths;
|
||||||
|
|
||||||
Value vEmptySet;
|
Bindings emptyBindings;
|
||||||
|
|
||||||
/* Store used to materialise .drv files. */
|
/* Store used to materialise .drv files. */
|
||||||
const ref<Store> store;
|
const ref<Store> store;
|
||||||
|
@ -339,12 +337,16 @@ public:
|
||||||
Env & allocEnv(size_t size);
|
Env & allocEnv(size_t size);
|
||||||
|
|
||||||
Value * allocAttr(Value & vAttrs, const Symbol & name);
|
Value * allocAttr(Value & vAttrs, const Symbol & name);
|
||||||
Value * allocAttr(Value & vAttrs, const std::string & name);
|
Value * allocAttr(Value & vAttrs, std::string_view name);
|
||||||
|
|
||||||
Bindings * allocBindings(size_t capacity);
|
Bindings * allocBindings(size_t capacity);
|
||||||
|
|
||||||
|
BindingsBuilder buildBindings(size_t capacity)
|
||||||
|
{
|
||||||
|
return BindingsBuilder(*this, allocBindings(capacity));
|
||||||
|
}
|
||||||
|
|
||||||
void mkList(Value & v, size_t length);
|
void mkList(Value & v, size_t length);
|
||||||
void mkAttrs(Value & v, size_t capacity);
|
|
||||||
void mkThunk_(Value & v, Expr * expr);
|
void mkThunk_(Value & v, Expr * expr);
|
||||||
void mkPos(Value & v, ptr<Pos> pos);
|
void mkPos(Value & v, ptr<Pos> pos);
|
||||||
|
|
||||||
|
@ -397,6 +399,8 @@ private:
|
||||||
friend struct ExprSelect;
|
friend struct ExprSelect;
|
||||||
friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v);
|
friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v);
|
||||||
friend void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v);
|
friend void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v);
|
||||||
|
|
||||||
|
friend struct Value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -682,7 +682,7 @@ void callFlake(EvalState & state,
|
||||||
auto vTmp1 = state.allocValue();
|
auto vTmp1 = state.allocValue();
|
||||||
auto vTmp2 = state.allocValue();
|
auto vTmp2 = state.allocValue();
|
||||||
|
|
||||||
mkString(*vLocks, lockedFlake.lockFile.to_string());
|
vLocks->mkString(lockedFlake.lockFile.to_string());
|
||||||
|
|
||||||
emitTreeAttrs(
|
emitTreeAttrs(
|
||||||
state,
|
state,
|
||||||
|
@ -692,7 +692,7 @@ void callFlake(EvalState & state,
|
||||||
false,
|
false,
|
||||||
lockedFlake.flake.forceDirty);
|
lockedFlake.flake.forceDirty);
|
||||||
|
|
||||||
mkString(*vRootSubdir, lockedFlake.flake.lockedRef.subdir);
|
vRootSubdir->mkString(lockedFlake.flake.lockedRef.subdir);
|
||||||
|
|
||||||
if (!state.vCallFlake) {
|
if (!state.vCallFlake) {
|
||||||
state.vCallFlake = allocRootValue(state.allocValue());
|
state.vCallFlake = allocRootValue(state.allocValue());
|
||||||
|
|
|
@ -254,15 +254,14 @@ bool DrvInfo::queryMetaBool(const string & name, bool def)
|
||||||
void DrvInfo::setMeta(const string & name, Value * v)
|
void DrvInfo::setMeta(const string & name, Value * v)
|
||||||
{
|
{
|
||||||
getMeta();
|
getMeta();
|
||||||
Bindings * old = meta;
|
auto attrs = state->buildBindings(1 + (meta ? meta->size() : 0));
|
||||||
meta = state->allocBindings(1 + (old ? old->size() : 0));
|
|
||||||
Symbol sym = state->symbols.create(name);
|
Symbol sym = state->symbols.create(name);
|
||||||
if (old)
|
if (meta)
|
||||||
for (auto i : *old)
|
for (auto i : *meta)
|
||||||
if (i.name != sym)
|
if (i.name != sym)
|
||||||
meta->push_back(i);
|
attrs.insert(i);
|
||||||
if (v) meta->push_back(Attr(sym, v));
|
if (v) attrs.insert(sym, v);
|
||||||
meta->sort();
|
meta = attrs.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,10 @@ class JSONSax : nlohmann::json_sax<json> {
|
||||||
ValueMap attrs;
|
ValueMap attrs;
|
||||||
std::unique_ptr<JSONState> resolve(EvalState & state) override
|
std::unique_ptr<JSONState> resolve(EvalState & state) override
|
||||||
{
|
{
|
||||||
Value & v = parent->value(state);
|
auto attrs2 = state.buildBindings(attrs.size());
|
||||||
state.mkAttrs(v, attrs.size());
|
|
||||||
for (auto & i : attrs)
|
for (auto & i : attrs)
|
||||||
v.attrs->push_back(Attr(i.first, i.second));
|
attrs2.insert(i.first, i.second);
|
||||||
|
parent->value(state).mkAttrs(attrs2.alreadySorted());
|
||||||
return std::move(parent);
|
return std::move(parent);
|
||||||
}
|
}
|
||||||
void add() override { v = nullptr; }
|
void add() override { v = nullptr; }
|
||||||
|
@ -76,45 +76,51 @@ class JSONSax : nlohmann::json_sax<json> {
|
||||||
EvalState & state;
|
EvalState & state;
|
||||||
std::unique_ptr<JSONState> rs;
|
std::unique_ptr<JSONState> rs;
|
||||||
|
|
||||||
template<typename T, typename... Args> inline bool handle_value(T f, Args... args)
|
|
||||||
{
|
|
||||||
f(rs->value(state), args...);
|
|
||||||
rs->add();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSONSax(EvalState & state, Value & v) : state(state), rs(new JSONState(&v)) {};
|
JSONSax(EvalState & state, Value & v) : state(state), rs(new JSONState(&v)) {};
|
||||||
|
|
||||||
bool null()
|
bool null()
|
||||||
{
|
{
|
||||||
return handle_value(mkNull);
|
rs->value(state).mkNull();
|
||||||
|
rs->add();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool boolean(bool val)
|
bool boolean(bool val)
|
||||||
{
|
{
|
||||||
return handle_value(mkBool, val);
|
rs->value(state).mkBool(val);
|
||||||
|
rs->add();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool number_integer(number_integer_t val)
|
bool number_integer(number_integer_t val)
|
||||||
{
|
{
|
||||||
return handle_value(mkInt, val);
|
rs->value(state).mkInt(val);
|
||||||
|
rs->add();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool number_unsigned(number_unsigned_t val)
|
bool number_unsigned(number_unsigned_t val)
|
||||||
{
|
{
|
||||||
return handle_value(mkInt, val);
|
rs->value(state).mkInt(val);
|
||||||
|
rs->add();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool number_float(number_float_t val, const string_t & s)
|
bool number_float(number_float_t val, const string_t & s)
|
||||||
{
|
{
|
||||||
return handle_value(mkFloat, val);
|
rs->value(state).mkFloat(val);
|
||||||
|
rs->add();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string(string_t & val)
|
bool string(string_t & val)
|
||||||
{
|
{
|
||||||
return handle_value<void(Value&, const char*)>(mkString, val.c_str());
|
rs->value(state).mkString(val);
|
||||||
|
rs->add();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NLOHMANN_JSON_VERSION_MAJOR >= 3 && NLOHMANN_JSON_VERSION_MINOR >= 8
|
#if NLOHMANN_JSON_VERSION_MAJOR >= 3 && NLOHMANN_JSON_VERSION_MINOR >= 8
|
||||||
bool binary(binary_t&)
|
bool binary(binary_t&)
|
||||||
{
|
{
|
||||||
|
|
|
@ -94,7 +94,7 @@ struct ExprInt : Expr
|
||||||
{
|
{
|
||||||
NixInt n;
|
NixInt n;
|
||||||
Value v;
|
Value v;
|
||||||
ExprInt(NixInt n) : n(n) { mkInt(v, n); };
|
ExprInt(NixInt n) : n(n) { v.mkInt(n); };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
Value * maybeThunk(EvalState & state, Env & env);
|
Value * maybeThunk(EvalState & state, Env & env);
|
||||||
};
|
};
|
||||||
|
@ -103,7 +103,7 @@ struct ExprFloat : Expr
|
||||||
{
|
{
|
||||||
NixFloat nf;
|
NixFloat nf;
|
||||||
Value v;
|
Value v;
|
||||||
ExprFloat(NixFloat nf) : nf(nf) { mkFloat(v, nf); };
|
ExprFloat(NixFloat nf) : nf(nf) { v.mkFloat(nf); };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
Value * maybeThunk(EvalState & state, Env & env);
|
Value * maybeThunk(EvalState & state, Env & env);
|
||||||
};
|
};
|
||||||
|
@ -112,7 +112,7 @@ struct ExprString : Expr
|
||||||
{
|
{
|
||||||
Symbol s;
|
Symbol s;
|
||||||
Value v;
|
Value v;
|
||||||
ExprString(const Symbol & s) : s(s) { mkString(v, s); };
|
ExprString(const Symbol & s) : s(s) { v.mkString(s); };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
Value * maybeThunk(EvalState & state, Env & env);
|
Value * maybeThunk(EvalState & state, Env & env);
|
||||||
};
|
};
|
||||||
|
|
|
@ -125,13 +125,15 @@ static Path realisePath(EvalState & state, const Pos & pos, Value & v, const Rea
|
||||||
the actual path.
|
the actual path.
|
||||||
|
|
||||||
The 'drv' and 'drvPath' outputs must correspond. */
|
The 'drv' and 'drvPath' outputs must correspond. */
|
||||||
static void mkOutputString(EvalState & state, Value & v,
|
static void mkOutputString(
|
||||||
const StorePath & drvPath, const BasicDerivation & drv,
|
EvalState & state,
|
||||||
std::pair<string, DerivationOutput> o)
|
BindingsBuilder & attrs,
|
||||||
|
const StorePath & drvPath,
|
||||||
|
const BasicDerivation & drv,
|
||||||
|
const std::pair<string, DerivationOutput> & o)
|
||||||
{
|
{
|
||||||
auto optOutputPath = o.second.path(*state.store, drv.name, o.first);
|
auto optOutputPath = o.second.path(*state.store, drv.name, o.first);
|
||||||
mkString(
|
attrs.alloc(o.first).mkString(
|
||||||
*state.allocAttr(v, state.symbols.create(o.first)),
|
|
||||||
optOutputPath
|
optOutputPath
|
||||||
? state.store->printStorePath(*optOutputPath)
|
? state.store->printStorePath(*optOutputPath)
|
||||||
/* Downstream we would substitute this for an actual path once
|
/* Downstream we would substitute this for an actual path once
|
||||||
|
@ -172,23 +174,19 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
|
||||||
if (auto optStorePath = isValidDerivationInStore()) {
|
if (auto optStorePath = isValidDerivationInStore()) {
|
||||||
auto storePath = *optStorePath;
|
auto storePath = *optStorePath;
|
||||||
Derivation drv = state.store->readDerivation(storePath);
|
Derivation drv = state.store->readDerivation(storePath);
|
||||||
Value & w = *state.allocValue();
|
auto attrs = state.buildBindings(3 + drv.outputs.size());
|
||||||
state.mkAttrs(w, 3 + drv.outputs.size());
|
attrs.alloc(state.sDrvPath).mkString(path, {"=" + path});
|
||||||
Value * v2 = state.allocAttr(w, state.sDrvPath);
|
attrs.alloc(state.sName).mkString(drv.env["name"]);
|
||||||
mkString(*v2, path, {"=" + path});
|
auto & outputsVal = attrs.alloc(state.sOutputs);
|
||||||
v2 = state.allocAttr(w, state.sName);
|
state.mkList(outputsVal, drv.outputs.size());
|
||||||
mkString(*v2, drv.env["name"]);
|
|
||||||
Value * outputsVal =
|
|
||||||
state.allocAttr(w, state.symbols.create("outputs"));
|
|
||||||
state.mkList(*outputsVal, drv.outputs.size());
|
|
||||||
unsigned int outputs_index = 0;
|
|
||||||
|
|
||||||
for (const auto & o : drv.outputs) {
|
for (const auto & [i, o] : enumerate(drv.outputs)) {
|
||||||
mkOutputString(state, w, storePath, drv, o);
|
mkOutputString(state, attrs, storePath, drv, o);
|
||||||
outputsVal->listElems()[outputs_index] = state.allocValue();
|
(outputsVal.listElems()[i] = state.allocValue())->mkString(o.first);
|
||||||
mkString(*(outputsVal->listElems()[outputs_index++]), o.first);
|
|
||||||
}
|
}
|
||||||
w.attrs->sort();
|
|
||||||
|
auto w = state.allocValue();
|
||||||
|
w->mkAttrs(attrs);
|
||||||
|
|
||||||
if (!state.vImportedDrvToDerivation) {
|
if (!state.vImportedDrvToDerivation) {
|
||||||
state.vImportedDrvToDerivation = allocRootValue(state.allocValue());
|
state.vImportedDrvToDerivation = allocRootValue(state.allocValue());
|
||||||
|
@ -198,7 +196,7 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
|
||||||
}
|
}
|
||||||
|
|
||||||
state.forceFunction(**state.vImportedDrvToDerivation, pos);
|
state.forceFunction(**state.vImportedDrvToDerivation, pos);
|
||||||
mkApp(v, **state.vImportedDrvToDerivation, w);
|
v.mkApp(*state.vImportedDrvToDerivation, w);
|
||||||
state.forceAttrs(v, pos);
|
state.forceAttrs(v, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,7 +412,7 @@ static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Valu
|
||||||
case nFloat: t = "float"; break;
|
case nFloat: t = "float"; break;
|
||||||
case nThunk: abort();
|
case nThunk: abort();
|
||||||
}
|
}
|
||||||
mkString(v, state.symbols.create(t));
|
v.mkString(state.symbols.create(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_typeOf({
|
static RegisterPrimOp primop_typeOf({
|
||||||
|
@ -432,7 +430,7 @@ static RegisterPrimOp primop_typeOf({
|
||||||
static void prim_isNull(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isNull(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nNull);
|
v.mkBool(args[0]->type() == nNull);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isNull({
|
static RegisterPrimOp primop_isNull({
|
||||||
|
@ -452,7 +450,7 @@ static RegisterPrimOp primop_isNull({
|
||||||
static void prim_isFunction(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isFunction(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nFunction);
|
v.mkBool(args[0]->type() == nFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isFunction({
|
static RegisterPrimOp primop_isFunction({
|
||||||
|
@ -468,7 +466,7 @@ static RegisterPrimOp primop_isFunction({
|
||||||
static void prim_isInt(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isInt(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nInt);
|
v.mkBool(args[0]->type() == nInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isInt({
|
static RegisterPrimOp primop_isInt({
|
||||||
|
@ -484,7 +482,7 @@ static RegisterPrimOp primop_isInt({
|
||||||
static void prim_isFloat(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isFloat(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nFloat);
|
v.mkBool(args[0]->type() == nFloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isFloat({
|
static RegisterPrimOp primop_isFloat({
|
||||||
|
@ -500,7 +498,7 @@ static RegisterPrimOp primop_isFloat({
|
||||||
static void prim_isString(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isString(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nString);
|
v.mkBool(args[0]->type() == nString);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isString({
|
static RegisterPrimOp primop_isString({
|
||||||
|
@ -516,7 +514,7 @@ static RegisterPrimOp primop_isString({
|
||||||
static void prim_isBool(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isBool(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nBool);
|
v.mkBool(args[0]->type() == nBool);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isBool({
|
static RegisterPrimOp primop_isBool({
|
||||||
|
@ -532,7 +530,7 @@ static RegisterPrimOp primop_isBool({
|
||||||
static void prim_isPath(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isPath(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nPath);
|
v.mkBool(args[0]->type() == nPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isPath({
|
static RegisterPrimOp primop_isPath({
|
||||||
|
@ -687,7 +685,7 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar
|
||||||
|
|
||||||
/* Call the `operator' function with `e' as argument. */
|
/* Call the `operator' function with `e' as argument. */
|
||||||
Value call;
|
Value call;
|
||||||
mkApp(call, *op->value, *e);
|
call.mkApp(op->value, e);
|
||||||
state.forceList(call, pos);
|
state.forceList(call, pos);
|
||||||
|
|
||||||
/* Add the values returned by the operator to the work set. */
|
/* Add the values returned by the operator to the work set. */
|
||||||
|
@ -763,7 +761,7 @@ static RegisterPrimOp primop_addErrorContext(RegisterPrimOp::Info {
|
||||||
static void prim_ceil(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_ceil(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
auto value = state.forceFloat(*args[0], args[0]->determinePos(pos));
|
auto value = state.forceFloat(*args[0], args[0]->determinePos(pos));
|
||||||
mkInt(v, ceil(value));
|
v.mkInt(ceil(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_ceil({
|
static RegisterPrimOp primop_ceil({
|
||||||
|
@ -782,7 +780,7 @@ static RegisterPrimOp primop_ceil({
|
||||||
static void prim_floor(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_floor(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
auto value = state.forceFloat(*args[0], args[0]->determinePos(pos));
|
auto value = state.forceFloat(*args[0], args[0]->determinePos(pos));
|
||||||
mkInt(v, floor(value));
|
v.mkInt(floor(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_floor({
|
static RegisterPrimOp primop_floor({
|
||||||
|
@ -802,16 +800,16 @@ static RegisterPrimOp primop_floor({
|
||||||
* else => {success=false; value=false;} */
|
* else => {success=false; value=false;} */
|
||||||
static void prim_tryEval(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_tryEval(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.mkAttrs(v, 2);
|
auto attrs = state.buildBindings(2);
|
||||||
try {
|
try {
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
v.attrs->push_back(Attr(state.sValue, args[0]));
|
attrs.insert(state.sValue, args[0]);
|
||||||
mkBool(*state.allocAttr(v, state.symbols.create("success")), true);
|
attrs.alloc("success").mkBool(true);
|
||||||
} catch (AssertionError & e) {
|
} catch (AssertionError & e) {
|
||||||
mkBool(*state.allocAttr(v, state.sValue), false);
|
attrs.alloc(state.sValue).mkBool(false);
|
||||||
mkBool(*state.allocAttr(v, state.symbols.create("success")), false);
|
attrs.alloc("success").mkBool(false);
|
||||||
}
|
}
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_tryEval({
|
static RegisterPrimOp primop_tryEval({
|
||||||
|
@ -839,7 +837,7 @@ static RegisterPrimOp primop_tryEval({
|
||||||
static void prim_getEnv(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_getEnv(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
string name = state.forceStringNoCtx(*args[0], pos);
|
string name = state.forceStringNoCtx(*args[0], pos);
|
||||||
mkString(v, evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or(""));
|
v.mkString(evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_getEnv({
|
static RegisterPrimOp primop_getEnv({
|
||||||
|
@ -1265,11 +1263,11 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
||||||
drvHashes.lock()->insert_or_assign(drvPath, h);
|
drvHashes.lock()->insert_or_assign(drvPath, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.mkAttrs(v, 1 + drv.outputs.size());
|
auto attrs = state.buildBindings(1 + drv.outputs.size());
|
||||||
mkString(*state.allocAttr(v, state.sDrvPath), drvPathS, {"=" + drvPathS});
|
attrs.alloc(state.sDrvPath).mkString(drvPathS, {"=" + drvPathS});
|
||||||
for (auto & i : drv.outputs)
|
for (auto & i : drv.outputs)
|
||||||
mkOutputString(state, v, drvPath, drv, i);
|
mkOutputString(state, attrs, drvPath, drv, i);
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_derivationStrict(RegisterPrimOp::Info {
|
static RegisterPrimOp primop_derivationStrict(RegisterPrimOp::Info {
|
||||||
|
@ -1287,7 +1285,7 @@ static RegisterPrimOp primop_derivationStrict(RegisterPrimOp::Info {
|
||||||
‘out’. */
|
‘out’. */
|
||||||
static void prim_placeholder(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_placeholder(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
mkString(v, hashPlaceholder(state.forceStringNoCtx(*args[0], pos)));
|
v.mkString(hashPlaceholder(state.forceStringNoCtx(*args[0], pos)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_placeholder({
|
static RegisterPrimOp primop_placeholder({
|
||||||
|
@ -1312,7 +1310,7 @@ static void prim_toPath(EvalState & state, const Pos & pos, Value * * args, Valu
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Path path = state.coerceToPath(pos, *args[0], context);
|
Path path = state.coerceToPath(pos, *args[0], context);
|
||||||
mkString(v, canonPath(path), context);
|
v.mkString(canonPath(path), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_toPath({
|
static RegisterPrimOp primop_toPath({
|
||||||
|
@ -1356,7 +1354,7 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
if (!settings.readOnlyMode)
|
if (!settings.readOnlyMode)
|
||||||
state.store->ensurePath(path2);
|
state.store->ensurePath(path2);
|
||||||
context.insert(state.store->printStorePath(path2));
|
context.insert(state.store->printStorePath(path2));
|
||||||
mkString(v, path, context);
|
v.mkString(path, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_storePath({
|
static RegisterPrimOp primop_storePath({
|
||||||
|
@ -1397,13 +1395,13 @@ static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args,
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mkBool(v, pathExists(state.checkSourcePath(path)));
|
v.mkBool(pathExists(state.checkSourcePath(path)));
|
||||||
} catch (SysError & e) {
|
} catch (SysError & e) {
|
||||||
/* Don't give away info from errors while canonicalising
|
/* Don't give away info from errors while canonicalising
|
||||||
‘path’ in restricted mode. */
|
‘path’ in restricted mode. */
|
||||||
mkBool(v, false);
|
v.mkBool(false);
|
||||||
} catch (RestrictedPathError & e) {
|
} catch (RestrictedPathError & e) {
|
||||||
mkBool(v, false);
|
v.mkBool(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1422,7 +1420,7 @@ static RegisterPrimOp primop_pathExists({
|
||||||
static void prim_baseNameOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_baseNameOf(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
mkString(v, baseNameOf(state.coerceToString(pos, *args[0], context, false, false)), context);
|
v.mkString(baseNameOf(state.coerceToString(pos, *args[0], context, false, false)), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_baseNameOf({
|
static RegisterPrimOp primop_baseNameOf({
|
||||||
|
@ -1443,7 +1441,7 @@ static void prim_dirOf(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Path dir = dirOf(state.coerceToString(pos, *args[0], context, false, false));
|
Path dir = dirOf(state.coerceToString(pos, *args[0], context, false, false));
|
||||||
if (args[0]->type() == nPath) mkPath(v, dir.c_str()); else mkString(v, dir, context);
|
if (args[0]->type() == nPath) v.mkPath(dir); else v.mkString(dir, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_dirOf({
|
static RegisterPrimOp primop_dirOf({
|
||||||
|
@ -1472,7 +1470,7 @@ static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
string s = readFile(path);
|
string s = readFile(path);
|
||||||
if (s.find((char) 0) != string::npos)
|
if (s.find((char) 0) != string::npos)
|
||||||
throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path);
|
throw Error("the contents of the file '%1%' cannot be represented as a Nix string", path);
|
||||||
mkString(v, s.c_str());
|
v.mkString(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_readFile({
|
static RegisterPrimOp primop_readFile({
|
||||||
|
@ -1524,7 +1522,7 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
|
|
||||||
string path = state.forceStringNoCtx(*args[1], pos);
|
string path = state.forceStringNoCtx(*args[1], pos);
|
||||||
|
|
||||||
mkPath(v, state.checkSourcePath(state.findFile(searchPath, path, pos)).c_str());
|
v.mkPath(state.checkSourcePath(state.findFile(searchPath, path, pos)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_findFile(RegisterPrimOp::Info {
|
static RegisterPrimOp primop_findFile(RegisterPrimOp::Info {
|
||||||
|
@ -1551,7 +1549,7 @@ static void prim_hashFile(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
throw EvalError("cannot read '%s' since path '%s' is not valid, at %s", path, e.path, pos);
|
throw EvalError("cannot read '%s' since path '%s' is not valid, at %s", path, e.path, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
mkString(v, hashFile(*ht, path).to_string(Base16, false));
|
v.mkString(hashFile(*ht, path).to_string(Base16, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_hashFile({
|
static RegisterPrimOp primop_hashFile({
|
||||||
|
@ -1579,20 +1577,20 @@ static void prim_readDir(EvalState & state, const Pos & pos, Value * * args, Val
|
||||||
}
|
}
|
||||||
|
|
||||||
DirEntries entries = readDirectory(path);
|
DirEntries entries = readDirectory(path);
|
||||||
state.mkAttrs(v, entries.size());
|
|
||||||
|
auto attrs = state.buildBindings(entries.size());
|
||||||
|
|
||||||
for (auto & ent : entries) {
|
for (auto & ent : entries) {
|
||||||
Value * ent_val = state.allocAttr(v, state.symbols.create(ent.name));
|
|
||||||
if (ent.type == DT_UNKNOWN)
|
if (ent.type == DT_UNKNOWN)
|
||||||
ent.type = getFileType(path + "/" + ent.name);
|
ent.type = getFileType(path + "/" + ent.name);
|
||||||
ent_val->mkString(
|
attrs.alloc(ent.name).mkString(
|
||||||
ent.type == DT_REG ? "regular" :
|
ent.type == DT_REG ? "regular" :
|
||||||
ent.type == DT_DIR ? "directory" :
|
ent.type == DT_DIR ? "directory" :
|
||||||
ent.type == DT_LNK ? "symlink" :
|
ent.type == DT_LNK ? "symlink" :
|
||||||
"unknown");
|
"unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_readDir({
|
static RegisterPrimOp primop_readDir({
|
||||||
|
@ -1628,7 +1626,7 @@ static void prim_toXML(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
PathSet context;
|
PathSet context;
|
||||||
printValueAsXML(state, true, false, *args[0], out, context, pos);
|
printValueAsXML(state, true, false, *args[0], out, context, pos);
|
||||||
mkString(v, out.str(), context);
|
v.mkString(out.str(), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_toXML({
|
static RegisterPrimOp primop_toXML({
|
||||||
|
@ -1736,7 +1734,7 @@ static void prim_toJSON(EvalState & state, const Pos & pos, Value * * args, Valu
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
PathSet context;
|
PathSet context;
|
||||||
printValueAsJSON(state, true, *args[0], pos, out, context);
|
printValueAsJSON(state, true, *args[0], pos, out, context);
|
||||||
mkString(v, out.str(), context);
|
v.mkString(out.str(), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_toJSON({
|
static RegisterPrimOp primop_toJSON({
|
||||||
|
@ -1810,7 +1808,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
|
||||||
result, since `storePath' itself has references to the paths
|
result, since `storePath' itself has references to the paths
|
||||||
used in args[1]. */
|
used in args[1]. */
|
||||||
|
|
||||||
mkString(v, storePath, {storePath});
|
v.mkString(storePath, {storePath});
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_toFile({
|
static RegisterPrimOp primop_toFile({
|
||||||
|
@ -1927,10 +1925,10 @@ static void addPath(
|
||||||
/* Call the filter function. The first argument is the path,
|
/* Call the filter function. The first argument is the path,
|
||||||
the second is a string indicating the type of the file. */
|
the second is a string indicating the type of the file. */
|
||||||
Value arg1;
|
Value arg1;
|
||||||
mkString(arg1, path);
|
arg1.mkString(path);
|
||||||
|
|
||||||
Value arg2;
|
Value arg2;
|
||||||
mkString(arg2,
|
arg2.mkString(
|
||||||
S_ISREG(st.st_mode) ? "regular" :
|
S_ISREG(st.st_mode) ? "regular" :
|
||||||
S_ISDIR(st.st_mode) ? "directory" :
|
S_ISDIR(st.st_mode) ? "directory" :
|
||||||
S_ISLNK(st.st_mode) ? "symlink" :
|
S_ISLNK(st.st_mode) ? "symlink" :
|
||||||
|
@ -1957,7 +1955,7 @@ static void addPath(
|
||||||
} else
|
} else
|
||||||
dstPath = state.store->printStorePath(*expectedStorePath);
|
dstPath = state.store->printStorePath(*expectedStorePath);
|
||||||
|
|
||||||
mkString(v, dstPath, {dstPath});
|
v.mkString(dstPath, {dstPath});
|
||||||
|
|
||||||
state.allowPath(dstPath);
|
state.allowPath(dstPath);
|
||||||
|
|
||||||
|
@ -2131,7 +2129,7 @@ static void prim_attrNames(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
|
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
for (auto & i : *args[0]->attrs)
|
for (auto & i : *args[0]->attrs)
|
||||||
mkString(*(v.listElems()[n++] = state.allocValue()), i.name);
|
(v.listElems()[n++] = state.allocValue())->mkString(i.name);
|
||||||
|
|
||||||
std::sort(v.listElems(), v.listElems() + n,
|
std::sort(v.listElems(), v.listElems() + n,
|
||||||
[](Value * v1, Value * v2) { return strcmp(v1->string.s, v2->string.s) < 0; });
|
[](Value * v1, Value * v2) { return strcmp(v1->string.s, v2->string.s) < 0; });
|
||||||
|
@ -2215,7 +2213,7 @@ static void prim_unsafeGetAttrPos(EvalState & state, const Pos & pos, Value * *
|
||||||
state.forceAttrs(*args[1], pos);
|
state.forceAttrs(*args[1], pos);
|
||||||
Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr));
|
Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr));
|
||||||
if (i == args[1]->attrs->end())
|
if (i == args[1]->attrs->end())
|
||||||
mkNull(v);
|
v.mkNull();
|
||||||
else
|
else
|
||||||
state.mkPos(v, i->pos);
|
state.mkPos(v, i->pos);
|
||||||
}
|
}
|
||||||
|
@ -2231,7 +2229,7 @@ static void prim_hasAttr(EvalState & state, const Pos & pos, Value * * args, Val
|
||||||
{
|
{
|
||||||
string attr = state.forceStringNoCtx(*args[0], pos);
|
string attr = state.forceStringNoCtx(*args[0], pos);
|
||||||
state.forceAttrs(*args[1], pos);
|
state.forceAttrs(*args[1], pos);
|
||||||
mkBool(v, args[1]->attrs->find(state.symbols.create(attr)) != args[1]->attrs->end());
|
v.mkBool(args[1]->attrs->find(state.symbols.create(attr)) != args[1]->attrs->end());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_hasAttr({
|
static RegisterPrimOp primop_hasAttr({
|
||||||
|
@ -2249,7 +2247,7 @@ static RegisterPrimOp primop_hasAttr({
|
||||||
static void prim_isAttrs(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isAttrs(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nAttrs);
|
v.mkBool(args[0]->type() == nAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isAttrs({
|
static RegisterPrimOp primop_isAttrs({
|
||||||
|
@ -2276,11 +2274,12 @@ static void prim_removeAttrs(EvalState & state, const Pos & pos, Value * * args,
|
||||||
/* Copy all attributes not in that set. Note that we don't need
|
/* Copy all attributes not in that set. Note that we don't need
|
||||||
to sort v.attrs because it's a subset of an already sorted
|
to sort v.attrs because it's a subset of an already sorted
|
||||||
vector. */
|
vector. */
|
||||||
state.mkAttrs(v, args[0]->attrs->size());
|
auto attrs = state.buildBindings(args[0]->attrs->size());
|
||||||
for (auto & i : *args[0]->attrs) {
|
for (auto & i : *args[0]->attrs) {
|
||||||
if (!names.count(i.name))
|
if (!names.count(i.name))
|
||||||
v.attrs->push_back(i);
|
attrs.insert(i);
|
||||||
}
|
}
|
||||||
|
v.mkAttrs(attrs.alreadySorted());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_removeAttrs({
|
static RegisterPrimOp primop_removeAttrs({
|
||||||
|
@ -2308,7 +2307,7 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args,
|
||||||
{
|
{
|
||||||
state.forceList(*args[0], pos);
|
state.forceList(*args[0], pos);
|
||||||
|
|
||||||
state.mkAttrs(v, args[0]->listSize());
|
auto attrs = state.buildBindings(args[0]->listSize());
|
||||||
|
|
||||||
std::set<Symbol> seen;
|
std::set<Symbol> seen;
|
||||||
|
|
||||||
|
@ -2334,11 +2333,11 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args,
|
||||||
v2->attrs,
|
v2->attrs,
|
||||||
pos
|
pos
|
||||||
);
|
);
|
||||||
v.attrs->push_back(Attr(sym, j2->value, j2->pos));
|
attrs.insert(sym, j2->value, j2->pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_listToAttrs({
|
static RegisterPrimOp primop_listToAttrs({
|
||||||
|
@ -2371,13 +2370,15 @@ static void prim_intersectAttrs(EvalState & state, const Pos & pos, Value * * ar
|
||||||
state.forceAttrs(*args[0], pos);
|
state.forceAttrs(*args[0], pos);
|
||||||
state.forceAttrs(*args[1], pos);
|
state.forceAttrs(*args[1], pos);
|
||||||
|
|
||||||
state.mkAttrs(v, std::min(args[0]->attrs->size(), args[1]->attrs->size()));
|
auto attrs = state.buildBindings(std::min(args[0]->attrs->size(), args[1]->attrs->size()));
|
||||||
|
|
||||||
for (auto & i : *args[0]->attrs) {
|
for (auto & i : *args[0]->attrs) {
|
||||||
Bindings::iterator j = args[1]->attrs->find(i.name);
|
Bindings::iterator j = args[1]->attrs->find(i.name);
|
||||||
if (j != args[1]->attrs->end())
|
if (j != args[1]->attrs->end())
|
||||||
v.attrs->push_back(*j);
|
attrs.insert(*j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v.mkAttrs(attrs.alreadySorted());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_intersectAttrs({
|
static RegisterPrimOp primop_intersectAttrs({
|
||||||
|
@ -2431,7 +2432,7 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
if (args[0]->isPrimOpApp() || args[0]->isPrimOp()) {
|
if (args[0]->isPrimOpApp() || args[0]->isPrimOp()) {
|
||||||
state.mkAttrs(v, 0);
|
v.mkAttrs(&state.emptyBindings);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!args[0]->isLambda())
|
if (!args[0]->isLambda())
|
||||||
|
@ -2441,18 +2442,15 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!args[0]->lambda.fun->hasFormals()) {
|
if (!args[0]->lambda.fun->hasFormals()) {
|
||||||
state.mkAttrs(v, 0);
|
v.mkAttrs(&state.emptyBindings);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.mkAttrs(v, args[0]->lambda.fun->formals->formals.size());
|
auto attrs = state.buildBindings(args[0]->lambda.fun->formals->formals.size());
|
||||||
for (auto & i : args[0]->lambda.fun->formals->formals) {
|
for (auto & i : args[0]->lambda.fun->formals->formals)
|
||||||
// !!! should optimise booleans (allocate only once)
|
// !!! should optimise booleans (allocate only once)
|
||||||
Value * value = state.allocValue();
|
attrs.alloc(i.name, ptr(&i.pos)).mkBool(i.def);
|
||||||
v.attrs->push_back(Attr(i.name, value, ptr(&i.pos)));
|
v.mkAttrs(attrs);
|
||||||
mkBool(*value, i.def);
|
|
||||||
}
|
|
||||||
v.attrs->sort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_functionArgs({
|
static RegisterPrimOp primop_functionArgs({
|
||||||
|
@ -2477,15 +2475,17 @@ static void prim_mapAttrs(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
{
|
{
|
||||||
state.forceAttrs(*args[1], pos);
|
state.forceAttrs(*args[1], pos);
|
||||||
|
|
||||||
state.mkAttrs(v, args[1]->attrs->size());
|
auto attrs = state.buildBindings(args[1]->attrs->size());
|
||||||
|
|
||||||
for (auto & i : *args[1]->attrs) {
|
for (auto & i : *args[1]->attrs) {
|
||||||
Value * vName = state.allocValue();
|
Value * vName = state.allocValue();
|
||||||
Value * vFun2 = state.allocValue();
|
Value * vFun2 = state.allocValue();
|
||||||
mkString(*vName, i.name);
|
vName->mkString(i.name);
|
||||||
mkApp(*vFun2, *args[0], *vName);
|
vFun2->mkApp(args[0], vName);
|
||||||
mkApp(*state.allocAttr(v, i.name), *vFun2, *i.value);
|
attrs.alloc(i.name).mkApp(vFun2, i.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v.mkAttrs(attrs.alreadySorted());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_mapAttrs({
|
static RegisterPrimOp primop_mapAttrs({
|
||||||
|
@ -2531,12 +2531,13 @@ static void prim_zipAttrsWith(EvalState & state, const Pos & pos, Value * * args
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.mkAttrs(v, attrsSeen.size());
|
auto attrs = state.buildBindings(attrsSeen.size());
|
||||||
for (auto & [sym, elem] : attrsSeen) {
|
for (auto & [sym, elem] : attrsSeen) {
|
||||||
Value * list = state.allocAttr(v, sym);
|
auto & list = attrs.alloc(sym);
|
||||||
state.mkList(*list, elem.first);
|
state.mkList(list, elem.first);
|
||||||
elem.second = list->listElems();
|
elem.second = list.listElems();
|
||||||
}
|
}
|
||||||
|
v.mkAttrs(attrs.alreadySorted());
|
||||||
|
|
||||||
for (unsigned int n = 0; n < listSize; ++n) {
|
for (unsigned int n = 0; n < listSize; ++n) {
|
||||||
Value * vElem = listElems[n];
|
Value * vElem = listElems[n];
|
||||||
|
@ -2545,12 +2546,12 @@ static void prim_zipAttrsWith(EvalState & state, const Pos & pos, Value * * args
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & attr : *v.attrs) {
|
for (auto & attr : *v.attrs) {
|
||||||
Value * name = state.allocValue();
|
auto name = state.allocValue();
|
||||||
mkString(*name, attr.name);
|
name->mkString(attr.name);
|
||||||
Value * call1 = state.allocValue();
|
auto call1 = state.allocValue();
|
||||||
mkApp(*call1, *args[0], *name);
|
call1->mkApp(args[0], name);
|
||||||
Value * call2 = state.allocValue();
|
auto call2 = state.allocValue();
|
||||||
mkApp(*call2, *call1, *attr.value);
|
call2->mkApp(call1, attr.value);
|
||||||
attr.value = call2;
|
attr.value = call2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2597,7 +2598,7 @@ static RegisterPrimOp primop_zipAttrsWith({
|
||||||
static void prim_isList(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_isList(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
mkBool(v, args[0]->type() == nList);
|
v.mkBool(args[0]->type() == nList);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_isList({
|
static RegisterPrimOp primop_isList({
|
||||||
|
@ -2695,8 +2696,8 @@ static void prim_map(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
state.mkList(v, args[1]->listSize());
|
state.mkList(v, args[1]->listSize());
|
||||||
|
|
||||||
for (unsigned int n = 0; n < v.listSize(); ++n)
|
for (unsigned int n = 0; n < v.listSize(); ++n)
|
||||||
mkApp(*(v.listElems()[n] = state.allocValue()),
|
(v.listElems()[n] = state.allocValue())->mkApp(
|
||||||
*args[0], *args[1]->listElems()[n]);
|
args[0], args[1]->listElems()[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_map({
|
static RegisterPrimOp primop_map({
|
||||||
|
@ -2765,7 +2766,7 @@ static void prim_elem(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
res = true;
|
res = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mkBool(v, res);
|
v.mkBool(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_elem({
|
static RegisterPrimOp primop_elem({
|
||||||
|
@ -2798,7 +2799,7 @@ static RegisterPrimOp primop_concatLists({
|
||||||
static void prim_length(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_length(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceList(*args[0], pos);
|
state.forceList(*args[0], pos);
|
||||||
mkInt(v, args[0]->listSize());
|
v.mkInt(args[0]->listSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_length({
|
static RegisterPrimOp primop_length({
|
||||||
|
@ -2855,12 +2856,12 @@ static void anyOrAll(bool any, EvalState & state, const Pos & pos, Value * * arg
|
||||||
state.callFunction(*args[0], *elem, vTmp, pos);
|
state.callFunction(*args[0], *elem, vTmp, pos);
|
||||||
bool res = state.forceBool(vTmp, pos);
|
bool res = state.forceBool(vTmp, pos);
|
||||||
if (res == any) {
|
if (res == any) {
|
||||||
mkBool(v, any);
|
v.mkBool(any);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mkBool(v, !any);
|
v.mkBool(!any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2907,9 +2908,9 @@ static void prim_genList(EvalState & state, const Pos & pos, Value * * args, Val
|
||||||
state.mkList(v, len);
|
state.mkList(v, len);
|
||||||
|
|
||||||
for (unsigned int n = 0; n < (unsigned int) len; ++n) {
|
for (unsigned int n = 0; n < (unsigned int) len; ++n) {
|
||||||
Value * arg = state.allocValue();
|
auto arg = state.allocValue();
|
||||||
mkInt(*arg, n);
|
arg->mkInt(n);
|
||||||
mkApp(*(v.listElems()[n] = state.allocValue()), *args[0], *arg);
|
(v.listElems()[n] = state.allocValue())->mkApp(args[0], arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3003,21 +3004,21 @@ static void prim_partition(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
wrong.push_back(vElem);
|
wrong.push_back(vElem);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.mkAttrs(v, 2);
|
auto attrs = state.buildBindings(2);
|
||||||
|
|
||||||
Value * vRight = state.allocAttr(v, state.sRight);
|
auto & vRight = attrs.alloc(state.sRight);
|
||||||
auto rsize = right.size();
|
auto rsize = right.size();
|
||||||
state.mkList(*vRight, rsize);
|
state.mkList(vRight, rsize);
|
||||||
if (rsize)
|
if (rsize)
|
||||||
memcpy(vRight->listElems(), right.data(), sizeof(Value *) * rsize);
|
memcpy(vRight.listElems(), right.data(), sizeof(Value *) * rsize);
|
||||||
|
|
||||||
Value * vWrong = state.allocAttr(v, state.sWrong);
|
auto & vWrong = attrs.alloc(state.sWrong);
|
||||||
auto wsize = wrong.size();
|
auto wsize = wrong.size();
|
||||||
state.mkList(*vWrong, wsize);
|
state.mkList(vWrong, wsize);
|
||||||
if (wsize)
|
if (wsize)
|
||||||
memcpy(vWrong->listElems(), wrong.data(), sizeof(Value *) * wsize);
|
memcpy(vWrong.listElems(), wrong.data(), sizeof(Value *) * wsize);
|
||||||
|
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_partition({
|
static RegisterPrimOp primop_partition({
|
||||||
|
@ -3059,14 +3060,16 @@ static void prim_groupBy(EvalState & state, const Pos & pos, Value * * args, Val
|
||||||
vector->second.push_back(vElem);
|
vector->second.push_back(vElem);
|
||||||
}
|
}
|
||||||
|
|
||||||
state.mkAttrs(v, attrs.size());
|
auto attrs2 = state.buildBindings(attrs.size());
|
||||||
|
|
||||||
for (auto & i : attrs) {
|
for (auto & i : attrs) {
|
||||||
Value * list = state.allocAttr(v, i.first);
|
auto & list = attrs2.alloc(i.first);
|
||||||
auto size = i.second.size();
|
auto size = i.second.size();
|
||||||
state.mkList(*list, size);
|
state.mkList(list, size);
|
||||||
memcpy(list->listElems(), i.second.data(), sizeof(Value *) * size);
|
memcpy(list.listElems(), i.second.data(), sizeof(Value *) * size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v.mkAttrs(attrs2.alreadySorted());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_groupBy({
|
static RegisterPrimOp primop_groupBy({
|
||||||
|
@ -3145,9 +3148,9 @@ static void prim_add(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
state.forceValue(*args[1], pos);
|
state.forceValue(*args[1], pos);
|
||||||
if (args[0]->type() == nFloat || args[1]->type() == nFloat)
|
if (args[0]->type() == nFloat || args[1]->type() == nFloat)
|
||||||
mkFloat(v, state.forceFloat(*args[0], pos) + state.forceFloat(*args[1], pos));
|
v.mkFloat(state.forceFloat(*args[0], pos) + state.forceFloat(*args[1], pos));
|
||||||
else
|
else
|
||||||
mkInt(v, state.forceInt(*args[0], pos) + state.forceInt(*args[1], pos));
|
v.mkInt(state.forceInt(*args[0], pos) + state.forceInt(*args[1], pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_add({
|
static RegisterPrimOp primop_add({
|
||||||
|
@ -3164,9 +3167,9 @@ static void prim_sub(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
state.forceValue(*args[1], pos);
|
state.forceValue(*args[1], pos);
|
||||||
if (args[0]->type() == nFloat || args[1]->type() == nFloat)
|
if (args[0]->type() == nFloat || args[1]->type() == nFloat)
|
||||||
mkFloat(v, state.forceFloat(*args[0], pos) - state.forceFloat(*args[1], pos));
|
v.mkFloat(state.forceFloat(*args[0], pos) - state.forceFloat(*args[1], pos));
|
||||||
else
|
else
|
||||||
mkInt(v, state.forceInt(*args[0], pos) - state.forceInt(*args[1], pos));
|
v.mkInt(state.forceInt(*args[0], pos) - state.forceInt(*args[1], pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_sub({
|
static RegisterPrimOp primop_sub({
|
||||||
|
@ -3183,9 +3186,9 @@ static void prim_mul(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
state.forceValue(*args[1], pos);
|
state.forceValue(*args[1], pos);
|
||||||
if (args[0]->type() == nFloat || args[1]->type() == nFloat)
|
if (args[0]->type() == nFloat || args[1]->type() == nFloat)
|
||||||
mkFloat(v, state.forceFloat(*args[0], pos) * state.forceFloat(*args[1], pos));
|
v.mkFloat(state.forceFloat(*args[0], pos) * state.forceFloat(*args[1], pos));
|
||||||
else
|
else
|
||||||
mkInt(v, state.forceInt(*args[0], pos) * state.forceInt(*args[1], pos));
|
v.mkInt(state.forceInt(*args[0], pos) * state.forceInt(*args[1], pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_mul({
|
static RegisterPrimOp primop_mul({
|
||||||
|
@ -3210,7 +3213,7 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
});
|
});
|
||||||
|
|
||||||
if (args[0]->type() == nFloat || args[1]->type() == nFloat) {
|
if (args[0]->type() == nFloat || args[1]->type() == nFloat) {
|
||||||
mkFloat(v, state.forceFloat(*args[0], pos) / state.forceFloat(*args[1], pos));
|
v.mkFloat(state.forceFloat(*args[0], pos) / state.forceFloat(*args[1], pos));
|
||||||
} else {
|
} else {
|
||||||
NixInt i1 = state.forceInt(*args[0], pos);
|
NixInt i1 = state.forceInt(*args[0], pos);
|
||||||
NixInt i2 = state.forceInt(*args[1], pos);
|
NixInt i2 = state.forceInt(*args[1], pos);
|
||||||
|
@ -3221,7 +3224,7 @@ static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value &
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
mkInt(v, i1 / i2);
|
v.mkInt(i1 / i2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3236,7 +3239,7 @@ static RegisterPrimOp primop_div({
|
||||||
|
|
||||||
static void prim_bitAnd(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_bitAnd(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
mkInt(v, state.forceInt(*args[0], pos) & state.forceInt(*args[1], pos));
|
v.mkInt(state.forceInt(*args[0], pos) & state.forceInt(*args[1], pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_bitAnd({
|
static RegisterPrimOp primop_bitAnd({
|
||||||
|
@ -3250,7 +3253,7 @@ static RegisterPrimOp primop_bitAnd({
|
||||||
|
|
||||||
static void prim_bitOr(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_bitOr(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
mkInt(v, state.forceInt(*args[0], pos) | state.forceInt(*args[1], pos));
|
v.mkInt(state.forceInt(*args[0], pos) | state.forceInt(*args[1], pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_bitOr({
|
static RegisterPrimOp primop_bitOr({
|
||||||
|
@ -3264,7 +3267,7 @@ static RegisterPrimOp primop_bitOr({
|
||||||
|
|
||||||
static void prim_bitXor(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_bitXor(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
mkInt(v, state.forceInt(*args[0], pos) ^ state.forceInt(*args[1], pos));
|
v.mkInt(state.forceInt(*args[0], pos) ^ state.forceInt(*args[1], pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_bitXor({
|
static RegisterPrimOp primop_bitXor({
|
||||||
|
@ -3281,7 +3284,7 @@ static void prim_lessThan(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
state.forceValue(*args[1], pos);
|
state.forceValue(*args[1], pos);
|
||||||
CompareValues comp{state};
|
CompareValues comp{state};
|
||||||
mkBool(v, comp(args[0], args[1]));
|
v.mkBool(comp(args[0], args[1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_lessThan({
|
static RegisterPrimOp primop_lessThan({
|
||||||
|
@ -3308,7 +3311,7 @@ static void prim_toString(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
string s = state.coerceToString(pos, *args[0], context, true, false);
|
string s = state.coerceToString(pos, *args[0], context, true, false);
|
||||||
mkString(v, s, context);
|
v.mkString(s, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_toString({
|
static RegisterPrimOp primop_toString({
|
||||||
|
@ -3352,7 +3355,7 @@ static void prim_substring(EvalState & state, const Pos & pos, Value * * args, V
|
||||||
.errPos = pos
|
.errPos = pos
|
||||||
});
|
});
|
||||||
|
|
||||||
mkString(v, (unsigned int) start >= s.size() ? "" : string(s, start, len), context);
|
v.mkString((unsigned int) start >= s.size() ? "" : string(s, start, len), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_substring({
|
static RegisterPrimOp primop_substring({
|
||||||
|
@ -3379,7 +3382,7 @@ static void prim_stringLength(EvalState & state, const Pos & pos, Value * * args
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
string s = state.coerceToString(pos, *args[0], context);
|
string s = state.coerceToString(pos, *args[0], context);
|
||||||
mkInt(v, s.size());
|
v.mkInt(s.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_stringLength({
|
static RegisterPrimOp primop_stringLength({
|
||||||
|
@ -3406,7 +3409,7 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
|
||||||
PathSet context; // discarded
|
PathSet context; // discarded
|
||||||
string s = state.forceString(*args[1], context, pos);
|
string s = state.forceString(*args[1], context, pos);
|
||||||
|
|
||||||
mkString(v, hashString(*ht, s).to_string(Base16, false));
|
v.mkString(hashString(*ht, s).to_string(Base16, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_hashString({
|
static RegisterPrimOp primop_hashString({
|
||||||
|
@ -3445,7 +3448,7 @@ void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
if (!std::regex_match(str, match, regex->second)) {
|
if (!std::regex_match(str, match, regex->second)) {
|
||||||
mkNull(v);
|
v.mkNull();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3454,9 +3457,9 @@ void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
state.mkList(v, len);
|
state.mkList(v, len);
|
||||||
for (size_t i = 0; i < len; ++i) {
|
for (size_t i = 0; i < len; ++i) {
|
||||||
if (!match[i+1].matched)
|
if (!match[i+1].matched)
|
||||||
mkNull(*(v.listElems()[i] = state.allocValue()));
|
(v.listElems()[i] = state.allocValue())->mkNull();
|
||||||
else
|
else
|
||||||
mkString(*(v.listElems()[i] = state.allocValue()), match[i + 1].str().c_str());
|
(v.listElems()[i] = state.allocValue())->mkString(match[i + 1].str());
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (std::regex_error &e) {
|
} catch (std::regex_error &e) {
|
||||||
|
@ -3531,7 +3534,6 @@ static void prim_split(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
const size_t len = std::distance(begin, end);
|
const size_t len = std::distance(begin, end);
|
||||||
state.mkList(v, 2 * len + 1);
|
state.mkList(v, 2 * len + 1);
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
Value * elem;
|
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
v.listElems()[idx++] = args[1];
|
v.listElems()[idx++] = args[1];
|
||||||
|
@ -3543,28 +3545,26 @@ static void prim_split(EvalState & state, const Pos & pos, Value * * args, Value
|
||||||
std::smatch match = *i;
|
std::smatch match = *i;
|
||||||
|
|
||||||
// Add a string for non-matched characters.
|
// Add a string for non-matched characters.
|
||||||
elem = v.listElems()[idx++] = state.allocValue();
|
(v.listElems()[idx++] = state.allocValue())->mkString(match.prefix().str());
|
||||||
mkString(*elem, match.prefix().str().c_str());
|
|
||||||
|
|
||||||
// Add a list for matched substrings.
|
// Add a list for matched substrings.
|
||||||
const size_t slen = match.size() - 1;
|
const size_t slen = match.size() - 1;
|
||||||
elem = v.listElems()[idx++] = state.allocValue();
|
auto elem = v.listElems()[idx++] = state.allocValue();
|
||||||
|
|
||||||
// Start at 1, beacause the first match is the whole string.
|
// Start at 1, beacause the first match is the whole string.
|
||||||
state.mkList(*elem, slen);
|
state.mkList(*elem, slen);
|
||||||
for (size_t si = 0; si < slen; ++si) {
|
for (size_t si = 0; si < slen; ++si) {
|
||||||
if (!match[si + 1].matched)
|
if (!match[si + 1].matched)
|
||||||
mkNull(*(elem->listElems()[si] = state.allocValue()));
|
(elem->listElems()[si] = state.allocValue())->mkNull();
|
||||||
else
|
else
|
||||||
mkString(*(elem->listElems()[si] = state.allocValue()), match[si + 1].str().c_str());
|
(elem->listElems()[si] = state.allocValue())->mkString(match[si + 1].str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a string for non-matched suffix characters.
|
// Add a string for non-matched suffix characters.
|
||||||
if (idx == 2 * len) {
|
if (idx == 2 * len)
|
||||||
elem = v.listElems()[idx++] = state.allocValue();
|
(v.listElems()[idx++] = state.allocValue())->mkString(match.suffix().str());
|
||||||
mkString(*elem, match.suffix().str().c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(idx == 2 * len + 1);
|
assert(idx == 2 * len + 1);
|
||||||
|
|
||||||
} catch (std::regex_error &e) {
|
} catch (std::regex_error &e) {
|
||||||
|
@ -3636,7 +3636,7 @@ static void prim_concatStringsSep(EvalState & state, const Pos & pos, Value * *
|
||||||
res += state.coerceToString(pos, *elem, context);
|
res += state.coerceToString(pos, *elem, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
mkString(v, res, context);
|
v.mkString(res, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_concatStringsSep({
|
static RegisterPrimOp primop_concatStringsSep({
|
||||||
|
@ -3705,7 +3705,7 @@ static void prim_replaceStrings(EvalState & state, const Pos & pos, Value * * ar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mkString(v, res, context);
|
v.mkString(res, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_replaceStrings({
|
static RegisterPrimOp primop_replaceStrings({
|
||||||
|
@ -3734,10 +3734,10 @@ static void prim_parseDrvName(EvalState & state, const Pos & pos, Value * * args
|
||||||
{
|
{
|
||||||
string name = state.forceStringNoCtx(*args[0], pos);
|
string name = state.forceStringNoCtx(*args[0], pos);
|
||||||
DrvName parsed(name);
|
DrvName parsed(name);
|
||||||
state.mkAttrs(v, 2);
|
auto attrs = state.buildBindings(2);
|
||||||
mkString(*state.allocAttr(v, state.sName), parsed.name);
|
attrs.alloc(state.sName).mkString(parsed.name);
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("version")), parsed.version);
|
attrs.alloc("version").mkString(parsed.version);
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_parseDrvName({
|
static RegisterPrimOp primop_parseDrvName({
|
||||||
|
@ -3758,7 +3758,7 @@ static void prim_compareVersions(EvalState & state, const Pos & pos, Value * * a
|
||||||
{
|
{
|
||||||
string version1 = state.forceStringNoCtx(*args[0], pos);
|
string version1 = state.forceStringNoCtx(*args[0], pos);
|
||||||
string version2 = state.forceStringNoCtx(*args[1], pos);
|
string version2 = state.forceStringNoCtx(*args[1], pos);
|
||||||
mkInt(v, compareVersions(version1, version2));
|
v.mkInt(compareVersions(version1, version2));
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_compareVersions({
|
static RegisterPrimOp primop_compareVersions({
|
||||||
|
@ -3786,11 +3786,8 @@ static void prim_splitVersion(EvalState & state, const Pos & pos, Value * * args
|
||||||
components.emplace_back(std::move(component));
|
components.emplace_back(std::move(component));
|
||||||
}
|
}
|
||||||
state.mkList(v, components.size());
|
state.mkList(v, components.size());
|
||||||
unsigned int n = 0;
|
for (const auto & [n, component] : enumerate(components))
|
||||||
for (auto & component : components) {
|
(v.listElems()[n] = state.allocValue())->mkString(std::move(component));
|
||||||
auto listElem = v.listElems()[n++] = state.allocValue();
|
|
||||||
mkString(*listElem, std::move(component));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_splitVersion({
|
static RegisterPrimOp primop_splitVersion({
|
||||||
|
@ -3840,37 +3837,37 @@ void EvalState::createBaseEnv()
|
||||||
Value v;
|
Value v;
|
||||||
|
|
||||||
/* `builtins' must be first! */
|
/* `builtins' must be first! */
|
||||||
mkAttrs(v, 128);
|
v.mkAttrs(buildBindings(128).finish());
|
||||||
addConstant("builtins", v);
|
addConstant("builtins", v);
|
||||||
|
|
||||||
mkBool(v, true);
|
v.mkBool(true);
|
||||||
addConstant("true", v);
|
addConstant("true", v);
|
||||||
|
|
||||||
mkBool(v, false);
|
v.mkBool(false);
|
||||||
addConstant("false", v);
|
addConstant("false", v);
|
||||||
|
|
||||||
mkNull(v);
|
v.mkNull();
|
||||||
addConstant("null", v);
|
addConstant("null", v);
|
||||||
|
|
||||||
if (!evalSettings.pureEval) {
|
if (!evalSettings.pureEval) {
|
||||||
mkInt(v, time(0));
|
v.mkInt(time(0));
|
||||||
addConstant("__currentTime", v);
|
addConstant("__currentTime", v);
|
||||||
|
|
||||||
mkString(v, settings.thisSystem.get());
|
v.mkString(settings.thisSystem.get());
|
||||||
addConstant("__currentSystem", v);
|
addConstant("__currentSystem", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
mkString(v, nixVersion);
|
v.mkString(nixVersion);
|
||||||
addConstant("__nixVersion", v);
|
addConstant("__nixVersion", v);
|
||||||
|
|
||||||
mkString(v, store->storeDir);
|
v.mkString(store->storeDir);
|
||||||
addConstant("__storeDir", v);
|
addConstant("__storeDir", v);
|
||||||
|
|
||||||
/* Language version. This should be increased every time a new
|
/* Language version. This should be increased every time a new
|
||||||
language feature gets added. It's not necessary to increase it
|
language feature gets added. It's not necessary to increase it
|
||||||
when primops get added, because you can just use `builtins ?
|
when primops get added, because you can just use `builtins ?
|
||||||
primOp' to check. */
|
primOp' to check. */
|
||||||
mkInt(v, 6);
|
v.mkInt(6);
|
||||||
addConstant("__langVersion", v);
|
addConstant("__langVersion", v);
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
@ -3883,11 +3880,10 @@ void EvalState::createBaseEnv()
|
||||||
mkList(v, searchPath.size());
|
mkList(v, searchPath.size());
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for (auto & i : searchPath) {
|
for (auto & i : searchPath) {
|
||||||
auto v2 = v.listElems()[n++] = allocValue();
|
auto attrs = buildBindings(2);
|
||||||
mkAttrs(*v2, 2);
|
attrs.alloc("path").mkString(i.second);
|
||||||
mkString(*allocAttr(*v2, symbols.create("path")), i.second);
|
attrs.alloc("prefix").mkString(i.first);
|
||||||
mkString(*allocAttr(*v2, symbols.create("prefix")), i.first);
|
(v.listElems()[n++] = allocValue())->mkAttrs(attrs);
|
||||||
v2->attrs->sort();
|
|
||||||
}
|
}
|
||||||
addConstant("__nixPath", v);
|
addConstant("__nixPath", v);
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@ namespace nix {
|
||||||
static void prim_unsafeDiscardStringContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_unsafeDiscardStringContext(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
string s = state.coerceToString(pos, *args[0], context);
|
v.mkString(state.coerceToString(pos, *args[0], context));
|
||||||
mkString(v, s, PathSet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_unsafeDiscardStringContext("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
|
static RegisterPrimOp primop_unsafeDiscardStringContext("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext);
|
||||||
|
@ -18,7 +17,7 @@ static void prim_hasContext(EvalState & state, const Pos & pos, Value * * args,
|
||||||
{
|
{
|
||||||
PathSet context;
|
PathSet context;
|
||||||
state.forceString(*args[0], context, pos);
|
state.forceString(*args[0], context, pos);
|
||||||
mkBool(v, !context.empty());
|
v.mkBool(!context.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_hasContext("__hasContext", 1, prim_hasContext);
|
static RegisterPrimOp primop_hasContext("__hasContext", 1, prim_hasContext);
|
||||||
|
@ -39,7 +38,7 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & po
|
||||||
for (auto & p : context)
|
for (auto & p : context)
|
||||||
context2.insert(p.at(0) == '=' ? string(p, 1) : p);
|
context2.insert(p.at(0) == '=' ? string(p, 1) : p);
|
||||||
|
|
||||||
mkString(v, s, context2);
|
v.mkString(s, context2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_unsafeDiscardOutputDependency("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency);
|
static RegisterPrimOp primop_unsafeDiscardOutputDependency("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency);
|
||||||
|
@ -103,27 +102,26 @@ static void prim_getContext(EvalState & state, const Pos & pos, Value * * args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.mkAttrs(v, contextInfos.size());
|
auto attrs = state.buildBindings(contextInfos.size());
|
||||||
|
|
||||||
auto sPath = state.symbols.create("path");
|
auto sPath = state.symbols.create("path");
|
||||||
auto sAllOutputs = state.symbols.create("allOutputs");
|
auto sAllOutputs = state.symbols.create("allOutputs");
|
||||||
for (const auto & info : contextInfos) {
|
for (const auto & info : contextInfos) {
|
||||||
auto & infoVal = *state.allocAttr(v, state.symbols.create(info.first));
|
auto infoAttrs = state.buildBindings(3);
|
||||||
state.mkAttrs(infoVal, 3);
|
|
||||||
if (info.second.path)
|
if (info.second.path)
|
||||||
mkBool(*state.allocAttr(infoVal, sPath), true);
|
infoAttrs.alloc(sPath).mkBool(true);
|
||||||
if (info.second.allOutputs)
|
if (info.second.allOutputs)
|
||||||
mkBool(*state.allocAttr(infoVal, sAllOutputs), true);
|
infoAttrs.alloc(sAllOutputs).mkBool(true);
|
||||||
if (!info.second.outputs.empty()) {
|
if (!info.second.outputs.empty()) {
|
||||||
auto & outputsVal = *state.allocAttr(infoVal, state.sOutputs);
|
auto & outputsVal = infoAttrs.alloc(state.sOutputs);
|
||||||
state.mkList(outputsVal, info.second.outputs.size());
|
state.mkList(outputsVal, info.second.outputs.size());
|
||||||
size_t i = 0;
|
for (const auto & [i, output] : enumerate(info.second.outputs))
|
||||||
for (const auto & output : info.second.outputs)
|
(outputsVal.listElems()[i] = state.allocValue())->mkString(output);
|
||||||
mkString(*(outputsVal.listElems()[i++] = state.allocValue()), output);
|
|
||||||
}
|
}
|
||||||
infoVal.attrs->sort();
|
attrs.alloc(info.first).mkAttrs(infoAttrs);
|
||||||
}
|
}
|
||||||
v.attrs->sort();
|
|
||||||
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_getContext("__getContext", 1, prim_getContext);
|
static RegisterPrimOp primop_getContext("__getContext", 1, prim_getContext);
|
||||||
|
@ -187,7 +185,7 @@ static void prim_appendContext(EvalState & state, const Pos & pos, Value * * arg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mkString(v, orig, context);
|
v.mkString(orig, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_appendContext("__appendContext", 2, prim_appendContext);
|
static RegisterPrimOp primop_appendContext("__appendContext", 2, prim_appendContext);
|
||||||
|
|
|
@ -70,19 +70,19 @@ static void prim_fetchMercurial(EvalState & state, const Pos & pos, Value * * ar
|
||||||
// FIXME: use name
|
// FIXME: use name
|
||||||
auto [tree, input2] = input.fetch(state.store);
|
auto [tree, input2] = input.fetch(state.store);
|
||||||
|
|
||||||
state.mkAttrs(v, 8);
|
auto attrs2 = state.buildBindings(8);
|
||||||
auto storePath = state.store->printStorePath(tree.storePath);
|
auto storePath = state.store->printStorePath(tree.storePath);
|
||||||
mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
|
attrs2.alloc(state.sOutPath).mkString(storePath, {storePath});
|
||||||
if (input2.getRef())
|
if (input2.getRef())
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("branch")), *input2.getRef());
|
attrs2.alloc("branch").mkString(*input2.getRef());
|
||||||
// Backward compatibility: set 'rev' to
|
// Backward compatibility: set 'rev' to
|
||||||
// 0000000000000000000000000000000000000000 for a dirty tree.
|
// 0000000000000000000000000000000000000000 for a dirty tree.
|
||||||
auto rev2 = input2.getRev().value_or(Hash(htSHA1));
|
auto rev2 = input2.getRev().value_or(Hash(htSHA1));
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("rev")), rev2.gitRev());
|
attrs2.alloc("rev").mkString(rev2.gitRev());
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), std::string(rev2.gitRev(), 0, 12));
|
attrs2.alloc("shortRev").mkString(rev2.gitRev().substr(0, 12));
|
||||||
if (auto revCount = input2.getRevCount())
|
if (auto revCount = input2.getRevCount())
|
||||||
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *revCount);
|
attrs2.alloc("revCount").mkInt(*revCount);
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs2);
|
||||||
|
|
||||||
state.allowPath(tree.storePath);
|
state.allowPath(tree.storePath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,49 +21,48 @@ void emitTreeAttrs(
|
||||||
{
|
{
|
||||||
assert(input.isImmutable());
|
assert(input.isImmutable());
|
||||||
|
|
||||||
state.mkAttrs(v, 8);
|
auto attrs = state.buildBindings(8);
|
||||||
|
|
||||||
auto storePath = state.store->printStorePath(tree.storePath);
|
auto storePath = state.store->printStorePath(tree.storePath);
|
||||||
|
|
||||||
mkString(*state.allocAttr(v, state.sOutPath), storePath, PathSet({storePath}));
|
attrs.alloc(state.sOutPath).mkString(storePath, {storePath});
|
||||||
|
|
||||||
// FIXME: support arbitrary input attributes.
|
// FIXME: support arbitrary input attributes.
|
||||||
|
|
||||||
auto narHash = input.getNarHash();
|
auto narHash = input.getNarHash();
|
||||||
assert(narHash);
|
assert(narHash);
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("narHash")),
|
attrs.alloc("narHash").mkString(narHash->to_string(SRI, true));
|
||||||
narHash->to_string(SRI, true));
|
|
||||||
|
|
||||||
if (input.getType() == "git")
|
if (input.getType() == "git")
|
||||||
mkBool(*state.allocAttr(v, state.symbols.create("submodules")),
|
attrs.alloc("submodules").mkBool(
|
||||||
fetchers::maybeGetBoolAttr(input.attrs, "submodules").value_or(false));
|
fetchers::maybeGetBoolAttr(input.attrs, "submodules").value_or(false));
|
||||||
|
|
||||||
if (!forceDirty) {
|
if (!forceDirty) {
|
||||||
|
|
||||||
if (auto rev = input.getRev()) {
|
if (auto rev = input.getRev()) {
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("rev")), rev->gitRev());
|
attrs.alloc("rev").mkString(rev->gitRev());
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), rev->gitShortRev());
|
attrs.alloc("shortRev").mkString(rev->gitShortRev());
|
||||||
} else if (emptyRevFallback) {
|
} else if (emptyRevFallback) {
|
||||||
// Backwards compat for `builtins.fetchGit`: dirty repos return an empty sha1 as rev
|
// Backwards compat for `builtins.fetchGit`: dirty repos return an empty sha1 as rev
|
||||||
auto emptyHash = Hash(htSHA1);
|
auto emptyHash = Hash(htSHA1);
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("rev")), emptyHash.gitRev());
|
attrs.alloc("rev").mkString(emptyHash.gitRev());
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("shortRev")), emptyHash.gitShortRev());
|
attrs.alloc("shortRev").mkString(emptyHash.gitShortRev());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto revCount = input.getRevCount())
|
if (auto revCount = input.getRevCount())
|
||||||
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), *revCount);
|
attrs.alloc("revCount").mkInt(*revCount);
|
||||||
else if (emptyRevFallback)
|
else if (emptyRevFallback)
|
||||||
mkInt(*state.allocAttr(v, state.symbols.create("revCount")), 0);
|
attrs.alloc("revCount").mkInt(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto lastModified = input.getLastModified()) {
|
if (auto lastModified = input.getLastModified()) {
|
||||||
mkInt(*state.allocAttr(v, state.symbols.create("lastModified")), *lastModified);
|
attrs.alloc("lastModified").mkInt(*lastModified);
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("lastModifiedDate")),
|
attrs.alloc("lastModifiedDate").mkString(
|
||||||
fmt("%s", std::put_time(std::gmtime(&*lastModified), "%Y%m%d%H%M%S")));
|
fmt("%s", std::put_time(std::gmtime(&*lastModified), "%Y%m%d%H%M%S")));
|
||||||
}
|
}
|
||||||
|
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fixURI(std::string uri, EvalState & state, const std::string & defaultScheme = "file")
|
std::string fixURI(std::string uri, EvalState & state, const std::string & defaultScheme = "file")
|
||||||
|
@ -248,7 +247,7 @@ static void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
||||||
state.allowPath(storePath);
|
state.allowPath(storePath);
|
||||||
|
|
||||||
auto path = state.store->printStorePath(storePath);
|
auto path = state.store->printStorePath(storePath);
|
||||||
mkString(v, path, PathSet({path}));
|
v.mkString(path, PathSet({path}));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prim_fetchurl(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
static void prim_fetchurl(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||||
|
|
|
@ -24,15 +24,12 @@ static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
for (auto & i : table) { (void) i; size++; }
|
for (auto & i : table) { (void) i; size++; }
|
||||||
|
|
||||||
state.mkAttrs(v, size);
|
auto attrs = state.buildBindings(size);
|
||||||
|
|
||||||
for(auto & elem: table) {
|
for(auto & elem : table)
|
||||||
|
visit(attrs.alloc(elem.first), elem.second);
|
||||||
|
|
||||||
auto & v2 = *state.allocAttr(v, state.symbols.create(elem.first));
|
v.mkAttrs(attrs);
|
||||||
visit(v2, elem.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
v.attrs->sort();
|
|
||||||
}
|
}
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::array:
|
case toml::value_t::array:
|
||||||
|
@ -46,16 +43,16 @@ static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
}
|
}
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::boolean:
|
case toml::value_t::boolean:
|
||||||
mkBool(v, toml::get<bool>(t));
|
v.mkBool(toml::get<bool>(t));
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::integer:
|
case toml::value_t::integer:
|
||||||
mkInt(v, toml::get<int64_t>(t));
|
v.mkInt(toml::get<int64_t>(t));
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::floating:
|
case toml::value_t::floating:
|
||||||
mkFloat(v, toml::get<NixFloat>(t));
|
v.mkFloat(toml::get<NixFloat>(t));
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::string:
|
case toml::value_t::string:
|
||||||
mkString(v, toml::get<std::string>(t));
|
v.mkString(toml::get<std::string>(t));
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::local_datetime:
|
case toml::value_t::local_datetime:
|
||||||
case toml::value_t::offset_datetime:
|
case toml::value_t::offset_datetime:
|
||||||
|
@ -65,7 +62,7 @@ static void prim_fromTOML(EvalState & state, const Pos & pos, Value * * args, Va
|
||||||
throw std::runtime_error("Dates and times are not supported");
|
throw std::runtime_error("Dates and times are not supported");
|
||||||
break;;
|
break;;
|
||||||
case toml::value_t::empty:
|
case toml::value_t::empty:
|
||||||
mkNull(v);
|
v.mkNull();
|
||||||
break;;
|
break;;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
class BindingsBuilder;
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
tInt = 1,
|
tInt = 1,
|
||||||
|
@ -235,6 +237,15 @@ public:
|
||||||
string.context = context;
|
string.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mkString(std::string_view s);
|
||||||
|
|
||||||
|
void mkString(std::string_view s, const PathSet & context);
|
||||||
|
|
||||||
|
inline void mkString(const Symbol & s)
|
||||||
|
{
|
||||||
|
mkString(((const std::string &) s).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
inline void mkPath(const char * s)
|
inline void mkPath(const char * s)
|
||||||
{
|
{
|
||||||
clearValue();
|
clearValue();
|
||||||
|
@ -242,6 +253,8 @@ public:
|
||||||
path = s;
|
path = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mkPath(std::string_view s);
|
||||||
|
|
||||||
inline void mkNull()
|
inline void mkNull()
|
||||||
{
|
{
|
||||||
clearValue();
|
clearValue();
|
||||||
|
@ -255,6 +268,8 @@ public:
|
||||||
attrs = a;
|
attrs = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value & mkAttrs(BindingsBuilder & bindings);
|
||||||
|
|
||||||
inline void mkList(size_t size)
|
inline void mkList(size_t size)
|
||||||
{
|
{
|
||||||
clearValue();
|
clearValue();
|
||||||
|
@ -383,45 +398,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: Remove these static functions, replace call sites with v.mk* instead
|
|
||||||
static inline void mkInt(Value & v, NixInt n)
|
|
||||||
{
|
|
||||||
v.mkInt(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mkFloat(Value & v, NixFloat n)
|
|
||||||
{
|
|
||||||
v.mkFloat(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mkBool(Value & v, bool b)
|
|
||||||
{
|
|
||||||
v.mkBool(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mkNull(Value & v)
|
|
||||||
{
|
|
||||||
v.mkNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mkApp(Value & v, Value & left, Value & right)
|
|
||||||
{
|
|
||||||
v.mkApp(&left, &right);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mkString(Value & v, const Symbol & s)
|
|
||||||
{
|
|
||||||
v.mkString(((const string &) s).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void mkString(Value & v, const char * s);
|
|
||||||
|
|
||||||
|
|
||||||
void mkPath(Value & v, const char * s);
|
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
typedef std::vector<Value *, traceable_allocator<Value *> > ValueVector;
|
typedef std::vector<Value *, traceable_allocator<Value *> > ValueVector;
|
||||||
typedef std::map<Symbol, Value *, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, Value *> > > ValueMap;
|
typedef std::map<Symbol, Value *, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, Value *> > > ValueMap;
|
||||||
|
|
|
@ -258,13 +258,10 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
auto autoArgs = myArgs.getAutoArgs(*state);
|
auto autoArgs = myArgs.getAutoArgs(*state);
|
||||||
|
|
||||||
if (runEnv) {
|
if (runEnv) {
|
||||||
auto newArgs = state->allocBindings(autoArgs->size() + 1);
|
auto newArgs = state->buildBindings(autoArgs->size() + 1);
|
||||||
auto tru = state->allocValue();
|
newArgs.alloc("inNixShell").mkBool(true);
|
||||||
mkBool(*tru, true);
|
for (auto & i : *autoArgs) newArgs.insert(i);
|
||||||
newArgs->push_back(Attr(state->symbols.create("inNixShell"), tru));
|
autoArgs = newArgs.finish();
|
||||||
for (auto & i : *autoArgs) newArgs->push_back(i);
|
|
||||||
newArgs->sort();
|
|
||||||
autoArgs = newArgs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packages) {
|
if (packages) {
|
||||||
|
|
|
@ -98,8 +98,11 @@ static bool isNixExpr(const Path & path, struct stat & st)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static constexpr size_t maxAttrs = 1024;
|
||||||
|
|
||||||
|
|
||||||
static void getAllExprs(EvalState & state,
|
static void getAllExprs(EvalState & state,
|
||||||
const Path & path, StringSet & attrs, Value & v)
|
const Path & path, StringSet & seen, BindingsBuilder & attrs)
|
||||||
{
|
{
|
||||||
StringSet namesSorted;
|
StringSet namesSorted;
|
||||||
for (auto & i : readDirectory(path)) namesSorted.insert(i.name);
|
for (auto & i : readDirectory(path)) namesSorted.insert(i.name);
|
||||||
|
@ -124,22 +127,21 @@ static void getAllExprs(EvalState & state,
|
||||||
string attrName = i;
|
string attrName = i;
|
||||||
if (hasSuffix(attrName, ".nix"))
|
if (hasSuffix(attrName, ".nix"))
|
||||||
attrName = string(attrName, 0, attrName.size() - 4);
|
attrName = string(attrName, 0, attrName.size() - 4);
|
||||||
if (!attrs.insert(attrName).second) {
|
if (!seen.insert(attrName).second) {
|
||||||
printError("warning: name collision in input Nix expressions, skipping '%1%'", path2);
|
printError("warning: name collision in input Nix expressions, skipping '%1%'", path2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Load the expression on demand. */
|
/* Load the expression on demand. */
|
||||||
Value & vFun = state.getBuiltin("import");
|
auto vArg = state.allocValue();
|
||||||
Value & vArg(*state.allocValue());
|
vArg->mkString(path2);
|
||||||
mkString(vArg, path2);
|
if (seen.size() == maxAttrs)
|
||||||
if (v.attrs->size() == v.attrs->capacity())
|
|
||||||
throw Error("too many Nix expressions in directory '%1%'", path);
|
throw Error("too many Nix expressions in directory '%1%'", path);
|
||||||
mkApp(*state.allocAttr(v, state.symbols.create(attrName)), vFun, vArg);
|
attrs.alloc(attrName).mkApp(&state.getBuiltin("import"), vArg);
|
||||||
}
|
}
|
||||||
else if (S_ISDIR(st.st_mode))
|
else if (S_ISDIR(st.st_mode))
|
||||||
/* `path2' is a directory (with no default.nix in it);
|
/* `path2' is a directory (with no default.nix in it);
|
||||||
recurse into it. */
|
recurse into it. */
|
||||||
getAllExprs(state, path2, attrs, v);
|
getAllExprs(state, path2, seen, attrs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,11 +163,11 @@ static void loadSourceExpr(EvalState & state, const Path & path, Value & v)
|
||||||
~/.nix-defexpr directory that includes some system-wide
|
~/.nix-defexpr directory that includes some system-wide
|
||||||
directory). */
|
directory). */
|
||||||
else if (S_ISDIR(st.st_mode)) {
|
else if (S_ISDIR(st.st_mode)) {
|
||||||
state.mkAttrs(v, 1024);
|
auto attrs = state.buildBindings(maxAttrs);
|
||||||
state.mkList(*state.allocAttr(v, state.symbols.create("_combineChannels")), 0);
|
attrs.alloc("_combineChannels").mkList(0);
|
||||||
StringSet attrs;
|
StringSet seen;
|
||||||
getAllExprs(state, path, attrs, v);
|
getAllExprs(state, path, seen, attrs);
|
||||||
v.attrs->sort();
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
else throw Error("path '%s' is not a directory or a Nix expression", path);
|
else throw Error("path '%s' is not a directory or a Nix expression", path);
|
||||||
|
@ -406,7 +408,7 @@ static void queryInstSources(EvalState & state,
|
||||||
Expr * eFun = state.parseExprFromString(i, absPath("."));
|
Expr * eFun = state.parseExprFromString(i, absPath("."));
|
||||||
Value vFun, vTmp;
|
Value vFun, vTmp;
|
||||||
state.eval(eFun, vFun);
|
state.eval(eFun, vFun);
|
||||||
mkApp(vTmp, vFun, vArg);
|
vTmp.mkApp(&vFun, &vArg);
|
||||||
getDerivations(state, vTmp, "", *instSource.autoArgs, elems, true);
|
getDerivations(state, vTmp, "", *instSource.autoArgs, elems, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,8 +678,8 @@ static void opUpgrade(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
static void setMetaFlag(EvalState & state, DrvInfo & drv,
|
static void setMetaFlag(EvalState & state, DrvInfo & drv,
|
||||||
const string & name, const string & value)
|
const string & name, const string & value)
|
||||||
{
|
{
|
||||||
Value * v = state.allocValue();
|
auto v = state.allocValue();
|
||||||
mkString(*v, value.c_str());
|
v->mkString(value);
|
||||||
drv.setMeta(name, v);
|
drv.setMeta(name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
StorePathSet references;
|
StorePathSet references;
|
||||||
Value manifest;
|
Value manifest;
|
||||||
state.mkList(manifest, elems.size());
|
state.mkList(manifest, elems.size());
|
||||||
unsigned int n = 0;
|
size_t n = 0;
|
||||||
for (auto & i : elems) {
|
for (auto & i : elems) {
|
||||||
/* Create a pseudo-derivation containing the name, system,
|
/* Create a pseudo-derivation containing the name, system,
|
||||||
output paths, and optionally the derivation path, as well
|
output paths, and optionally the derivation path, as well
|
||||||
|
@ -59,28 +59,25 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
DrvInfo::Outputs outputs = i.queryOutputs(true);
|
DrvInfo::Outputs outputs = i.queryOutputs(true);
|
||||||
StringSet metaNames = i.queryMetaNames();
|
StringSet metaNames = i.queryMetaNames();
|
||||||
|
|
||||||
Value & v(*state.allocValue());
|
auto attrs = state.buildBindings(7 + outputs.size());
|
||||||
manifest.listElems()[n++] = &v;
|
|
||||||
state.mkAttrs(v, 7 + outputs.size());
|
|
||||||
|
|
||||||
mkString(*state.allocAttr(v, state.sType), "derivation");
|
attrs.alloc(state.sType).mkString("derivation");
|
||||||
mkString(*state.allocAttr(v, state.sName), i.queryName());
|
attrs.alloc(state.sName).mkString(i.queryName());
|
||||||
auto system = i.querySystem();
|
auto system = i.querySystem();
|
||||||
if (!system.empty())
|
if (!system.empty())
|
||||||
mkString(*state.allocAttr(v, state.sSystem), system);
|
attrs.alloc(state.sSystem).mkString(system);
|
||||||
mkString(*state.allocAttr(v, state.sOutPath), i.queryOutPath());
|
attrs.alloc(state.sOutPath).mkString(i.queryOutPath());
|
||||||
if (drvPath != "")
|
if (drvPath != "")
|
||||||
mkString(*state.allocAttr(v, state.sDrvPath), i.queryDrvPath());
|
attrs.alloc(state.sDrvPath).mkString(i.queryDrvPath());
|
||||||
|
|
||||||
// Copy each output meant for installation.
|
// Copy each output meant for installation.
|
||||||
Value & vOutputs = *state.allocAttr(v, state.sOutputs);
|
auto & vOutputs = attrs.alloc(state.sOutputs);
|
||||||
state.mkList(vOutputs, outputs.size());
|
state.mkList(vOutputs, outputs.size());
|
||||||
unsigned int m = 0;
|
for (const auto & [m, j] : enumerate(outputs)) {
|
||||||
for (auto & j : outputs) {
|
(vOutputs.listElems()[m] = state.allocValue())->mkString(j.first);
|
||||||
mkString(*(vOutputs.listElems()[m++] = state.allocValue()), j.first);
|
auto outputAttrs = state.buildBindings(2);
|
||||||
Value & vOutputs = *state.allocAttr(v, state.symbols.create(j.first));
|
outputAttrs.alloc(state.sOutPath).mkString(j.second);
|
||||||
state.mkAttrs(vOutputs, 2);
|
attrs.alloc(j.first).mkAttrs(outputAttrs);
|
||||||
mkString(*state.allocAttr(vOutputs, state.sOutPath), j.second);
|
|
||||||
|
|
||||||
/* This is only necessary when installing store paths, e.g.,
|
/* This is only necessary when installing store paths, e.g.,
|
||||||
`nix-env -i /nix/store/abcd...-foo'. */
|
`nix-env -i /nix/store/abcd...-foo'. */
|
||||||
|
@ -91,15 +88,16 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the meta attributes.
|
// Copy the meta attributes.
|
||||||
Value & vMeta = *state.allocAttr(v, state.sMeta);
|
auto meta = state.buildBindings(metaNames.size());
|
||||||
state.mkAttrs(vMeta, metaNames.size());
|
|
||||||
for (auto & j : metaNames) {
|
for (auto & j : metaNames) {
|
||||||
Value * v = i.queryMeta(j);
|
Value * v = i.queryMeta(j);
|
||||||
if (!v) continue;
|
if (!v) continue;
|
||||||
vMeta.attrs->push_back(Attr(state.symbols.create(j), v));
|
meta.insert(state.symbols.create(j), v);
|
||||||
}
|
}
|
||||||
vMeta.attrs->sort();
|
|
||||||
v.attrs->sort();
|
attrs.alloc(state.sMeta).mkAttrs(meta);
|
||||||
|
|
||||||
|
(manifest.listElems()[n++] = state.allocValue())->mkAttrs(attrs);
|
||||||
|
|
||||||
if (drvPath != "") references.insert(state.store->parseStorePath(drvPath));
|
if (drvPath != "") references.insert(state.store->parseStorePath(drvPath));
|
||||||
}
|
}
|
||||||
|
@ -118,13 +116,16 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
|
|
||||||
/* Construct a Nix expression that calls the user environment
|
/* Construct a Nix expression that calls the user environment
|
||||||
builder with the manifest as argument. */
|
builder with the manifest as argument. */
|
||||||
Value args, topLevel;
|
auto attrs = state.buildBindings(3);
|
||||||
state.mkAttrs(args, 3);
|
attrs.alloc("manifest").mkString(
|
||||||
mkString(*state.allocAttr(args, state.symbols.create("manifest")),
|
state.store->printStorePath(manifestFile),
|
||||||
state.store->printStorePath(manifestFile), {state.store->printStorePath(manifestFile)});
|
{state.store->printStorePath(manifestFile)});
|
||||||
args.attrs->push_back(Attr(state.symbols.create("derivations"), &manifest));
|
attrs.insert(state.symbols.create("derivations"), &manifest);
|
||||||
args.attrs->sort();
|
Value args;
|
||||||
mkApp(topLevel, envBuilder, args);
|
args.mkAttrs(attrs);
|
||||||
|
|
||||||
|
Value topLevel;
|
||||||
|
topLevel.mkApp(&envBuilder, &args);
|
||||||
|
|
||||||
/* Evaluate it. */
|
/* Evaluate it. */
|
||||||
debug("evaluating user environment builder");
|
debug("evaluating user environment builder");
|
||||||
|
|
|
@ -78,20 +78,20 @@ struct CmdBundle : InstallableCommand
|
||||||
Strings{bundlerName == "" ? "defaultBundler" : bundlerName},
|
Strings{bundlerName == "" ? "defaultBundler" : bundlerName},
|
||||||
Strings({"bundlers."}), lockFlags);
|
Strings({"bundlers."}), lockFlags);
|
||||||
|
|
||||||
Value * arg = evalState->allocValue();
|
auto attrs = evalState->buildBindings(2);
|
||||||
evalState->mkAttrs(*arg, 2);
|
|
||||||
|
|
||||||
PathSet context;
|
PathSet context;
|
||||||
for (auto & i : app.context)
|
for (auto & i : app.context)
|
||||||
context.insert("=" + store->printStorePath(i.path));
|
context.insert("=" + store->printStorePath(i.path));
|
||||||
mkString(*evalState->allocAttr(*arg, evalState->symbols.create("program")), app.program, context);
|
attrs.alloc("program").mkString(app.program, context);
|
||||||
|
|
||||||
mkString(*evalState->allocAttr(*arg, evalState->symbols.create("system")), settings.thisSystem.get());
|
attrs.alloc("system").mkString(settings.thisSystem.get());
|
||||||
|
|
||||||
arg->attrs->sort();
|
|
||||||
|
|
||||||
auto vRes = evalState->allocValue();
|
auto vRes = evalState->allocValue();
|
||||||
evalState->callFunction(*bundler.toValue(*evalState).first, *arg, *vRes, noPos);
|
evalState->callFunction(
|
||||||
|
*bundler.toValue(*evalState).first,
|
||||||
|
evalState->allocValue()->mkAttrs(attrs),
|
||||||
|
*vRes, noPos);
|
||||||
|
|
||||||
if (!evalState->isDerivation(*vRes))
|
if (!evalState->isDerivation(*vRes))
|
||||||
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
||||||
|
|
|
@ -187,14 +187,11 @@ static void showHelp(std::vector<std::string> subcommand, MultiCommand & topleve
|
||||||
, "/"),
|
, "/"),
|
||||||
*vUtils);
|
*vUtils);
|
||||||
|
|
||||||
auto vArgs = state.allocValue();
|
auto attrs = state.buildBindings(16);
|
||||||
state.mkAttrs(*vArgs, 16);
|
attrs.alloc("command").mkString(toplevel.toJSON().dump());
|
||||||
auto vJson = state.allocAttr(*vArgs, state.symbols.create("command"));
|
|
||||||
mkString(*vJson, toplevel.toJSON().dump());
|
|
||||||
vArgs->attrs->sort();
|
|
||||||
|
|
||||||
auto vRes = state.allocValue();
|
auto vRes = state.allocValue();
|
||||||
state.callFunction(*vGenerateManpage, *vArgs, *vRes, noPos);
|
state.callFunction(*vGenerateManpage, state.allocValue()->mkAttrs(attrs), *vRes, noPos);
|
||||||
|
|
||||||
auto attr = vRes->attrs->get(state.symbols.create(mdName + ".md"));
|
auto attr = vRes->attrs->get(state.symbols.create(mdName + ".md"));
|
||||||
if (!attr)
|
if (!attr)
|
||||||
|
|
|
@ -16,9 +16,9 @@ static GlobalConfig::Register rs(&mySettings);
|
||||||
static void prim_anotherNull (EvalState & state, const Pos & pos, Value ** args, Value & v)
|
static void prim_anotherNull (EvalState & state, const Pos & pos, Value ** args, Value & v)
|
||||||
{
|
{
|
||||||
if (mySettings.settingSet)
|
if (mySettings.settingSet)
|
||||||
mkNull(v);
|
v.mkNull();
|
||||||
else
|
else
|
||||||
mkBool(v, false);
|
v.mkBool(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp rp("anotherNull", 0, prim_anotherNull);
|
static RegisterPrimOp rp("anotherNull", 0, prim_anotherNull);
|
||||||
|
|
Loading…
Reference in a new issue