forked from lix-project/lix
store Symbols in a table as well, like positions
this slightly increases the amount of memory used for any given symbol, but this increase is more than made up for if the symbol is referenced more than once in the EvalState that holds it. on average every symbol should be referenced at least twice (once to introduce a binding, once to use it), so we expect no increase in memory on average. symbol tables are limited to 2³² entries like position tables, and similar arguments apply to why overflow is not likely: 2³² symbols would require as many string instances (at 24 bytes each) and map entries (at 24 bytes or more each, assuming that the map holds on average at most one item per bucket as the docs say). a full symbol table would require at least 192GB of memory just for symbols, which is well out of reach. (an ofborg eval of nixpks today creates less than a million symbols!)
This commit is contained in:
parent
00a3280232
commit
8775be3393
|
@ -235,7 +235,7 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
|
||||||
|
|
||||||
if (v2.type() == nAttrs) {
|
if (v2.type() == nAttrs) {
|
||||||
for (auto & i : *v2.attrs) {
|
for (auto & i : *v2.attrs) {
|
||||||
std::string name = i.name;
|
std::string name = state->symbols[i.name];
|
||||||
if (name.find(searchWord) == 0) {
|
if (name.find(searchWord) == 0) {
|
||||||
if (prefix_ == "")
|
if (prefix_ == "")
|
||||||
completions->add(name);
|
completions->add(name);
|
||||||
|
@ -600,7 +600,7 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
|
||||||
|
|
||||||
auto drvInfo = DerivationInfo {
|
auto drvInfo = DerivationInfo {
|
||||||
std::move(drvPath),
|
std::move(drvPath),
|
||||||
attr->getAttr(state->sOutputName)->getString()
|
attr->getAttr("outputName")->getString()
|
||||||
};
|
};
|
||||||
|
|
||||||
return {attrPath, getLockedFlake()->flake.lockedRef, std::move(drvInfo)};
|
return {attrPath, getLockedFlake()->flake.lockedRef, std::move(drvInfo)};
|
||||||
|
|
|
@ -36,7 +36,7 @@ std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s)
|
||||||
{
|
{
|
||||||
std::vector<Symbol> res;
|
std::vector<Symbol> res;
|
||||||
for (auto & a : parseAttrPath(s))
|
for (auto & a : parseAttrPath(s))
|
||||||
res.push_back(state.symbols.create(a));
|
res.emplace_back(a);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||||
if (a == v->attrs->end()) {
|
if (a == v->attrs->end()) {
|
||||||
std::set<std::string> attrNames;
|
std::set<std::string> attrNames;
|
||||||
for (auto & attr : *v->attrs)
|
for (auto & attr : *v->attrs)
|
||||||
attrNames.insert(attr.name);
|
attrNames.insert(state.symbols[attr.name]);
|
||||||
|
|
||||||
auto suggestions = Suggestions::bestMatches(attrNames, attr);
|
auto suggestions = Suggestions::bestMatches(attrNames, attr);
|
||||||
throw AttrPathNotFound(suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath);
|
throw AttrPathNotFound(suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath);
|
||||||
|
|
|
@ -26,7 +26,7 @@ Bindings * EvalState::allocBindings(size_t capacity)
|
||||||
/* Create a new attribute named 'name' on an existing attribute set stored
|
/* Create a new attribute named 'name' on an existing attribute set stored
|
||||||
in 'vAttrs' and return the newly allocated Value which is associated with
|
in 'vAttrs' and return the newly allocated Value which is associated with
|
||||||
this attribute. */
|
this attribute. */
|
||||||
Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
|
Value * EvalState::allocAttr(Value & vAttrs, const SymbolIdx & name)
|
||||||
{
|
{
|
||||||
Value * v = allocValue();
|
Value * v = allocValue();
|
||||||
vAttrs.attrs->push_back(Attr(name, v));
|
vAttrs.attrs->push_back(Attr(name, v));
|
||||||
|
@ -40,7 +40,7 @@ Value * EvalState::allocAttr(Value & vAttrs, std::string_view name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Value & BindingsBuilder::alloc(const Symbol & name, PosIdx pos)
|
Value & BindingsBuilder::alloc(const SymbolIdx & name, PosIdx pos)
|
||||||
{
|
{
|
||||||
auto value = state.allocValue();
|
auto value = state.allocValue();
|
||||||
bindings->push_back(Attr(name, value, pos));
|
bindings->push_back(Attr(name, value, pos));
|
||||||
|
|
|
@ -15,10 +15,10 @@ struct Value;
|
||||||
/* Map one attribute name to its value. */
|
/* Map one attribute name to its value. */
|
||||||
struct Attr
|
struct Attr
|
||||||
{
|
{
|
||||||
Symbol name;
|
SymbolIdx name;
|
||||||
Value * value;
|
Value * value;
|
||||||
PosIdx pos;
|
PosIdx pos;
|
||||||
Attr(Symbol name, Value * value, PosIdx pos = noPos)
|
Attr(SymbolIdx name, Value * value, PosIdx pos = noPos)
|
||||||
: name(name), value(value), pos(pos) { };
|
: name(name), value(value), pos(pos) { };
|
||||||
Attr() { };
|
Attr() { };
|
||||||
bool operator < (const Attr & a) const
|
bool operator < (const Attr & a) const
|
||||||
|
@ -57,7 +57,7 @@ public:
|
||||||
attrs[size_++] = attr;
|
attrs[size_++] = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator find(const Symbol & name)
|
iterator find(const SymbolIdx & name)
|
||||||
{
|
{
|
||||||
Attr key(name, 0);
|
Attr key(name, 0);
|
||||||
iterator i = std::lower_bound(begin(), end(), key);
|
iterator i = std::lower_bound(begin(), end(), key);
|
||||||
|
@ -65,7 +65,7 @@ public:
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
|
|
||||||
Attr * get(const Symbol & name)
|
Attr * get(const SymbolIdx & name)
|
||||||
{
|
{
|
||||||
Attr key(name, 0);
|
Attr key(name, 0);
|
||||||
iterator i = std::lower_bound(begin(), end(), key);
|
iterator i = std::lower_bound(begin(), end(), key);
|
||||||
|
@ -86,14 +86,15 @@ public:
|
||||||
size_t capacity() { return capacity_; }
|
size_t capacity() { return capacity_; }
|
||||||
|
|
||||||
/* Returns the attributes in lexicographically sorted order. */
|
/* Returns the attributes in lexicographically sorted order. */
|
||||||
std::vector<const Attr *> lexicographicOrder() const
|
std::vector<const Attr *> lexicographicOrder(const SymbolTable & symbols) const
|
||||||
{
|
{
|
||||||
std::vector<const Attr *> res;
|
std::vector<const Attr *> res;
|
||||||
res.reserve(size_);
|
res.reserve(size_);
|
||||||
for (size_t n = 0; n < size_; n++)
|
for (size_t n = 0; n < size_; n++)
|
||||||
res.emplace_back(&attrs[n]);
|
res.emplace_back(&attrs[n]);
|
||||||
std::sort(res.begin(), res.end(), [](const Attr * a, const Attr * b) {
|
std::sort(res.begin(), res.end(), [&](const Attr * a, const Attr * b) {
|
||||||
return (const std::string &) a->name < (const std::string &) b->name;
|
std::string_view sa = symbols[a->name], sb = symbols[b->name];
|
||||||
|
return sa < sb;
|
||||||
});
|
});
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +119,7 @@ public:
|
||||||
: bindings(bindings), state(state)
|
: bindings(bindings), state(state)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void insert(Symbol name, Value * value, PosIdx pos = noPos)
|
void insert(SymbolIdx name, Value * value, PosIdx pos = noPos)
|
||||||
{
|
{
|
||||||
insert(Attr(name, value, pos));
|
insert(Attr(name, value, pos));
|
||||||
}
|
}
|
||||||
|
@ -133,7 +134,7 @@ public:
|
||||||
bindings->push_back(attr);
|
bindings->push_back(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value & alloc(const Symbol & name, PosIdx pos = noPos);
|
Value & alloc(const SymbolIdx & name, PosIdx pos = noPos);
|
||||||
|
|
||||||
Value & alloc(std::string_view name, PosIdx pos = noPos);
|
Value & alloc(std::string_view name, PosIdx pos = noPos);
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,7 @@ struct AttrDb
|
||||||
std::vector<Symbol> attrs;
|
std::vector<Symbol> attrs;
|
||||||
auto queryAttributes(state->queryAttributes.use()(rowId));
|
auto queryAttributes(state->queryAttributes.use()(rowId));
|
||||||
while (queryAttributes.next())
|
while (queryAttributes.next())
|
||||||
attrs.push_back(symbols.create(queryAttributes.getStr(0)));
|
attrs.emplace_back(queryAttributes.getStr(0));
|
||||||
return {{rowId, attrs}};
|
return {{rowId, attrs}};
|
||||||
}
|
}
|
||||||
case AttrType::String: {
|
case AttrType::String: {
|
||||||
|
@ -325,7 +325,7 @@ AttrCursor::AttrCursor(
|
||||||
AttrKey AttrCursor::getKey()
|
AttrKey AttrCursor::getKey()
|
||||||
{
|
{
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return {0, root->state.sEpsilon};
|
return {0, {""}};
|
||||||
if (!parent->first->cachedValue) {
|
if (!parent->first->cachedValue) {
|
||||||
parent->first->cachedValue = root->db->getAttr(
|
parent->first->cachedValue = root->db->getAttr(
|
||||||
parent->first->getKey(), root->state.symbols);
|
parent->first->getKey(), root->state.symbols);
|
||||||
|
@ -340,7 +340,7 @@ Value & AttrCursor::getValue()
|
||||||
if (parent) {
|
if (parent) {
|
||||||
auto & vParent = parent->first->getValue();
|
auto & vParent = parent->first->getValue();
|
||||||
root->state.forceAttrs(vParent, noPos);
|
root->state.forceAttrs(vParent, noPos);
|
||||||
auto attr = vParent.attrs->get(parent->second);
|
auto attr = vParent.attrs->get(root->state.symbols.create(parent->second));
|
||||||
if (!attr)
|
if (!attr)
|
||||||
throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr());
|
throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr());
|
||||||
_value = allocRootValue(attr->value);
|
_value = allocRootValue(attr->value);
|
||||||
|
@ -419,7 +419,7 @@ Suggestions AttrCursor::getSuggestionsForAttr(Symbol name)
|
||||||
return Suggestions::bestMatches(strAttrNames, name);
|
return Suggestions::bestMatches(strAttrNames, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErrors)
|
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name, bool forceErrors)
|
||||||
{
|
{
|
||||||
if (root->db) {
|
if (root->db) {
|
||||||
if (!cachedValue)
|
if (!cachedValue)
|
||||||
|
@ -461,10 +461,10 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
|
||||||
|
|
||||||
for (auto & attr : *v.attrs) {
|
for (auto & attr : *v.attrs) {
|
||||||
if (root->db)
|
if (root->db)
|
||||||
root->db->setPlaceholder({cachedValue->first, attr.name});
|
root->db->setPlaceholder({cachedValue->first, root->state.symbols[attr.name]});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto attr = v.attrs->get(name);
|
auto attr = v.attrs->get(root->state.symbols.create(name));
|
||||||
|
|
||||||
if (!attr) {
|
if (!attr) {
|
||||||
if (root->db) {
|
if (root->db) {
|
||||||
|
@ -486,12 +486,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
|
||||||
root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2));
|
root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
|
ref<AttrCursor> AttrCursor::getAttr(std::string_view name, bool forceErrors)
|
||||||
{
|
|
||||||
return maybeGetAttr(root->state.symbols.create(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
|
|
||||||
{
|
{
|
||||||
auto p = maybeGetAttr(name, forceErrors);
|
auto p = maybeGetAttr(name, forceErrors);
|
||||||
if (!p)
|
if (!p)
|
||||||
|
@ -499,11 +494,6 @@ ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
|
||||||
return ref(p);
|
return ref(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<AttrCursor> AttrCursor::getAttr(std::string_view name)
|
|
||||||
{
|
|
||||||
return getAttr(root->state.symbols.create(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
|
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
|
||||||
{
|
{
|
||||||
auto res = shared_from_this();
|
auto res = shared_from_this();
|
||||||
|
@ -616,7 +606,7 @@ std::vector<Symbol> AttrCursor::getAttrs()
|
||||||
|
|
||||||
std::vector<Symbol> attrs;
|
std::vector<Symbol> attrs;
|
||||||
for (auto & attr : *getValue().attrs)
|
for (auto & attr : *getValue().attrs)
|
||||||
attrs.push_back(attr.name);
|
attrs.push_back(root->state.symbols[attr.name]);
|
||||||
std::sort(attrs.begin(), attrs.end(), [](const Symbol & a, const Symbol & b) {
|
std::sort(attrs.begin(), attrs.end(), [](const Symbol & a, const Symbol & b) {
|
||||||
return (const std::string &) a < (const std::string &) b;
|
return (const std::string &) a < (const std::string &) b;
|
||||||
});
|
});
|
||||||
|
@ -635,7 +625,7 @@ bool AttrCursor::isDerivation()
|
||||||
|
|
||||||
StorePath AttrCursor::forceDerivation()
|
StorePath AttrCursor::forceDerivation()
|
||||||
{
|
{
|
||||||
auto aDrvPath = getAttr(root->state.sDrvPath, true);
|
auto aDrvPath = getAttr("drvPath", true);
|
||||||
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
|
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
|
||||||
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
|
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
|
||||||
/* The eval cache contains 'drvPath', but the actual path has
|
/* The eval cache contains 'drvPath', but the actual path has
|
||||||
|
|
|
@ -96,13 +96,9 @@ public:
|
||||||
|
|
||||||
Suggestions getSuggestionsForAttr(Symbol name);
|
Suggestions getSuggestionsForAttr(Symbol name);
|
||||||
|
|
||||||
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false);
|
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name, bool forceErrors = false);
|
||||||
|
|
||||||
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
|
ref<AttrCursor> getAttr(std::string_view name, bool forceErrors = false);
|
||||||
|
|
||||||
ref<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
|
|
||||||
|
|
||||||
ref<AttrCursor> getAttr(std::string_view name);
|
|
||||||
|
|
||||||
/* Get an attribute along a chain of attrsets. Note that this does
|
/* Get an attribute along a chain of attrsets. Note that this does
|
||||||
not auto-call functors or functions. */
|
not auto-call functors or functions. */
|
||||||
|
|
|
@ -96,7 +96,8 @@ RootValue allocRootValue(Value * v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Value::print(std::ostream & str, std::set<const void *> * seen) const
|
void Value::print(const SymbolTable & symbols, std::ostream & str,
|
||||||
|
std::set<const void *> * seen) const
|
||||||
{
|
{
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
||||||
|
@ -129,9 +130,9 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
|
||||||
str << "«repeated»";
|
str << "«repeated»";
|
||||||
else {
|
else {
|
||||||
str << "{ ";
|
str << "{ ";
|
||||||
for (auto & i : attrs->lexicographicOrder()) {
|
for (auto & i : attrs->lexicographicOrder(symbols)) {
|
||||||
str << i->name << " = ";
|
str << symbols[i->name] << " = ";
|
||||||
i->value->print(str, seen);
|
i->value->print(symbols, str, seen);
|
||||||
str << "; ";
|
str << "; ";
|
||||||
}
|
}
|
||||||
str << "}";
|
str << "}";
|
||||||
|
@ -146,7 +147,7 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
|
||||||
else {
|
else {
|
||||||
str << "[ ";
|
str << "[ ";
|
||||||
for (auto v2 : listItems()) {
|
for (auto v2 : listItems()) {
|
||||||
v2->print(str, seen);
|
v2->print(symbols, str, seen);
|
||||||
str << " ";
|
str << " ";
|
||||||
}
|
}
|
||||||
str << "]";
|
str << "]";
|
||||||
|
@ -177,17 +178,18 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Value::print(std::ostream & str, bool showRepeated) const
|
void Value::print(const SymbolTable & symbols, std::ostream & str, bool showRepeated) const
|
||||||
{
|
{
|
||||||
std::set<const void *> seen;
|
std::set<const void *> seen;
|
||||||
print(str, showRepeated ? nullptr : &seen);
|
print(symbols, str, showRepeated ? nullptr : &seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const Value & v)
|
std::string printValue(const EvalState & state, const Value & v)
|
||||||
{
|
{
|
||||||
v.print(str, false);
|
std::ostringstream out;
|
||||||
return str;
|
v.print(state.symbols, out);
|
||||||
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -306,9 +308,9 @@ static BoehmGCStackAllocator boehmGCStackAllocator;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static Symbol getName(const AttrName & name, EvalState & state, Env & env)
|
static SymbolIdx getName(const AttrName & name, EvalState & state, Env & env)
|
||||||
{
|
{
|
||||||
if (name.symbol.set()) {
|
if (name.symbol) {
|
||||||
return name.symbol;
|
return name.symbol;
|
||||||
} else {
|
} else {
|
||||||
Value nameValue;
|
Value nameValue;
|
||||||
|
@ -639,7 +641,7 @@ Value * EvalState::addPrimOp(const std::string & name,
|
||||||
size_t arity, PrimOpFun primOp)
|
size_t arity, PrimOpFun primOp)
|
||||||
{
|
{
|
||||||
auto name2 = name.substr(0, 2) == "__" ? name.substr(2) : name;
|
auto name2 = name.substr(0, 2) == "__" ? name.substr(2) : name;
|
||||||
Symbol sym = symbols.create(name2);
|
auto sym = symbols.create(name2);
|
||||||
|
|
||||||
/* Hack to make constants lazy: turn them into a application of
|
/* Hack to make constants lazy: turn them into a application of
|
||||||
the primop to a dummy value. */
|
the primop to a dummy value. */
|
||||||
|
@ -673,7 +675,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
|
||||||
return addConstant(primOp.name, v);
|
return addConstant(primOp.name, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol envName = symbols.create(primOp.name);
|
auto envName = symbols.create(primOp.name);
|
||||||
if (hasPrefix(primOp.name, "__"))
|
if (hasPrefix(primOp.name, "__"))
|
||||||
primOp.name = primOp.name.substr(2);
|
primOp.name = primOp.name.substr(2);
|
||||||
|
|
||||||
|
@ -767,11 +769,11 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::throwEvalError(const PosIdx p1, const char * s, const Symbol & sym, const PosIdx p2) const
|
void EvalState::throwEvalError(const PosIdx p1, const char * s, const SymbolIdx sym, const PosIdx p2) const
|
||||||
{
|
{
|
||||||
// p1 is where the error occurred; p2 is a position mentioned in the message.
|
// p1 is where the error occurred; p2 is a position mentioned in the message.
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt(s, sym, positions[p2]),
|
.msg = hintfmt(s, symbols[sym], positions[p2]),
|
||||||
.errPos = positions[p1]
|
.errPos = positions[p1]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -785,19 +787,19 @@ void EvalState::throwTypeError(const PosIdx pos, const char * s) const
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun,
|
void EvalState::throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun,
|
||||||
const Symbol & s2) const
|
const SymbolIdx s2) const
|
||||||
{
|
{
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
.msg = hintfmt(s, fun.showNamePos(positions), s2),
|
.msg = hintfmt(s, fun.showNamePos(*this), symbols[s2]),
|
||||||
.errPos = positions[pos]
|
.errPos = positions[pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s,
|
void EvalState::throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s,
|
||||||
const ExprLambda & fun, const Symbol & s2) const
|
const ExprLambda & fun, const SymbolIdx s2) const
|
||||||
{
|
{
|
||||||
throw TypeError(ErrorInfo {
|
throw TypeError(ErrorInfo {
|
||||||
.msg = hintfmt(s, fun.showNamePos(positions), s2),
|
.msg = hintfmt(s, fun.showNamePos(*this), symbols[s2]),
|
||||||
.errPos = positions[pos],
|
.errPos = positions[pos],
|
||||||
.suggestions = suggestions,
|
.suggestions = suggestions,
|
||||||
});
|
});
|
||||||
|
@ -901,7 +903,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||||
return j->value;
|
return j->value;
|
||||||
}
|
}
|
||||||
if (!env->prevWith)
|
if (!env->prevWith)
|
||||||
throwUndefinedVarError(var.pos, "undefined variable '%1%'", var.name);
|
throwUndefinedVarError(var.pos, "undefined variable '%1%'", symbols[var.name]);
|
||||||
for (size_t l = env->prevWith; l; --l, env = env->up) ;
|
for (size_t l = env->prevWith; l; --l, env = env->up) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1187,7 +1189,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
if (nameVal.type() == nNull)
|
if (nameVal.type() == nNull)
|
||||||
continue;
|
continue;
|
||||||
state.forceStringNoCtx(nameVal);
|
state.forceStringNoCtx(nameVal);
|
||||||
Symbol nameSym = state.symbols.create(nameVal.string.s);
|
auto nameSym = state.symbols.create(nameVal.string.s);
|
||||||
Bindings::iterator j = v.attrs->find(nameSym);
|
Bindings::iterator j = v.attrs->find(nameSym);
|
||||||
if (j != v.attrs->end())
|
if (j != v.attrs->end())
|
||||||
state.throwEvalError(i.pos, "dynamic attribute '%1%' already defined at %2%", nameSym, j->pos);
|
state.throwEvalError(i.pos, "dynamic attribute '%1%' already defined at %2%", nameSym, j->pos);
|
||||||
|
@ -1243,10 +1245,12 @@ static std::string showAttrPath(EvalState & state, Env & env, const AttrPath & a
|
||||||
for (auto & i : attrPath) {
|
for (auto & i : attrPath) {
|
||||||
if (!first) out << '.'; else first = false;
|
if (!first) out << '.'; else first = false;
|
||||||
try {
|
try {
|
||||||
out << getName(i, state, env);
|
out << state.symbols[getName(i, state, env)];
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
assert(!i.symbol.set());
|
assert(!i.symbol);
|
||||||
out << "\"${" << *i.expr << "}\"";
|
out << "\"${";
|
||||||
|
i.expr->show(state.symbols, out);
|
||||||
|
out << "}\"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out.str();
|
return out.str();
|
||||||
|
@ -1266,7 +1270,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||||
for (auto & i : attrPath) {
|
for (auto & i : attrPath) {
|
||||||
state.nrLookups++;
|
state.nrLookups++;
|
||||||
Bindings::iterator j;
|
Bindings::iterator j;
|
||||||
Symbol name = getName(i, state, env);
|
auto name = getName(i, state, env);
|
||||||
if (def) {
|
if (def) {
|
||||||
state.forceValue(*vAttrs, pos);
|
state.forceValue(*vAttrs, pos);
|
||||||
if (vAttrs->type() != nAttrs ||
|
if (vAttrs->type() != nAttrs ||
|
||||||
|
@ -1280,11 +1284,11 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||||
if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) {
|
if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) {
|
||||||
std::set<std::string> allAttrNames;
|
std::set<std::string> allAttrNames;
|
||||||
for (auto & attr : *vAttrs->attrs)
|
for (auto & attr : *vAttrs->attrs)
|
||||||
allAttrNames.insert(attr.name);
|
allAttrNames.insert(state.symbols[attr.name]);
|
||||||
state.throwEvalError(
|
state.throwEvalError(
|
||||||
pos,
|
pos,
|
||||||
Suggestions::bestMatches(allAttrNames, name),
|
Suggestions::bestMatches(allAttrNames, state.symbols[name]),
|
||||||
"attribute '%1%' missing", name);
|
"attribute '%1%' missing", state.symbols[name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vAttrs = j->value;
|
vAttrs = j->value;
|
||||||
|
@ -1316,7 +1320,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
|
||||||
for (auto & i : attrPath) {
|
for (auto & i : attrPath) {
|
||||||
state.forceValue(*vAttrs, noPos);
|
state.forceValue(*vAttrs, noPos);
|
||||||
Bindings::iterator j;
|
Bindings::iterator j;
|
||||||
Symbol name = getName(i, state, env);
|
auto name = getName(i, state, env);
|
||||||
if (vAttrs->type() != nAttrs ||
|
if (vAttrs->type() != nAttrs ||
|
||||||
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
|
||||||
{
|
{
|
||||||
|
@ -1366,7 +1370,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
ExprLambda & lambda(*vCur.lambda.fun);
|
ExprLambda & lambda(*vCur.lambda.fun);
|
||||||
|
|
||||||
auto size =
|
auto size =
|
||||||
(!lambda.arg.set() ? 0 : 1) +
|
(!lambda.arg ? 0 : 1) +
|
||||||
(lambda.hasFormals() ? lambda.formals->formals.size() : 0);
|
(lambda.hasFormals() ? lambda.formals->formals.size() : 0);
|
||||||
Env & env2(allocEnv(size));
|
Env & env2(allocEnv(size));
|
||||||
env2.up = vCur.lambda.env;
|
env2.up = vCur.lambda.env;
|
||||||
|
@ -1379,7 +1383,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
else {
|
else {
|
||||||
forceAttrs(*args[0], pos);
|
forceAttrs(*args[0], pos);
|
||||||
|
|
||||||
if (lambda.arg.set())
|
if (lambda.arg)
|
||||||
env2.values[displ++] = args[0];
|
env2.values[displ++] = args[0];
|
||||||
|
|
||||||
/* For each formal argument, get the actual argument. If
|
/* For each formal argument, get the actual argument. If
|
||||||
|
@ -1407,10 +1411,10 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
if (!lambda.formals->has(i.name)) {
|
if (!lambda.formals->has(i.name)) {
|
||||||
std::set<std::string> formalNames;
|
std::set<std::string> formalNames;
|
||||||
for (auto & formal : lambda.formals->formals)
|
for (auto & formal : lambda.formals->formals)
|
||||||
formalNames.insert(formal.name);
|
formalNames.insert(symbols[formal.name]);
|
||||||
throwTypeError(
|
throwTypeError(
|
||||||
pos,
|
pos,
|
||||||
Suggestions::bestMatches(formalNames, i.name),
|
Suggestions::bestMatches(formalNames, symbols[i.name]),
|
||||||
"%1% called with unexpected argument '%2%'",
|
"%1% called with unexpected argument '%2%'",
|
||||||
lambda,
|
lambda,
|
||||||
i.name);
|
i.name);
|
||||||
|
@ -1428,8 +1432,8 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
if (loggerSettings.showTrace.get()) {
|
if (loggerSettings.showTrace.get()) {
|
||||||
addErrorTrace(e, lambda.pos, "while evaluating %s",
|
addErrorTrace(e, lambda.pos, "while evaluating %s",
|
||||||
(lambda.name.set()
|
(lambda.name
|
||||||
? "'" + (const std::string &) lambda.name + "'"
|
? concatStrings("'", symbols[lambda.name], "'")
|
||||||
: "anonymous lambda"));
|
: "anonymous lambda"));
|
||||||
addErrorTrace(e, pos, "from call site%s", "");
|
addErrorTrace(e, pos, "from call site%s", "");
|
||||||
}
|
}
|
||||||
|
@ -1578,7 +1582,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
||||||
Nix attempted to evaluate a function as a top level expression; in
|
Nix attempted to evaluate a function as a top level expression; in
|
||||||
this case it must have its arguments supplied either by default
|
this case it must have its arguments supplied either by default
|
||||||
values, or passed explicitly with '--arg' or '--argstr'. See
|
values, or passed explicitly with '--arg' or '--argstr'. See
|
||||||
https://nixos.org/manual/nix/stable/#ss-functions.)", i.name);
|
https://nixos.org/manual/nix/stable/#ss-functions.)", symbols[i.name]);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1610,7 +1614,7 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
if (!state.evalBool(env, cond, pos)) {
|
if (!state.evalBool(env, cond, pos)) {
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
cond->show(out);
|
cond->show(state.symbols, out);
|
||||||
state.throwAssertionError(pos, "assertion '%1%' failed", out.str());
|
state.throwAssertionError(pos, "assertion '%1%' failed", out.str());
|
||||||
}
|
}
|
||||||
body->eval(state, env, v);
|
body->eval(state, env, v);
|
||||||
|
@ -1844,7 +1848,7 @@ void EvalState::forceValueDeep(Value & v)
|
||||||
try {
|
try {
|
||||||
recurse(*i.value);
|
recurse(*i.value);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
addErrorTrace(e, i.pos, "while evaluating the attribute '%1%'", i.name);
|
addErrorTrace(e, i.pos, "while evaluating the attribute '%1%'", symbols[i.name]);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2267,7 +2271,7 @@ void EvalState::printStats()
|
||||||
auto list = topObj.list("functions");
|
auto list = topObj.list("functions");
|
||||||
for (auto & i : functionCalls) {
|
for (auto & i : functionCalls) {
|
||||||
auto obj = list.object();
|
auto obj = list.object();
|
||||||
if (i.first->name.set())
|
if (i.first->name)
|
||||||
obj.attr("name", (const std::string &) i.first->name);
|
obj.attr("name", (const std::string &) i.first->name);
|
||||||
else
|
else
|
||||||
obj.attr("name", nullptr);
|
obj.attr("name", nullptr);
|
||||||
|
|
|
@ -53,7 +53,8 @@ void copyContext(const Value & v, PathSet & context);
|
||||||
typedef std::map<Path, StorePath> SrcToStore;
|
typedef std::map<Path, StorePath> SrcToStore;
|
||||||
|
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const Value & v);
|
std::ostream & printValue(const EvalState & state, std::ostream & str, const Value & v);
|
||||||
|
std::string printValue(const EvalState & state, const Value & v);
|
||||||
|
|
||||||
|
|
||||||
typedef std::pair<std::string, std::string> SearchPathElem;
|
typedef std::pair<std::string, std::string> SearchPathElem;
|
||||||
|
@ -77,7 +78,7 @@ public:
|
||||||
|
|
||||||
static inline std::string derivationNixPath = "//builtin/derivation.nix";
|
static inline std::string derivationNixPath = "//builtin/derivation.nix";
|
||||||
|
|
||||||
const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue,
|
const SymbolIdx sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue,
|
||||||
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
|
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
|
||||||
sFile, sLine, sColumn, sFunctor, sToString,
|
sFile, sLine, sColumn, sFunctor, sToString,
|
||||||
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
|
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
|
||||||
|
@ -86,7 +87,7 @@ public:
|
||||||
sRecurseForDerivations,
|
sRecurseForDerivations,
|
||||||
sDescription, sSelf, sEpsilon, sStartSet, sOperator, sKey, sPath,
|
sDescription, sSelf, sEpsilon, sStartSet, sOperator, sKey, sPath,
|
||||||
sPrefix;
|
sPrefix;
|
||||||
Symbol sDerivationNix;
|
SymbolIdx sDerivationNix;
|
||||||
|
|
||||||
/* If set, force copying files to the Nix store even if they
|
/* If set, force copying files to the Nix store even if they
|
||||||
already exist there. */
|
already exist there. */
|
||||||
|
@ -268,14 +269,14 @@ public:
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3) const;
|
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwEvalError(const PosIdx p1, const char * s, const Symbol & sym, const PosIdx p2) const;
|
void throwEvalError(const PosIdx p1, const char * s, const SymbolIdx sym, const PosIdx p2) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const PosIdx pos, const char * s) const;
|
void throwTypeError(const PosIdx pos, const char * s) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun, const Symbol & s2) const;
|
void throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun, const SymbolIdx s2) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s,
|
void throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s,
|
||||||
const ExprLambda & fun, const Symbol & s2) const;
|
const ExprLambda & fun, const SymbolIdx s2) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const char * s, const Value & v) const;
|
void throwTypeError(const char * s, const Value & v) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
@ -391,7 +392,7 @@ public:
|
||||||
inline Value * allocValue();
|
inline Value * allocValue();
|
||||||
inline Env & allocEnv(size_t size);
|
inline Env & allocEnv(size_t size);
|
||||||
|
|
||||||
Value * allocAttr(Value & vAttrs, const Symbol & name);
|
Value * allocAttr(Value & vAttrs, const SymbolIdx & name);
|
||||||
Value * allocAttr(Value & vAttrs, std::string_view name);
|
Value * allocAttr(Value & vAttrs, std::string_view name);
|
||||||
|
|
||||||
Bindings * allocBindings(size_t capacity);
|
Bindings * allocBindings(size_t capacity);
|
||||||
|
|
|
@ -127,21 +127,23 @@ static FlakeInput parseFlakeInput(EvalState & state,
|
||||||
} else {
|
} else {
|
||||||
switch (attr.value->type()) {
|
switch (attr.value->type()) {
|
||||||
case nString:
|
case nString:
|
||||||
attrs.emplace(attr.name, attr.value->string.s);
|
attrs.emplace(state.symbols[attr.name], attr.value->string.s);
|
||||||
break;
|
break;
|
||||||
case nBool:
|
case nBool:
|
||||||
attrs.emplace(attr.name, Explicit<bool> { attr.value->boolean });
|
attrs.emplace(state.symbols[attr.name], Explicit<bool> { attr.value->boolean });
|
||||||
break;
|
break;
|
||||||
case nInt:
|
case nInt:
|
||||||
attrs.emplace(attr.name, (long unsigned int)attr.value->integer);
|
attrs.emplace(state.symbols[attr.name], (long unsigned int)attr.value->integer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw TypeError("flake input attribute '%s' is %s while a string, Boolean, or integer is expected",
|
throw TypeError("flake input attribute '%s' is %s while a string, Boolean, or integer is expected",
|
||||||
attr.name, showType(*attr.value));
|
state.symbols[attr.name], showType(*attr.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(state.positions[attr.pos], hintfmt("in flake attribute '%s'", attr.name));
|
e.addTrace(
|
||||||
|
state.positions[attr.pos],
|
||||||
|
hintfmt("in flake attribute '%s'", state.symbols[attr.name]));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,9 +178,9 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
|
||||||
expectType(state, nAttrs, *value, pos);
|
expectType(state, nAttrs, *value, pos);
|
||||||
|
|
||||||
for (nix::Attr & inputAttr : *(*value).attrs) {
|
for (nix::Attr & inputAttr : *(*value).attrs) {
|
||||||
inputs.emplace(inputAttr.name,
|
inputs.emplace(state.symbols[inputAttr.name],
|
||||||
parseFlakeInput(state,
|
parseFlakeInput(state,
|
||||||
inputAttr.name,
|
state.symbols[inputAttr.name],
|
||||||
inputAttr.value,
|
inputAttr.value,
|
||||||
inputAttr.pos,
|
inputAttr.pos,
|
||||||
baseDir,
|
baseDir,
|
||||||
|
@ -218,7 +220,7 @@ static Flake getFlake(
|
||||||
Value vInfo;
|
Value vInfo;
|
||||||
state.evalFile(flakeFile, vInfo, true); // FIXME: symlink attack
|
state.evalFile(flakeFile, vInfo, true); // FIXME: symlink attack
|
||||||
|
|
||||||
expectType(state, nAttrs, vInfo, state.positions.add({state.symbols.create(flakeFile), foFile}, 0, 0));
|
expectType(state, nAttrs, vInfo, state.positions.add({flakeFile, foFile}, 0, 0));
|
||||||
|
|
||||||
if (auto description = vInfo.attrs->get(state.sDescription)) {
|
if (auto description = vInfo.attrs->get(state.sDescription)) {
|
||||||
expectType(state, nString, *description->value, description->pos);
|
expectType(state, nString, *description->value, description->pos);
|
||||||
|
@ -238,8 +240,8 @@ static Flake getFlake(
|
||||||
if (outputs->value->isLambda() && outputs->value->lambda.fun->hasFormals()) {
|
if (outputs->value->isLambda() && outputs->value->lambda.fun->hasFormals()) {
|
||||||
for (auto & formal : outputs->value->lambda.fun->formals->formals) {
|
for (auto & formal : outputs->value->lambda.fun->formals->formals) {
|
||||||
if (formal.name != state.sSelf)
|
if (formal.name != state.sSelf)
|
||||||
flake.inputs.emplace(formal.name, FlakeInput {
|
flake.inputs.emplace(state.symbols[formal.name], FlakeInput {
|
||||||
.ref = parseFlakeRef(formal.name)
|
.ref = parseFlakeRef(state.symbols[formal.name])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,30 +257,36 @@ static Flake getFlake(
|
||||||
for (auto & setting : *nixConfig->value->attrs) {
|
for (auto & setting : *nixConfig->value->attrs) {
|
||||||
forceTrivialValue(state, *setting.value, setting.pos);
|
forceTrivialValue(state, *setting.value, setting.pos);
|
||||||
if (setting.value->type() == nString)
|
if (setting.value->type() == nString)
|
||||||
flake.config.settings.insert({setting.name, std::string(state.forceStringNoCtx(*setting.value, setting.pos))});
|
flake.config.settings.emplace(
|
||||||
|
state.symbols[setting.name],
|
||||||
|
std::string(state.forceStringNoCtx(*setting.value, setting.pos)));
|
||||||
else if (setting.value->type() == nPath) {
|
else if (setting.value->type() == nPath) {
|
||||||
PathSet emptyContext = {};
|
PathSet emptyContext = {};
|
||||||
flake.config.settings.emplace(
|
flake.config.settings.emplace(
|
||||||
setting.name,
|
state.symbols[setting.name],
|
||||||
state.coerceToString(setting.pos, *setting.value, emptyContext, false, true, true) .toOwned());
|
state.coerceToString(setting.pos, *setting.value, emptyContext, false, true, true) .toOwned());
|
||||||
}
|
}
|
||||||
else if (setting.value->type() == nInt)
|
else if (setting.value->type() == nInt)
|
||||||
flake.config.settings.insert({setting.name, state.forceInt(*setting.value, setting.pos)});
|
flake.config.settings.emplace(
|
||||||
|
state.symbols[setting.name],
|
||||||
|
state.forceInt(*setting.value, setting.pos));
|
||||||
else if (setting.value->type() == nBool)
|
else if (setting.value->type() == nBool)
|
||||||
flake.config.settings.insert({setting.name, Explicit<bool> { state.forceBool(*setting.value, setting.pos) }});
|
flake.config.settings.emplace(
|
||||||
|
state.symbols[setting.name],
|
||||||
|
Explicit<bool> { state.forceBool(*setting.value, setting.pos) });
|
||||||
else if (setting.value->type() == nList) {
|
else if (setting.value->type() == nList) {
|
||||||
std::vector<std::string> ss;
|
std::vector<std::string> ss;
|
||||||
for (auto elem : setting.value->listItems()) {
|
for (auto elem : setting.value->listItems()) {
|
||||||
if (elem->type() != nString)
|
if (elem->type() != nString)
|
||||||
throw TypeError("list element in flake configuration setting '%s' is %s while a string is expected",
|
throw TypeError("list element in flake configuration setting '%s' is %s while a string is expected",
|
||||||
setting.name, showType(*setting.value));
|
state.symbols[setting.name], showType(*setting.value));
|
||||||
ss.emplace_back(state.forceStringNoCtx(*elem, setting.pos));
|
ss.emplace_back(state.forceStringNoCtx(*elem, setting.pos));
|
||||||
}
|
}
|
||||||
flake.config.settings.insert({setting.name, ss});
|
flake.config.settings.emplace(state.symbols[setting.name], ss);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw TypeError("flake configuration setting '%s' is %s",
|
throw TypeError("flake configuration setting '%s' is %s",
|
||||||
setting.name, showType(*setting.value));
|
state.symbols[setting.name], showType(*setting.value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +296,7 @@ static Flake getFlake(
|
||||||
attr.name != sOutputs &&
|
attr.name != sOutputs &&
|
||||||
attr.name != sNixConfig)
|
attr.name != sNixConfig)
|
||||||
throw Error("flake '%s' has an unsupported attribute '%s', at %s",
|
throw Error("flake '%s' has an unsupported attribute '%s', at %s",
|
||||||
lockedRef, attr.name, state.positions[attr.pos]);
|
lockedRef, state.symbols[attr.name], state.positions[attr.pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return flake;
|
return flake;
|
||||||
|
|
|
@ -179,7 +179,7 @@ StringSet DrvInfo::queryMetaNames()
|
||||||
StringSet res;
|
StringSet res;
|
||||||
if (!getMeta()) return res;
|
if (!getMeta()) return res;
|
||||||
for (auto & i : *meta)
|
for (auto & i : *meta)
|
||||||
res.insert(i.name);
|
res.emplace(state->symbols[i.name]);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ void DrvInfo::setMeta(const std::string & name, Value * v)
|
||||||
{
|
{
|
||||||
getMeta();
|
getMeta();
|
||||||
auto attrs = state->buildBindings(1 + (meta ? meta->size() : 0));
|
auto attrs = state->buildBindings(1 + (meta ? meta->size() : 0));
|
||||||
Symbol sym = state->symbols.create(name);
|
auto sym = state->symbols.create(name);
|
||||||
if (meta)
|
if (meta)
|
||||||
for (auto i : *meta)
|
for (auto i : *meta)
|
||||||
if (i.name != sym)
|
if (i.name != sym)
|
||||||
|
@ -356,11 +356,11 @@ static void getDerivations(EvalState & state, Value & vIn,
|
||||||
there are names clashes between derivations, the derivation
|
there are names clashes between derivations, the derivation
|
||||||
bound to the attribute with the "lower" name should take
|
bound to the attribute with the "lower" name should take
|
||||||
precedence). */
|
precedence). */
|
||||||
for (auto & i : v.attrs->lexicographicOrder()) {
|
for (auto & i : v.attrs->lexicographicOrder(state.symbols)) {
|
||||||
debug("evaluating attribute '%1%'", i->name);
|
debug("evaluating attribute '%1%'", state.symbols[i->name]);
|
||||||
if (!std::regex_match(std::string(i->name), attrRegex))
|
if (!std::regex_match(std::string(state.symbols[i->name]), attrRegex))
|
||||||
continue;
|
continue;
|
||||||
std::string pathPrefix2 = addToPath(pathPrefix, i->name);
|
std::string pathPrefix2 = addToPath(pathPrefix, state.symbols[i->name]);
|
||||||
if (combineChannels)
|
if (combineChannels)
|
||||||
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||||
else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
|
else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "nixexpr.hh"
|
#include "nixexpr.hh"
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
|
#include "eval.hh"
|
||||||
|
#include "symbol-table.hh"
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -10,12 +12,6 @@ namespace nix {
|
||||||
|
|
||||||
/* Displaying abstract syntax trees. */
|
/* Displaying abstract syntax trees. */
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const Expr & e)
|
|
||||||
{
|
|
||||||
e.show(str);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void showString(std::ostream & str, std::string_view s)
|
static void showString(std::ostream & str, std::string_view s)
|
||||||
{
|
{
|
||||||
str << '"';
|
str << '"';
|
||||||
|
@ -54,81 +50,101 @@ static void showId(std::ostream & str, std::string_view s)
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const Symbol & sym)
|
std::ostream & operator << (std::ostream & str, const Symbol & sym)
|
||||||
{
|
{
|
||||||
showId(str, *sym.s);
|
showId(str, sym.s);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Expr::show(std::ostream & str) const
|
void Expr::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprInt::show(std::ostream & str) const
|
void ExprInt::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << n;
|
str << n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprFloat::show(std::ostream & str) const
|
void ExprFloat::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << nf;
|
str << nf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprString::show(std::ostream & str) const
|
void ExprString::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
showString(str, s);
|
showString(str, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprPath::show(std::ostream & str) const
|
void ExprPath::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << s;
|
str << s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprVar::show(std::ostream & str) const
|
void ExprVar::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << name;
|
str << symbols[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprSelect::show(std::ostream & str) const
|
void ExprSelect::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "(" << *e << ")." << showAttrPath(attrPath);
|
str << "(";
|
||||||
if (def) str << " or (" << *def << ")";
|
e->show(symbols, str);
|
||||||
|
str << ")." << showAttrPath(symbols, attrPath);
|
||||||
|
if (def) {
|
||||||
|
str << " or (";
|
||||||
|
def->show(symbols, str);
|
||||||
|
str << ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprOpHasAttr::show(std::ostream & str) const
|
void ExprOpHasAttr::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "((" << *e << ") ? " << showAttrPath(attrPath) << ")";
|
str << "((";
|
||||||
|
e->show(symbols, str);
|
||||||
|
str << ") ? " << showAttrPath(symbols, attrPath) << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprAttrs::show(std::ostream & str) const
|
void ExprAttrs::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
if (recursive) str << "rec ";
|
if (recursive) str << "rec ";
|
||||||
str << "{ ";
|
str << "{ ";
|
||||||
typedef const decltype(attrs)::value_type * Attr;
|
typedef const decltype(attrs)::value_type * Attr;
|
||||||
std::vector<Attr> sorted;
|
std::vector<Attr> sorted;
|
||||||
for (auto & i : attrs) sorted.push_back(&i);
|
for (auto & i : attrs) sorted.push_back(&i);
|
||||||
std::sort(sorted.begin(), sorted.end(), [](Attr a, Attr b) {
|
std::sort(sorted.begin(), sorted.end(), [&](Attr a, Attr b) {
|
||||||
return (const std::string &) a->first < (const std::string &) b->first;
|
std::string_view sa = symbols[a->first], sb = symbols[b->first];
|
||||||
});
|
return sa < sb;
|
||||||
|
});
|
||||||
for (auto & i : sorted) {
|
for (auto & i : sorted) {
|
||||||
if (i->second.inherited)
|
if (i->second.inherited)
|
||||||
str << "inherit " << i->first << " " << "; ";
|
str << "inherit " << symbols[i->first] << " " << "; ";
|
||||||
else
|
else {
|
||||||
str << i->first << " = " << *i->second.e << "; ";
|
str << symbols[i->first] << " = ";
|
||||||
|
i->second.e->show(symbols, str);
|
||||||
|
str << "; ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto & i : dynamicAttrs) {
|
||||||
|
str << "\"${";
|
||||||
|
i.nameExpr->show(symbols, str);
|
||||||
|
str << "}\" = ";
|
||||||
|
i.valueExpr->show(symbols, str);
|
||||||
|
str << "; ";
|
||||||
}
|
}
|
||||||
for (auto & i : dynamicAttrs)
|
|
||||||
str << "\"${" << *i.nameExpr << "}\" = " << *i.valueExpr << "; ";
|
|
||||||
str << "}";
|
str << "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprList::show(std::ostream & str) const
|
void ExprList::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "[ ";
|
str << "[ ";
|
||||||
for (auto & i : elems)
|
for (auto & i : elems) {
|
||||||
str << "(" << *i << ") ";
|
str << "(";
|
||||||
|
i->show(symbols, str);
|
||||||
|
str << ") ";
|
||||||
|
}
|
||||||
str << "]";
|
str << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprLambda::show(std::ostream & str) const
|
void ExprLambda::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "(";
|
str << "(";
|
||||||
if (hasFormals()) {
|
if (hasFormals()) {
|
||||||
|
@ -136,74 +152,100 @@ void ExprLambda::show(std::ostream & str) const
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto & i : formals->formals) {
|
for (auto & i : formals->formals) {
|
||||||
if (first) first = false; else str << ", ";
|
if (first) first = false; else str << ", ";
|
||||||
str << i.name;
|
str << symbols[i.name];
|
||||||
if (i.def) str << " ? " << *i.def;
|
if (i.def) {
|
||||||
|
str << " ? ";
|
||||||
|
i.def->show(symbols, str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (formals->ellipsis) {
|
if (formals->ellipsis) {
|
||||||
if (!first) str << ", ";
|
if (!first) str << ", ";
|
||||||
str << "...";
|
str << "...";
|
||||||
}
|
}
|
||||||
str << " }";
|
str << " }";
|
||||||
if (arg.set()) str << " @ ";
|
if (arg) str << " @ ";
|
||||||
}
|
}
|
||||||
if (arg.set()) str << arg;
|
if (arg) str << symbols[arg];
|
||||||
str << ": " << *body << ")";
|
str << ": ";
|
||||||
|
body->show(symbols, str);
|
||||||
|
str << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprCall::show(std::ostream & str) const
|
void ExprCall::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << '(' << *fun;
|
str << '(';
|
||||||
|
fun->show(symbols, str);
|
||||||
for (auto e : args) {
|
for (auto e : args) {
|
||||||
str << ' ';
|
str << ' ';
|
||||||
str << *e;
|
e->show(symbols, str);
|
||||||
}
|
}
|
||||||
str << ')';
|
str << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprLet::show(std::ostream & str) const
|
void ExprLet::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "(let ";
|
str << "(let ";
|
||||||
for (auto & i : attrs->attrs)
|
for (auto & i : attrs->attrs)
|
||||||
if (i.second.inherited) {
|
if (i.second.inherited) {
|
||||||
str << "inherit " << i.first << "; ";
|
str << "inherit " << symbols[i.first] << "; ";
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
str << i.first << " = " << *i.second.e << "; ";
|
str << symbols[i.first] << " = ";
|
||||||
str << "in " << *body << ")";
|
i.second.e->show(symbols, str);
|
||||||
|
str << "; ";
|
||||||
|
}
|
||||||
|
str << "in ";
|
||||||
|
body->show(symbols, str);
|
||||||
|
str << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprWith::show(std::ostream & str) const
|
void ExprWith::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "(with " << *attrs << "; " << *body << ")";
|
str << "(with ";
|
||||||
|
attrs->show(symbols, str);
|
||||||
|
str << "; ";
|
||||||
|
body->show(symbols, str);
|
||||||
|
str << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprIf::show(std::ostream & str) const
|
void ExprIf::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "(if " << *cond << " then " << *then << " else " << *else_ << ")";
|
str << "(if ";
|
||||||
|
cond->show(symbols, str);
|
||||||
|
str << " then ";
|
||||||
|
then->show(symbols, str);
|
||||||
|
str << " else ";
|
||||||
|
else_->show(symbols, str);
|
||||||
|
str << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprAssert::show(std::ostream & str) const
|
void ExprAssert::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "assert " << *cond << "; " << *body;
|
str << "assert ";
|
||||||
|
cond->show(symbols, str);
|
||||||
|
str << "; ";
|
||||||
|
body->show(symbols, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprOpNot::show(std::ostream & str) const
|
void ExprOpNot::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "(! " << *e << ")";
|
str << "(! ";
|
||||||
|
e->show(symbols, str);
|
||||||
|
str << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprConcatStrings::show(std::ostream & str) const
|
void ExprConcatStrings::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
bool first = true;
|
bool first = true;
|
||||||
str << "(";
|
str << "(";
|
||||||
for (auto & i : *es) {
|
for (auto & i : *es) {
|
||||||
if (first) first = false; else str << " + ";
|
if (first) first = false; else str << " + ";
|
||||||
str << *i.second;
|
i.second->show(symbols, str);
|
||||||
}
|
}
|
||||||
str << ")";
|
str << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprPos::show(std::ostream & str) const
|
void ExprPos::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "__curPos";
|
str << "__curPos";
|
||||||
}
|
}
|
||||||
|
@ -234,16 +276,19 @@ std::ostream & operator << (std::ostream & str, const Pos & pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string showAttrPath(const AttrPath & attrPath)
|
std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath)
|
||||||
{
|
{
|
||||||
std::ostringstream out;
|
std::ostringstream out;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (auto & i : attrPath) {
|
for (auto & i : attrPath) {
|
||||||
if (!first) out << '.'; else first = false;
|
if (!first) out << '.'; else first = false;
|
||||||
if (i.symbol.set())
|
if (i.symbol)
|
||||||
out << i.symbol;
|
out << symbols[i.symbol];
|
||||||
else
|
else {
|
||||||
out << "\"${" << *i.expr << "}\"";
|
out << "\"${";
|
||||||
|
i.expr->show(symbols, out);
|
||||||
|
out << "}\"";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
@ -252,28 +297,28 @@ std::string showAttrPath(const AttrPath & attrPath)
|
||||||
|
|
||||||
/* Computing levels/displacements for variables. */
|
/* Computing levels/displacements for variables. */
|
||||||
|
|
||||||
void Expr::bindVars(const PosTable & pt, const StaticEnv & env)
|
void Expr::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprInt::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprInt::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprFloat::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprFloat::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprString::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprString::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprPath::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprPath::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprVar::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprVar::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
/* Check whether the variable appears in the environment. If so,
|
/* Check whether the variable appears in the environment. If so,
|
||||||
set its level and displacement. */
|
set its level and displacement. */
|
||||||
|
@ -299,31 +344,31 @@ void ExprVar::bindVars(const PosTable & pt, const StaticEnv & env)
|
||||||
"undefined variable" error now. */
|
"undefined variable" error now. */
|
||||||
if (withLevel == -1)
|
if (withLevel == -1)
|
||||||
throw UndefinedVarError({
|
throw UndefinedVarError({
|
||||||
.msg = hintfmt("undefined variable '%1%'", name),
|
.msg = hintfmt("undefined variable '%1%'", es.symbols[name]),
|
||||||
.errPos = pt[pos]
|
.errPos = es.positions[pos]
|
||||||
});
|
});
|
||||||
fromWith = true;
|
fromWith = true;
|
||||||
this->level = withLevel;
|
this->level = withLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprSelect::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprSelect::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
e->bindVars(pt, env);
|
e->bindVars(es, env);
|
||||||
if (def) def->bindVars(pt, env);
|
if (def) def->bindVars(es, env);
|
||||||
for (auto & i : attrPath)
|
for (auto & i : attrPath)
|
||||||
if (!i.symbol.set())
|
if (!i.symbol)
|
||||||
i.expr->bindVars(pt, env);
|
i.expr->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprOpHasAttr::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprOpHasAttr::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
e->bindVars(pt, env);
|
e->bindVars(es, env);
|
||||||
for (auto & i : attrPath)
|
for (auto & i : attrPath)
|
||||||
if (!i.symbol.set())
|
if (!i.symbol)
|
||||||
i.expr->bindVars(pt, env);
|
i.expr->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprAttrs::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprAttrs::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
const StaticEnv * dynamicEnv = &env;
|
const StaticEnv * dynamicEnv = &env;
|
||||||
StaticEnv newEnv(false, &env, recursive ? attrs.size() : 0);
|
StaticEnv newEnv(false, &env, recursive ? attrs.size() : 0);
|
||||||
|
@ -338,35 +383,35 @@ void ExprAttrs::bindVars(const PosTable & pt, const StaticEnv & env)
|
||||||
// No need to sort newEnv since attrs is in sorted order.
|
// No need to sort newEnv since attrs is in sorted order.
|
||||||
|
|
||||||
for (auto & i : attrs)
|
for (auto & i : attrs)
|
||||||
i.second.e->bindVars(pt, i.second.inherited ? env : newEnv);
|
i.second.e->bindVars(es, i.second.inherited ? env : newEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
for (auto & i : attrs)
|
for (auto & i : attrs)
|
||||||
i.second.e->bindVars(pt, env);
|
i.second.e->bindVars(es, env);
|
||||||
|
|
||||||
for (auto & i : dynamicAttrs) {
|
for (auto & i : dynamicAttrs) {
|
||||||
i.nameExpr->bindVars(pt, *dynamicEnv);
|
i.nameExpr->bindVars(es, *dynamicEnv);
|
||||||
i.valueExpr->bindVars(pt, *dynamicEnv);
|
i.valueExpr->bindVars(es, *dynamicEnv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprList::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprList::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
for (auto & i : elems)
|
for (auto & i : elems)
|
||||||
i->bindVars(pt, env);
|
i->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprLambda::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprLambda::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
StaticEnv newEnv(
|
StaticEnv newEnv(
|
||||||
false, &env,
|
false, &env,
|
||||||
(hasFormals() ? formals->formals.size() : 0) +
|
(hasFormals() ? formals->formals.size() : 0) +
|
||||||
(!arg.set() ? 0 : 1));
|
(!arg ? 0 : 1));
|
||||||
|
|
||||||
Displacement displ = 0;
|
Displacement displ = 0;
|
||||||
|
|
||||||
if (arg.set()) newEnv.vars.emplace_back(arg, displ++);
|
if (arg) newEnv.vars.emplace_back(arg, displ++);
|
||||||
|
|
||||||
if (hasFormals()) {
|
if (hasFormals()) {
|
||||||
for (auto & i : formals->formals)
|
for (auto & i : formals->formals)
|
||||||
|
@ -375,20 +420,20 @@ void ExprLambda::bindVars(const PosTable & pt, const StaticEnv & env)
|
||||||
newEnv.sort();
|
newEnv.sort();
|
||||||
|
|
||||||
for (auto & i : formals->formals)
|
for (auto & i : formals->formals)
|
||||||
if (i.def) i.def->bindVars(pt, newEnv);
|
if (i.def) i.def->bindVars(es, newEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
body->bindVars(pt, newEnv);
|
body->bindVars(es, newEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprCall::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprCall::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
fun->bindVars(pt, env);
|
fun->bindVars(es, env);
|
||||||
for (auto e : args)
|
for (auto e : args)
|
||||||
e->bindVars(pt, env);
|
e->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprLet::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprLet::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
StaticEnv newEnv(false, &env, attrs->attrs.size());
|
StaticEnv newEnv(false, &env, attrs->attrs.size());
|
||||||
|
|
||||||
|
@ -399,12 +444,12 @@ void ExprLet::bindVars(const PosTable & pt, const StaticEnv & env)
|
||||||
// No need to sort newEnv since attrs->attrs is in sorted order.
|
// No need to sort newEnv since attrs->attrs is in sorted order.
|
||||||
|
|
||||||
for (auto & i : attrs->attrs)
|
for (auto & i : attrs->attrs)
|
||||||
i.second.e->bindVars(pt, i.second.inherited ? env : newEnv);
|
i.second.e->bindVars(es, i.second.inherited ? env : newEnv);
|
||||||
|
|
||||||
body->bindVars(pt, newEnv);
|
body->bindVars(es, newEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprWith::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprWith::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
/* Does this `with' have an enclosing `with'? If so, record its
|
/* Does this `with' have an enclosing `with'? If so, record its
|
||||||
level so that `lookupVar' can look up variables in the previous
|
level so that `lookupVar' can look up variables in the previous
|
||||||
|
@ -418,57 +463,60 @@ void ExprWith::bindVars(const PosTable & pt, const StaticEnv & env)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs->bindVars(pt, env);
|
attrs->bindVars(es, env);
|
||||||
StaticEnv newEnv(true, &env);
|
StaticEnv newEnv(true, &env);
|
||||||
body->bindVars(pt, newEnv);
|
body->bindVars(es, newEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprIf::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprIf::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
cond->bindVars(pt, env);
|
cond->bindVars(es, env);
|
||||||
then->bindVars(pt, env);
|
then->bindVars(es, env);
|
||||||
else_->bindVars(pt, env);
|
else_->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprAssert::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprAssert::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
cond->bindVars(pt, env);
|
cond->bindVars(es, env);
|
||||||
body->bindVars(pt, env);
|
body->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprOpNot::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprOpNot::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
e->bindVars(pt, env);
|
e->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprConcatStrings::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprConcatStrings::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
for (auto & i : *es)
|
for (auto & i : *this->es)
|
||||||
i.second->bindVars(pt, env);
|
i.second->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprPos::bindVars(const PosTable & pt, const StaticEnv & env)
|
void ExprPos::bindVars(const EvalState & es, const StaticEnv & env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Storing function names. */
|
/* Storing function names. */
|
||||||
|
|
||||||
void Expr::setName(Symbol & name)
|
void Expr::setName(SymbolIdx name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ExprLambda::setName(Symbol & name)
|
void ExprLambda::setName(SymbolIdx name)
|
||||||
{
|
{
|
||||||
this->name = name;
|
this->name = name;
|
||||||
body->setName(name);
|
body->setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string ExprLambda::showNamePos(const PosTable & pt) const
|
std::string ExprLambda::showNamePos(const EvalState & state) const
|
||||||
{
|
{
|
||||||
return fmt("%1% at %2%", name.set() ? "'" + (std::string) name + "'" : "anonymous function", pt[pos]);
|
std::string id(name
|
||||||
|
? concatStrings("'", state.symbols[name], "'")
|
||||||
|
: "anonymous function");
|
||||||
|
return fmt("%1% at %2%", id, state.positions[pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -478,8 +526,7 @@ std::string ExprLambda::showNamePos(const PosTable & pt) const
|
||||||
size_t SymbolTable::totalSize() const
|
size_t SymbolTable::totalSize() const
|
||||||
{
|
{
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
for (auto & i : store)
|
dump([&] (const Symbol & s) { n += std::string_view(s).size(); });
|
||||||
n += i.size();
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,15 +125,15 @@ struct StaticEnv;
|
||||||
/* An attribute path is a sequence of attribute names. */
|
/* An attribute path is a sequence of attribute names. */
|
||||||
struct AttrName
|
struct AttrName
|
||||||
{
|
{
|
||||||
Symbol symbol;
|
SymbolIdx symbol;
|
||||||
Expr * expr;
|
Expr * expr;
|
||||||
AttrName(const Symbol & s) : symbol(s) {};
|
AttrName(const SymbolIdx & s) : symbol(s) {};
|
||||||
AttrName(Expr * e) : expr(e) {};
|
AttrName(Expr * e) : expr(e) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<AttrName> AttrPath;
|
typedef std::vector<AttrName> AttrPath;
|
||||||
|
|
||||||
std::string showAttrPath(const AttrPath & attrPath);
|
std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath);
|
||||||
|
|
||||||
|
|
||||||
/* Abstract syntax of Nix expressions. */
|
/* Abstract syntax of Nix expressions. */
|
||||||
|
@ -141,19 +141,17 @@ std::string showAttrPath(const AttrPath & attrPath);
|
||||||
struct Expr
|
struct Expr
|
||||||
{
|
{
|
||||||
virtual ~Expr() { };
|
virtual ~Expr() { };
|
||||||
virtual void show(std::ostream & str) const;
|
virtual void show(const SymbolTable & symbols, std::ostream & str) const;
|
||||||
virtual void bindVars(const PosTable & pt, const StaticEnv & env);
|
virtual void bindVars(const EvalState & es, const StaticEnv & env);
|
||||||
virtual void eval(EvalState & state, Env & env, Value & v);
|
virtual void eval(EvalState & state, Env & env, Value & v);
|
||||||
virtual Value * maybeThunk(EvalState & state, Env & env);
|
virtual Value * maybeThunk(EvalState & state, Env & env);
|
||||||
virtual void setName(Symbol & name);
|
virtual void setName(SymbolIdx name);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, const Expr & e);
|
|
||||||
|
|
||||||
#define COMMON_METHODS \
|
#define COMMON_METHODS \
|
||||||
void show(std::ostream & str) const; \
|
void show(const SymbolTable & symbols, std::ostream & str) const; \
|
||||||
void eval(EvalState & state, Env & env, Value & v); \
|
void eval(EvalState & state, Env & env, Value & v); \
|
||||||
void bindVars(const PosTable & pt, const StaticEnv & env);
|
void bindVars(const EvalState & es, const StaticEnv & env);
|
||||||
|
|
||||||
struct ExprInt : Expr
|
struct ExprInt : Expr
|
||||||
{
|
{
|
||||||
|
@ -197,7 +195,7 @@ typedef uint32_t Displacement;
|
||||||
struct ExprVar : Expr
|
struct ExprVar : Expr
|
||||||
{
|
{
|
||||||
PosIdx pos;
|
PosIdx pos;
|
||||||
Symbol name;
|
SymbolIdx name;
|
||||||
|
|
||||||
/* Whether the variable comes from an environment (e.g. a rec, let
|
/* Whether the variable comes from an environment (e.g. a rec, let
|
||||||
or function argument) or from a "with". */
|
or function argument) or from a "with". */
|
||||||
|
@ -212,8 +210,8 @@ struct ExprVar : Expr
|
||||||
Level level;
|
Level level;
|
||||||
Displacement displ;
|
Displacement displ;
|
||||||
|
|
||||||
ExprVar(const Symbol & name) : name(name) { };
|
ExprVar(const SymbolIdx & name) : name(name) { };
|
||||||
ExprVar(const PosIdx & pos, const Symbol & name) : pos(pos), name(name) { };
|
ExprVar(const PosIdx & pos, const SymbolIdx & name) : pos(pos), name(name) { };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
Value * maybeThunk(EvalState & state, Env & env);
|
Value * maybeThunk(EvalState & state, Env & env);
|
||||||
};
|
};
|
||||||
|
@ -224,7 +222,7 @@ struct ExprSelect : Expr
|
||||||
Expr * e, * def;
|
Expr * e, * def;
|
||||||
AttrPath attrPath;
|
AttrPath attrPath;
|
||||||
ExprSelect(const PosIdx & pos, Expr * e, const AttrPath & attrPath, Expr * def) : pos(pos), e(e), def(def), attrPath(attrPath) { };
|
ExprSelect(const PosIdx & pos, Expr * e, const AttrPath & attrPath, Expr * def) : pos(pos), e(e), def(def), attrPath(attrPath) { };
|
||||||
ExprSelect(const PosIdx & pos, Expr * e, const Symbol & name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); };
|
ExprSelect(const PosIdx & pos, Expr * e, const SymbolIdx & name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -249,7 +247,7 @@ struct ExprAttrs : Expr
|
||||||
: inherited(inherited), e(e), pos(pos) { };
|
: inherited(inherited), e(e), pos(pos) { };
|
||||||
AttrDef() { };
|
AttrDef() { };
|
||||||
};
|
};
|
||||||
typedef std::map<Symbol, AttrDef> AttrDefs;
|
typedef std::map<SymbolIdx, AttrDef> AttrDefs;
|
||||||
AttrDefs attrs;
|
AttrDefs attrs;
|
||||||
struct DynamicAttrDef {
|
struct DynamicAttrDef {
|
||||||
Expr * nameExpr, * valueExpr;
|
Expr * nameExpr, * valueExpr;
|
||||||
|
@ -274,9 +272,8 @@ struct ExprList : Expr
|
||||||
struct Formal
|
struct Formal
|
||||||
{
|
{
|
||||||
PosIdx pos;
|
PosIdx pos;
|
||||||
Symbol name;
|
SymbolIdx name;
|
||||||
Expr * def;
|
Expr * def;
|
||||||
Formal(const PosIdx & pos, const Symbol & name, Expr * def) : pos(pos), name(name), def(def) { };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Formals
|
struct Formals
|
||||||
|
@ -285,18 +282,19 @@ struct Formals
|
||||||
Formals_ formals;
|
Formals_ formals;
|
||||||
bool ellipsis;
|
bool ellipsis;
|
||||||
|
|
||||||
bool has(Symbol arg) const {
|
bool has(SymbolIdx arg) const {
|
||||||
auto it = std::lower_bound(formals.begin(), formals.end(), arg,
|
auto it = std::lower_bound(formals.begin(), formals.end(), arg,
|
||||||
[] (const Formal & f, const Symbol & sym) { return f.name < sym; });
|
[] (const Formal & f, const SymbolIdx & sym) { return f.name < sym; });
|
||||||
return it != formals.end() && it->name == arg;
|
return it != formals.end() && it->name == arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Formal> lexicographicOrder() const
|
std::vector<Formal> lexicographicOrder(const SymbolTable & symbols) const
|
||||||
{
|
{
|
||||||
std::vector<Formal> result(formals.begin(), formals.end());
|
std::vector<Formal> result(formals.begin(), formals.end());
|
||||||
std::sort(result.begin(), result.end(),
|
std::sort(result.begin(), result.end(),
|
||||||
[] (const Formal & a, const Formal & b) {
|
[&] (const Formal & a, const Formal & b) {
|
||||||
return std::string_view(a.name) < std::string_view(b.name);
|
std::string_view sa = symbols[a.name], sb = symbols[b.name];
|
||||||
|
return sa < sb;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -305,16 +303,20 @@ struct Formals
|
||||||
struct ExprLambda : Expr
|
struct ExprLambda : Expr
|
||||||
{
|
{
|
||||||
PosIdx pos;
|
PosIdx pos;
|
||||||
Symbol name;
|
SymbolIdx name;
|
||||||
Symbol arg;
|
SymbolIdx arg;
|
||||||
Formals * formals;
|
Formals * formals;
|
||||||
Expr * body;
|
Expr * body;
|
||||||
ExprLambda(const PosIdx & pos, const Symbol & arg, Formals * formals, Expr * body)
|
ExprLambda(PosIdx pos, SymbolIdx arg, Formals * formals, Expr * body)
|
||||||
: pos(pos), arg(arg), formals(formals), body(body)
|
: pos(pos), arg(arg), formals(formals), body(body)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
void setName(Symbol & name);
|
ExprLambda(PosIdx pos, Formals * formals, Expr * body)
|
||||||
std::string showNamePos(const PosTable & pt) const;
|
: pos(pos), formals(formals), body(body)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void setName(SymbolIdx name);
|
||||||
|
std::string showNamePos(const EvalState & state) const;
|
||||||
inline bool hasFormals() const { return formals != nullptr; }
|
inline bool hasFormals() const { return formals != nullptr; }
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
};
|
};
|
||||||
|
@ -377,13 +379,13 @@ struct ExprOpNot : Expr
|
||||||
Expr * e1, * e2; \
|
Expr * e1, * e2; \
|
||||||
name(Expr * e1, Expr * e2) : e1(e1), e2(e2) { }; \
|
name(Expr * e1, Expr * e2) : e1(e1), e2(e2) { }; \
|
||||||
name(const PosIdx & pos, Expr * e1, Expr * e2) : pos(pos), e1(e1), e2(e2) { }; \
|
name(const PosIdx & pos, Expr * e1, Expr * e2) : pos(pos), e1(e1), e2(e2) { }; \
|
||||||
void show(std::ostream & str) const \
|
void show(const SymbolTable & symbols, std::ostream & str) const \
|
||||||
{ \
|
{ \
|
||||||
str << "(" << *e1 << " " s " " << *e2 << ")"; \
|
str << "("; e1->show(symbols, str); str << " " s " "; e2->show(symbols, str); str << ")"; \
|
||||||
} \
|
} \
|
||||||
void bindVars(const PosTable & pt, const StaticEnv & env) \
|
void bindVars(const EvalState & es, const StaticEnv & env) \
|
||||||
{ \
|
{ \
|
||||||
e1->bindVars(pt, env); e2->bindVars(pt, env); \
|
e1->bindVars(es, env); e2->bindVars(es, env); \
|
||||||
} \
|
} \
|
||||||
void eval(EvalState & state, Env & env, Value & v); \
|
void eval(EvalState & state, Env & env, Value & v); \
|
||||||
};
|
};
|
||||||
|
@ -423,7 +425,7 @@ struct StaticEnv
|
||||||
const StaticEnv * up;
|
const StaticEnv * up;
|
||||||
|
|
||||||
// Note: these must be in sorted order.
|
// Note: these must be in sorted order.
|
||||||
typedef std::vector<std::pair<Symbol, Displacement>> Vars;
|
typedef std::vector<std::pair<SymbolIdx, Displacement>> Vars;
|
||||||
Vars vars;
|
Vars vars;
|
||||||
|
|
||||||
StaticEnv(bool isWith, const StaticEnv * up, size_t expectedSize = 0) : isWith(isWith), up(up) {
|
StaticEnv(bool isWith, const StaticEnv * up, size_t expectedSize = 0) : isWith(isWith), up(up) {
|
||||||
|
@ -447,7 +449,7 @@ struct StaticEnv
|
||||||
vars.erase(it, end);
|
vars.erase(it, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vars::const_iterator find(const Symbol & name) const
|
Vars::const_iterator find(const SymbolIdx & name) const
|
||||||
{
|
{
|
||||||
Vars::value_type key(name, 0);
|
Vars::value_type key(name, 0);
|
||||||
auto i = std::lower_bound(vars.begin(), vars.end(), key);
|
auto i = std::lower_bound(vars.begin(), vars.end(), key);
|
||||||
|
|
|
@ -77,26 +77,26 @@ using namespace nix;
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos)
|
static void dupAttr(const EvalState & state, const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos)
|
||||||
{
|
{
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("attribute '%1%' already defined at %2%",
|
.msg = hintfmt("attribute '%1%' already defined at %2%",
|
||||||
showAttrPath(attrPath), prevPos),
|
showAttrPath(state.symbols, attrPath), state.positions[prevPos]),
|
||||||
.errPos = pos
|
.errPos = state.positions[pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
|
static void dupAttr(const EvalState & state, SymbolIdx attr, const PosIdx pos, const PosIdx prevPos)
|
||||||
{
|
{
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("attribute '%1%' already defined at %2%", attr, prevPos),
|
.msg = hintfmt("attribute '%1%' already defined at %2%", state.symbols[attr], state.positions[prevPos]),
|
||||||
.errPos = pos
|
.errPos = state.positions[pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
||||||
Expr * e, const PosIdx pos, const nix::PosTable & pt)
|
Expr * e, const PosIdx pos, const nix::EvalState & state)
|
||||||
{
|
{
|
||||||
AttrPath::iterator i;
|
AttrPath::iterator i;
|
||||||
// All attrpaths have at least one attr
|
// All attrpaths have at least one attr
|
||||||
|
@ -104,15 +104,15 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
||||||
// Checking attrPath validity.
|
// Checking attrPath validity.
|
||||||
// ===========================
|
// ===========================
|
||||||
for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
|
for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
|
||||||
if (i->symbol.set()) {
|
if (i->symbol) {
|
||||||
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
||||||
if (j != attrs->attrs.end()) {
|
if (j != attrs->attrs.end()) {
|
||||||
if (!j->second.inherited) {
|
if (!j->second.inherited) {
|
||||||
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
|
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
|
||||||
if (!attrs2) dupAttr(attrPath, pt[pos], pt[j->second.pos]);
|
if (!attrs2) dupAttr(state, attrPath, pos, j->second.pos);
|
||||||
attrs = attrs2;
|
attrs = attrs2;
|
||||||
} else
|
} else
|
||||||
dupAttr(attrPath, pt[pos], pt[j->second.pos]);
|
dupAttr(state, attrPath, pos, j->second.pos);
|
||||||
} else {
|
} else {
|
||||||
ExprAttrs * nested = new ExprAttrs;
|
ExprAttrs * nested = new ExprAttrs;
|
||||||
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
|
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
|
||||||
|
@ -126,7 +126,7 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
||||||
}
|
}
|
||||||
// Expr insertion.
|
// Expr insertion.
|
||||||
// ==========================
|
// ==========================
|
||||||
if (i->symbol.set()) {
|
if (i->symbol) {
|
||||||
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
||||||
if (j != attrs->attrs.end()) {
|
if (j != attrs->attrs.end()) {
|
||||||
// This attr path is already defined. However, if both
|
// This attr path is already defined. However, if both
|
||||||
|
@ -139,11 +139,11 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
||||||
for (auto & ad : ae->attrs) {
|
for (auto & ad : ae->attrs) {
|
||||||
auto j2 = jAttrs->attrs.find(ad.first);
|
auto j2 = jAttrs->attrs.find(ad.first);
|
||||||
if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error.
|
if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error.
|
||||||
dupAttr(ad.first, pt[j2->second.pos], pt[ad.second.pos]);
|
dupAttr(state, ad.first, j2->second.pos, ad.second.pos);
|
||||||
jAttrs->attrs.emplace(ad.first, ad.second);
|
jAttrs->attrs.emplace(ad.first, ad.second);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dupAttr(attrPath, pt[pos], pt[j->second.pos]);
|
dupAttr(state, attrPath, pos, j->second.pos);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This attr path is not defined. Let's create it.
|
// This attr path is not defined. Let's create it.
|
||||||
|
@ -157,14 +157,14 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
||||||
|
|
||||||
|
|
||||||
static Formals * toFormals(ParseData & data, ParserFormals * formals,
|
static Formals * toFormals(ParseData & data, ParserFormals * formals,
|
||||||
PosIdx pos = noPos, Symbol arg = {})
|
PosIdx pos = noPos, SymbolIdx arg = {})
|
||||||
{
|
{
|
||||||
std::sort(formals->formals.begin(), formals->formals.end(),
|
std::sort(formals->formals.begin(), formals->formals.end(),
|
||||||
[] (const auto & a, const auto & b) {
|
[] (const auto & a, const auto & b) {
|
||||||
return std::tie(a.name, a.pos) < std::tie(b.name, b.pos);
|
return std::tie(a.name, a.pos) < std::tie(b.name, b.pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
std::optional<std::pair<Symbol, PosIdx>> duplicate;
|
std::optional<std::pair<SymbolIdx, PosIdx>> duplicate;
|
||||||
for (size_t i = 0; i + 1 < formals->formals.size(); i++) {
|
for (size_t i = 0; i + 1 < formals->formals.size(); i++) {
|
||||||
if (formals->formals[i].name != formals->formals[i + 1].name)
|
if (formals->formals[i].name != formals->formals[i + 1].name)
|
||||||
continue;
|
continue;
|
||||||
|
@ -173,7 +173,7 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
|
||||||
}
|
}
|
||||||
if (duplicate)
|
if (duplicate)
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("duplicate formal function argument '%1%'", duplicate->first),
|
.msg = hintfmt("duplicate formal function argument '%1%'", data.symbols[duplicate->first]),
|
||||||
.errPos = data.state.positions[duplicate->second]
|
.errPos = data.state.positions[duplicate->second]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -181,9 +181,9 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
|
||||||
result.ellipsis = formals->ellipsis;
|
result.ellipsis = formals->ellipsis;
|
||||||
result.formals = std::move(formals->formals);
|
result.formals = std::move(formals->formals);
|
||||||
|
|
||||||
if (arg.set() && result.has(arg))
|
if (arg && result.has(arg))
|
||||||
throw ParseError({
|
throw ParseError({
|
||||||
.msg = hintfmt("duplicate formal function argument '%1%'", arg),
|
.msg = hintfmt("duplicate formal function argument '%1%'", data.symbols[arg]),
|
||||||
.errPos = data.state.positions[pos]
|
.errPos = data.state.positions[pos]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -369,15 +369,15 @@ expr_function
|
||||||
: ID ':' expr_function
|
: ID ':' expr_function
|
||||||
{ $$ = new ExprLambda(CUR_POS, data->symbols.create($1), 0, $3); }
|
{ $$ = new ExprLambda(CUR_POS, data->symbols.create($1), 0, $3); }
|
||||||
| '{' formals '}' ':' expr_function
|
| '{' formals '}' ':' expr_function
|
||||||
{ $$ = new ExprLambda(CUR_POS, {}, toFormals(*data, $2), $5); }
|
{ $$ = new ExprLambda(CUR_POS, toFormals(*data, $2), $5); }
|
||||||
| '{' formals '}' '@' ID ':' expr_function
|
| '{' formals '}' '@' ID ':' expr_function
|
||||||
{
|
{
|
||||||
Symbol arg = data->symbols.create($5);
|
auto arg = data->symbols.create($5);
|
||||||
$$ = new ExprLambda(CUR_POS, arg, toFormals(*data, $2, CUR_POS, arg), $7);
|
$$ = new ExprLambda(CUR_POS, arg, toFormals(*data, $2, CUR_POS, arg), $7);
|
||||||
}
|
}
|
||||||
| ID '@' '{' formals '}' ':' expr_function
|
| ID '@' '{' formals '}' ':' expr_function
|
||||||
{
|
{
|
||||||
Symbol arg = data->symbols.create($1);
|
auto arg = data->symbols.create($1);
|
||||||
$$ = new ExprLambda(CUR_POS, arg, toFormals(*data, $4, CUR_POS, arg), $7);
|
$$ = new ExprLambda(CUR_POS, arg, toFormals(*data, $4, CUR_POS, arg), $7);
|
||||||
}
|
}
|
||||||
| ASSERT expr ';' expr_function
|
| ASSERT expr ';' expr_function
|
||||||
|
@ -532,13 +532,12 @@ ind_string_parts
|
||||||
;
|
;
|
||||||
|
|
||||||
binds
|
binds
|
||||||
: binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data), data->state.positions); }
|
: binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data), data->state); }
|
||||||
| binds INHERIT attrs ';'
|
| binds INHERIT attrs ';'
|
||||||
{ $$ = $1;
|
{ $$ = $1;
|
||||||
for (auto & i : *$3) {
|
for (auto & i : *$3) {
|
||||||
if ($$->attrs.find(i.symbol) != $$->attrs.end())
|
if ($$->attrs.find(i.symbol) != $$->attrs.end())
|
||||||
dupAttr(i.symbol, data->state.positions[makeCurPos(@3, data)],
|
dupAttr(data->state, i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos);
|
||||||
data->state.positions[$$->attrs[i.symbol].pos]);
|
|
||||||
auto pos = makeCurPos(@3, data);
|
auto pos = makeCurPos(@3, data);
|
||||||
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true));
|
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true));
|
||||||
}
|
}
|
||||||
|
@ -548,8 +547,7 @@ binds
|
||||||
/* !!! Should ensure sharing of the expression in $4. */
|
/* !!! Should ensure sharing of the expression in $4. */
|
||||||
for (auto & i : *$6) {
|
for (auto & i : *$6) {
|
||||||
if ($$->attrs.find(i.symbol) != $$->attrs.end())
|
if ($$->attrs.find(i.symbol) != $$->attrs.end())
|
||||||
dupAttr(i.symbol, data->state.positions[makeCurPos(@6, data)],
|
dupAttr(data->state, i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos);
|
||||||
data->state.positions[$$->attrs[i.symbol].pos]);
|
|
||||||
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data)));
|
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -623,8 +621,8 @@ formals
|
||||||
;
|
;
|
||||||
|
|
||||||
formal
|
formal
|
||||||
: ID { $$ = new Formal(CUR_POS, data->symbols.create($1), 0); }
|
: ID { $$ = new Formal{CUR_POS, data->symbols.create($1), 0}; }
|
||||||
| ID '?' expr { $$ = new Formal(CUR_POS, data->symbols.create($1), $3); }
|
| ID '?' expr { $$ = new Formal{CUR_POS, data->symbols.create($1), $3}; }
|
||||||
;
|
;
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
@ -670,7 +668,7 @@ Expr * EvalState::parse(char * text, size_t length, FileOrigin origin,
|
||||||
|
|
||||||
if (res) throw ParseError(data.error.value());
|
if (res) throw ParseError(data.error.value());
|
||||||
|
|
||||||
data.result->bindVars(positions, staticEnv);
|
data.result->bindVars(*this, staticEnv);
|
||||||
|
|
||||||
return data.result;
|
return data.result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,7 +403,7 @@ static void prim_typeOf(EvalState & state, const PosIdx pos, Value * * args, Val
|
||||||
case nFloat: t = "float"; break;
|
case nFloat: t = "float"; break;
|
||||||
case nThunk: abort();
|
case nThunk: abort();
|
||||||
}
|
}
|
||||||
v.mkString(state.symbols.create(t));
|
v.mkString(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_typeOf({
|
static RegisterPrimOp primop_typeOf({
|
||||||
|
@ -584,7 +584,7 @@ typedef std::list<Value *> ValueList;
|
||||||
static Bindings::iterator getAttr(
|
static Bindings::iterator getAttr(
|
||||||
EvalState & state,
|
EvalState & state,
|
||||||
std::string_view funcName,
|
std::string_view funcName,
|
||||||
Symbol attrSym,
|
SymbolIdx attrSym,
|
||||||
Bindings * attrSet,
|
Bindings * attrSet,
|
||||||
const PosIdx pos)
|
const PosIdx pos)
|
||||||
{
|
{
|
||||||
|
@ -592,7 +592,7 @@ static Bindings::iterator getAttr(
|
||||||
if (value == attrSet->end()) {
|
if (value == attrSet->end()) {
|
||||||
hintformat errorMsg = hintfmt(
|
hintformat errorMsg = hintfmt(
|
||||||
"attribute '%s' missing for call to '%s'",
|
"attribute '%s' missing for call to '%s'",
|
||||||
attrSym,
|
state.symbols[attrSym],
|
||||||
funcName
|
funcName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -919,7 +919,7 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu
|
||||||
if (args[0]->type() == nString)
|
if (args[0]->type() == nString)
|
||||||
printError("trace: %1%", args[0]->string.s);
|
printError("trace: %1%", args[0]->string.s);
|
||||||
else
|
else
|
||||||
printError("trace: %1%", *args[0]);
|
printError("trace: %1%", printValue(state, *args[0]));
|
||||||
state.forceValue(*args[1], pos);
|
state.forceValue(*args[1], pos);
|
||||||
v = *args[1];
|
v = *args[1];
|
||||||
}
|
}
|
||||||
|
@ -998,9 +998,9 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
|
||||||
StringSet outputs;
|
StringSet outputs;
|
||||||
outputs.insert("out");
|
outputs.insert("out");
|
||||||
|
|
||||||
for (auto & i : args[0]->attrs->lexicographicOrder()) {
|
for (auto & i : args[0]->attrs->lexicographicOrder(state.symbols)) {
|
||||||
if (i->name == state.sIgnoreNulls) continue;
|
if (i->name == state.sIgnoreNulls) continue;
|
||||||
const std::string & key = i->name;
|
const std::string & key = state.symbols[i->name];
|
||||||
vomit("processing attribute '%1%'", key);
|
vomit("processing attribute '%1%'", key);
|
||||||
|
|
||||||
auto handleHashMode = [&](const std::string_view s) {
|
auto handleHashMode = [&](const std::string_view s) {
|
||||||
|
@ -2046,7 +2046,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
PathSet context;
|
PathSet context;
|
||||||
|
|
||||||
for (auto & attr : *args[0]->attrs) {
|
for (auto & attr : *args[0]->attrs) {
|
||||||
auto & n(attr.name);
|
auto & n(state.symbols[attr.name]);
|
||||||
if (n == "path")
|
if (n == "path")
|
||||||
path = state.coerceToPath(attr.pos, *attr.value, context);
|
path = state.coerceToPath(attr.pos, *attr.value, context);
|
||||||
else if (attr.name == state.sName)
|
else if (attr.name == state.sName)
|
||||||
|
@ -2060,7 +2060,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos), htSHA256);
|
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos), htSHA256);
|
||||||
else
|
else
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt("unsupported argument '%1%' to 'addPath'", attr.name),
|
.msg = hintfmt("unsupported argument '%1%' to 'addPath'", state.symbols[attr.name]),
|
||||||
.errPos = state.positions[attr.pos]
|
.errPos = state.positions[attr.pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2126,7 +2126,7 @@ static void prim_attrNames(EvalState & state, const PosIdx pos, Value * * args,
|
||||||
|
|
||||||
size_t n = 0;
|
size_t n = 0;
|
||||||
for (auto & i : *args[0]->attrs)
|
for (auto & i : *args[0]->attrs)
|
||||||
(v.listElems()[n++] = state.allocValue())->mkString(i.name);
|
(v.listElems()[n++] = state.allocValue())->mkString(state.symbols[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; });
|
||||||
|
@ -2156,8 +2156,9 @@ static void prim_attrValues(EvalState & state, const PosIdx pos, Value * * args,
|
||||||
v.listElems()[n++] = (Value *) &i;
|
v.listElems()[n++] = (Value *) &i;
|
||||||
|
|
||||||
std::sort(v.listElems(), v.listElems() + n,
|
std::sort(v.listElems(), v.listElems() + n,
|
||||||
[](Value * v1, Value * v2) {
|
[&](Value * v1, Value * v2) {
|
||||||
std::string_view s1 = ((Attr *) v1)->name, s2 = ((Attr *) v2)->name;
|
std::string_view s1 = state.symbols[((Attr *) v1)->name],
|
||||||
|
s2 = state.symbols[((Attr *) v2)->name];
|
||||||
return s1 < s2;
|
return s1 < s2;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2312,7 +2313,7 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args
|
||||||
|
|
||||||
auto attrs = state.buildBindings(args[0]->listSize());
|
auto attrs = state.buildBindings(args[0]->listSize());
|
||||||
|
|
||||||
std::set<Symbol> seen;
|
std::set<SymbolIdx> seen;
|
||||||
|
|
||||||
for (auto v2 : args[0]->listItems()) {
|
for (auto v2 : args[0]->listItems()) {
|
||||||
state.forceAttrs(*v2, pos);
|
state.forceAttrs(*v2, pos);
|
||||||
|
@ -2327,7 +2328,7 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args
|
||||||
|
|
||||||
auto name = state.forceStringNoCtx(*j->value, j->pos);
|
auto name = state.forceStringNoCtx(*j->value, j->pos);
|
||||||
|
|
||||||
Symbol sym = state.symbols.create(name);
|
auto sym = state.symbols.create(name);
|
||||||
if (seen.insert(sym).second) {
|
if (seen.insert(sym).second) {
|
||||||
Bindings::iterator j2 = getAttr(
|
Bindings::iterator j2 = getAttr(
|
||||||
state,
|
state,
|
||||||
|
@ -2396,7 +2397,7 @@ static RegisterPrimOp primop_intersectAttrs({
|
||||||
|
|
||||||
static void prim_catAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_catAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
Symbol attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos));
|
auto attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos));
|
||||||
state.forceList(*args[1], pos);
|
state.forceList(*args[1], pos);
|
||||||
|
|
||||||
Value * res[args[1]->listSize()];
|
Value * res[args[1]->listSize()];
|
||||||
|
@ -2483,7 +2484,7 @@ static void prim_mapAttrs(EvalState & state, const PosIdx pos, Value * * args, V
|
||||||
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();
|
||||||
vName->mkString(i.name);
|
vName->mkString(state.symbols[i.name]);
|
||||||
vFun2->mkApp(args[0], vName);
|
vFun2->mkApp(args[0], vName);
|
||||||
attrs.alloc(i.name).mkApp(vFun2, i.value);
|
attrs.alloc(i.name).mkApp(vFun2, i.value);
|
||||||
}
|
}
|
||||||
|
@ -2515,7 +2516,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg
|
||||||
// attribute with the merge function application. this way we need not
|
// attribute with the merge function application. this way we need not
|
||||||
// use (slightly slower) temporary storage the GC does not know about.
|
// use (slightly slower) temporary storage the GC does not know about.
|
||||||
|
|
||||||
std::map<Symbol, std::pair<size_t, Value * *>> attrsSeen;
|
std::map<SymbolIdx, std::pair<size_t, Value * *>> attrsSeen;
|
||||||
|
|
||||||
state.forceFunction(*args[0], pos);
|
state.forceFunction(*args[0], pos);
|
||||||
state.forceList(*args[1], pos);
|
state.forceList(*args[1], pos);
|
||||||
|
@ -2550,7 +2551,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg
|
||||||
|
|
||||||
for (auto & attr : *v.attrs) {
|
for (auto & attr : *v.attrs) {
|
||||||
auto name = state.allocValue();
|
auto name = state.allocValue();
|
||||||
name->mkString(attr.name);
|
name->mkString(state.symbols[attr.name]);
|
||||||
auto call1 = state.allocValue();
|
auto call1 = state.allocValue();
|
||||||
call1->mkApp(args[0], name);
|
call1->mkApp(args[0], name);
|
||||||
auto call2 = state.allocValue();
|
auto call2 = state.allocValue();
|
||||||
|
@ -3058,7 +3059,7 @@ static void prim_groupBy(EvalState & state, const PosIdx pos, Value * * args, Va
|
||||||
Value res;
|
Value res;
|
||||||
state.callFunction(*args[0], *vElem, res, pos);
|
state.callFunction(*args[0], *vElem, res, pos);
|
||||||
auto name = state.forceStringNoCtx(res, pos);
|
auto name = state.forceStringNoCtx(res, pos);
|
||||||
Symbol sym = state.symbols.create(name);
|
auto sym = state.symbols.create(name);
|
||||||
auto vector = attrs.try_emplace(sym, ValueVector()).first;
|
auto vector = attrs.try_emplace(sym, ValueVector()).first;
|
||||||
vector->second.push_back(vElem);
|
vector->second.push_back(vElem);
|
||||||
}
|
}
|
||||||
|
@ -3932,7 +3933,7 @@ void EvalState::createBaseEnv()
|
||||||
// the parser needs two NUL bytes as terminators; one of them
|
// the parser needs two NUL bytes as terminators; one of them
|
||||||
// is implied by being a C string.
|
// is implied by being a C string.
|
||||||
"\0";
|
"\0";
|
||||||
eval(parse(code, sizeof(code), foFile, sDerivationNix, "/", staticBaseEnv), *vDerivation);
|
eval(parse(code, sizeof(code), foFile, derivationNixPath, "/", staticBaseEnv), *vDerivation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -144,45 +144,46 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
|
||||||
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 (auto & i : *args[1]->attrs) {
|
for (auto & i : *args[1]->attrs) {
|
||||||
if (!state.store->isStorePath(i.name))
|
const auto & name = state.symbols[i.name];
|
||||||
|
if (!state.store->isStorePath(name))
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt("Context key '%s' is not a store path", i.name),
|
.msg = hintfmt("Context key '%s' is not a store path", name),
|
||||||
.errPos = state.positions[i.pos]
|
.errPos = state.positions[i.pos]
|
||||||
});
|
});
|
||||||
if (!settings.readOnlyMode)
|
if (!settings.readOnlyMode)
|
||||||
state.store->ensurePath(state.store->parseStorePath(i.name));
|
state.store->ensurePath(state.store->parseStorePath(name));
|
||||||
state.forceAttrs(*i.value, i.pos);
|
state.forceAttrs(*i.value, i.pos);
|
||||||
auto iter = i.value->attrs->find(sPath);
|
auto iter = i.value->attrs->find(sPath);
|
||||||
if (iter != i.value->attrs->end()) {
|
if (iter != i.value->attrs->end()) {
|
||||||
if (state.forceBool(*iter->value, iter->pos))
|
if (state.forceBool(*iter->value, iter->pos))
|
||||||
context.insert(i.name);
|
context.emplace(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = i.value->attrs->find(sAllOutputs);
|
iter = i.value->attrs->find(sAllOutputs);
|
||||||
if (iter != i.value->attrs->end()) {
|
if (iter != i.value->attrs->end()) {
|
||||||
if (state.forceBool(*iter->value, iter->pos)) {
|
if (state.forceBool(*iter->value, iter->pos)) {
|
||||||
if (!isDerivation(i.name)) {
|
if (!isDerivation(name)) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", i.name),
|
.msg = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", name),
|
||||||
.errPos = state.positions[i.pos]
|
.errPos = state.positions[i.pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
context.insert("=" + std::string(i.name));
|
context.insert(concatStrings("=", name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = i.value->attrs->find(state.sOutputs);
|
iter = i.value->attrs->find(state.sOutputs);
|
||||||
if (iter != i.value->attrs->end()) {
|
if (iter != i.value->attrs->end()) {
|
||||||
state.forceList(*iter->value, iter->pos);
|
state.forceList(*iter->value, iter->pos);
|
||||||
if (iter->value->listSize() && !isDerivation(i.name)) {
|
if (iter->value->listSize() && !isDerivation(name)) {
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", i.name),
|
.msg = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", name),
|
||||||
.errPos = state.positions[i.pos]
|
.errPos = state.positions[i.pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (auto elem : iter->value->listItems()) {
|
for (auto elem : iter->value->listItems()) {
|
||||||
auto name = state.forceStringNoCtx(*elem, iter->pos);
|
auto outputName = state.forceStringNoCtx(*elem, iter->pos);
|
||||||
context.insert(concatStrings("!", name, "!", i.name));
|
context.insert(concatStrings("!", outputName, "!", name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,14 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg
|
||||||
std::optional<StorePath> toPath;
|
std::optional<StorePath> toPath;
|
||||||
|
|
||||||
for (auto & attr : *args[0]->attrs) {
|
for (auto & attr : *args[0]->attrs) {
|
||||||
if (attr.name == "fromPath") {
|
const auto & attrName = state.symbols[attr.name];
|
||||||
|
|
||||||
|
if (attrName == "fromPath") {
|
||||||
PathSet context;
|
PathSet context;
|
||||||
fromPath = state.coerceToStorePath(attr.pos, *attr.value, context);
|
fromPath = state.coerceToStorePath(attr.pos, *attr.value, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (attr.name == "toPath") {
|
else if (attrName == "toPath") {
|
||||||
state.forceValue(*attr.value, attr.pos);
|
state.forceValue(*attr.value, attr.pos);
|
||||||
toCA = true;
|
toCA = true;
|
||||||
if (attr.value->type() != nString || attr.value->string.s != std::string("")) {
|
if (attr.value->type() != nString || attr.value->string.s != std::string("")) {
|
||||||
|
@ -29,12 +31,12 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (attr.name == "fromStore")
|
else if (attrName == "fromStore")
|
||||||
fromStoreUrl = state.forceStringNoCtx(*attr.value, attr.pos);
|
fromStoreUrl = state.forceStringNoCtx(*attr.value, attr.pos);
|
||||||
|
|
||||||
else
|
else
|
||||||
throw Error({
|
throw Error({
|
||||||
.msg = hintfmt("attribute '%s' isn't supported in call to 'fetchClosure'", attr.name),
|
.msg = hintfmt("attribute '%s' isn't supported in call to 'fetchClosure'", attrName),
|
||||||
.errPos = state.positions[pos]
|
.errPos = state.positions[pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
|
||||||
state.forceAttrs(*args[0], pos);
|
state.forceAttrs(*args[0], pos);
|
||||||
|
|
||||||
for (auto & attr : *args[0]->attrs) {
|
for (auto & attr : *args[0]->attrs) {
|
||||||
std::string_view n(attr.name);
|
std::string_view n(state.symbols[attr.name]);
|
||||||
if (n == "url")
|
if (n == "url")
|
||||||
url = state.coerceToString(attr.pos, *attr.value, context, false, false).toOwned();
|
url = state.coerceToString(attr.pos, *attr.value, context, false, false).toOwned();
|
||||||
else if (n == "rev") {
|
else if (n == "rev") {
|
||||||
|
@ -38,7 +38,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
|
||||||
name = state.forceStringNoCtx(*attr.value, attr.pos);
|
name = state.forceStringNoCtx(*attr.value, attr.pos);
|
||||||
else
|
else
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name),
|
.msg = hintfmt("unsupported argument '%s' to 'fetchMercurial'", state.symbols[attr.name]),
|
||||||
.errPos = state.positions[attr.pos]
|
.errPos = state.positions[attr.pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,20 +126,20 @@ static void fetchTree(
|
||||||
state.forceValue(*attr.value, attr.pos);
|
state.forceValue(*attr.value, attr.pos);
|
||||||
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
||||||
auto s = state.coerceToString(attr.pos, *attr.value, context, false, false).toOwned();
|
auto s = state.coerceToString(attr.pos, *attr.value, context, false, false).toOwned();
|
||||||
attrs.emplace(attr.name,
|
attrs.emplace(state.symbols[attr.name],
|
||||||
attr.name == "url"
|
state.symbols[attr.name] == "url"
|
||||||
? type == "git"
|
? type == "git"
|
||||||
? fixURIForGit(s, state)
|
? fixURIForGit(s, state)
|
||||||
: fixURI(s, state)
|
: fixURI(s, state)
|
||||||
: s);
|
: s);
|
||||||
}
|
}
|
||||||
else if (attr.value->type() == nBool)
|
else if (attr.value->type() == nBool)
|
||||||
attrs.emplace(attr.name, Explicit<bool>{attr.value->boolean});
|
attrs.emplace(state.symbols[attr.name], Explicit<bool>{attr.value->boolean});
|
||||||
else if (attr.value->type() == nInt)
|
else if (attr.value->type() == nInt)
|
||||||
attrs.emplace(attr.name, uint64_t(attr.value->integer));
|
attrs.emplace(state.symbols[attr.name], uint64_t(attr.value->integer));
|
||||||
else
|
else
|
||||||
throw TypeError("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
|
throw TypeError("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
|
||||||
attr.name, showType(*attr.value));
|
state.symbols[attr.name], showType(*attr.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.allowNameArgument)
|
if (!params.allowNameArgument)
|
||||||
|
@ -198,7 +198,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
|
||||||
state.forceAttrs(*args[0], pos);
|
state.forceAttrs(*args[0], pos);
|
||||||
|
|
||||||
for (auto & attr : *args[0]->attrs) {
|
for (auto & attr : *args[0]->attrs) {
|
||||||
std::string n(attr.name);
|
std::string_view n(state.symbols[attr.name]);
|
||||||
if (n == "url")
|
if (n == "url")
|
||||||
url = state.forceStringNoCtx(*attr.value, attr.pos);
|
url = state.forceStringNoCtx(*attr.value, attr.pos);
|
||||||
else if (n == "sha256")
|
else if (n == "sha256")
|
||||||
|
@ -207,7 +207,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
|
||||||
name = state.forceStringNoCtx(*attr.value, attr.pos);
|
name = state.forceStringNoCtx(*attr.value, attr.pos);
|
||||||
else
|
else
|
||||||
throw EvalError({
|
throw EvalError({
|
||||||
.msg = hintfmt("unsupported argument '%s' to '%s'", attr.name, who),
|
.msg = hintfmt("unsupported argument '%s' to '%s'", n, who),
|
||||||
.errPos = state.positions[attr.pos]
|
.errPos = state.positions[attr.pos]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,46 +16,25 @@ namespace nix {
|
||||||
|
|
||||||
class Symbol
|
class Symbol
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
const std::string * s; // pointer into SymbolTable
|
|
||||||
Symbol(const std::string * s) : s(s) { };
|
|
||||||
friend class SymbolTable;
|
friend class SymbolTable;
|
||||||
|
private:
|
||||||
|
std::string s;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Symbol() : s(0) { };
|
Symbol(std::string_view s) : s(s) { }
|
||||||
|
|
||||||
bool operator == (const Symbol & s2) const
|
|
||||||
{
|
|
||||||
return s == s2.s;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: remove
|
// FIXME: remove
|
||||||
bool operator == (std::string_view s2) const
|
bool operator == (std::string_view s2) const
|
||||||
{
|
{
|
||||||
return s->compare(s2) == 0;
|
return s == s2;
|
||||||
}
|
|
||||||
|
|
||||||
bool operator != (const Symbol & s2) const
|
|
||||||
{
|
|
||||||
return s != s2.s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator < (const Symbol & s2) const
|
|
||||||
{
|
|
||||||
return s < s2.s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
operator const std::string & () const
|
operator const std::string & () const
|
||||||
{
|
{
|
||||||
return *s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator const std::string_view () const
|
operator const std::string_view () const
|
||||||
{
|
|
||||||
return *s;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool set() const
|
|
||||||
{
|
{
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -63,38 +42,64 @@ public:
|
||||||
friend std::ostream & operator << (std::ostream & str, const Symbol & sym);
|
friend std::ostream & operator << (std::ostream & str, const Symbol & sym);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SymbolIdx
|
||||||
|
{
|
||||||
|
friend class SymbolTable;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
explicit SymbolIdx(uint32_t id): id(id) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
SymbolIdx() : id(0) {}
|
||||||
|
|
||||||
|
explicit operator bool() const { return id > 0; }
|
||||||
|
|
||||||
|
bool operator<(const SymbolIdx other) const { return id < other.id; }
|
||||||
|
bool operator==(const SymbolIdx other) const { return id == other.id; }
|
||||||
|
bool operator!=(const SymbolIdx other) const { return id != other.id; }
|
||||||
|
};
|
||||||
|
|
||||||
class SymbolTable
|
class SymbolTable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string_view, Symbol> symbols;
|
std::unordered_map<std::string_view, std::pair<const Symbol *, uint32_t>> symbols;
|
||||||
std::list<std::string> store;
|
ChunkedVector<Symbol, 8192> store{16};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Symbol create(std::string_view s)
|
SymbolIdx create(std::string_view s)
|
||||||
{
|
{
|
||||||
// Most symbols are looked up more than once, so we trade off insertion performance
|
// Most symbols are looked up more than once, so we trade off insertion performance
|
||||||
// for lookup performance.
|
// for lookup performance.
|
||||||
// TODO: could probably be done more efficiently with transparent Hash and Equals
|
// TODO: could probably be done more efficiently with transparent Hash and Equals
|
||||||
// on the original implementation using unordered_set
|
// on the original implementation using unordered_set
|
||||||
auto it = symbols.find(s);
|
auto it = symbols.find(s);
|
||||||
if (it != symbols.end()) return it->second;
|
if (it != symbols.end()) return SymbolIdx(it->second.second + 1);
|
||||||
|
|
||||||
auto & rawSym = store.emplace_back(s);
|
const auto & [rawSym, idx] = store.add(s);
|
||||||
return symbols.emplace(rawSym, Symbol(&rawSym)).first->second;
|
symbols.emplace(rawSym, std::make_pair(&rawSym, idx));
|
||||||
|
return SymbolIdx(idx + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Symbol & operator[](SymbolIdx s) const
|
||||||
|
{
|
||||||
|
if (s.id == 0 || s.id > store.size())
|
||||||
|
abort();
|
||||||
|
return store[s.id - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const
|
size_t size() const
|
||||||
{
|
{
|
||||||
return symbols.size();
|
return store.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t totalSize() const;
|
size_t totalSize() const;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void dump(T callback)
|
void dump(T callback) const
|
||||||
{
|
{
|
||||||
for (auto & s : store)
|
store.forEach(callback);
|
||||||
callback(s);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ void printValueAsJSON(EvalState & state, bool strict,
|
||||||
auto obj(out.object());
|
auto obj(out.object());
|
||||||
StringSet names;
|
StringSet names;
|
||||||
for (auto & j : *v.attrs)
|
for (auto & j : *v.attrs)
|
||||||
names.insert(j.name);
|
names.emplace(state.symbols[j.name]);
|
||||||
for (auto & j : names) {
|
for (auto & j : names) {
|
||||||
Attr & a(*v.attrs->find(state.symbols.create(j)));
|
Attr & a(*v.attrs->find(state.symbols.create(j)));
|
||||||
auto placeholder(obj.placeholder(j));
|
auto placeholder(obj.placeholder(j));
|
||||||
|
|
|
@ -22,7 +22,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||||
const PosIdx pos);
|
const PosIdx pos);
|
||||||
|
|
||||||
|
|
||||||
static void posToXML(XMLAttrs & xmlAttrs, const Pos & pos)
|
static void posToXML(EvalState & state, XMLAttrs & xmlAttrs, const Pos & pos)
|
||||||
{
|
{
|
||||||
xmlAttrs["path"] = pos.file;
|
xmlAttrs["path"] = pos.file;
|
||||||
xmlAttrs["line"] = (format("%1%") % pos.line).str();
|
xmlAttrs["line"] = (format("%1%") % pos.line).str();
|
||||||
|
@ -36,14 +36,14 @@ static void showAttrs(EvalState & state, bool strict, bool location,
|
||||||
StringSet names;
|
StringSet names;
|
||||||
|
|
||||||
for (auto & i : attrs)
|
for (auto & i : attrs)
|
||||||
names.insert(i.name);
|
names.emplace(state.symbols[i.name]);
|
||||||
|
|
||||||
for (auto & i : names) {
|
for (auto & i : names) {
|
||||||
Attr & a(*attrs.find(state.symbols.create(i)));
|
Attr & a(*attrs.find(state.symbols.create(i)));
|
||||||
|
|
||||||
XMLAttrs xmlAttrs;
|
XMLAttrs xmlAttrs;
|
||||||
xmlAttrs["name"] = i;
|
xmlAttrs["name"] = i;
|
||||||
if (location && a.pos) posToXML(xmlAttrs, state.positions[a.pos]);
|
if (location && a.pos) posToXML(state, xmlAttrs, state.positions[a.pos]);
|
||||||
|
|
||||||
XMLOpenElement _(doc, "attr", xmlAttrs);
|
XMLOpenElement _(doc, "attr", xmlAttrs);
|
||||||
printValueAsXML(state, strict, location,
|
printValueAsXML(state, strict, location,
|
||||||
|
@ -134,18 +134,18 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
XMLAttrs xmlAttrs;
|
XMLAttrs xmlAttrs;
|
||||||
if (location) posToXML(xmlAttrs, state.positions[v.lambda.fun->pos]);
|
if (location) posToXML(state, xmlAttrs, state.positions[v.lambda.fun->pos]);
|
||||||
XMLOpenElement _(doc, "function", xmlAttrs);
|
XMLOpenElement _(doc, "function", xmlAttrs);
|
||||||
|
|
||||||
if (v.lambda.fun->hasFormals()) {
|
if (v.lambda.fun->hasFormals()) {
|
||||||
XMLAttrs attrs;
|
XMLAttrs attrs;
|
||||||
if (v.lambda.fun->arg.set()) attrs["name"] = v.lambda.fun->arg;
|
if (v.lambda.fun->arg) attrs["name"] = state.symbols[v.lambda.fun->arg];
|
||||||
if (v.lambda.fun->formals->ellipsis) attrs["ellipsis"] = "1";
|
if (v.lambda.fun->formals->ellipsis) attrs["ellipsis"] = "1";
|
||||||
XMLOpenElement _(doc, "attrspat", attrs);
|
XMLOpenElement _(doc, "attrspat", attrs);
|
||||||
for (auto & i : v.lambda.fun->formals->lexicographicOrder())
|
for (auto & i : v.lambda.fun->formals->lexicographicOrder(state.symbols))
|
||||||
doc.writeEmptyElement("attr", singletonAttrs("name", i.name));
|
doc.writeEmptyElement("attr", singletonAttrs("name", state.symbols[i.name]));
|
||||||
} else
|
} else
|
||||||
doc.writeEmptyElement("varpat", singletonAttrs("name", v.lambda.fun->arg));
|
doc.writeEmptyElement("varpat", singletonAttrs("name", state.symbols[v.lambda.fun->arg]));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ struct Env;
|
||||||
struct Expr;
|
struct Expr;
|
||||||
struct ExprLambda;
|
struct ExprLambda;
|
||||||
struct PrimOp;
|
struct PrimOp;
|
||||||
class Symbol;
|
class SymbolIdx;
|
||||||
class PosIdx;
|
class PosIdx;
|
||||||
struct Pos;
|
struct Pos;
|
||||||
class StorePath;
|
class StorePath;
|
||||||
|
@ -121,11 +121,11 @@ private:
|
||||||
|
|
||||||
friend std::string showType(const Value & v);
|
friend std::string showType(const Value & v);
|
||||||
|
|
||||||
void print(std::ostream & str, std::set<const void *> * seen) const;
|
void print(const SymbolTable & symbols, std::ostream & str, std::set<const void *> * seen) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void print(std::ostream & str, bool showRepeated = false) const;
|
void print(const SymbolTable & symbols, std::ostream & str, bool showRepeated = false) const;
|
||||||
|
|
||||||
// Functions needed to distinguish the type
|
// Functions needed to distinguish the type
|
||||||
// These should be removed eventually, by putting the functionality that's
|
// These should be removed eventually, by putting the functionality that's
|
||||||
|
@ -253,7 +253,7 @@ public:
|
||||||
|
|
||||||
inline void mkString(const Symbol & s)
|
inline void mkString(const Symbol & s)
|
||||||
{
|
{
|
||||||
mkString(((const std::string &) s).c_str());
|
mkString(std::string_view(s).data());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void mkPath(const char * s)
|
inline void mkPath(const char * s)
|
||||||
|
@ -410,12 +410,12 @@ public:
|
||||||
|
|
||||||
#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<SymbolIdx, Value *, std::less<SymbolIdx>, traceable_allocator<std::pair<const SymbolIdx, Value *> > > ValueMap;
|
||||||
typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector> > > ValueVectorMap;
|
typedef std::map<SymbolIdx, ValueVector, std::less<SymbolIdx>, traceable_allocator<std::pair<const SymbolIdx, ValueVector> > > ValueVectorMap;
|
||||||
#else
|
#else
|
||||||
typedef std::vector<Value *> ValueVector;
|
typedef std::vector<Value *> ValueVector;
|
||||||
typedef std::map<Symbol, Value *> ValueMap;
|
typedef std::map<SymbolIdx, Value *> ValueMap;
|
||||||
typedef std::map<Symbol, ValueVector> ValueVectorMap;
|
typedef std::map<SymbolIdx, ValueVector> ValueVectorMap;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,14 @@ public:
|
||||||
{
|
{
|
||||||
return chunks[idx / ChunkSize][idx % ChunkSize];
|
return chunks[idx / ChunkSize][idx % ChunkSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Fn>
|
||||||
|
void forEach(Fn fn) const
|
||||||
|
{
|
||||||
|
for (const auto & c : chunks)
|
||||||
|
for (const auto & e : c)
|
||||||
|
fn(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1241,7 +1241,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
Attr & a(*attrs.find(i.name));
|
Attr & a(*attrs.find(i.name));
|
||||||
if(a.value->type() != nString) continue;
|
if(a.value->type() != nString) continue;
|
||||||
XMLAttrs attrs3;
|
XMLAttrs attrs3;
|
||||||
attrs3["type"] = i.name;
|
attrs3["type"] = globals.state->symbols[i.name];
|
||||||
attrs3["value"] = a.value->string.s;
|
attrs3["value"] = a.value->string.s;
|
||||||
xml.writeEmptyElement("string", attrs3);
|
xml.writeEmptyElement("string", attrs3);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
the store; we need it for future modifications of the
|
the store; we need it for future modifications of the
|
||||||
environment. */
|
environment. */
|
||||||
std::ostringstream str;
|
std::ostringstream str;
|
||||||
manifest.print(str, true);
|
manifest.print(state.symbols, str, true);
|
||||||
auto manifestFile = state.store->addTextToStore("env-manifest.nix",
|
auto manifestFile = state.store->addTextToStore("env-manifest.nix",
|
||||||
str.str(), references);
|
str.str(), references);
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,8 @@ void processExpr(EvalState & state, const Strings & attrPaths,
|
||||||
bool evalOnly, OutputKind output, bool location, Expr * e)
|
bool evalOnly, OutputKind output, bool location, Expr * e)
|
||||||
{
|
{
|
||||||
if (parseOnly) {
|
if (parseOnly) {
|
||||||
std::cout << format("%1%\n") % *e;
|
e->show(state.symbols, std::cout);
|
||||||
|
std::cout << "\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +56,8 @@ void processExpr(EvalState & state, const Strings & attrPaths,
|
||||||
printValueAsJSON(state, strict, vRes, v.determinePos(noPos), std::cout, context);
|
printValueAsJSON(state, strict, vRes, v.determinePos(noPos), std::cout, context);
|
||||||
else {
|
else {
|
||||||
if (strict) state.forceValueDeep(vRes);
|
if (strict) state.forceValueDeep(vRes);
|
||||||
std::cout << vRes << std::endl;
|
vRes.print(state.symbols, std::cout);
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DrvInfos drvs;
|
DrvInfos drvs;
|
||||||
|
|
|
@ -85,9 +85,9 @@ UnresolvedApp Installable::toApp(EvalState & state)
|
||||||
|
|
||||||
else if (type == "derivation") {
|
else if (type == "derivation") {
|
||||||
auto drvPath = cursor->forceDerivation();
|
auto drvPath = cursor->forceDerivation();
|
||||||
auto outPath = cursor->getAttr(state.sOutPath)->getString();
|
auto outPath = cursor->getAttr("outPath")->getString();
|
||||||
auto outputName = cursor->getAttr(state.sOutputName)->getString();
|
auto outputName = cursor->getAttr("outputName")->getString();
|
||||||
auto name = cursor->getAttr(state.sName)->getString();
|
auto name = cursor->getAttr("name")->getString();
|
||||||
auto aPname = cursor->maybeGetAttr("pname");
|
auto aPname = cursor->maybeGetAttr("pname");
|
||||||
auto aMeta = cursor->maybeGetAttr("meta");
|
auto aMeta = cursor->maybeGetAttr("meta");
|
||||||
auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr;
|
auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr;
|
||||||
|
|
|
@ -88,17 +88,19 @@ struct CmdEval : MixJSON, InstallableCommand
|
||||||
else if (v.type() == nAttrs) {
|
else if (v.type() == nAttrs) {
|
||||||
if (mkdir(path.c_str(), 0777) == -1)
|
if (mkdir(path.c_str(), 0777) == -1)
|
||||||
throw SysError("creating directory '%s'", path);
|
throw SysError("creating directory '%s'", path);
|
||||||
for (auto & attr : *v.attrs)
|
for (auto & attr : *v.attrs) {
|
||||||
|
std::string_view name = state->symbols[attr.name];
|
||||||
try {
|
try {
|
||||||
if (attr.name == "." || attr.name == "..")
|
if (name == "." || name == "..")
|
||||||
throw Error("invalid file name '%s'", attr.name);
|
throw Error("invalid file name '%s'", name);
|
||||||
recurse(*attr.value, attr.pos, path + "/" + std::string(attr.name));
|
recurse(*attr.value, attr.pos, concatStrings(path, "/", name));
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(
|
e.addTrace(
|
||||||
state->positions[attr.pos],
|
state->positions[attr.pos],
|
||||||
hintfmt("while evaluating the attribute '%s'", attr.name));
|
hintfmt("while evaluating the attribute '%s'", name));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw TypeError("value at '%s' is not a string or an attribute set", state->positions[pos]);
|
throw TypeError("value at '%s' is not a string or an attribute set", state->positions[pos]);
|
||||||
|
@ -119,7 +121,7 @@ struct CmdEval : MixJSON, InstallableCommand
|
||||||
|
|
||||||
else {
|
else {
|
||||||
state->forceValueDeep(*v);
|
state->forceValueDeep(*v);
|
||||||
logger->cout("%s", *v);
|
logger->cout("%s", printValue(*state, *v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -139,11 +139,11 @@ static void enumerateOutputs(EvalState & state, Value & vFlake,
|
||||||
else. This way we can disable IFD for hydraJobs and then enable
|
else. This way we can disable IFD for hydraJobs and then enable
|
||||||
it for other outputs. */
|
it for other outputs. */
|
||||||
if (auto attr = aOutputs->value->attrs->get(sHydraJobs))
|
if (auto attr = aOutputs->value->attrs->get(sHydraJobs))
|
||||||
callback(attr->name, *attr->value, attr->pos);
|
callback(state.symbols[attr->name], *attr->value, attr->pos);
|
||||||
|
|
||||||
for (auto & attr : *aOutputs->value->attrs) {
|
for (auto & attr : *aOutputs->value->attrs) {
|
||||||
if (attr.name != sHydraJobs)
|
if (attr.name != sHydraJobs)
|
||||||
callback(attr.name, *attr.value, attr.pos);
|
callback(state.symbols[attr.name], *attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,14 +254,6 @@ struct CmdFlakeInfo : CmdFlakeMetadata
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool argHasName(std::string_view arg, std::string_view expected)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
arg == expected
|
|
||||||
|| arg == "_"
|
|
||||||
|| (hasPrefix(arg, "_") && arg.substr(1) == expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CmdFlakeCheck : FlakeCommand
|
struct CmdFlakeCheck : FlakeCommand
|
||||||
{
|
{
|
||||||
bool build = true;
|
bool build = true;
|
||||||
|
@ -319,6 +311,14 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
return state->positions[p];
|
return state->positions[p];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto argHasName = [&] (SymbolIdx arg, std::string_view expected) {
|
||||||
|
std::string_view name = state->symbols[arg];
|
||||||
|
return
|
||||||
|
name == expected
|
||||||
|
|| name == "_"
|
||||||
|
|| (hasPrefix(name, "_") && name.substr(1) == expected);
|
||||||
|
};
|
||||||
|
|
||||||
auto checkSystemName = [&](const std::string & system, const PosIdx pos) {
|
auto checkSystemName = [&](const std::string & system, const PosIdx pos) {
|
||||||
// FIXME: what's the format of "system"?
|
// FIXME: what's the format of "system"?
|
||||||
if (system.find('-') == std::string::npos)
|
if (system.find('-') == std::string::npos)
|
||||||
|
@ -390,7 +390,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(
|
e.addTrace(
|
||||||
state->positions[attr.pos],
|
state->positions[attr.pos],
|
||||||
hintfmt("while evaluating the option '%s'", attr.name));
|
hintfmt("while evaluating the option '%s'", state->symbols[attr.name]));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
@ -414,7 +414,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
|
|
||||||
for (auto & attr : *v.attrs) {
|
for (auto & attr : *v.attrs) {
|
||||||
state->forceAttrs(*attr.value, attr.pos);
|
state->forceAttrs(*attr.value, attr.pos);
|
||||||
auto attrPath2 = attrPath + "." + (std::string) attr.name;
|
auto attrPath2 = concatStrings(attrPath, ".", state->symbols[attr.name]);
|
||||||
if (state->isDerivation(*attr.value)) {
|
if (state->isDerivation(*attr.value)) {
|
||||||
Activity act(*logger, lvlChatty, actUnknown,
|
Activity act(*logger, lvlChatty, actUnknown,
|
||||||
fmt("checking Hydra job '%s'", attrPath2));
|
fmt("checking Hydra job '%s'", attrPath2));
|
||||||
|
@ -468,7 +468,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
throw Error("template '%s' lacks attribute 'description'", attrPath);
|
throw Error("template '%s' lacks attribute 'description'", attrPath);
|
||||||
|
|
||||||
for (auto & attr : *v.attrs) {
|
for (auto & attr : *v.attrs) {
|
||||||
std::string name(attr.name);
|
std::string_view name(state->symbols[attr.name]);
|
||||||
if (name != "path" && name != "description" && name != "welcomeText")
|
if (name != "path" && name != "description" && name != "welcomeText")
|
||||||
throw Error("template '%s' has unsupported attribute '%s'", attrPath, name);
|
throw Error("template '%s' has unsupported attribute '%s'", attrPath, name);
|
||||||
}
|
}
|
||||||
|
@ -522,13 +522,14 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
if (name == "checks") {
|
if (name == "checks") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
const auto & attr_name = state->symbols[attr.name];
|
||||||
|
checkSystemName(attr_name, attr.pos);
|
||||||
state->forceAttrs(*attr.value, attr.pos);
|
state->forceAttrs(*attr.value, attr.pos);
|
||||||
for (auto & attr2 : *attr.value->attrs) {
|
for (auto & attr2 : *attr.value->attrs) {
|
||||||
auto drvPath = checkDerivation(
|
auto drvPath = checkDerivation(
|
||||||
fmt("%s.%s.%s", name, attr.name, attr2.name),
|
fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
|
||||||
*attr2.value, attr2.pos);
|
*attr2.value, attr2.pos);
|
||||||
if (drvPath && (std::string) attr.name == settings.thisSystem.get())
|
if (drvPath && attr_name == settings.thisSystem.get())
|
||||||
drvPaths.push_back(DerivedPath::Built{*drvPath});
|
drvPaths.push_back(DerivedPath::Built{*drvPath});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -537,9 +538,10 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "formatter") {
|
else if (name == "formatter") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
const auto & attr_name = state->symbols[attr.name];
|
||||||
|
checkSystemName(attr_name, attr.pos);
|
||||||
checkApp(
|
checkApp(
|
||||||
fmt("%s.%s", name, attr.name),
|
fmt("%s.%s", name, attr_name),
|
||||||
*attr.value, attr.pos);
|
*attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -547,11 +549,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "packages" || name == "devShells") {
|
else if (name == "packages" || name == "devShells") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
const auto & attr_name = state->symbols[attr.name];
|
||||||
|
checkSystemName(attr_name, attr.pos);
|
||||||
state->forceAttrs(*attr.value, attr.pos);
|
state->forceAttrs(*attr.value, attr.pos);
|
||||||
for (auto & attr2 : *attr.value->attrs)
|
for (auto & attr2 : *attr.value->attrs)
|
||||||
checkDerivation(
|
checkDerivation(
|
||||||
fmt("%s.%s.%s", name, attr.name, attr2.name),
|
fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
|
||||||
*attr2.value, attr2.pos);
|
*attr2.value, attr2.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,11 +562,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "apps") {
|
else if (name == "apps") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
const auto & attr_name = state->symbols[attr.name];
|
||||||
|
checkSystemName(attr_name, attr.pos);
|
||||||
state->forceAttrs(*attr.value, attr.pos);
|
state->forceAttrs(*attr.value, attr.pos);
|
||||||
for (auto & attr2 : *attr.value->attrs)
|
for (auto & attr2 : *attr.value->attrs)
|
||||||
checkApp(
|
checkApp(
|
||||||
fmt("%s.%s.%s", name, attr.name, attr2.name),
|
fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
|
||||||
*attr2.value, attr2.pos);
|
*attr2.value, attr2.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,9 +575,10 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "defaultPackage" || name == "devShell") {
|
else if (name == "defaultPackage" || name == "devShell") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
const auto & attr_name = state->symbols[attr.name];
|
||||||
|
checkSystemName(attr_name, attr.pos);
|
||||||
checkDerivation(
|
checkDerivation(
|
||||||
fmt("%s.%s", name, attr.name),
|
fmt("%s.%s", name, attr_name),
|
||||||
*attr.value, attr.pos);
|
*attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,9 +586,10 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "defaultApp") {
|
else if (name == "defaultApp") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
const auto & attr_name = state->symbols[attr.name];
|
||||||
|
checkSystemName(attr_name, attr.pos);
|
||||||
checkApp(
|
checkApp(
|
||||||
fmt("%s.%s", name, attr.name),
|
fmt("%s.%s", name, attr_name),
|
||||||
*attr.value, attr.pos);
|
*attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -591,7 +597,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "legacyPackages") {
|
else if (name == "legacyPackages") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
checkSystemName(state->symbols[attr.name], attr.pos);
|
||||||
// FIXME: do getDerivations?
|
// FIXME: do getDerivations?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -602,7 +608,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "overlays") {
|
else if (name == "overlays") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs)
|
for (auto & attr : *vOutput.attrs)
|
||||||
checkOverlay(fmt("%s.%s", name, attr.name),
|
checkOverlay(fmt("%s.%s", name, state->symbols[attr.name]),
|
||||||
*attr.value, attr.pos);
|
*attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,14 +618,14 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "nixosModules") {
|
else if (name == "nixosModules") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs)
|
for (auto & attr : *vOutput.attrs)
|
||||||
checkModule(fmt("%s.%s", name, attr.name),
|
checkModule(fmt("%s.%s", name, state->symbols[attr.name]),
|
||||||
*attr.value, attr.pos);
|
*attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (name == "nixosConfigurations") {
|
else if (name == "nixosConfigurations") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs)
|
for (auto & attr : *vOutput.attrs)
|
||||||
checkNixOSConfiguration(fmt("%s.%s", name, attr.name),
|
checkNixOSConfiguration(fmt("%s.%s", name, state->symbols[attr.name]),
|
||||||
*attr.value, attr.pos);
|
*attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,16 +638,17 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "templates") {
|
else if (name == "templates") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs)
|
for (auto & attr : *vOutput.attrs)
|
||||||
checkTemplate(fmt("%s.%s", name, attr.name),
|
checkTemplate(fmt("%s.%s", name, state->symbols[attr.name]),
|
||||||
*attr.value, attr.pos);
|
*attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (name == "defaultBundler") {
|
else if (name == "defaultBundler") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
const auto & attr_name = state->symbols[attr.name];
|
||||||
|
checkSystemName(attr_name, attr.pos);
|
||||||
checkBundler(
|
checkBundler(
|
||||||
fmt("%s.%s", name, attr.name),
|
fmt("%s.%s", name, attr_name),
|
||||||
*attr.value, attr.pos);
|
*attr.value, attr.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -649,11 +656,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
else if (name == "bundlers") {
|
else if (name == "bundlers") {
|
||||||
state->forceAttrs(vOutput, pos);
|
state->forceAttrs(vOutput, pos);
|
||||||
for (auto & attr : *vOutput.attrs) {
|
for (auto & attr : *vOutput.attrs) {
|
||||||
checkSystemName(attr.name, attr.pos);
|
const auto & attr_name = state->symbols[attr.name];
|
||||||
|
checkSystemName(attr_name, attr.pos);
|
||||||
state->forceAttrs(*attr.value, attr.pos);
|
state->forceAttrs(*attr.value, attr.pos);
|
||||||
for (auto & attr2 : *attr.value->attrs) {
|
for (auto & attr2 : *attr.value->attrs) {
|
||||||
checkBundler(
|
checkBundler(
|
||||||
fmt("%s.%s.%s", name, attr.name, attr2.name),
|
fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
|
||||||
*attr2.value, attr2.pos);
|
*attr2.value, attr2.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1000,7 +1008,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
||||||
|
|
||||||
auto showDerivation = [&]()
|
auto showDerivation = [&]()
|
||||||
{
|
{
|
||||||
auto name = visitor.getAttr(state->sName)->getString();
|
auto name = visitor.getAttr("name")->getString();
|
||||||
if (json) {
|
if (json) {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
if (auto aMeta = visitor.maybeGetAttr("meta")) {
|
if (auto aMeta = visitor.maybeGetAttr("meta")) {
|
||||||
|
|
|
@ -302,7 +302,7 @@ void mainWrapped(int argc, char * * argv)
|
||||||
b["arity"] = primOp->arity;
|
b["arity"] = primOp->arity;
|
||||||
b["args"] = primOp->args;
|
b["args"] = primOp->args;
|
||||||
b["doc"] = trim(stripIndentation(primOp->doc));
|
b["doc"] = trim(stripIndentation(primOp->doc));
|
||||||
res[(std::string) builtin.name] = std::move(b);
|
res[state.symbols[builtin.name]] = std::move(b);
|
||||||
}
|
}
|
||||||
std::cout << res.dump() << "\n";
|
std::cout << res.dump() << "\n";
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -73,7 +73,7 @@ struct NixRepl
|
||||||
void initEnv();
|
void initEnv();
|
||||||
void reloadFiles();
|
void reloadFiles();
|
||||||
void addAttrsToScope(Value & attrs);
|
void addAttrsToScope(Value & attrs);
|
||||||
void addVarToScope(const Symbol & name, Value & v);
|
void addVarToScope(const SymbolIdx name, Value & v);
|
||||||
Expr * parseString(std::string s);
|
Expr * parseString(std::string s);
|
||||||
void evalString(std::string s, Value & v);
|
void evalString(std::string s, Value & v);
|
||||||
|
|
||||||
|
@ -347,9 +347,9 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
||||||
state->forceAttrs(v, noPos);
|
state->forceAttrs(v, noPos);
|
||||||
|
|
||||||
for (auto & i : *v.attrs) {
|
for (auto & i : *v.attrs) {
|
||||||
std::string name = i.name;
|
std::string_view name = state->symbols[i.name];
|
||||||
if (name.substr(0, cur2.size()) != cur2) continue;
|
if (name.substr(0, cur2.size()) != cur2) continue;
|
||||||
completions.insert(prev + expr + "." + name);
|
completions.insert(concatStrings(prev, expr, ".", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (ParseError & e) {
|
} catch (ParseError & e) {
|
||||||
|
@ -464,8 +464,9 @@ bool NixRepl::processLine(std::string line)
|
||||||
const auto [file, line] = [&] () -> std::pair<std::string, uint32_t> {
|
const auto [file, line] = [&] () -> std::pair<std::string, uint32_t> {
|
||||||
if (v.type() == nPath || v.type() == nString) {
|
if (v.type() == nPath || v.type() == nString) {
|
||||||
PathSet context;
|
PathSet context;
|
||||||
auto filename = state->coerceToString(noPos, v, context);
|
auto filename = state->coerceToString(noPos, v, context).toOwned();
|
||||||
return {state->symbols.create(*filename), 0};
|
state->symbols.create(filename);
|
||||||
|
return {filename, 0};
|
||||||
} else if (v.isLambda()) {
|
} else if (v.isLambda()) {
|
||||||
auto pos = state->positions[v.lambda.fun->pos];
|
auto pos = state->positions[v.lambda.fun->pos];
|
||||||
return {pos.file, pos.line};
|
return {pos.file, pos.line};
|
||||||
|
@ -672,7 +673,7 @@ void NixRepl::initEnv()
|
||||||
|
|
||||||
varNames.clear();
|
varNames.clear();
|
||||||
for (auto & i : state->staticBaseEnv.vars)
|
for (auto & i : state->staticBaseEnv.vars)
|
||||||
varNames.insert(i.first);
|
varNames.emplace(state->symbols[i.first]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -702,7 +703,7 @@ void NixRepl::addAttrsToScope(Value & attrs)
|
||||||
for (auto & i : *attrs.attrs) {
|
for (auto & i : *attrs.attrs) {
|
||||||
staticEnv.vars.emplace_back(i.name, displ);
|
staticEnv.vars.emplace_back(i.name, displ);
|
||||||
env->values[displ++] = i.value;
|
env->values[displ++] = i.value;
|
||||||
varNames.insert((std::string) i.name);
|
varNames.emplace(state->symbols[i.name]);
|
||||||
}
|
}
|
||||||
staticEnv.sort();
|
staticEnv.sort();
|
||||||
staticEnv.deduplicate();
|
staticEnv.deduplicate();
|
||||||
|
@ -710,7 +711,7 @@ void NixRepl::addAttrsToScope(Value & attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NixRepl::addVarToScope(const Symbol & name, Value & v)
|
void NixRepl::addVarToScope(const SymbolIdx name, Value & v)
|
||||||
{
|
{
|
||||||
if (displ >= envSize)
|
if (displ >= envSize)
|
||||||
throw Error("environment full; cannot add more variables");
|
throw Error("environment full; cannot add more variables");
|
||||||
|
@ -719,7 +720,7 @@ void NixRepl::addVarToScope(const Symbol & name, Value & v)
|
||||||
staticEnv.vars.emplace_back(name, displ);
|
staticEnv.vars.emplace_back(name, displ);
|
||||||
staticEnv.sort();
|
staticEnv.sort();
|
||||||
env->values[displ++] = &v;
|
env->values[displ++] = &v;
|
||||||
varNames.insert((std::string) name);
|
varNames.emplace(state->symbols[name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -812,7 +813,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
|
||||||
typedef std::map<std::string, Value *> Sorted;
|
typedef std::map<std::string, Value *> Sorted;
|
||||||
Sorted sorted;
|
Sorted sorted;
|
||||||
for (auto & i : *v.attrs)
|
for (auto & i : *v.attrs)
|
||||||
sorted[i.name] = i.value;
|
sorted.emplace(state->symbols[i.name], i.value);
|
||||||
|
|
||||||
for (auto & i : sorted) {
|
for (auto & i : sorted) {
|
||||||
if (isVarName(i.first))
|
if (isVarName(i.first))
|
||||||
|
|
|
@ -154,7 +154,7 @@ struct CmdSearch : InstallableCommand, MixJSON
|
||||||
recurse();
|
recurse();
|
||||||
|
|
||||||
else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) {
|
else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) {
|
||||||
auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations);
|
auto attr = cursor.maybeGetAttr("recurseForDerivations");
|
||||||
if (attr && attr->getBool())
|
if (attr && attr->getBool())
|
||||||
recurse();
|
recurse();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue