diff options
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 171 |
1 files changed, 93 insertions, 78 deletions
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: |