diff options
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/attr-path.cc | 11 | ||||
-rw-r--r-- | src/libexpr/download.cc | 236 | ||||
-rw-r--r-- | src/libexpr/download.hh | 22 | ||||
-rw-r--r-- | src/libexpr/eval-inline.hh | 4 | ||||
-rw-r--r-- | src/libexpr/eval.cc | 171 | ||||
-rw-r--r-- | src/libexpr/get-drvs.cc | 38 | ||||
-rw-r--r-- | src/libexpr/json-to-value.cc | 2 | ||||
-rw-r--r-- | src/libexpr/local.mk | 2 | ||||
-rw-r--r-- | src/libexpr/names.cc | 4 | ||||
-rw-r--r-- | src/libexpr/nixexpr.cc | 92 | ||||
-rw-r--r-- | src/libexpr/parser.y | 20 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 262 | ||||
-rw-r--r-- | src/libexpr/value-to-json.cc | 34 | ||||
-rw-r--r-- | src/libexpr/value-to-xml.cc | 46 | ||||
-rw-r--r-- | src/libexpr/value.hh | 29 |
15 files changed, 405 insertions, 568 deletions
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index fdd61a5fd375..55379f94b189 100644 --- a/src/libexpr/attr-path.cc +++ b/src/libexpr/attr-path.cc @@ -42,11 +42,10 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath, Value * v = &vIn; - foreach (Strings::iterator, i, tokens) { + for (auto & attr : tokens) { - /* Is *i an index (integer) or a normal attribute name? */ + /* Is i an index (integer) or a normal attribute name? */ enum { apAttr, apIndex } apType = apAttr; - string attr = *i; unsigned int attrIndex; if (string2Int(attr, attrIndex)) apType = apIndex; @@ -77,15 +76,15 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath, else if (apType == apIndex) { - if (v->type != tList) + if (!v->isList()) throw TypeError( format("the expression selected by the selection path ‘%1%’ should be a list but is %2%") % attrPath % showType(*v)); - if (attrIndex >= v->list.length) + if (attrIndex >= v->listSize()) throw Error(format("list index %1% in selection path ‘%2%’ is out of range") % attrIndex % attrPath); - v = v->list.elems[attrIndex]; + v = v->listElems()[attrIndex]; } } diff --git a/src/libexpr/download.cc b/src/libexpr/download.cc deleted file mode 100644 index 9bf3e13aa9da..000000000000 --- a/src/libexpr/download.cc +++ /dev/null @@ -1,236 +0,0 @@ -#include "download.hh" -#include "util.hh" -#include "globals.hh" -#include "hash.hh" -#include "store-api.hh" - -#include <curl/curl.h> - -namespace nix { - -struct Curl -{ - CURL * curl; - string data; - string etag, status, expectedETag; - - struct curl_slist * requestHeaders; - - static size_t writeCallback(void * contents, size_t size, size_t nmemb, void * userp) - { - Curl & c(* (Curl *) userp); - size_t realSize = size * nmemb; - c.data.append((char *) contents, realSize); - return realSize; - } - - static size_t headerCallback(void * contents, size_t size, size_t nmemb, void * userp) - { - Curl & c(* (Curl *) userp); - size_t realSize = size * nmemb; - string line = string((char *) contents, realSize); - printMsg(lvlVomit, format("got header: %1%") % trim(line)); - if (line.compare(0, 5, "HTTP/") == 0) { // new response starts - c.etag = ""; - auto ss = tokenizeString<vector<string>>(line, " "); - c.status = ss.size() >= 2 ? ss[1] : ""; - } else { - auto i = line.find(':'); - if (i != string::npos) { - string name = trim(string(line, 0, i)); - if (name == "ETag") { // FIXME: case - c.etag = trim(string(line, i + 1)); - /* Hack to work around a GitHub bug: it sends - ETags, but ignores If-None-Match. So if we get - the expected ETag on a 200 response, then shut - down the connection because we already have the - data. */ - printMsg(lvlDebug, format("got ETag: %1%") % c.etag); - if (c.etag == c.expectedETag && c.status == "200") { - printMsg(lvlDebug, format("shutting down on 200 HTTP response with expected ETag")); - return 0; - } - } - } - } - return realSize; - } - - static int progressCallback(void * clientp, double dltotal, double dlnow, double ultotal, double ulnow) - { - return _isInterrupted; - } - - Curl() - { - requestHeaders = 0; - - curl = curl_easy_init(); - if (!curl) throw Error("unable to initialize curl"); - - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_CAINFO, getEnv("SSL_CERT_FILE", "/etc/ssl/certs/ca-certificates.crt").c_str()); - curl_easy_setopt(curl, CURLOPT_USERAGENT, ("Nix/" + nixVersion).c_str()); - curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); - - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &curl); - - curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, headerCallback); - curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *) &curl); - - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progressCallback); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - } - - ~Curl() - { - if (curl) curl_easy_cleanup(curl); - if (requestHeaders) curl_slist_free_all(requestHeaders); - } - - bool fetch(const string & url, const string & expectedETag = "") - { - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - - data.clear(); - - if (requestHeaders) { - curl_slist_free_all(requestHeaders); - requestHeaders = 0; - } - - if (!expectedETag.empty()) { - this->expectedETag = expectedETag; - requestHeaders = curl_slist_append(requestHeaders, ("If-None-Match: " + expectedETag).c_str()); - } - - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, requestHeaders); - - CURLcode res = curl_easy_perform(curl); - checkInterrupt(); - if (res == CURLE_WRITE_ERROR && etag == expectedETag) return false; - if (res != CURLE_OK) - throw DownloadError(format("unable to download ‘%1%’: %2% (%3%)") - % url % curl_easy_strerror(res) % res); - - long httpStatus = 0; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpStatus); - if (httpStatus == 304) return false; - - return true; - } -}; - - -DownloadResult downloadFile(string url, string expectedETag) -{ - DownloadResult res; - Curl curl; - if (curl.fetch(url, expectedETag)) { - res.cached = false; - res.data = curl.data; - } else - res.cached = true; - res.etag = curl.etag; - return res; -} - - -Path downloadFileCached(const string & url, bool unpack) -{ - Path cacheDir = getEnv("XDG_CACHE_HOME", getEnv("HOME", "") + "/.cache") + "/nix/tarballs"; - createDirs(cacheDir); - - string urlHash = printHash32(hashString(htSHA256, url)); - - Path dataFile = cacheDir + "/" + urlHash + ".info"; - Path fileLink = cacheDir + "/" + urlHash + "-file"; - - Path storePath; - - string expectedETag; - - int ttl = settings.get("tarball-ttl", 60 * 60); - bool skip = false; - - if (pathExists(fileLink) && pathExists(dataFile)) { - storePath = readLink(fileLink); - store->addTempRoot(storePath); - if (store->isValidPath(storePath)) { - auto ss = tokenizeString<vector<string>>(readFile(dataFile), "\n"); - if (ss.size() >= 3 && ss[0] == url) { - time_t lastChecked; - if (string2Int(ss[2], lastChecked) && lastChecked + ttl >= time(0)) - skip = true; - else if (!ss[1].empty()) { - printMsg(lvlDebug, format("verifying previous ETag ‘%1%’") % ss[1]); - expectedETag = ss[1]; - } - } - } else - storePath = ""; - } - - string name; - auto p = url.rfind('/'); - if (p != string::npos) name = string(url, p + 1); - - if (!skip) { - - if (storePath.empty()) - printMsg(lvlInfo, format("downloading ‘%1%’...") % url); - else - printMsg(lvlInfo, format("checking ‘%1%’...") % url); - - try { - auto res = downloadFile(url, expectedETag); - - if (!res.cached) - storePath = store->addTextToStore(name, res.data, PathSet(), false); - - assert(!storePath.empty()); - replaceSymlink(storePath, fileLink); - - writeFile(dataFile, url + "\n" + res.etag + "\n" + int2String(time(0)) + "\n"); - } catch (DownloadError & e) { - if (storePath.empty()) throw; - printMsg(lvlError, format("warning: %1%; using cached result") % e.msg()); - } - } - - if (unpack) { - Path unpackedLink = cacheDir + "/" + baseNameOf(storePath) + "-unpacked"; - Path unpackedStorePath; - if (pathExists(unpackedLink)) { - unpackedStorePath = readLink(unpackedLink); - store->addTempRoot(unpackedStorePath); - if (!store->isValidPath(unpackedStorePath)) - unpackedStorePath = ""; - } - if (unpackedStorePath.empty()) { - printMsg(lvlInfo, format("unpacking ‘%1%’...") % url); - Path tmpDir = createTempDir(); - AutoDelete autoDelete(tmpDir, true); - // FIXME: this requires GNU tar for decompression. - runProgram("tar", true, {"xf", storePath, "-C", tmpDir, "--strip-components", "1"}, ""); - unpackedStorePath = store->addToStore(name, tmpDir, true, htSHA256, defaultPathFilter, false); - } - replaceSymlink(unpackedStorePath, unpackedLink); - return unpackedStorePath; - } - - return storePath; -} - - -bool isUri(const string & s) -{ - size_t pos = s.find("://"); - if (pos == string::npos) return false; - string scheme(s, 0, pos); - return scheme == "http" || scheme == "https" || scheme == "file"; -} - - -} diff --git a/src/libexpr/download.hh b/src/libexpr/download.hh deleted file mode 100644 index 28c9117e4227..000000000000 --- a/src/libexpr/download.hh +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "types.hh" -#include <string> - -namespace nix { - -struct DownloadResult -{ - bool cached; - string data, etag; -}; - -DownloadResult downloadFile(string url, string expectedETag = ""); - -Path downloadFileCached(const string & url, bool unpack); - -MakeError(DownloadError, Error) - -bool isUri(const string & s); - -} diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index c275f7ba83e8..178e06c80186 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -66,7 +66,7 @@ inline void EvalState::forceAttrs(Value & v, const Pos & pos) inline void EvalState::forceList(Value & v) { forceValue(v); - if (v.type != tList) + if (!v.isList()) throwTypeError("value is %1% while a list was expected", v); } @@ -74,7 +74,7 @@ inline void EvalState::forceList(Value & v) inline void EvalState::forceList(Value & v, const Pos & pos) { forceValue(v); - if (v.type != tList) + if (!v.isList()) throwTypeError("value is %1% while a list was expected, at %2%", v, pos); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index eab38c9da174..044256112d50 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -57,6 +57,8 @@ static void * allocBytes(size_t n) static void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v) { + checkInterrupt(); + if (active.find(&v) != active.end()) { str << "<CYCLE>"; return; @@ -90,8 +92,8 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con str << "{ "; typedef std::map<string, Value *> Sorted; Sorted sorted; - foreach (Bindings::iterator, i, *v.attrs) - sorted[i->name] = i->value; + for (auto & i : *v.attrs) + sorted[i.name] = i.value; for (auto & i : sorted) { str << i.first << " = "; printValue(str, active, *i.second); @@ -100,10 +102,12 @@ static void printValue(std::ostream & str, std::set<const Value *> & active, con str << "}"; break; } - case tList: + case tList1: + case tList2: + case tListN: str << "[ "; - for (unsigned int n = 0; n < v.list.length; ++n) { - printValue(str, active, *v.list.elems[n]); + for (unsigned int n = 0; n < v.listSize(); ++n) { + printValue(str, active, *v.listElems()[n]); str << " "; } str << "]"; @@ -149,7 +153,7 @@ string showType(const Value & v) case tPath: return "a path"; case tNull: return "null"; case tAttrs: return "a set"; - case tList: return "a list"; + case tList1: case tList2: case tListN: return "a list"; case tThunk: return "a thunk"; case tApp: return "a function application"; case tLambda: return "a function"; @@ -434,8 +438,8 @@ void mkString(Value & v, const string & s, const PathSet & context) unsigned int n = 0; v.string.context = (const char * *) allocBytes((context.size() + 1) * sizeof(char *)); - foreach (PathSet::const_iterator, i, context) - v.string.context[n++] = dupString(i->c_str()); + for (auto & i : context) + v.string.context[n++] = dupString(i.c_str()); v.string.context[n] = 0; } } @@ -497,13 +501,19 @@ Env & EvalState::allocEnv(unsigned int size) } -void EvalState::mkList(Value & v, unsigned int length) +void EvalState::mkList(Value & v, unsigned int size) { clearValue(v); - v.type = tList; - v.list.length = length; - v.list.elems = length ? (Value * *) allocBytes(length * sizeof(Value *)) : 0; - nrListElems += length; + if (size == 1) + v.type = tList1; + else if (size == 2) + v.type = tList2; + else { + v.type = tListN; + v.bigList.size = size; + v.bigList.elems = size ? (Value * *) allocBytes(size * sizeof(Value *)) : 0; + } + nrListElems += size; } @@ -691,15 +701,15 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) environment, while the inherited attributes are evaluated in the original environment. */ unsigned int displ = 0; - foreach (AttrDefs::iterator, i, attrs) { + for (auto & i : attrs) { Value * vAttr; - if (hasOverrides && !i->second.inherited) { + if (hasOverrides && !i.second.inherited) { vAttr = state.allocValue(); - mkThunk(*vAttr, env2, i->second.e); + mkThunk(*vAttr, env2, i.second.e); } else - vAttr = i->second.e->maybeThunk(state, i->second.inherited ? env : env2); + vAttr = i.second.e->maybeThunk(state, i.second.inherited ? env : env2); env2.values[displ++] = vAttr; - v.attrs->push_back(Attr(i->first, vAttr, &i->second.pos)); + v.attrs->push_back(Attr(i.first, vAttr, &i.second.pos)); } /* If the rec contains an attribute called `__overrides', then @@ -730,13 +740,13 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) } else - foreach (AttrDefs::iterator, i, attrs) - v.attrs->push_back(Attr(i->first, i->second.e->maybeThunk(state, env), &i->second.pos)); + for (auto & i : attrs) + v.attrs->push_back(Attr(i.first, i.second.e->maybeThunk(state, env), &i.second.pos)); /* Dynamic attrs apply *after* rec and __overrides. */ - foreach (DynamicAttrDefs::iterator, i, dynamicAttrs) { + for (auto & i : dynamicAttrs) { Value nameVal; - i->nameExpr->eval(state, *dynamicEnv, nameVal); + i.nameExpr->eval(state, *dynamicEnv, nameVal); state.forceValue(nameVal); if (nameVal.type == tNull) continue; @@ -744,11 +754,11 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) Symbol nameSym = state.symbols.create(nameVal.string.s); Bindings::iterator j = v.attrs->find(nameSym); if (j != v.attrs->end()) - throwEvalError("dynamic attribute ‘%1%’ at %2% already defined at %3%", nameSym, i->pos, *j->pos); + throwEvalError("dynamic attribute ‘%1%’ at %2% already defined at %3%", nameSym, i.pos, *j->pos); - i->valueExpr->setName(nameSym); + i.valueExpr->setName(nameSym); /* Keep sorted order so find can catch duplicates */ - v.attrs->push_back(Attr(nameSym, i->valueExpr->maybeThunk(state, *dynamicEnv), &i->pos)); + v.attrs->push_back(Attr(nameSym, i.valueExpr->maybeThunk(state, *dynamicEnv), &i.pos)); v.attrs->sort(); // FIXME: inefficient } } @@ -765,8 +775,8 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) while the inherited attributes are evaluated in the original environment. */ unsigned int displ = 0; - foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs) - env2.values[displ++] = i->second.e->maybeThunk(state, i->second.inherited ? env : env2); + for (auto & i : attrs->attrs) + env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2); body->eval(state, env2, v); } @@ -775,8 +785,8 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) void ExprList::eval(EvalState & state, Env & env, Value & v) { state.mkList(v, elems.size()); - for (unsigned int n = 0; n < v.list.length; ++n) - v.list.elems[n] = elems[n]->maybeThunk(state, env); + for (unsigned int n = 0; n < elems.size(); ++n) + v.listElems()[n] = elems[n]->maybeThunk(state, env); } @@ -817,10 +827,10 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) try { - foreach (AttrPath::const_iterator, i, attrPath) { + for (auto & i : attrPath) { nrLookups++; Bindings::iterator j; - Symbol name = getName(*i, state, env); + Symbol name = getName(i, state, env); if (def) { state.forceValue(*vAttrs); if (vAttrs->type != tAttrs || @@ -859,10 +869,10 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) e->eval(state, env, vTmp); - foreach (AttrPath::const_iterator, i, attrPath) { + for (auto & i : attrPath) { state.forceValue(*vAttrs); Bindings::iterator j; - Symbol name = getName(*i, state, env); + Symbol name = getName(i, state, env); if (vAttrs->type != tAttrs || (j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) { @@ -975,12 +985,12 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po there is no matching actual argument but the formal argument has a default, use the default. */ unsigned int attrsUsed = 0; - foreach (Formals::Formals_::iterator, i, lambda.formals->formals) { - Bindings::iterator j = arg.attrs->find(i->name); + for (auto & i : lambda.formals->formals) { + Bindings::iterator j = arg.attrs->find(i.name); if (j == arg.attrs->end()) { - if (!i->def) throwTypeError("%1% called without required argument ‘%2%’, at %3%", - lambda, i->name, pos); - env2.values[displ++] = i->def->maybeThunk(*this, env2); + if (!i.def) throwTypeError("%1% called without required argument ‘%2%’, at %3%", + lambda, i.name, pos); + env2.values[displ++] = i.def->maybeThunk(*this, env2); } else { attrsUsed++; env2.values[displ++] = j->value; @@ -992,9 +1002,9 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po if (!lambda.formals->ellipsis && attrsUsed != arg.attrs->size()) { /* Nope, so show the first unexpected argument to the user. */ - foreach (Bindings::iterator, i, *arg.attrs) - if (lambda.formals->argNames.find(i->name) == lambda.formals->argNames.end()) - throwTypeError("%1% called with unexpected argument ‘%2%’, at %3%", lambda, i->name, pos); + for (auto & i : *arg.attrs) + if (lambda.formals->argNames.find(i.name) == lambda.formals->argNames.end()) + throwTypeError("%1% called with unexpected argument ‘%2%’, at %3%", lambda, i.name, pos); abort(); // can't happen } } @@ -1036,12 +1046,12 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res) Value * actualArgs = allocValue(); mkAttrs(*actualArgs, fun.lambda.fun->formals->formals.size()); - foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) { - Bindings::iterator j = args.find(i->name); + for (auto & i : fun.lambda.fun->formals->formals) { + Bindings::iterator j = args.find(i.name); if (j != args.end()) actualArgs->attrs->push_back(*j); - else if (!i->def) - throwTypeError("cannot auto-call a function that has an argument without a default value (‘%1%’)", i->name); + else if (!i.def) + throwTypeError("cannot auto-call a function that has an argument without a default value (‘%1%’)", i.name); } actualArgs->attrs->sort(); @@ -1169,20 +1179,21 @@ void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, co unsigned int len = 0; for (unsigned int n = 0; n < nrLists; ++n) { forceList(*lists[n], pos); - unsigned int l = lists[n]->list.length; + unsigned int l = lists[n]->listSize(); len += l; if (l) nonEmpty = lists[n]; } - if (nonEmpty && len == nonEmpty->list.length) { + if (nonEmpty && len == nonEmpty->listSize()) { v = *nonEmpty; return; } mkList(v, len); + auto out = v.listElems(); for (unsigned int n = 0, pos = 0; n < nrLists; ++n) { - unsigned int l = lists[n]->list.length; - memcpy(v.list.elems + pos, lists[n]->list.elems, l * sizeof(Value *)); + unsigned int l = lists[n]->listSize(); + memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *)); pos += l; } } @@ -1197,9 +1208,9 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) bool first = !forceString; ValueType firstType = tString; - foreach (vector<Expr *>::iterator, i, *es) { + for (auto & i : *es) { Value vTmp; - (*i)->eval(state, env, vTmp); + i->eval(state, env, vTmp); /* If the first element is a path, then the result will also be a path, we don't copy anything (yet - that's done later, @@ -1258,9 +1269,9 @@ void EvalState::forceValueDeep(Value & v) } } - else if (v.type == tList) { - for (unsigned int n = 0; n < v.list.length; ++n) - recurse(*v.list.elems[n]); + else if (v.isList()) { + for (unsigned int n = 0; n < v.listSize(); ++n) + recurse(*v.listElems()[n]); } }; @@ -1384,14 +1395,14 @@ string EvalState::coerceToString(const Pos & pos, Value & v, PathSet & context, if (v.type == tInt) return int2String(v.integer); if (v.type == tNull) return ""; - if (v.type == tList) { + if (v.isList()) { string result; - for (unsigned int n = 0; n < v.list.length; ++n) { - result += coerceToString(pos, *v.list.elems[n], + for (unsigned int n = 0; n < v.listSize(); ++n) { + result += coerceToString(pos, *v.listElems()[n], context, coerceMore, copyToStore); - if (n < v.list.length - 1 + if (n < v.listSize() - 1 /* !!! not quite correct */ - && (v.list.elems[n]->type != tList || v.list.elems[n]->list.length != 0)) + && (!v.listElems()[n]->isList() || v.listElems()[n]->listSize() != 0)) result += " "; } return result; @@ -1462,10 +1473,12 @@ bool EvalState::eqValues(Value & v1, Value & v2) case tNull: return true; - case tList: - if (v1.list.length != v2.list.length) return false; - for (unsigned int n = 0; n < v1.list.length; ++n) - if (!eqValues(*v1.list.elems[n], *v2.list.elems[n])) return false; + case tList1: + case tList2: + case tListN: + if (v1.listSize() != v2.listSize()) return false; + for (unsigned int n = 0; n < v1.listSize(); ++n) + if (!eqValues(*v1.listElems()[n], *v2.listElems()[n])) return false; return true; case tAttrs: { @@ -1551,25 +1564,25 @@ void EvalState::printStats() printMsg(v, format("calls to %1% primops:") % primOpCalls.size()); typedef std::multimap<unsigned int, Symbol> PrimOpCalls_; PrimOpCalls_ primOpCalls_; - foreach (PrimOpCalls::iterator, i, primOpCalls) - primOpCalls_.insert(std::pair<unsigned int, Symbol>(i->second, i->first)); - foreach_reverse (PrimOpCalls_::reverse_iterator, i, primOpCalls_) + for (auto & i : primOpCalls) + primOpCalls_.insert(std::pair<unsigned int, Symbol>(i.second, i.first)); + for (auto i = primOpCalls_.rbegin(); i != primOpCalls_.rend(); ++i) printMsg(v, format("%1$10d %2%") % i->first % i->second); printMsg(v, format("calls to %1% functions:") % functionCalls.size()); typedef std::multimap<unsigned int, ExprLambda *> FunctionCalls_; FunctionCalls_ functionCalls_; - foreach (FunctionCalls::iterator, i, functionCalls) - functionCalls_.insert(std::pair<unsigned int, ExprLambda *>(i->second, i->first)); - foreach_reverse (FunctionCalls_::reverse_iterator, i, functionCalls_) + for (auto & i : functionCalls) + functionCalls_.insert(std::pair<unsigned int, ExprLambda *>(i.second, i.first)); + for (auto i = functionCalls_.rbegin(); i != functionCalls_.rend(); ++i) printMsg(v, format("%1$10d %2%") % i->first % i->second->showNamePos()); printMsg(v, format("evaluations of %1% attributes:") % attrSelects.size()); typedef std::multimap<unsigned int, Pos> AttrSelects_; AttrSelects_ attrSelects_; - foreach (AttrSelects::iterator, i, attrSelects) - attrSelects_.insert(std::pair<unsigned int, Pos>(i->second, i->first)); - foreach_reverse (AttrSelects_::reverse_iterator, i, attrSelects_) + for (auto & i : attrSelects) + attrSelects_.insert(std::pair<unsigned int, Pos>(i.second, i.first)); + for (auto i = attrSelects_.rbegin(); i != attrSelects_.rend(); ++i) printMsg(v, format("%1$10d %2%") % i->first % i->second); } @@ -1613,12 +1626,14 @@ size_t valueSize(Value & v) sz += doValue(*i.value); } break; - case tList: - if (seen.find(v.list.elems) == seen.end()) { - seen.insert(v.list.elems); - sz += v.list.length * sizeof(Value *); - for (unsigned int n = 0; n < v.list.length; ++n) - sz += doValue(*v.list.elems[n]); + case tList1: + case tList2: + case tListN: + if (seen.find(v.listElems()) == seen.end()) { + seen.insert(v.listElems()); + sz += v.listSize() * sizeof(Value *); + for (unsigned int n = 0; n < v.listSize(); ++n) + sz += doValue(*v.listElems()[n]); } break; case tThunk: diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 1c9fa02a366a..1002ee6285af 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -39,9 +39,9 @@ DrvInfo::Outputs DrvInfo::queryOutputs() state->forceList(*i->value, *i->pos); /* For each output... */ - for (unsigned int j = 0; j < i->value->list.length; ++j) { + for (unsigned int j = 0; j < i->value->listSize(); ++j) { /* Evaluate the corresponding set. */ - string name = state->forceStringNoCtx(*i->value->list.elems[j], *i->pos); + string name = state->forceStringNoCtx(*i->value->listElems()[j], *i->pos); Bindings::iterator out = attrs->find(state->symbols.create(name)); if (out == attrs->end()) continue; // FIXME: throw error? state->forceAttrs(*out->value); @@ -85,8 +85,8 @@ StringSet DrvInfo::queryMetaNames() { StringSet res; if (!getMeta()) return res; - foreach (Bindings::iterator, i, *meta) - res.insert(i->name); + for (auto & i : *meta) + res.insert(i.name); return res; } @@ -94,16 +94,16 @@ StringSet DrvInfo::queryMetaNames() bool DrvInfo::checkMeta(Value & v) { state->forceValue(v); - if (v.type == tList) { - for (unsigned int n = 0; n < v.list.length; ++n) - if (!checkMeta(*v.list.elems[n])) return false; + if (v.isList()) { + for (unsigned int n = 0; n < v.listSize(); ++n) + if (!checkMeta(*v.listElems()[n])) return false; return true; } else if (v.type == tAttrs) { Bindings::iterator i = v.attrs->find(state->sOutPath); if (i != v.attrs->end()) return false; - foreach (Bindings::iterator, i, *v.attrs) - if (!checkMeta(*i->value)) return false; + for (auto & i : *v.attrs) + if (!checkMeta(*i.value)) return false; return true; } else return v.type == tInt || v.type == tBool || v.type == tString; @@ -255,13 +255,13 @@ static void getDerivations(EvalState & state, Value & vIn, precedence). */ typedef std::map<string, Symbol> SortedSymbols; SortedSymbols attrs; - foreach (Bindings::iterator, i, *v.attrs) - attrs.insert(std::pair<string, Symbol>(i->name, i->name)); + for (auto & i : *v.attrs) + attrs.insert(std::pair<string, Symbol>(i.name, i.name)); - foreach (SortedSymbols::iterator, i, attrs) { - startNest(nest, lvlDebug, format("evaluating attribute ‘%1%’") % i->first); - string pathPrefix2 = addToPath(pathPrefix, i->first); - Value & v2(*v.attrs->find(i->second)->value); + for (auto & i : attrs) { + startNest(nest, lvlDebug, format("evaluating attribute ‘%1%’") % i.first); + string pathPrefix2 = addToPath(pathPrefix, i.first); + Value & v2(*v.attrs->find(i.second)->value); if (combineChannels) getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); else if (getDerivation(state, v2, pathPrefix2, drvs, done, ignoreAssertionFailures)) { @@ -277,13 +277,13 @@ static void getDerivations(EvalState & state, Value & vIn, } } - else if (v.type == tList) { - for (unsigned int n = 0; n < v.list.length; ++n) { + else if (v.isList()) { + for (unsigned int n = 0; n < v.listSize(); ++n) { startNest(nest, lvlDebug, format("evaluating list element")); string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str()); - if (getDerivation(state, *v.list.elems[n], pathPrefix2, drvs, done, ignoreAssertionFailures)) - getDerivations(state, *v.list.elems[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); + if (getDerivation(state, *v.listElems()[n], pathPrefix2, drvs, done, ignoreAssertionFailures)) + getDerivations(state, *v.listElems()[n], pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures); } } diff --git a/src/libexpr/json-to-value.cc b/src/libexpr/json-to-value.cc index 1892b0bac1af..0898b560911b 100644 --- a/src/libexpr/json-to-value.cc +++ b/src/libexpr/json-to-value.cc @@ -73,7 +73,7 @@ static void parseJSON(EvalState & state, const char * & s, Value & v) s++; state.mkList(v, values.size()); for (size_t n = 0; n < values.size(); ++n) - v.list.elems[n] = values[n]; + v.listElems()[n] = values[n]; } else if (*s == '{') { diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk index 35e84980a6dd..4c1f4de19187 100644 --- a/src/libexpr/local.mk +++ b/src/libexpr/local.mk @@ -8,7 +8,7 @@ libexpr_SOURCES := $(wildcard $(d)/*.cc) $(d)/lexer-tab.cc $(d)/parser-tab.cc libexpr_LIBS = libutil libstore libformat -libexpr_LDFLAGS = -ldl -lcurl +libexpr_LDFLAGS = -ldl # The dependency on libgc must be propagated (i.e. meaning that # programs/libraries that use libexpr must explicitly pass -lgc), diff --git a/src/libexpr/names.cc b/src/libexpr/names.cc index cda5aa1952ea..7bca9b6550be 100644 --- a/src/libexpr/names.cc +++ b/src/libexpr/names.cc @@ -98,8 +98,8 @@ int compareVersions(const string & v1, const string & v2) DrvNames drvNamesFromArgs(const Strings & opArgs) { DrvNames result; - foreach (Strings::const_iterator, i, opArgs) - result.push_back(DrvName(*i)); + for (auto & i : opArgs) + result.push_back(DrvName(i)); return result; } diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index 43f3161f8baf..35db52a13acc 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -97,21 +97,21 @@ void ExprAttrs::show(std::ostream & str) { if (recursive) str << "rec "; str << "{ "; - foreach (AttrDefs::iterator, i, attrs) - if (i->second.inherited) - str << "inherit " << i->first << " " << "; "; + for (auto & i : attrs) + if (i.second.inherited) + str << "inherit " << i.first << " " << "; "; else - str << i->first << " = " << *i->second.e << "; "; - foreach (DynamicAttrDefs::iterator, i, dynamicAttrs) - str << "\"${" << *i->nameExpr << "}\" = " << *i->valueExpr << "; "; + str << i.first << " = " << *i.second.e << "; "; + for (auto & i : dynamicAttrs) + str << "\"${" << *i.nameExpr << "}\" = " << *i.valueExpr << "; "; str << "}"; } void ExprList::show(std::ostream & str) { str << "[ "; - foreach (vector<Expr *>::iterator, i, elems) - str << "(" << **i << ") "; + for (auto & i : elems) + str << "(" << *i << ") "; str << "]"; } @@ -121,10 +121,10 @@ void ExprLambda::show(std::ostream & str) if (matchAttrs) { str << "{ "; bool first = true; - foreach (Formals::Formals_::iterator, i, formals->formals) { + for (auto & i : formals->formals) { if (first) first = false; else str << ", "; - str << i->name; - if (i->def) str << " ? " << *i->def; + str << i.name; + if (i.def) str << " ? " << *i.def; } if (formals->ellipsis) { if (!first) str << ", "; @@ -140,12 +140,12 @@ void ExprLambda::show(std::ostream & str) void ExprLet::show(std::ostream & str) { str << "(let "; - foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs) - if (i->second.inherited) { - str << "inherit " << i->first << "; "; + for (auto & i : attrs->attrs) + if (i.second.inherited) { + str << "inherit " << i.first << "; "; } else - str << i->first << " = " << *i->second.e << "; "; + str << i.first << " = " << *i.second.e << "; "; str << "in " << *body << ")"; } @@ -173,9 +173,9 @@ void ExprConcatStrings::show(std::ostream & str) { bool first = true; str << "("; - foreach (vector<Expr *>::iterator, i, *es) { + for (auto & i : *es) { if (first) first = false; else str << " + "; - str << **i; + str << *i; } str << ")"; } @@ -267,17 +267,17 @@ void ExprSelect::bindVars(const StaticEnv & env) { e->bindVars(env); if (def) def->bindVars(env); - foreach (AttrPath::iterator, i, attrPath) - if (!i->symbol.set()) - i->expr->bindVars(env); + for (auto & i : attrPath) + if (!i.symbol.set()) + i.expr->bindVars(env); } void ExprOpHasAttr::bindVars(const StaticEnv & env) { e->bindVars(env); - foreach (AttrPath::iterator, i, attrPath) - if (!i->symbol.set()) - i->expr->bindVars(env); + for (auto & i : attrPath) + if (!i.symbol.set()) + i.expr->bindVars(env); } void ExprAttrs::bindVars(const StaticEnv & env) @@ -289,27 +289,27 @@ void ExprAttrs::bindVars(const StaticEnv & env) dynamicEnv = &newEnv; unsigned int displ = 0; - foreach (AttrDefs::iterator, i, attrs) - newEnv.vars[i->first] = i->second.displ = displ++; + for (auto & i : attrs) + newEnv.vars[i.first] = i.second.displ = displ++; - foreach (AttrDefs::iterator, i, attrs) - i->second.e->bindVars(i->second.inherited ? env : newEnv); + for (auto & i : attrs) + i.second.e->bindVars(i.second.inherited ? env : newEnv); } else - foreach (AttrDefs::iterator, i, attrs) - i->second.e->bindVars(env); + for (auto & i : attrs) + i.second.e->bindVars(env); - foreach (DynamicAttrDefs::iterator, i, dynamicAttrs) { - i->nameExpr->bindVars(*dynamicEnv); - i->valueExpr->bindVars(*dynamicEnv); + for (auto & i : dynamicAttrs) { + i.nameExpr->bindVars(*dynamicEnv); + i.valueExpr->bindVars(*dynamicEnv); } } void ExprList::bindVars(const StaticEnv & env) { - foreach (vector<Expr *>::iterator, i, elems) - (*i)->bindVars(env); + for (auto & i : elems) + i->bindVars(env); } void ExprLambda::bindVars(const StaticEnv & env) @@ -321,11 +321,11 @@ void ExprLambda::bindVars(const StaticEnv & env) if (!arg.empty()) newEnv.vars[arg] = displ++; if (matchAttrs) { - foreach (Formals::Formals_::iterator, i, formals->formals) - newEnv.vars[i->name] = displ++; + for (auto & i : formals->formals) + newEnv.vars[i.name] = displ++; - foreach (Formals::Formals_::iterator, i, formals->formals) - if (i->def) i->def->bindVars(newEnv); + for (auto & i : formals->formals) + if (i.def) i.def->bindVars(newEnv); } body->bindVars(newEnv); @@ -336,11 +336,11 @@ void ExprLet::bindVars(const StaticEnv & env) StaticEnv newEnv(false, &env); unsigned int displ = 0; - foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs) - newEnv.vars[i->first] = i->second.displ = displ++; + for (auto & i : attrs->attrs) + newEnv.vars[i.first] = i.second.displ = displ++; - foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs) - i->second.e->bindVars(i->second.inherited ? env : newEnv); + for (auto & i : attrs->attrs) + i.second.e->bindVars(i.second.inherited ? env : newEnv); body->bindVars(newEnv); } @@ -384,8 +384,8 @@ void ExprOpNot::bindVars(const StaticEnv & env) void ExprConcatStrings::bindVars(const StaticEnv & env) { - foreach (vector<Expr *>::iterator, i, *es) - (*i)->bindVars(env); + for (auto & i : *es) + i->bindVars(env); } void ExprPos::bindVars(const StaticEnv & env) @@ -419,8 +419,8 @@ string ExprLambda::showNamePos() const size_t SymbolTable::totalSize() const { size_t n = 0; - foreach (Symbols::const_iterator, i, symbols) - n += i->size(); + for (auto & i : symbols) + n += i.size(); return n; } diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 1f830b7e3c15..d34882f361cf 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -136,8 +136,8 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, vector<Ex bool atStartOfLine = true; /* = seen only whitespace in the current line */ unsigned int minIndent = 1000000; unsigned int curIndent = 0; - foreach (vector<Expr *>::iterator, i, es) { - ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i); + for (auto & i : es) { + ExprIndStr * e = dynamic_cast<ExprIndStr *>(i); if (!e) { /* Anti-quotations end the current start-of-line whitespace. */ if (atStartOfLine) { @@ -419,20 +419,20 @@ binds : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); } | binds INHERIT attrs ';' { $$ = $1; - foreach (AttrPath::iterator, i, *$3) { - if ($$->attrs.find(i->symbol) != $$->attrs.end()) - dupAttr(i->symbol, makeCurPos(@3, data), $$->attrs[i->symbol].pos); + for (auto & i : *$3) { + if ($$->attrs.find(i.symbol) != $$->attrs.end()) + dupAttr(i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos); Pos pos = makeCurPos(@3, data); - $$->attrs[i->symbol] = ExprAttrs::AttrDef(new ExprVar(CUR_POS, i->symbol), pos, true); + $$->attrs[i.symbol] = ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true); } } | binds INHERIT '(' expr ')' attrs ';' { $$ = $1; /* !!! Should ensure sharing of the expression in $4. */ - foreach (AttrPath::iterator, i, *$6) { - if ($$->attrs.find(i->symbol) != $$->attrs.end()) - dupAttr(i->symbol, makeCurPos(@6, data), $$->attrs[i->symbol].pos); - $$->attrs[i->symbol] = ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i->symbol), makeCurPos(@6, data)); + for (auto & i : *$6) { + if ($$->attrs.find(i.symbol) != $$->attrs.end()) + dupAttr(i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos); + $$->attrs[i.symbol] = ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data)); } } | { $$ = new ExprAttrs; } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 355b81adf76d..7a4aad3cd57b 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -86,9 +86,11 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args if (isStorePath(path) && store->isValidPath(path) && isDerivation(path)) { Derivation drv = readDerivation(path); Value & w = *state.allocValue(); - state.mkAttrs(w, 2 + drv.outputs.size()); + state.mkAttrs(w, 3 + drv.outputs.size()); Value * v2 = state.allocAttr(w, state.sDrvPath); mkString(*v2, path, singleton<PathSet>("=" + path)); + v2 = state.allocAttr(w, state.sName); + mkString(*v2, drv.env["name"]); Value * outputsVal = state.allocAttr(w, state.symbols.create("outputs")); state.mkList(*outputsVal, drv.outputs.size()); @@ -98,8 +100,8 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args v2 = state.allocAttr(w, state.symbols.create(o.first)); mkString(*v2, o.second.path, singleton<PathSet>("!" + o.first + "!" + path)); - outputsVal->list.elems[outputs_index] = state.allocValue(); - mkString(*(outputsVal->list.elems[outputs_index++]), o.first); + outputsVal->listElems()[outputs_index] = state.allocValue(); + mkString(*(outputsVal->listElems()[outputs_index++]), o.first); } w.attrs->sort(); Value fun; @@ -186,7 +188,7 @@ static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Valu case tPath: t = "path"; break; case tNull: t = "null"; break; case tAttrs: t = "set"; break; - case tList: t = "list"; break; + case tList1: case tList2: case tListN: t = "list"; break; case tLambda: case tPrimOp: case tPrimOpApp: @@ -282,8 +284,8 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar state.forceList(*startSet->value, pos); ValueList workSet; - for (unsigned int n = 0; n < startSet->value->list.length; ++n) - workSet.push_back(startSet->value->list.elems[n]); + for (unsigned int n = 0; n < startSet->value->listSize(); ++n) + workSet.push_back(startSet->value->listElems()[n]); /* Get the operator. */ Bindings::iterator op = @@ -321,17 +323,17 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar state.forceList(call, pos); /* Add the values returned by the operator to the work set. */ - for (unsigned int n = 0; n < call.list.length; ++n) { - state.forceValue(*call.list.elems[n]); - workSet.push_back(call.list.elems[n]); + for (unsigned int n = 0; n < call.listSize(); ++n) { + state.forceValue(*call.listElems()[n]); + workSet.push_back(call.listElems()[n]); } } /* Create the result list. */ state.mkList(v, res.size()); unsigned int n = 0; - foreach (ValueList::iterator, i, res) - v.list.elems[n++] = *i; + for (auto & i : res) + v.listElems()[n++] = i; } @@ -477,24 +479,24 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * StringSet outputs; outputs.insert("out"); - foreach (Bindings::iterator, i, *args[0]->attrs) { - if (i->name == state.sIgnoreNulls) continue; - string key = i->name; + for (auto & i : *args[0]->attrs) { + if (i.name == state.sIgnoreNulls) continue; + string key = i.name; startNest(nest, lvlVomit, format("processing attribute ‘%1%’") % key); try { if (ignoreNulls) { - state.forceValue(*i->value); - if (i->value->type == tNull) continue; + state.forceValue(*i.value); + if (i.value->type == tNull) continue; } /* The `args' attribute is special: it supplies the command-line arguments to the builder. */ if (key == "args") { - state.forceList(*i->value, pos); - for (unsigned int n = 0; n < i->value->list.length; ++n) { - string s = state.coerceToString(posDrvName, *i->value->list.elems[n], context, true); + state.forceList(*i.value, pos); + for (unsigned int n = 0; n < i.value->listSize(); ++n) { + string s = state.coerceToString(posDrvName, *i.value->listElems()[n], context, true); drv.args.push_back(s); } } @@ -502,11 +504,11 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * /* All other attributes are passed to the builder through the environment. */ else { - string s = state.coerceToString(posDrvName, *i->value, context, true); + string s = state.coerceToString(posDrvName, *i.value, context, true); drv.env[key] = s; if (key == "builder") drv.builder = s; - else if (i->name == state.sSystem) drv.platform = s; - else if (i->name == state.sName) { + else if (i.name == state.sSystem) drv.platform = s; + else if (i.name == state.sName) { drvName = s; printMsg(lvlVomit, format("derivation name is ‘%1%’") % drvName); } @@ -520,17 +522,17 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * else if (key == "outputs") { Strings tmp = tokenizeString<Strings>(s); outputs.clear(); - foreach (Strings::iterator, j, tmp) { - if (outputs.find(*j) != outputs.end()) - throw EvalError(format("duplicate derivation output ‘%1%’, at %2%") % *j % posDrvName); - /* !!! Check whether *j is a valid attribute + for (auto & j : tmp) { + if (outputs.find(j) != outputs.end()) + throw EvalError(format("duplicate derivation output ‘%1%’, at %2%") % j % posDrvName); + /* !!! Check whether j is a valid attribute name. */ /* Derivations cannot be named ‘drv’, because then we'd have an attribute ‘drvPath’ in the resulting set. */ - if (*j == "drv") + if (j == "drv") throw EvalError(format("invalid derivation output name ‘drv’, at %1%") % posDrvName); - outputs.insert(*j); + outputs.insert(j); } if (outputs.empty()) throw EvalError(format("derivation cannot have an empty set of outputs, at %1%") % posDrvName); @@ -547,8 +549,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * /* Everything in the context of the strings in the derivation attributes should be added as dependencies of the resulting derivation. */ - foreach (PathSet::iterator, i, context) { - Path path = *i; + for (auto & path : context) { /* Paths marked with `=' denote that the path of a derivation is explicitly passed to the builder. Since that allows the @@ -560,10 +561,10 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * if (path.at(0) == '=') { /* !!! This doesn't work if readOnlyMode is set. */ PathSet refs; computeFSClosure(*store, string(path, 1), refs); - foreach (PathSet::iterator, j, refs) { - drv.inputSrcs.insert(*j); - if (isDerivation(*j)) - drv.inputDrvs[*j] = store->queryDerivationOutputNames(*j); + for (auto & j : refs) { + drv.inputSrcs.insert(j); + if (isDerivation(j)) + drv.inputDrvs[j] = store->queryDerivationOutputNames(j); } } @@ -622,20 +623,20 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * are empty, and the corresponding environment variables have an empty value. This ensures that changes in the set of output names do get reflected in the hash. */ - foreach (StringSet::iterator, i, outputs) { - drv.env[*i] = ""; - drv.outputs[*i] = DerivationOutput("", "", ""); + for (auto & i : outputs) { + drv.env[i] = ""; + drv.outputs[i] = DerivationOutput("", "", ""); } /* Use the masked derivation expression to compute the output path. */ Hash h = hashDerivationModulo(*store, drv); - foreach (DerivationOutputs::iterator, i, drv.outputs) - if (i->second.path == "") { - Path outPath = makeOutputPath(i->first, h, drvName); - drv.env[i->first] = outPath; - i->second.path = outPath; + for (auto & i : drv.outputs) + if (i.second.path == "") { + Path outPath = makeOutputPath(i.first, h, drvName); + drv.env[i.first] = outPath; + i.second.path = outPath; } } @@ -652,9 +653,9 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * state.mkAttrs(v, 1 + drv.outputs.size()); mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath)); - foreach (DerivationOutputs::iterator, i, drv.outputs) { - mkString(*state.allocAttr(v, state.symbols.create(i->first)), - i->second.path, singleton<PathSet>("!" + i->first + "!" + drvPath)); + for (auto & i : drv.outputs) { + mkString(*state.allocAttr(v, state.symbols.create(i.first)), + i.second.path, singleton<PathSet>("!" + i.first + "!" + drvPath)); } v.attrs->sort(); } @@ -765,8 +766,8 @@ static void prim_findFile(EvalState & state, const Pos & pos, Value * * args, Va SearchPath searchPath; PathSet context; - for (unsigned int n = 0; n < args[0]->list.length; ++n) { - Value & v2(*args[0]->list.elems[n]); + for (unsigned int n = 0; n < args[0]->listSize(); ++n) { + Value & v2(*args[0]->listElems()[n]); state.forceAttrs(v2, pos); string prefix; @@ -871,11 +872,14 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu PathSet refs; - foreach (PathSet::iterator, i, context) { - Path path = *i; + for (auto path : context) { if (path.at(0) == '=') path = string(path, 1); - if (isDerivation(path)) - throw EvalError(format("in ‘toFile’: the file ‘%1%’ cannot refer to derivation outputs, at %2%") % name % pos); + if (isDerivation(path)) { + /* See prim_unsafeDiscardOutputDependency. */ + if (path.at(0) != '~') + throw EvalError(format("in ‘toFile’: the file ‘%1%’ cannot refer to derivation outputs, at %2%") % name % pos); + path = string(path, 1); + } refs.insert(path); } @@ -968,9 +972,9 @@ static void prim_attrNames(EvalState & state, const Pos & pos, Value * * args, V unsigned int n = 0; for (auto & i : *args[0]->attrs) - mkString(*(v.list.elems[n++] = state.allocValue()), i.name); + mkString(*(v.listElems()[n++] = state.allocValue()), i.name); - std::sort(v.list.elems, v.list.elems + n, + std::sort(v.listElems(), v.listElems() + n, [](Value * v1, Value * v2) { return strcmp(v1->string.s, v2->string.s) < 0; }); } @@ -985,13 +989,13 @@ static void prim_attrValues(EvalState & state, const Pos & pos, Value * * args, unsigned int n = 0; for (auto & i : *args[0]->attrs) - v.list.elems[n++] = (Value *) &i; + v.listElems()[n++] = (Value *) &i; - std::sort(v.list.elems, v.list.elems + n, + std::sort(v.listElems(), v.listElems() + n, [](Value * v1, Value * v2) { return (string) ((Attr *) v1)->name < (string) ((Attr *) v2)->name; }); for (unsigned int i = 0; i < n; ++i) - v.list.elems[i] = ((Attr *) v.list.elems[i])->value; + v.listElems()[i] = ((Attr *) v.listElems()[i])->value; } @@ -1048,18 +1052,18 @@ static void prim_removeAttrs(EvalState & state, const Pos & pos, Value * * args, /* Get the attribute names to be removed. */ std::set<Symbol> names; - for (unsigned int i = 0; i < args[1]->list.length; ++i) { - state.forceStringNoCtx(*args[1]->list.elems[i], pos); - names.insert(state.symbols.create(args[1]->list.elems[i]->string.s)); + for (unsigned int i = 0; i < args[1]->listSize(); ++i) { + state.forceStringNoCtx(*args[1]->listElems()[i], pos); + names.insert(state.symbols.create(args[1]->listElems()[i]->string.s)); } /* Copy all attributes not in that set. Note that we don't need to sort v.attrs because it's a subset of an already sorted vector. */ state.mkAttrs(v, args[0]->attrs->size()); - foreach (Bindings::iterator, i, *args[0]->attrs) { - if (names.find(i->name) == names.end()) - v.attrs->push_back(*i); + for (auto & i : *args[0]->attrs) { + if (names.find(i.name) == names.end()) + v.attrs->push_back(i); } } @@ -1073,12 +1077,12 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args, { state.forceList(*args[0], pos); - state.mkAttrs(v, args[0]->list.length); + state.mkAttrs(v, args[0]->listSize()); std::set<Symbol> seen; - for (unsigned int i = 0; i < args[0]->list.length; ++i) { - Value & v2(*args[0]->list.elems[i]); + for (unsigned int i = 0; i < args[0]->listSize(); ++i) { + Value & v2(*args[0]->listElems()[i]); state.forceAttrs(v2, pos); Bindings::iterator j = v2.attrs->find(state.sName); @@ -1111,8 +1115,8 @@ static void prim_intersectAttrs(EvalState & state, const Pos & pos, Value * * ar state.mkAttrs(v, std::min(args[0]->attrs->size(), args[1]->attrs->size())); - foreach (Bindings::iterator, i, *args[0]->attrs) { - Bindings::iterator j = args[1]->attrs->find(i->name); + for (auto & i : *args[0]->attrs) { + Bindings::iterator j = args[1]->attrs->find(i.name); if (j != args[1]->attrs->end()) v.attrs->push_back(*j); } @@ -1131,11 +1135,11 @@ static void prim_catAttrs(EvalState & state, const Pos & pos, Value * * args, Va Symbol attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos)); state.forceList(*args[1], pos); - Value * res[args[1]->list.length]; + Value * res[args[1]->listSize()]; unsigned int found = 0; - for (unsigned int n = 0; n < args[1]->list.length; ++n) { - Value & v2(*args[1]->list.elems[n]); + for (unsigned int n = 0; n < args[1]->listSize(); ++n) { + Value & v2(*args[1]->listElems()[n]); state.forceAttrs(v2, pos); Bindings::iterator i = v2.attrs->find(attrName); if (i != v2.attrs->end()) @@ -1144,7 +1148,7 @@ static void prim_catAttrs(EvalState & state, const Pos & pos, Value * * args, Va state.mkList(v, found); for (unsigned int n = 0; n < found; ++n) - v.list.elems[n] = res[n]; + v.listElems()[n] = res[n]; } @@ -1173,9 +1177,9 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args } state.mkAttrs(v, args[0]->lambda.fun->formals->formals.size()); - foreach (Formals::Formals_::iterator, i, args[0]->lambda.fun->formals->formals) + for (auto & i : args[0]->lambda.fun->formals->formals) // !!! should optimise booleans (allocate only once) - mkBool(*state.allocAttr(v, i->name), i->def); + mkBool(*state.allocAttr(v, i.name), i.def); v.attrs->sort(); } @@ -1189,17 +1193,17 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args static void prim_isList(EvalState & state, const Pos & pos, Value * * args, Value & v) { state.forceValue(*args[0]); - mkBool(v, args[0]->type == tList); + mkBool(v, args[0]->isList()); } static void elemAt(EvalState & state, const Pos & pos, Value & list, int n, Value & v) { state.forceList(list, pos); - if (n < 0 || (unsigned int) n >= list.list.length) + if (n < 0 || (unsigned int) n >= list.listSize()) throw Error(format("list index %1% is out of bounds, at %2%") % n % pos); - state.forceValue(*list.list.elems[n]); - v = *list.list.elems[n]; + state.forceValue(*list.listElems()[n]); + v = *list.listElems()[n]; } @@ -1223,11 +1227,11 @@ static void prim_head(EvalState & state, const Pos & pos, Value * * args, Value static void prim_tail(EvalState & state, const Pos & pos, Value * * args, Value & v) { state.forceList(*args[0], pos); - if (args[0]->list.length == 0) + if (args[0]->listSize() == 0) throw Error(format("‘tail’ called on an empty list, at %1%") % pos); - state.mkList(v, args[0]->list.length - 1); - for (unsigned int n = 0; n < v.list.length; ++n) - v.list.elems[n] = args[0]->list.elems[n + 1]; + state.mkList(v, args[0]->listSize() - 1); + for (unsigned int n = 0; n < v.listSize(); ++n) + v.listElems()[n] = args[0]->listElems()[n + 1]; } @@ -1237,11 +1241,11 @@ static void prim_map(EvalState & state, const Pos & pos, Value * * args, Value & state.forceFunction(*args[0], pos); state.forceList(*args[1], pos); - state.mkList(v, args[1]->list.length); + state.mkList(v, args[1]->listSize()); - for (unsigned int n = 0; n < v.list.length; ++n) - mkApp(*(v.list.elems[n] = state.allocValue()), - *args[0], *args[1]->list.elems[n]); + for (unsigned int n = 0; n < v.listSize(); ++n) + mkApp(*(v.listElems()[n] = state.allocValue()), + *args[0], *args[1]->listElems()[n]); } @@ -1254,15 +1258,15 @@ static void prim_filter(EvalState & state, const Pos & pos, Value * * args, Valu state.forceList(*args[1], pos); // FIXME: putting this on the stack is risky. - Value * vs[args[1]->list.length]; + Value * vs[args[1]->listSize()]; unsigned int k = 0; bool same = true; - for (unsigned int n = 0; n < args[1]->list.length; ++n) { + for (unsigned int n = 0; n < args[1]->listSize(); ++n) { Value res; - state.callFunction(*args[0], *args[1]->list.elems[n], res, noPos); + state.callFunction(*args[0], *args[1]->listElems()[n], res, noPos); if (state.forceBool(res)) - vs[k++] = args[1]->list.elems[n]; + vs[k++] = args[1]->listElems()[n]; else same = false; } @@ -1271,7 +1275,7 @@ static void prim_filter(EvalState & state, const Pos & pos, Value * * args, Valu v = *args[1]; else { state.mkList(v, k); - for (unsigned int n = 0; n < k; ++n) v.list.elems[n] = vs[n]; + for (unsigned int n = 0; n < k; ++n) v.listElems()[n] = vs[n]; } } @@ -1281,8 +1285,8 @@ static void prim_elem(EvalState & state, const Pos & pos, Value * * args, Value { bool res = false; state.forceList(*args[1], pos); - for (unsigned int n = 0; n < args[1]->list.length; ++n) - if (state.eqValues(*args[0], *args[1]->list.elems[n])) { + for (unsigned int n = 0; n < args[1]->listSize(); ++n) + if (state.eqValues(*args[0], *args[1]->listElems()[n])) { res = true; break; } @@ -1294,7 +1298,7 @@ static void prim_elem(EvalState & state, const Pos & pos, Value * * args, Value static void prim_concatLists(EvalState & state, const Pos & pos, Value * * args, Value & v) { state.forceList(*args[0], pos); - state.concatLists(v, args[0]->list.length, args[0]->list.elems, pos); + state.concatLists(v, args[0]->listSize(), args[0]->listElems(), pos); } @@ -1302,7 +1306,61 @@ static void prim_concatLists(EvalState & state, const Pos & pos, Value * * args, static void prim_length(EvalState & state, const Pos & pos, Value * * args, Value & v) { state.forceList(*args[0], pos); - mkInt(v, args[0]->list.length); + mkInt(v, args[0]->listSize()); +} + + +/* Reduce a list by applying a binary operator, from left to + right. The operator is applied strictly. */ +static void prim_foldlStrict(EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + state.forceFunction(*args[0], pos); + state.forceList(*args[2], pos); + + Value * vCur = args[1]; + + if (args[2]->listSize()) + for (unsigned int n = 0; n < args[2]->listSize(); ++n) { + Value vTmp; + state.callFunction(*args[0], *vCur, vTmp, pos); + vCur = n == args[2]->listSize() - 1 ? &v : state.allocValue(); + state.callFunction(vTmp, *args[2]->listElems()[n], *vCur, pos); + } + else + v = *vCur; + + state.forceValue(v); +} + + +static void anyOrAll(bool any, EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + state.forceFunction(*args[0], pos); + state.forceList(*args[1], pos); + + Value vTmp; + for (unsigned int n = 0; n < args[1]->listSize(); ++n) { + state.callFunction(*args[0], *args[1]->listElems()[n], vTmp, pos); + bool res = state.forceBool(vTmp); + if (res == any) { + mkBool(v, any); + return; + } + } + + mkBool(v, !any); +} + + +static void prim_any(EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + anyOrAll(true, state, pos, args, v); +} + + +static void prim_all(EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + anyOrAll(false, state, pos, args, v); } @@ -1407,11 +1465,8 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & po string s = state.coerceToString(pos, *args[0], context); PathSet context2; - foreach (PathSet::iterator, i, context) { - Path p = *i; - if (p.at(0) == '=') p = "~" + string(p, 1); - context2.insert(p); - } + for (auto & p : context) + context2.insert(p.at(0) == '=' ? "~" + string(p, 1) : p); mkString(v, s, context2); } @@ -1452,9 +1507,9 @@ static void prim_match(EvalState & state, const Pos & pos, Value * * args, Value for (unsigned int n = 0; n < len; ++n) { auto i = subs.find(n); if (i == subs.end()) - mkNull(*(v.list.elems[n] = state.allocValue())); + mkNull(*(v.listElems()[n] = state.allocValue())); else - mkString(*(v.list.elems[n] = state.allocValue()), i->second); + mkString(*(v.listElems()[n] = state.allocValue()), i->second); } } @@ -1646,6 +1701,9 @@ void EvalState::createBaseEnv() addPrimOp("__elem", 2, prim_elem); addPrimOp("__concatLists", 1, prim_concatLists); addPrimOp("__length", 1, prim_length); + addPrimOp("__foldl'", 3, prim_foldlStrict); + addPrimOp("__any", 2, prim_any); + addPrimOp("__all", 2, prim_all); // Integer arithmetic addPrimOp("__add", 2, prim_add); @@ -1685,7 +1743,7 @@ void EvalState::createBaseEnv() mkList(v, searchPath.size()); int n = 0; for (auto & i : searchPath) { - v2 = v.list.elems[n++] = allocValue(); + v2 = v.listElems()[n++] = allocValue(); mkAttrs(*v2, 2); mkString(*allocAttr(*v2, symbols.create("path")), i.second); mkString(*allocAttr(*v2, symbols.create("prefix")), i.first); diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc index cdb71341875a..b0cf85e21f18 100644 --- a/src/libexpr/value-to-json.cc +++ b/src/libexpr/value-to-json.cc @@ -12,14 +12,14 @@ namespace nix { void escapeJSON(std::ostream & str, const string & s) { str << "\""; - foreach (string::const_iterator, i, s) - if (*i == '\"' || *i == '\\') str << "\\" << *i; - else if (*i == '\n') str << "\\n"; - else if (*i == '\r') str << "\\r"; - else if (*i == '\t') str << "\\t"; - else if (*i >= 0 && *i < 32) - str << "\\u" << std::setfill('0') << std::setw(4) << std::hex << (uint16_t) *i << std::dec; - else str << *i; + for (auto & i : s) + if (i == '\"' || i == '\\') str << "\\" << i; + else if (i == '\n') str << "\\n"; + else if (i == '\r') str << "\\r"; + else if (i == '\t') str << "\\t"; + else if (i >= 0 && i < 32) + str << "\\u" << std::setfill('0') << std::setw(4) << std::hex << (uint16_t) i << std::dec; + else str << i; str << "\""; } @@ -59,11 +59,11 @@ void printValueAsJSON(EvalState & state, bool strict, if (i == v.attrs->end()) { JSONObject json(str); StringSet names; - foreach (Bindings::iterator, i, *v.attrs) - names.insert(i->name); - foreach (StringSet::iterator, i, names) { - Attr & a(*v.attrs->find(state.symbols.create(*i))); - json.attr(*i); + for (auto & j : *v.attrs) + names.insert(j.name); + for (auto & j : names) { + Attr & a(*v.attrs->find(state.symbols.create(j))); + json.attr(j); printValueAsJSON(state, strict, *a.value, str, context); } } else @@ -71,16 +71,16 @@ void printValueAsJSON(EvalState & state, bool strict, break; } - case tList: { + case tList1: case tList2: case tListN: { JSONList json(str); - for (unsigned int n = 0; n < v.list.length; ++n) { + for (unsigned int n = 0; n < v.listSize(); ++n) { json.elem(); - printValueAsJSON(state, strict, *v.list.elems[n], str, context); + printValueAsJSON(state, strict, *v.listElems()[n], str, context); } break; } - case tExternal: + case tExternal: v.external->printValueAsJSON(state, strict, str, context); break; diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc index bbbb7039bf70..cb52ce1e67bd 100644 --- a/src/libexpr/value-to-xml.cc +++ b/src/libexpr/value-to-xml.cc @@ -8,7 +8,7 @@ namespace nix { - + static XMLAttrs singletonAttrs(const string & name, const string & value) { XMLAttrs attrs; @@ -33,17 +33,17 @@ static void showAttrs(EvalState & state, bool strict, bool location, Bindings & attrs, XMLWriter & doc, PathSet & context, PathSet & drvsSeen) { StringSet names; - - foreach (Bindings::iterator, i, attrs) - names.insert(i->name); - - foreach (StringSet::iterator, i, names) { - Attr & a(*attrs.find(state.symbols.create(*i))); - + + for (auto & i : attrs) + names.insert(i.name); + + for (auto & i : names) { + Attr & a(*attrs.find(state.symbols.create(i))); + XMLAttrs xmlAttrs; - xmlAttrs["name"] = *i; + xmlAttrs["name"] = i; if (location && a.pos != &noPos) posToXML(xmlAttrs, *a.pos); - + XMLOpenElement _(doc, "attr", xmlAttrs); printValueAsXML(state, strict, location, *a.value, doc, context, drvsSeen); @@ -57,7 +57,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location, checkInterrupt(); if (strict) state.forceValue(v); - + switch (v.type) { case tInt: @@ -85,7 +85,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location, case tAttrs: if (state.isDerivation(v)) { XMLAttrs xmlAttrs; - + Bindings::iterator a = v.attrs->find(state.symbols.create("derivation")); Path drvPath; @@ -95,7 +95,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location, if (a->value->type == tString) xmlAttrs["drvPath"] = drvPath = a->value->string.s; } - + a = v.attrs->find(state.sOutPath); if (a != v.attrs->end()) { if (strict) state.forceValue(*a->value); @@ -116,13 +116,13 @@ static void printValueAsXML(EvalState & state, bool strict, bool location, XMLOpenElement _(doc, "attrs"); showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen); } - + break; - case tList: { + case tList1: case tList2: case tListN: { XMLOpenElement _(doc, "list"); - for (unsigned int n = 0; n < v.list.length; ++n) - printValueAsXML(state, strict, location, *v.list.elems[n], doc, context, drvsSeen); + for (unsigned int n = 0; n < v.listSize(); ++n) + printValueAsXML(state, strict, location, *v.listElems()[n], doc, context, drvsSeen); break; } @@ -130,17 +130,17 @@ static void printValueAsXML(EvalState & state, bool strict, bool location, XMLAttrs xmlAttrs; if (location) posToXML(xmlAttrs, v.lambda.fun->pos); XMLOpenElement _(doc, "function", xmlAttrs); - + if (v.lambda.fun->matchAttrs) { XMLAttrs attrs; if (!v.lambda.fun->arg.empty()) attrs["name"] = v.lambda.fun->arg; if (v.lambda.fun->formals->ellipsis) attrs["ellipsis"] = "1"; XMLOpenElement _(doc, "attrspat", attrs); - foreach (Formals::Formals_::iterator, i, v.lambda.fun->formals->formals) - doc.writeEmptyElement("attr", singletonAttrs("name", i->name)); + for (auto & i : v.lambda.fun->formals->formals) + doc.writeEmptyElement("attr", singletonAttrs("name", i.name)); } else doc.writeEmptyElement("varpat", singletonAttrs("name", v.lambda.fun->arg)); - + break; } @@ -166,9 +166,9 @@ void printValueAsXML(EvalState & state, bool strict, bool location, { XMLWriter doc(true, out); XMLOpenElement root(doc, "expr"); - PathSet drvsSeen; + PathSet drvsSeen; printValueAsXML(state, strict, location, v, doc, context, drvsSeen); } - + } diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh index c06b5a6d1153..e6d1502cb607 100644 --- a/src/libexpr/value.hh +++ b/src/libexpr/value.hh @@ -12,7 +12,9 @@ typedef enum { tPath, tNull, tAttrs, - tList, + tList1, + tList2, + tListN, tThunk, tApp, tLambda, @@ -119,9 +121,10 @@ struct Value const char * path; Bindings * attrs; struct { - unsigned int length; + unsigned int size; Value * * elems; - } list; + } bigList; + Value * smallList[2]; struct { Env * env; Expr * expr; @@ -139,6 +142,26 @@ struct Value } primOpApp; ExternalValueBase * external; }; + + bool isList() const + { + return type == tList1 || type == tList2 || type == tListN; + } + + Value * * listElems() + { + return type == tList1 || type == tList2 ? smallList : bigList.elems; + } + + const Value * const * listElems() const + { + return type == tList1 || type == tList2 ? smallList : bigList.elems; + } + + unsigned int listSize() const + { + return type == tList1 ? 1 : type == tList2 ? 2 : bigList.size; + } }; |