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) {
|
||||
for (auto & i : *v2.attrs) {
|
||||
std::string name = i.name;
|
||||
std::string name = state->symbols[i.name];
|
||||
if (name.find(searchWord) == 0) {
|
||||
if (prefix_ == "")
|
||||
completions->add(name);
|
||||
|
@ -600,7 +600,7 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
|
|||
|
||||
auto drvInfo = DerivationInfo {
|
||||
std::move(drvPath),
|
||||
attr->getAttr(state->sOutputName)->getString()
|
||||
attr->getAttr("outputName")->getString()
|
||||
};
|
||||
|
||||
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;
|
||||
for (auto & a : parseAttrPath(s))
|
||||
res.push_back(state.symbols.create(a));
|
||||
res.emplace_back(a);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
|||
if (a == v->attrs->end()) {
|
||||
std::set<std::string> attrNames;
|
||||
for (auto & attr : *v->attrs)
|
||||
attrNames.insert(attr.name);
|
||||
attrNames.insert(state.symbols[attr.name]);
|
||||
|
||||
auto suggestions = Suggestions::bestMatches(attrNames, attr);
|
||||
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
|
||||
in 'vAttrs' and return the newly allocated Value which is associated with
|
||||
this attribute. */
|
||||
Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
|
||||
Value * EvalState::allocAttr(Value & vAttrs, const SymbolIdx & name)
|
||||
{
|
||||
Value * v = allocValue();
|
||||
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();
|
||||
bindings->push_back(Attr(name, value, pos));
|
||||
|
|
|
@ -15,10 +15,10 @@ struct Value;
|
|||
/* Map one attribute name to its value. */
|
||||
struct Attr
|
||||
{
|
||||
Symbol name;
|
||||
SymbolIdx name;
|
||||
Value * value;
|
||||
PosIdx pos;
|
||||
Attr(Symbol name, Value * value, PosIdx pos = noPos)
|
||||
Attr(SymbolIdx name, Value * value, PosIdx pos = noPos)
|
||||
: name(name), value(value), pos(pos) { };
|
||||
Attr() { };
|
||||
bool operator < (const Attr & a) const
|
||||
|
@ -57,7 +57,7 @@ public:
|
|||
attrs[size_++] = attr;
|
||||
}
|
||||
|
||||
iterator find(const Symbol & name)
|
||||
iterator find(const SymbolIdx & name)
|
||||
{
|
||||
Attr key(name, 0);
|
||||
iterator i = std::lower_bound(begin(), end(), key);
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
return end();
|
||||
}
|
||||
|
||||
Attr * get(const Symbol & name)
|
||||
Attr * get(const SymbolIdx & name)
|
||||
{
|
||||
Attr key(name, 0);
|
||||
iterator i = std::lower_bound(begin(), end(), key);
|
||||
|
@ -86,14 +86,15 @@ public:
|
|||
size_t capacity() { return capacity_; }
|
||||
|
||||
/* 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;
|
||||
res.reserve(size_);
|
||||
for (size_t n = 0; n < size_; n++)
|
||||
res.emplace_back(&attrs[n]);
|
||||
std::sort(res.begin(), res.end(), [](const Attr * a, const Attr * b) {
|
||||
return (const std::string &) a->name < (const std::string &) b->name;
|
||||
std::sort(res.begin(), res.end(), [&](const Attr * a, const Attr * b) {
|
||||
std::string_view sa = symbols[a->name], sb = symbols[b->name];
|
||||
return sa < sb;
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
@ -118,7 +119,7 @@ public:
|
|||
: 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));
|
||||
}
|
||||
|
@ -133,7 +134,7 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ struct AttrDb
|
|||
std::vector<Symbol> attrs;
|
||||
auto queryAttributes(state->queryAttributes.use()(rowId));
|
||||
while (queryAttributes.next())
|
||||
attrs.push_back(symbols.create(queryAttributes.getStr(0)));
|
||||
attrs.emplace_back(queryAttributes.getStr(0));
|
||||
return {{rowId, attrs}};
|
||||
}
|
||||
case AttrType::String: {
|
||||
|
@ -325,7 +325,7 @@ AttrCursor::AttrCursor(
|
|||
AttrKey AttrCursor::getKey()
|
||||
{
|
||||
if (!parent)
|
||||
return {0, root->state.sEpsilon};
|
||||
return {0, {""}};
|
||||
if (!parent->first->cachedValue) {
|
||||
parent->first->cachedValue = root->db->getAttr(
|
||||
parent->first->getKey(), root->state.symbols);
|
||||
|
@ -340,7 +340,7 @@ Value & AttrCursor::getValue()
|
|||
if (parent) {
|
||||
auto & vParent = parent->first->getValue();
|
||||
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)
|
||||
throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr());
|
||||
_value = allocRootValue(attr->value);
|
||||
|
@ -419,7 +419,7 @@ Suggestions AttrCursor::getSuggestionsForAttr(Symbol 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 (!cachedValue)
|
||||
|
@ -461,10 +461,10 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
|
|||
|
||||
for (auto & attr : *v.attrs) {
|
||||
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 (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));
|
||||
}
|
||||
|
||||
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
|
||||
{
|
||||
return maybeGetAttr(root->state.symbols.create(name));
|
||||
}
|
||||
|
||||
ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
|
||||
ref<AttrCursor> AttrCursor::getAttr(std::string_view name, bool forceErrors)
|
||||
{
|
||||
auto p = maybeGetAttr(name, forceErrors);
|
||||
if (!p)
|
||||
|
@ -499,11 +494,6 @@ ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
|
|||
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)
|
||||
{
|
||||
auto res = shared_from_this();
|
||||
|
@ -616,7 +606,7 @@ std::vector<Symbol> AttrCursor::getAttrs()
|
|||
|
||||
std::vector<Symbol> 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) {
|
||||
return (const std::string &) a < (const std::string &) b;
|
||||
});
|
||||
|
@ -635,7 +625,7 @@ bool AttrCursor::isDerivation()
|
|||
|
||||
StorePath AttrCursor::forceDerivation()
|
||||
{
|
||||
auto aDrvPath = getAttr(root->state.sDrvPath, true);
|
||||
auto aDrvPath = getAttr("drvPath", true);
|
||||
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
|
||||
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
|
||||
/* The eval cache contains 'drvPath', but the actual path has
|
||||
|
|
|
@ -96,13 +96,9 @@ public:
|
|||
|
||||
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(Symbol name, bool forceErrors = false);
|
||||
|
||||
ref<AttrCursor> getAttr(std::string_view name);
|
||||
ref<AttrCursor> getAttr(std::string_view name, bool forceErrors = false);
|
||||
|
||||
/* Get an attribute along a chain of attrsets. Note that this does
|
||||
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();
|
||||
|
||||
|
@ -129,9 +130,9 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
|
|||
str << "«repeated»";
|
||||
else {
|
||||
str << "{ ";
|
||||
for (auto & i : attrs->lexicographicOrder()) {
|
||||
str << i->name << " = ";
|
||||
i->value->print(str, seen);
|
||||
for (auto & i : attrs->lexicographicOrder(symbols)) {
|
||||
str << symbols[i->name] << " = ";
|
||||
i->value->print(symbols, str, seen);
|
||||
str << "; ";
|
||||
}
|
||||
str << "}";
|
||||
|
@ -146,7 +147,7 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
|
|||
else {
|
||||
str << "[ ";
|
||||
for (auto v2 : listItems()) {
|
||||
v2->print(str, seen);
|
||||
v2->print(symbols, str, seen);
|
||||
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;
|
||||
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);
|
||||
return str;
|
||||
std::ostringstream out;
|
||||
v.print(state.symbols, out);
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
|
@ -306,9 +308,9 @@ static BoehmGCStackAllocator boehmGCStackAllocator;
|
|||
#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;
|
||||
} else {
|
||||
Value nameValue;
|
||||
|
@ -639,7 +641,7 @@ Value * EvalState::addPrimOp(const std::string & name,
|
|||
size_t arity, PrimOpFun primOp)
|
||||
{
|
||||
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
|
||||
the primop to a dummy value. */
|
||||
|
@ -673,7 +675,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
|
|||
return addConstant(primOp.name, v);
|
||||
}
|
||||
|
||||
Symbol envName = symbols.create(primOp.name);
|
||||
auto envName = symbols.create(primOp.name);
|
||||
if (hasPrefix(primOp.name, "__"))
|
||||
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.
|
||||
throw EvalError({
|
||||
.msg = hintfmt(s, sym, positions[p2]),
|
||||
.msg = hintfmt(s, symbols[sym], positions[p2]),
|
||||
.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,
|
||||
const Symbol & s2) const
|
||||
const SymbolIdx s2) const
|
||||
{
|
||||
throw TypeError({
|
||||
.msg = hintfmt(s, fun.showNamePos(positions), s2),
|
||||
.msg = hintfmt(s, fun.showNamePos(*this), symbols[s2]),
|
||||
.errPos = positions[pos]
|
||||
});
|
||||
}
|
||||
|
||||
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 {
|
||||
.msg = hintfmt(s, fun.showNamePos(positions), s2),
|
||||
.msg = hintfmt(s, fun.showNamePos(*this), symbols[s2]),
|
||||
.errPos = positions[pos],
|
||||
.suggestions = suggestions,
|
||||
});
|
||||
|
@ -901,7 +903,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
|||
return j->value;
|
||||
}
|
||||
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) ;
|
||||
}
|
||||
}
|
||||
|
@ -1187,7 +1189,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
|||
if (nameVal.type() == nNull)
|
||||
continue;
|
||||
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);
|
||||
if (j != v.attrs->end())
|
||||
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) {
|
||||
if (!first) out << '.'; else first = false;
|
||||
try {
|
||||
out << getName(i, state, env);
|
||||
out << state.symbols[getName(i, state, env)];
|
||||
} catch (Error & e) {
|
||||
assert(!i.symbol.set());
|
||||
out << "\"${" << *i.expr << "}\"";
|
||||
assert(!i.symbol);
|
||||
out << "\"${";
|
||||
i.expr->show(state.symbols, out);
|
||||
out << "}\"";
|
||||
}
|
||||
}
|
||||
return out.str();
|
||||
|
@ -1266,7 +1270,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
|||
for (auto & i : attrPath) {
|
||||
state.nrLookups++;
|
||||
Bindings::iterator j;
|
||||
Symbol name = getName(i, state, env);
|
||||
auto name = getName(i, state, env);
|
||||
if (def) {
|
||||
state.forceValue(*vAttrs, pos);
|
||||
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()) {
|
||||
std::set<std::string> allAttrNames;
|
||||
for (auto & attr : *vAttrs->attrs)
|
||||
allAttrNames.insert(attr.name);
|
||||
allAttrNames.insert(state.symbols[attr.name]);
|
||||
state.throwEvalError(
|
||||
pos,
|
||||
Suggestions::bestMatches(allAttrNames, name),
|
||||
"attribute '%1%' missing", name);
|
||||
Suggestions::bestMatches(allAttrNames, state.symbols[name]),
|
||||
"attribute '%1%' missing", state.symbols[name]);
|
||||
}
|
||||
}
|
||||
vAttrs = j->value;
|
||||
|
@ -1316,7 +1320,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
|
|||
for (auto & i : attrPath) {
|
||||
state.forceValue(*vAttrs, noPos);
|
||||
Bindings::iterator j;
|
||||
Symbol name = getName(i, state, env);
|
||||
auto name = getName(i, state, env);
|
||||
if (vAttrs->type() != nAttrs ||
|
||||
(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);
|
||||
|
||||
auto size =
|
||||
(!lambda.arg.set() ? 0 : 1) +
|
||||
(!lambda.arg ? 0 : 1) +
|
||||
(lambda.hasFormals() ? lambda.formals->formals.size() : 0);
|
||||
Env & env2(allocEnv(size));
|
||||
env2.up = vCur.lambda.env;
|
||||
|
@ -1379,7 +1383,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
|||
else {
|
||||
forceAttrs(*args[0], pos);
|
||||
|
||||
if (lambda.arg.set())
|
||||
if (lambda.arg)
|
||||
env2.values[displ++] = args[0];
|
||||
|
||||
/* 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)) {
|
||||
std::set<std::string> formalNames;
|
||||
for (auto & formal : lambda.formals->formals)
|
||||
formalNames.insert(formal.name);
|
||||
formalNames.insert(symbols[formal.name]);
|
||||
throwTypeError(
|
||||
pos,
|
||||
Suggestions::bestMatches(formalNames, i.name),
|
||||
Suggestions::bestMatches(formalNames, symbols[i.name]),
|
||||
"%1% called with unexpected argument '%2%'",
|
||||
lambda,
|
||||
i.name);
|
||||
|
@ -1428,8 +1432,8 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
|||
} catch (Error & e) {
|
||||
if (loggerSettings.showTrace.get()) {
|
||||
addErrorTrace(e, lambda.pos, "while evaluating %s",
|
||||
(lambda.name.set()
|
||||
? "'" + (const std::string &) lambda.name + "'"
|
||||
(lambda.name
|
||||
? concatStrings("'", symbols[lambda.name], "'")
|
||||
: "anonymous lambda"));
|
||||
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
|
||||
this case it must have its arguments supplied either by default
|
||||
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)) {
|
||||
std::ostringstream out;
|
||||
cond->show(out);
|
||||
cond->show(state.symbols, out);
|
||||
state.throwAssertionError(pos, "assertion '%1%' failed", out.str());
|
||||
}
|
||||
body->eval(state, env, v);
|
||||
|
@ -1844,7 +1848,7 @@ void EvalState::forceValueDeep(Value & v)
|
|||
try {
|
||||
recurse(*i.value);
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
@ -2267,7 +2271,7 @@ void EvalState::printStats()
|
|||
auto list = topObj.list("functions");
|
||||
for (auto & i : functionCalls) {
|
||||
auto obj = list.object();
|
||||
if (i.first->name.set())
|
||||
if (i.first->name)
|
||||
obj.attr("name", (const std::string &) i.first->name);
|
||||
else
|
||||
obj.attr("name", nullptr);
|
||||
|
|
|
@ -53,7 +53,8 @@ void copyContext(const Value & v, PathSet & context);
|
|||
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;
|
||||
|
@ -77,7 +78,7 @@ public:
|
|||
|
||||
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,
|
||||
sFile, sLine, sColumn, sFunctor, sToString,
|
||||
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
|
||||
|
@ -86,7 +87,7 @@ public:
|
|||
sRecurseForDerivations,
|
||||
sDescription, sSelf, sEpsilon, sStartSet, sOperator, sKey, sPath,
|
||||
sPrefix;
|
||||
Symbol sDerivationNix;
|
||||
SymbolIdx sDerivationNix;
|
||||
|
||||
/* If set, force copying files to the Nix store even if they
|
||||
already exist there. */
|
||||
|
@ -268,14 +269,14 @@ public:
|
|||
[[gnu::noinline, gnu::noreturn]]
|
||||
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3) const;
|
||||
[[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]]
|
||||
void throwTypeError(const PosIdx pos, const char * s) const;
|
||||
[[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]]
|
||||
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]]
|
||||
void throwTypeError(const char * s, const Value & v) const;
|
||||
[[gnu::noinline, gnu::noreturn]]
|
||||
|
@ -391,7 +392,7 @@ public:
|
|||
inline Value * allocValue();
|
||||
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);
|
||||
|
||||
Bindings * allocBindings(size_t capacity);
|
||||
|
|
|
@ -127,21 +127,23 @@ static FlakeInput parseFlakeInput(EvalState & state,
|
|||
} else {
|
||||
switch (attr.value->type()) {
|
||||
case nString:
|
||||
attrs.emplace(attr.name, attr.value->string.s);
|
||||
attrs.emplace(state.symbols[attr.name], attr.value->string.s);
|
||||
break;
|
||||
case nBool:
|
||||
attrs.emplace(attr.name, Explicit<bool> { attr.value->boolean });
|
||||
attrs.emplace(state.symbols[attr.name], Explicit<bool> { attr.value->boolean });
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -176,9 +178,9 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
|
|||
expectType(state, nAttrs, *value, pos);
|
||||
|
||||
for (nix::Attr & inputAttr : *(*value).attrs) {
|
||||
inputs.emplace(inputAttr.name,
|
||||
inputs.emplace(state.symbols[inputAttr.name],
|
||||
parseFlakeInput(state,
|
||||
inputAttr.name,
|
||||
state.symbols[inputAttr.name],
|
||||
inputAttr.value,
|
||||
inputAttr.pos,
|
||||
baseDir,
|
||||
|
@ -218,7 +220,7 @@ static Flake getFlake(
|
|||
Value vInfo;
|
||||
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)) {
|
||||
expectType(state, nString, *description->value, description->pos);
|
||||
|
@ -238,8 +240,8 @@ static Flake getFlake(
|
|||
if (outputs->value->isLambda() && outputs->value->lambda.fun->hasFormals()) {
|
||||
for (auto & formal : outputs->value->lambda.fun->formals->formals) {
|
||||
if (formal.name != state.sSelf)
|
||||
flake.inputs.emplace(formal.name, FlakeInput {
|
||||
.ref = parseFlakeRef(formal.name)
|
||||
flake.inputs.emplace(state.symbols[formal.name], FlakeInput {
|
||||
.ref = parseFlakeRef(state.symbols[formal.name])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -255,30 +257,36 @@ static Flake getFlake(
|
|||
for (auto & setting : *nixConfig->value->attrs) {
|
||||
forceTrivialValue(state, *setting.value, setting.pos);
|
||||
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) {
|
||||
PathSet emptyContext = {};
|
||||
flake.config.settings.emplace(
|
||||
setting.name,
|
||||
state.symbols[setting.name],
|
||||
state.coerceToString(setting.pos, *setting.value, emptyContext, false, true, true) .toOwned());
|
||||
}
|
||||
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)
|
||||
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) {
|
||||
std::vector<std::string> ss;
|
||||
for (auto elem : setting.value->listItems()) {
|
||||
if (elem->type() != nString)
|
||||
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));
|
||||
}
|
||||
flake.config.settings.insert({setting.name, ss});
|
||||
flake.config.settings.emplace(state.symbols[setting.name], ss);
|
||||
}
|
||||
else
|
||||
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 != sNixConfig)
|
||||
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;
|
||||
|
|
|
@ -179,7 +179,7 @@ StringSet DrvInfo::queryMetaNames()
|
|||
StringSet res;
|
||||
if (!getMeta()) return res;
|
||||
for (auto & i : *meta)
|
||||
res.insert(i.name);
|
||||
res.emplace(state->symbols[i.name]);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,7 @@ void DrvInfo::setMeta(const std::string & name, Value * v)
|
|||
{
|
||||
getMeta();
|
||||
auto attrs = state->buildBindings(1 + (meta ? meta->size() : 0));
|
||||
Symbol sym = state->symbols.create(name);
|
||||
auto sym = state->symbols.create(name);
|
||||
if (meta)
|
||||
for (auto i : *meta)
|
||||
if (i.name != sym)
|
||||
|
@ -356,11 +356,11 @@ static void getDerivations(EvalState & state, Value & vIn,
|
|||
there are names clashes between derivations, the derivation
|
||||
bound to the attribute with the "lower" name should take
|
||||
precedence). */
|
||||
for (auto & i : v.attrs->lexicographicOrder()) {
|
||||
debug("evaluating attribute '%1%'", i->name);
|
||||
if (!std::regex_match(std::string(i->name), attrRegex))
|
||||
for (auto & i : v.attrs->lexicographicOrder(state.symbols)) {
|
||||
debug("evaluating attribute '%1%'", state.symbols[i->name]);
|
||||
if (!std::regex_match(std::string(state.symbols[i->name]), attrRegex))
|
||||
continue;
|
||||
std::string pathPrefix2 = addToPath(pathPrefix, i->name);
|
||||
std::string pathPrefix2 = addToPath(pathPrefix, state.symbols[i->name]);
|
||||
if (combineChannels)
|
||||
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||
else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "nixexpr.hh"
|
||||
#include "derivations.hh"
|
||||
#include "eval.hh"
|
||||
#include "symbol-table.hh"
|
||||
#include "util.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
|
@ -10,12 +12,6 @@ namespace nix {
|
|||
|
||||
/* 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)
|
||||
{
|
||||
str << '"';
|
||||
|
@ -54,81 +50,101 @@ static void showId(std::ostream & str, std::string_view s)
|
|||
|
||||
std::ostream & operator << (std::ostream & str, const Symbol & sym)
|
||||
{
|
||||
showId(str, *sym.s);
|
||||
showId(str, sym.s);
|
||||
return str;
|
||||
}
|
||||
|
||||
void Expr::show(std::ostream & str) const
|
||||
void Expr::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
void ExprInt::show(std::ostream & str) const
|
||||
void ExprInt::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
str << n;
|
||||
}
|
||||
|
||||
void ExprFloat::show(std::ostream & str) const
|
||||
void ExprFloat::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
str << nf;
|
||||
}
|
||||
|
||||
void ExprString::show(std::ostream & str) const
|
||||
void ExprString::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
showString(str, s);
|
||||
}
|
||||
|
||||
void ExprPath::show(std::ostream & str) const
|
||||
void ExprPath::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
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);
|
||||
if (def) str << " or (" << *def << ")";
|
||||
str << "(";
|
||||
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 ";
|
||||
str << "{ ";
|
||||
typedef const decltype(attrs)::value_type * Attr;
|
||||
std::vector<Attr> sorted;
|
||||
for (auto & i : attrs) sorted.push_back(&i);
|
||||
std::sort(sorted.begin(), sorted.end(), [](Attr a, Attr b) {
|
||||
return (const std::string &) a->first < (const std::string &) b->first;
|
||||
std::sort(sorted.begin(), sorted.end(), [&](Attr a, Attr b) {
|
||||
std::string_view sa = symbols[a->first], sb = symbols[b->first];
|
||||
return sa < sb;
|
||||
});
|
||||
for (auto & i : sorted) {
|
||||
if (i->second.inherited)
|
||||
str << "inherit " << i->first << " " << "; ";
|
||||
else
|
||||
str << i->first << " = " << *i->second.e << "; ";
|
||||
str << "inherit " << symbols[i->first] << " " << "; ";
|
||||
else {
|
||||
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 << "}";
|
||||
}
|
||||
|
||||
void ExprList::show(std::ostream & str) const
|
||||
void ExprList::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
str << "[ ";
|
||||
for (auto & i : elems)
|
||||
str << "(" << *i << ") ";
|
||||
for (auto & i : elems) {
|
||||
str << "(";
|
||||
i->show(symbols, str);
|
||||
str << ") ";
|
||||
}
|
||||
str << "]";
|
||||
}
|
||||
|
||||
void ExprLambda::show(std::ostream & str) const
|
||||
void ExprLambda::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
str << "(";
|
||||
if (hasFormals()) {
|
||||
|
@ -136,74 +152,100 @@ void ExprLambda::show(std::ostream & str) const
|
|||
bool first = true;
|
||||
for (auto & i : formals->formals) {
|
||||
if (first) first = false; else str << ", ";
|
||||
str << i.name;
|
||||
if (i.def) str << " ? " << *i.def;
|
||||
str << symbols[i.name];
|
||||
if (i.def) {
|
||||
str << " ? ";
|
||||
i.def->show(symbols, str);
|
||||
}
|
||||
}
|
||||
if (formals->ellipsis) {
|
||||
if (!first) str << ", ";
|
||||
str << "...";
|
||||
}
|
||||
str << " }";
|
||||
if (arg.set()) str << " @ ";
|
||||
if (arg) str << " @ ";
|
||||
}
|
||||
if (arg.set()) str << arg;
|
||||
str << ": " << *body << ")";
|
||||
if (arg) str << symbols[arg];
|
||||
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) {
|
||||
str << ' ';
|
||||
str << *e;
|
||||
e->show(symbols, str);
|
||||
}
|
||||
str << ')';
|
||||
}
|
||||
|
||||
void ExprLet::show(std::ostream & str) const
|
||||
void ExprLet::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
str << "(let ";
|
||||
for (auto & i : attrs->attrs)
|
||||
if (i.second.inherited) {
|
||||
str << "inherit " << i.first << "; ";
|
||||
str << "inherit " << symbols[i.first] << "; ";
|
||||
}
|
||||
else
|
||||
str << i.first << " = " << *i.second.e << "; ";
|
||||
str << "in " << *body << ")";
|
||||
else {
|
||||
str << symbols[i.first] << " = ";
|
||||
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;
|
||||
str << "(";
|
||||
for (auto & i : *es) {
|
||||
if (first) first = false; else str << " + ";
|
||||
str << *i.second;
|
||||
i.second->show(symbols, str);
|
||||
}
|
||||
str << ")";
|
||||
}
|
||||
|
||||
void ExprPos::show(std::ostream & str) const
|
||||
void ExprPos::show(const SymbolTable & symbols, std::ostream & str) const
|
||||
{
|
||||
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;
|
||||
bool first = true;
|
||||
for (auto & i : attrPath) {
|
||||
if (!first) out << '.'; else first = false;
|
||||
if (i.symbol.set())
|
||||
out << i.symbol;
|
||||
else
|
||||
out << "\"${" << *i.expr << "}\"";
|
||||
if (i.symbol)
|
||||
out << symbols[i.symbol];
|
||||
else {
|
||||
out << "\"${";
|
||||
i.expr->show(symbols, out);
|
||||
out << "}\"";
|
||||
}
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
@ -252,28 +297,28 @@ std::string showAttrPath(const AttrPath & attrPath)
|
|||
|
||||
/* Computing levels/displacements for variables. */
|
||||
|
||||
void Expr::bindVars(const PosTable & pt, const StaticEnv & env)
|
||||
void Expr::bindVars(const EvalState & es, const StaticEnv & env)
|
||||
{
|
||||
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,
|
||||
set its level and displacement. */
|
||||
|
@ -299,31 +344,31 @@ void ExprVar::bindVars(const PosTable & pt, const StaticEnv & env)
|
|||
"undefined variable" error now. */
|
||||
if (withLevel == -1)
|
||||
throw UndefinedVarError({
|
||||
.msg = hintfmt("undefined variable '%1%'", name),
|
||||
.errPos = pt[pos]
|
||||
.msg = hintfmt("undefined variable '%1%'", es.symbols[name]),
|
||||
.errPos = es.positions[pos]
|
||||
});
|
||||
fromWith = true;
|
||||
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);
|
||||
if (def) def->bindVars(pt, env);
|
||||
e->bindVars(es, env);
|
||||
if (def) def->bindVars(es, env);
|
||||
for (auto & i : attrPath)
|
||||
if (!i.symbol.set())
|
||||
i.expr->bindVars(pt, env);
|
||||
if (!i.symbol)
|
||||
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)
|
||||
if (!i.symbol.set())
|
||||
i.expr->bindVars(pt, env);
|
||||
if (!i.symbol)
|
||||
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;
|
||||
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.
|
||||
|
||||
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
|
||||
for (auto & i : attrs)
|
||||
i.second.e->bindVars(pt, env);
|
||||
i.second.e->bindVars(es, env);
|
||||
|
||||
for (auto & i : dynamicAttrs) {
|
||||
i.nameExpr->bindVars(pt, *dynamicEnv);
|
||||
i.valueExpr->bindVars(pt, *dynamicEnv);
|
||||
i.nameExpr->bindVars(es, *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)
|
||||
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(
|
||||
false, &env,
|
||||
(hasFormals() ? formals->formals.size() : 0) +
|
||||
(!arg.set() ? 0 : 1));
|
||||
(!arg ? 0 : 1));
|
||||
|
||||
Displacement displ = 0;
|
||||
|
||||
if (arg.set()) newEnv.vars.emplace_back(arg, displ++);
|
||||
if (arg) newEnv.vars.emplace_back(arg, displ++);
|
||||
|
||||
if (hasFormals()) {
|
||||
for (auto & i : formals->formals)
|
||||
|
@ -375,20 +420,20 @@ void ExprLambda::bindVars(const PosTable & pt, const StaticEnv & env)
|
|||
newEnv.sort();
|
||||
|
||||
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)
|
||||
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());
|
||||
|
||||
|
@ -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.
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
attrs->bindVars(pt, env);
|
||||
attrs->bindVars(es, 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);
|
||||
then->bindVars(pt, env);
|
||||
else_->bindVars(pt, env);
|
||||
cond->bindVars(es, env);
|
||||
then->bindVars(es, 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);
|
||||
body->bindVars(pt, env);
|
||||
cond->bindVars(es, 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)
|
||||
i.second->bindVars(pt, env);
|
||||
for (auto & i : *this->es)
|
||||
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. */
|
||||
|
||||
void Expr::setName(Symbol & name)
|
||||
void Expr::setName(SymbolIdx name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void ExprLambda::setName(Symbol & name)
|
||||
void ExprLambda::setName(SymbolIdx name)
|
||||
{
|
||||
this->name = 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 n = 0;
|
||||
for (auto & i : store)
|
||||
n += i.size();
|
||||
dump([&] (const Symbol & s) { n += std::string_view(s).size(); });
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,15 +125,15 @@ struct StaticEnv;
|
|||
/* An attribute path is a sequence of attribute names. */
|
||||
struct AttrName
|
||||
{
|
||||
Symbol symbol;
|
||||
SymbolIdx symbol;
|
||||
Expr * expr;
|
||||
AttrName(const Symbol & s) : symbol(s) {};
|
||||
AttrName(const SymbolIdx & s) : symbol(s) {};
|
||||
AttrName(Expr * e) : expr(e) {};
|
||||
};
|
||||
|
||||
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. */
|
||||
|
@ -141,19 +141,17 @@ std::string showAttrPath(const AttrPath & attrPath);
|
|||
struct Expr
|
||||
{
|
||||
virtual ~Expr() { };
|
||||
virtual void show(std::ostream & str) const;
|
||||
virtual void bindVars(const PosTable & pt, const StaticEnv & env);
|
||||
virtual void show(const SymbolTable & symbols, std::ostream & str) const;
|
||||
virtual void bindVars(const EvalState & es, const StaticEnv & env);
|
||||
virtual void eval(EvalState & state, Env & env, Value & v);
|
||||
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 \
|
||||
void show(std::ostream & str) const; \
|
||||
void show(const SymbolTable & symbols, std::ostream & str) const; \
|
||||
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
|
||||
{
|
||||
|
@ -197,7 +195,7 @@ typedef uint32_t Displacement;
|
|||
struct ExprVar : Expr
|
||||
{
|
||||
PosIdx pos;
|
||||
Symbol name;
|
||||
SymbolIdx name;
|
||||
|
||||
/* Whether the variable comes from an environment (e.g. a rec, let
|
||||
or function argument) or from a "with". */
|
||||
|
@ -212,8 +210,8 @@ struct ExprVar : Expr
|
|||
Level level;
|
||||
Displacement displ;
|
||||
|
||||
ExprVar(const Symbol & name) : name(name) { };
|
||||
ExprVar(const PosIdx & pos, const Symbol & name) : pos(pos), name(name) { };
|
||||
ExprVar(const SymbolIdx & name) : name(name) { };
|
||||
ExprVar(const PosIdx & pos, const SymbolIdx & name) : pos(pos), name(name) { };
|
||||
COMMON_METHODS
|
||||
Value * maybeThunk(EvalState & state, Env & env);
|
||||
};
|
||||
|
@ -224,7 +222,7 @@ struct ExprSelect : Expr
|
|||
Expr * e, * 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
|
||||
};
|
||||
|
||||
|
@ -249,7 +247,7 @@ struct ExprAttrs : Expr
|
|||
: inherited(inherited), e(e), pos(pos) { };
|
||||
AttrDef() { };
|
||||
};
|
||||
typedef std::map<Symbol, AttrDef> AttrDefs;
|
||||
typedef std::map<SymbolIdx, AttrDef> AttrDefs;
|
||||
AttrDefs attrs;
|
||||
struct DynamicAttrDef {
|
||||
Expr * nameExpr, * valueExpr;
|
||||
|
@ -274,9 +272,8 @@ struct ExprList : Expr
|
|||
struct Formal
|
||||
{
|
||||
PosIdx pos;
|
||||
Symbol name;
|
||||
SymbolIdx name;
|
||||
Expr * def;
|
||||
Formal(const PosIdx & pos, const Symbol & name, Expr * def) : pos(pos), name(name), def(def) { };
|
||||
};
|
||||
|
||||
struct Formals
|
||||
|
@ -285,18 +282,19 @@ struct Formals
|
|||
Formals_ formals;
|
||||
bool ellipsis;
|
||||
|
||||
bool has(Symbol arg) const {
|
||||
bool has(SymbolIdx arg) const {
|
||||
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;
|
||||
}
|
||||
|
||||
std::vector<Formal> lexicographicOrder() const
|
||||
std::vector<Formal> lexicographicOrder(const SymbolTable & symbols) const
|
||||
{
|
||||
std::vector<Formal> result(formals.begin(), formals.end());
|
||||
std::sort(result.begin(), result.end(),
|
||||
[] (const Formal & a, const Formal & b) {
|
||||
return std::string_view(a.name) < std::string_view(b.name);
|
||||
[&] (const Formal & a, const Formal & b) {
|
||||
std::string_view sa = symbols[a.name], sb = symbols[b.name];
|
||||
return sa < sb;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
@ -305,16 +303,20 @@ struct Formals
|
|||
struct ExprLambda : Expr
|
||||
{
|
||||
PosIdx pos;
|
||||
Symbol name;
|
||||
Symbol arg;
|
||||
SymbolIdx name;
|
||||
SymbolIdx arg;
|
||||
Formals * formals;
|
||||
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)
|
||||
{
|
||||
};
|
||||
void setName(Symbol & name);
|
||||
std::string showNamePos(const PosTable & pt) const;
|
||||
ExprLambda(PosIdx pos, Formals * formals, Expr * body)
|
||||
: pos(pos), formals(formals), body(body)
|
||||
{
|
||||
}
|
||||
void setName(SymbolIdx name);
|
||||
std::string showNamePos(const EvalState & state) const;
|
||||
inline bool hasFormals() const { return formals != nullptr; }
|
||||
COMMON_METHODS
|
||||
};
|
||||
|
@ -377,13 +379,13 @@ struct ExprOpNot : Expr
|
|||
Expr * e1, * e2; \
|
||||
name(Expr * e1, Expr * e2) : 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); \
|
||||
};
|
||||
|
@ -423,7 +425,7 @@ struct StaticEnv
|
|||
const StaticEnv * up;
|
||||
|
||||
// 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;
|
||||
|
||||
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::const_iterator find(const Symbol & name) const
|
||||
Vars::const_iterator find(const SymbolIdx & name) const
|
||||
{
|
||||
Vars::value_type key(name, 0);
|
||||
auto i = std::lower_bound(vars.begin(), vars.end(), key);
|
||||
|
|
|
@ -77,26 +77,26 @@ using 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({
|
||||
.msg = hintfmt("attribute '%1%' already defined at %2%",
|
||||
showAttrPath(attrPath), prevPos),
|
||||
.errPos = pos
|
||||
showAttrPath(state.symbols, attrPath), state.positions[prevPos]),
|
||||
.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({
|
||||
.msg = hintfmt("attribute '%1%' already defined at %2%", attr, prevPos),
|
||||
.errPos = pos
|
||||
.msg = hintfmt("attribute '%1%' already defined at %2%", state.symbols[attr], state.positions[prevPos]),
|
||||
.errPos = state.positions[pos]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
// All attrpaths have at least one attr
|
||||
|
@ -104,15 +104,15 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
|||
// Checking attrPath validity.
|
||||
// ===========================
|
||||
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);
|
||||
if (j != attrs->attrs.end()) {
|
||||
if (!j->second.inherited) {
|
||||
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;
|
||||
} else
|
||||
dupAttr(attrPath, pt[pos], pt[j->second.pos]);
|
||||
dupAttr(state, attrPath, pos, j->second.pos);
|
||||
} else {
|
||||
ExprAttrs * nested = new ExprAttrs;
|
||||
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
|
||||
|
@ -126,7 +126,7 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
|
|||
}
|
||||
// Expr insertion.
|
||||
// ==========================
|
||||
if (i->symbol.set()) {
|
||||
if (i->symbol) {
|
||||
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
|
||||
if (j != attrs->attrs.end()) {
|
||||
// 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) {
|
||||
auto j2 = jAttrs->attrs.find(ad.first);
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
dupAttr(attrPath, pt[pos], pt[j->second.pos]);
|
||||
dupAttr(state, attrPath, pos, j->second.pos);
|
||||
}
|
||||
} else {
|
||||
// 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,
|
||||
PosIdx pos = noPos, Symbol arg = {})
|
||||
PosIdx pos = noPos, SymbolIdx arg = {})
|
||||
{
|
||||
std::sort(formals->formals.begin(), formals->formals.end(),
|
||||
[] (const auto & a, const auto & b) {
|
||||
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++) {
|
||||
if (formals->formals[i].name != formals->formals[i + 1].name)
|
||||
continue;
|
||||
|
@ -173,7 +173,7 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
|
|||
}
|
||||
if (duplicate)
|
||||
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]
|
||||
});
|
||||
|
||||
|
@ -181,9 +181,9 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
|
|||
result.ellipsis = formals->ellipsis;
|
||||
result.formals = std::move(formals->formals);
|
||||
|
||||
if (arg.set() && result.has(arg))
|
||||
if (arg && result.has(arg))
|
||||
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]
|
||||
});
|
||||
|
||||
|
@ -369,15 +369,15 @@ expr_function
|
|||
: ID ':' expr_function
|
||||
{ $$ = new ExprLambda(CUR_POS, data->symbols.create($1), 0, $3); }
|
||||
| '{' formals '}' ':' expr_function
|
||||
{ $$ = new ExprLambda(CUR_POS, {}, toFormals(*data, $2), $5); }
|
||||
{ $$ = new ExprLambda(CUR_POS, toFormals(*data, $2), $5); }
|
||||
| '{' 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);
|
||||
}
|
||||
| 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);
|
||||
}
|
||||
| ASSERT expr ';' expr_function
|
||||
|
@ -532,13 +532,12 @@ ind_string_parts
|
|||
;
|
||||
|
||||
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 ';'
|
||||
{ $$ = $1;
|
||||
for (auto & i : *$3) {
|
||||
if ($$->attrs.find(i.symbol) != $$->attrs.end())
|
||||
dupAttr(i.symbol, data->state.positions[makeCurPos(@3, data)],
|
||||
data->state.positions[$$->attrs[i.symbol].pos]);
|
||||
dupAttr(data->state, i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos);
|
||||
auto pos = makeCurPos(@3, data);
|
||||
$$->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. */
|
||||
for (auto & i : *$6) {
|
||||
if ($$->attrs.find(i.symbol) != $$->attrs.end())
|
||||
dupAttr(i.symbol, data->state.positions[makeCurPos(@6, data)],
|
||||
data->state.positions[$$->attrs[i.symbol].pos]);
|
||||
dupAttr(data->state, i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos);
|
||||
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data)));
|
||||
}
|
||||
}
|
||||
|
@ -623,8 +621,8 @@ formals
|
|||
;
|
||||
|
||||
formal
|
||||
: ID { $$ = new Formal(CUR_POS, data->symbols.create($1), 0); }
|
||||
| ID '?' expr { $$ = new Formal(CUR_POS, data->symbols.create($1), $3); }
|
||||
: ID { $$ = new Formal{CUR_POS, data->symbols.create($1), 0}; }
|
||||
| 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());
|
||||
|
||||
data.result->bindVars(positions, staticEnv);
|
||||
data.result->bindVars(*this, staticEnv);
|
||||
|
||||
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 nThunk: abort();
|
||||
}
|
||||
v.mkString(state.symbols.create(t));
|
||||
v.mkString(t);
|
||||
}
|
||||
|
||||
static RegisterPrimOp primop_typeOf({
|
||||
|
@ -584,7 +584,7 @@ typedef std::list<Value *> ValueList;
|
|||
static Bindings::iterator getAttr(
|
||||
EvalState & state,
|
||||
std::string_view funcName,
|
||||
Symbol attrSym,
|
||||
SymbolIdx attrSym,
|
||||
Bindings * attrSet,
|
||||
const PosIdx pos)
|
||||
{
|
||||
|
@ -592,7 +592,7 @@ static Bindings::iterator getAttr(
|
|||
if (value == attrSet->end()) {
|
||||
hintformat errorMsg = hintfmt(
|
||||
"attribute '%s' missing for call to '%s'",
|
||||
attrSym,
|
||||
state.symbols[attrSym],
|
||||
funcName
|
||||
);
|
||||
|
||||
|
@ -919,7 +919,7 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu
|
|||
if (args[0]->type() == nString)
|
||||
printError("trace: %1%", args[0]->string.s);
|
||||
else
|
||||
printError("trace: %1%", *args[0]);
|
||||
printError("trace: %1%", printValue(state, *args[0]));
|
||||
state.forceValue(*args[1], pos);
|
||||
v = *args[1];
|
||||
}
|
||||
|
@ -998,9 +998,9 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
|
|||
StringSet outputs;
|
||||
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;
|
||||
const std::string & key = i->name;
|
||||
const std::string & key = state.symbols[i->name];
|
||||
vomit("processing attribute '%1%'", key);
|
||||
|
||||
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;
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
auto & n(attr.name);
|
||||
auto & n(state.symbols[attr.name]);
|
||||
if (n == "path")
|
||||
path = state.coerceToPath(attr.pos, *attr.value, context);
|
||||
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);
|
||||
else
|
||||
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]
|
||||
});
|
||||
}
|
||||
|
@ -2126,7 +2126,7 @@ static void prim_attrNames(EvalState & state, const PosIdx pos, Value * * args,
|
|||
|
||||
size_t n = 0;
|
||||
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,
|
||||
[](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;
|
||||
|
||||
std::sort(v.listElems(), v.listElems() + n,
|
||||
[](Value * v1, Value * v2) {
|
||||
std::string_view s1 = ((Attr *) v1)->name, s2 = ((Attr *) v2)->name;
|
||||
[&](Value * v1, Value * v2) {
|
||||
std::string_view s1 = state.symbols[((Attr *) v1)->name],
|
||||
s2 = state.symbols[((Attr *) v2)->name];
|
||||
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());
|
||||
|
||||
std::set<Symbol> seen;
|
||||
std::set<SymbolIdx> seen;
|
||||
|
||||
for (auto v2 : args[0]->listItems()) {
|
||||
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);
|
||||
|
||||
Symbol sym = state.symbols.create(name);
|
||||
auto sym = state.symbols.create(name);
|
||||
if (seen.insert(sym).second) {
|
||||
Bindings::iterator j2 = getAttr(
|
||||
state,
|
||||
|
@ -2396,7 +2397,7 @@ static RegisterPrimOp primop_intersectAttrs({
|
|||
|
||||
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);
|
||||
|
||||
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) {
|
||||
Value * vName = state.allocValue();
|
||||
Value * vFun2 = state.allocValue();
|
||||
vName->mkString(i.name);
|
||||
vName->mkString(state.symbols[i.name]);
|
||||
vFun2->mkApp(args[0], vName);
|
||||
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
|
||||
// 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.forceList(*args[1], pos);
|
||||
|
@ -2550,7 +2551,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg
|
|||
|
||||
for (auto & attr : *v.attrs) {
|
||||
auto name = state.allocValue();
|
||||
name->mkString(attr.name);
|
||||
name->mkString(state.symbols[attr.name]);
|
||||
auto call1 = state.allocValue();
|
||||
call1->mkApp(args[0], name);
|
||||
auto call2 = state.allocValue();
|
||||
|
@ -3058,7 +3059,7 @@ static void prim_groupBy(EvalState & state, const PosIdx pos, Value * * args, Va
|
|||
Value res;
|
||||
state.callFunction(*args[0], *vElem, 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;
|
||||
vector->second.push_back(vElem);
|
||||
}
|
||||
|
@ -3932,7 +3933,7 @@ void EvalState::createBaseEnv()
|
|||
// the parser needs two NUL bytes as terminators; one of them
|
||||
// is implied by being a C string.
|
||||
"\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 sAllOutputs = state.symbols.create("allOutputs");
|
||||
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({
|
||||
.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]
|
||||
});
|
||||
if (!settings.readOnlyMode)
|
||||
state.store->ensurePath(state.store->parseStorePath(i.name));
|
||||
state.store->ensurePath(state.store->parseStorePath(name));
|
||||
state.forceAttrs(*i.value, i.pos);
|
||||
auto iter = i.value->attrs->find(sPath);
|
||||
if (iter != i.value->attrs->end()) {
|
||||
if (state.forceBool(*iter->value, iter->pos))
|
||||
context.insert(i.name);
|
||||
context.emplace(name);
|
||||
}
|
||||
|
||||
iter = i.value->attrs->find(sAllOutputs);
|
||||
if (iter != i.value->attrs->end()) {
|
||||
if (state.forceBool(*iter->value, iter->pos)) {
|
||||
if (!isDerivation(i.name)) {
|
||||
if (!isDerivation(name)) {
|
||||
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]
|
||||
});
|
||||
}
|
||||
context.insert("=" + std::string(i.name));
|
||||
context.insert(concatStrings("=", name));
|
||||
}
|
||||
}
|
||||
|
||||
iter = i.value->attrs->find(state.sOutputs);
|
||||
if (iter != i.value->attrs->end()) {
|
||||
state.forceList(*iter->value, iter->pos);
|
||||
if (iter->value->listSize() && !isDerivation(i.name)) {
|
||||
if (iter->value->listSize() && !isDerivation(name)) {
|
||||
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]
|
||||
});
|
||||
}
|
||||
for (auto elem : iter->value->listItems()) {
|
||||
auto name = state.forceStringNoCtx(*elem, iter->pos);
|
||||
context.insert(concatStrings("!", name, "!", i.name));
|
||||
auto outputName = state.forceStringNoCtx(*elem, iter->pos);
|
||||
context.insert(concatStrings("!", outputName, "!", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,14 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg
|
|||
std::optional<StorePath> toPath;
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
if (attr.name == "fromPath") {
|
||||
const auto & attrName = state.symbols[attr.name];
|
||||
|
||||
if (attrName == "fromPath") {
|
||||
PathSet context;
|
||||
fromPath = state.coerceToStorePath(attr.pos, *attr.value, context);
|
||||
}
|
||||
|
||||
else if (attr.name == "toPath") {
|
||||
else if (attrName == "toPath") {
|
||||
state.forceValue(*attr.value, attr.pos);
|
||||
toCA = true;
|
||||
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);
|
||||
|
||||
else
|
||||
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]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
|
|||
state.forceAttrs(*args[0], pos);
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
std::string_view n(attr.name);
|
||||
std::string_view n(state.symbols[attr.name]);
|
||||
if (n == "url")
|
||||
url = state.coerceToString(attr.pos, *attr.value, context, false, false).toOwned();
|
||||
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);
|
||||
else
|
||||
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]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -126,20 +126,20 @@ static void fetchTree(
|
|||
state.forceValue(*attr.value, attr.pos);
|
||||
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
||||
auto s = state.coerceToString(attr.pos, *attr.value, context, false, false).toOwned();
|
||||
attrs.emplace(attr.name,
|
||||
attr.name == "url"
|
||||
attrs.emplace(state.symbols[attr.name],
|
||||
state.symbols[attr.name] == "url"
|
||||
? type == "git"
|
||||
? fixURIForGit(s, state)
|
||||
: fixURI(s, state)
|
||||
: s);
|
||||
}
|
||||
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)
|
||||
attrs.emplace(attr.name, uint64_t(attr.value->integer));
|
||||
attrs.emplace(state.symbols[attr.name], uint64_t(attr.value->integer));
|
||||
else
|
||||
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)
|
||||
|
@ -198,7 +198,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
|
|||
state.forceAttrs(*args[0], pos);
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
std::string n(attr.name);
|
||||
std::string_view n(state.symbols[attr.name]);
|
||||
if (n == "url")
|
||||
url = state.forceStringNoCtx(*attr.value, attr.pos);
|
||||
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);
|
||||
else
|
||||
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]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -16,46 +16,25 @@ namespace nix {
|
|||
|
||||
class Symbol
|
||||
{
|
||||
private:
|
||||
const std::string * s; // pointer into SymbolTable
|
||||
Symbol(const std::string * s) : s(s) { };
|
||||
friend class SymbolTable;
|
||||
private:
|
||||
std::string s;
|
||||
|
||||
public:
|
||||
Symbol() : s(0) { };
|
||||
|
||||
bool operator == (const Symbol & s2) const
|
||||
{
|
||||
return s == s2.s;
|
||||
}
|
||||
Symbol(std::string_view s) : s(s) { }
|
||||
|
||||
// FIXME: remove
|
||||
bool operator == (std::string_view s2) const
|
||||
{
|
||||
return s->compare(s2) == 0;
|
||||
}
|
||||
|
||||
bool operator != (const Symbol & s2) const
|
||||
{
|
||||
return s != s2.s;
|
||||
}
|
||||
|
||||
bool operator < (const Symbol & s2) const
|
||||
{
|
||||
return s < s2.s;
|
||||
return s == s2;
|
||||
}
|
||||
|
||||
operator const std::string & () const
|
||||
{
|
||||
return *s;
|
||||
return s;
|
||||
}
|
||||
|
||||
operator const std::string_view () const
|
||||
{
|
||||
return *s;
|
||||
}
|
||||
|
||||
bool set() const
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
@ -63,38 +42,64 @@ public:
|
|||
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
|
||||
{
|
||||
private:
|
||||
std::unordered_map<std::string_view, Symbol> symbols;
|
||||
std::list<std::string> store;
|
||||
std::unordered_map<std::string_view, std::pair<const Symbol *, uint32_t>> symbols;
|
||||
ChunkedVector<Symbol, 8192> store{16};
|
||||
|
||||
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
|
||||
// for lookup performance.
|
||||
// TODO: could probably be done more efficiently with transparent Hash and Equals
|
||||
// on the original implementation using unordered_set
|
||||
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);
|
||||
return symbols.emplace(rawSym, Symbol(&rawSym)).first->second;
|
||||
const auto & [rawSym, idx] = store.add(s);
|
||||
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
|
||||
{
|
||||
return symbols.size();
|
||||
return store.size();
|
||||
}
|
||||
|
||||
size_t totalSize() const;
|
||||
|
||||
template<typename T>
|
||||
void dump(T callback)
|
||||
void dump(T callback) const
|
||||
{
|
||||
for (auto & s : store)
|
||||
callback(s);
|
||||
store.forEach(callback);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ void printValueAsJSON(EvalState & state, bool strict,
|
|||
auto obj(out.object());
|
||||
StringSet names;
|
||||
for (auto & j : *v.attrs)
|
||||
names.insert(j.name);
|
||||
names.emplace(state.symbols[j.name]);
|
||||
for (auto & j : names) {
|
||||
Attr & a(*v.attrs->find(state.symbols.create(j)));
|
||||
auto placeholder(obj.placeholder(j));
|
||||
|
|
|
@ -22,7 +22,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
|||
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["line"] = (format("%1%") % pos.line).str();
|
||||
|
@ -36,14 +36,14 @@ static void showAttrs(EvalState & state, bool strict, bool location,
|
|||
StringSet names;
|
||||
|
||||
for (auto & i : attrs)
|
||||
names.insert(i.name);
|
||||
names.emplace(state.symbols[i.name]);
|
||||
|
||||
for (auto & i : names) {
|
||||
Attr & a(*attrs.find(state.symbols.create(i)));
|
||||
|
||||
XMLAttrs xmlAttrs;
|
||||
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);
|
||||
printValueAsXML(state, strict, location,
|
||||
|
@ -134,18 +134,18 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
|||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
if (v.lambda.fun->hasFormals()) {
|
||||
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";
|
||||
XMLOpenElement _(doc, "attrspat", attrs);
|
||||
for (auto & i : v.lambda.fun->formals->lexicographicOrder())
|
||||
doc.writeEmptyElement("attr", singletonAttrs("name", i.name));
|
||||
for (auto & i : v.lambda.fun->formals->lexicographicOrder(state.symbols))
|
||||
doc.writeEmptyElement("attr", singletonAttrs("name", state.symbols[i.name]));
|
||||
} else
|
||||
doc.writeEmptyElement("varpat", singletonAttrs("name", v.lambda.fun->arg));
|
||||
doc.writeEmptyElement("varpat", singletonAttrs("name", state.symbols[v.lambda.fun->arg]));
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ struct Env;
|
|||
struct Expr;
|
||||
struct ExprLambda;
|
||||
struct PrimOp;
|
||||
class Symbol;
|
||||
class SymbolIdx;
|
||||
class PosIdx;
|
||||
struct Pos;
|
||||
class StorePath;
|
||||
|
@ -121,11 +121,11 @@ private:
|
|||
|
||||
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:
|
||||
|
||||
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
|
||||
// These should be removed eventually, by putting the functionality that's
|
||||
|
@ -253,7 +253,7 @@ public:
|
|||
|
||||
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)
|
||||
|
@ -410,12 +410,12 @@ public:
|
|||
|
||||
#if HAVE_BOEHMGC
|
||||
typedef std::vector<Value *, traceable_allocator<Value *> > ValueVector;
|
||||
typedef std::map<Symbol, Value *, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, Value *> > > ValueMap;
|
||||
typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector> > > ValueVectorMap;
|
||||
typedef std::map<SymbolIdx, Value *, std::less<SymbolIdx>, traceable_allocator<std::pair<const SymbolIdx, Value *> > > ValueMap;
|
||||
typedef std::map<SymbolIdx, ValueVector, std::less<SymbolIdx>, traceable_allocator<std::pair<const SymbolIdx, ValueVector> > > ValueVectorMap;
|
||||
#else
|
||||
typedef std::vector<Value *> ValueVector;
|
||||
typedef std::map<Symbol, Value *> ValueMap;
|
||||
typedef std::map<Symbol, ValueVector> ValueVectorMap;
|
||||
typedef std::map<SymbolIdx, Value *> ValueMap;
|
||||
typedef std::map<SymbolIdx, ValueVector> ValueVectorMap;
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -152,6 +152,14 @@ public:
|
|||
{
|
||||
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));
|
||||
if(a.value->type() != nString) continue;
|
||||
XMLAttrs attrs3;
|
||||
attrs3["type"] = i.name;
|
||||
attrs3["type"] = globals.state->symbols[i.name];
|
||||
attrs3["value"] = a.value->string.s;
|
||||
xml.writeEmptyElement("string", attrs3);
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
|||
the store; we need it for future modifications of the
|
||||
environment. */
|
||||
std::ostringstream str;
|
||||
manifest.print(str, true);
|
||||
manifest.print(state.symbols, str, true);
|
||||
auto manifestFile = state.store->addTextToStore("env-manifest.nix",
|
||||
str.str(), references);
|
||||
|
||||
|
|
|
@ -31,7 +31,8 @@ void processExpr(EvalState & state, const Strings & attrPaths,
|
|||
bool evalOnly, OutputKind output, bool location, Expr * e)
|
||||
{
|
||||
if (parseOnly) {
|
||||
std::cout << format("%1%\n") % *e;
|
||||
e->show(state.symbols, std::cout);
|
||||
std::cout << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -55,7 +56,8 @@ void processExpr(EvalState & state, const Strings & attrPaths,
|
|||
printValueAsJSON(state, strict, vRes, v.determinePos(noPos), std::cout, context);
|
||||
else {
|
||||
if (strict) state.forceValueDeep(vRes);
|
||||
std::cout << vRes << std::endl;
|
||||
vRes.print(state.symbols, std::cout);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
} else {
|
||||
DrvInfos drvs;
|
||||
|
|
|
@ -85,9 +85,9 @@ UnresolvedApp Installable::toApp(EvalState & state)
|
|||
|
||||
else if (type == "derivation") {
|
||||
auto drvPath = cursor->forceDerivation();
|
||||
auto outPath = cursor->getAttr(state.sOutPath)->getString();
|
||||
auto outputName = cursor->getAttr(state.sOutputName)->getString();
|
||||
auto name = cursor->getAttr(state.sName)->getString();
|
||||
auto outPath = cursor->getAttr("outPath")->getString();
|
||||
auto outputName = cursor->getAttr("outputName")->getString();
|
||||
auto name = cursor->getAttr("name")->getString();
|
||||
auto aPname = cursor->maybeGetAttr("pname");
|
||||
auto aMeta = cursor->maybeGetAttr("meta");
|
||||
auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr;
|
||||
|
|
|
@ -88,18 +88,20 @@ struct CmdEval : MixJSON, InstallableCommand
|
|||
else if (v.type() == nAttrs) {
|
||||
if (mkdir(path.c_str(), 0777) == -1)
|
||||
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 {
|
||||
if (attr.name == "." || attr.name == "..")
|
||||
throw Error("invalid file name '%s'", attr.name);
|
||||
recurse(*attr.value, attr.pos, path + "/" + std::string(attr.name));
|
||||
if (name == "." || name == "..")
|
||||
throw Error("invalid file name '%s'", name);
|
||||
recurse(*attr.value, attr.pos, concatStrings(path, "/", name));
|
||||
} catch (Error & e) {
|
||||
e.addTrace(
|
||||
state->positions[attr.pos],
|
||||
hintfmt("while evaluating the attribute '%s'", attr.name));
|
||||
hintfmt("while evaluating the attribute '%s'", name));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
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 {
|
||||
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
|
||||
it for other outputs. */
|
||||
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) {
|
||||
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
|
||||
{
|
||||
bool build = true;
|
||||
|
@ -319,6 +311,14 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
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) {
|
||||
// FIXME: what's the format of "system"?
|
||||
if (system.find('-') == std::string::npos)
|
||||
|
@ -390,7 +390,7 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
} catch (Error & e) {
|
||||
e.addTrace(
|
||||
state->positions[attr.pos],
|
||||
hintfmt("while evaluating the option '%s'", attr.name));
|
||||
hintfmt("while evaluating the option '%s'", state->symbols[attr.name]));
|
||||
throw;
|
||||
}
|
||||
} else
|
||||
|
@ -414,7 +414,7 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
|
||||
for (auto & attr : *v.attrs) {
|
||||
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)) {
|
||||
Activity act(*logger, lvlChatty, actUnknown,
|
||||
fmt("checking Hydra job '%s'", attrPath2));
|
||||
|
@ -468,7 +468,7 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
throw Error("template '%s' lacks attribute 'description'", attrPath);
|
||||
|
||||
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")
|
||||
throw Error("template '%s' has unsupported attribute '%s'", attrPath, name);
|
||||
}
|
||||
|
@ -522,13 +522,14 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
if (name == "checks") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
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);
|
||||
for (auto & attr2 : *attr.value->attrs) {
|
||||
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);
|
||||
if (drvPath && (std::string) attr.name == settings.thisSystem.get())
|
||||
if (drvPath && attr_name == settings.thisSystem.get())
|
||||
drvPaths.push_back(DerivedPath::Built{*drvPath});
|
||||
}
|
||||
}
|
||||
|
@ -537,9 +538,10 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "formatter") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
checkSystemName(attr.name, attr.pos);
|
||||
const auto & attr_name = state->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
checkApp(
|
||||
fmt("%s.%s", name, attr.name),
|
||||
fmt("%s.%s", name, attr_name),
|
||||
*attr.value, attr.pos);
|
||||
}
|
||||
}
|
||||
|
@ -547,11 +549,12 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "packages" || name == "devShells") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
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);
|
||||
for (auto & attr2 : *attr.value->attrs)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -559,11 +562,12 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "apps") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
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);
|
||||
for (auto & attr2 : *attr.value->attrs)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -571,9 +575,10 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "defaultPackage" || name == "devShell") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
checkSystemName(attr.name, attr.pos);
|
||||
const auto & attr_name = state->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
checkDerivation(
|
||||
fmt("%s.%s", name, attr.name),
|
||||
fmt("%s.%s", name, attr_name),
|
||||
*attr.value, attr.pos);
|
||||
}
|
||||
}
|
||||
|
@ -581,9 +586,10 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "defaultApp") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
checkSystemName(attr.name, attr.pos);
|
||||
const auto & attr_name = state->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
checkApp(
|
||||
fmt("%s.%s", name, attr.name),
|
||||
fmt("%s.%s", name, attr_name),
|
||||
*attr.value, attr.pos);
|
||||
}
|
||||
}
|
||||
|
@ -591,7 +597,7 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "legacyPackages") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
checkSystemName(attr.name, attr.pos);
|
||||
checkSystemName(state->symbols[attr.name], attr.pos);
|
||||
// FIXME: do getDerivations?
|
||||
}
|
||||
}
|
||||
|
@ -602,7 +608,7 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "overlays") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -612,14 +618,14 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "nixosModules") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
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);
|
||||
}
|
||||
|
||||
else if (name == "nixosConfigurations") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -632,16 +638,17 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "templates") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
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);
|
||||
}
|
||||
|
||||
else if (name == "defaultBundler") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
checkSystemName(attr.name, attr.pos);
|
||||
const auto & attr_name = state->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
checkBundler(
|
||||
fmt("%s.%s", name, attr.name),
|
||||
fmt("%s.%s", name, attr_name),
|
||||
*attr.value, attr.pos);
|
||||
}
|
||||
}
|
||||
|
@ -649,11 +656,12 @@ struct CmdFlakeCheck : FlakeCommand
|
|||
else if (name == "bundlers") {
|
||||
state->forceAttrs(vOutput, pos);
|
||||
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);
|
||||
for (auto & attr2 : *attr.value->attrs) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1000,7 +1008,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
|||
|
||||
auto showDerivation = [&]()
|
||||
{
|
||||
auto name = visitor.getAttr(state->sName)->getString();
|
||||
auto name = visitor.getAttr("name")->getString();
|
||||
if (json) {
|
||||
std::optional<std::string> description;
|
||||
if (auto aMeta = visitor.maybeGetAttr("meta")) {
|
||||
|
|
|
@ -302,7 +302,7 @@ void mainWrapped(int argc, char * * argv)
|
|||
b["arity"] = primOp->arity;
|
||||
b["args"] = primOp->args;
|
||||
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";
|
||||
return;
|
||||
|
|
|
@ -73,7 +73,7 @@ struct NixRepl
|
|||
void initEnv();
|
||||
void reloadFiles();
|
||||
void addAttrsToScope(Value & attrs);
|
||||
void addVarToScope(const Symbol & name, Value & v);
|
||||
void addVarToScope(const SymbolIdx name, Value & v);
|
||||
Expr * parseString(std::string s);
|
||||
void evalString(std::string s, Value & v);
|
||||
|
||||
|
@ -347,9 +347,9 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
|||
state->forceAttrs(v, noPos);
|
||||
|
||||
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;
|
||||
completions.insert(prev + expr + "." + name);
|
||||
completions.insert(concatStrings(prev, expr, ".", name));
|
||||
}
|
||||
|
||||
} catch (ParseError & e) {
|
||||
|
@ -464,8 +464,9 @@ bool NixRepl::processLine(std::string line)
|
|||
const auto [file, line] = [&] () -> std::pair<std::string, uint32_t> {
|
||||
if (v.type() == nPath || v.type() == nString) {
|
||||
PathSet context;
|
||||
auto filename = state->coerceToString(noPos, v, context);
|
||||
return {state->symbols.create(*filename), 0};
|
||||
auto filename = state->coerceToString(noPos, v, context).toOwned();
|
||||
state->symbols.create(filename);
|
||||
return {filename, 0};
|
||||
} else if (v.isLambda()) {
|
||||
auto pos = state->positions[v.lambda.fun->pos];
|
||||
return {pos.file, pos.line};
|
||||
|
@ -672,7 +673,7 @@ void NixRepl::initEnv()
|
|||
|
||||
varNames.clear();
|
||||
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) {
|
||||
staticEnv.vars.emplace_back(i.name, displ);
|
||||
env->values[displ++] = i.value;
|
||||
varNames.insert((std::string) i.name);
|
||||
varNames.emplace(state->symbols[i.name]);
|
||||
}
|
||||
staticEnv.sort();
|
||||
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)
|
||||
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.sort();
|
||||
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;
|
||||
Sorted sorted;
|
||||
for (auto & i : *v.attrs)
|
||||
sorted[i.name] = i.value;
|
||||
sorted.emplace(state->symbols[i.name], i.value);
|
||||
|
||||
for (auto & i : sorted) {
|
||||
if (isVarName(i.first))
|
||||
|
|
|
@ -154,7 +154,7 @@ struct CmdSearch : InstallableCommand, MixJSON
|
|||
recurse();
|
||||
|
||||
else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) {
|
||||
auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations);
|
||||
auto attr = cursor.maybeGetAttr("recurseForDerivations");
|
||||
if (attr && attr->getBool())
|
||||
recurse();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue