* Use the new ATermMap.

This commit is contained in:
Eelco Dolstra 2006-05-04 12:21:08 +00:00
parent 9840368cad
commit 0832956089
10 changed files with 194 additions and 336 deletions

View File

@ -4,7 +4,7 @@
EvalState::EvalState() EvalState::EvalState()
: normalForms(32768, 50) : normalForms(32768), primOps(128)
{ {
nrEvaluated = nrCached = 0; nrEvaluated = nrCached = 0;
@ -17,7 +17,7 @@ EvalState::EvalState()
void EvalState::addPrimOp(const string & name, void EvalState::addPrimOp(const string & name,
unsigned int arity, PrimOp primOp) unsigned int arity, PrimOp primOp)
{ {
primOps.set(name, makePrimOpDef(arity, ATmakeBlob(0, (void *) primOp))); primOps.set(toATerm(name), makePrimOpDef(arity, ATmakeBlob(0, (void *) primOp)));
} }
@ -25,7 +25,6 @@ void EvalState::addPrimOp(const string & name,
static Expr substArgs(Expr body, ATermList formals, Expr arg) static Expr substArgs(Expr body, ATermList formals, Expr arg)
{ {
ATermMap subs(ATgetLength(formals) * 2); ATermMap subs(ATgetLength(formals) * 2);
Expr undefined = makeUndefined();
/* ({x ? E1; y ? E2, z}: E3) {x = E4; z = E5;} /* ({x ? E1; y ? E2, z}: E3) {x = E4; z = E5;}
@ -44,7 +43,7 @@ static Expr substArgs(Expr body, ATermList formals, Expr arg)
for (ATermIterator i(formals); i; ++i) { for (ATermIterator i(formals); i; ++i) {
Expr name, def; Expr name, def;
if (matchNoDefFormal(*i, name)) if (matchNoDefFormal(*i, name))
subs.set(name, undefined); subs.set(name, makeUndefined());
else if (matchDefFormal(*i, name, def)) else if (matchDefFormal(*i, name, def))
subs.set(name, def); subs.set(name, def);
else abort(); /* can't happen */ else abort(); /* can't happen */
@ -52,22 +51,21 @@ static Expr substArgs(Expr body, ATermList formals, Expr arg)
/* Get the actual arguments, and check that they match with the /* Get the actual arguments, and check that they match with the
formals. */ formals. */
ATermMap args; ATermMap args(128); /* !!! fix */
queryAllAttrs(arg, args); queryAllAttrs(arg, args);
for (ATermIterator i(args.keys()); i; ++i) { for (ATermMap::const_iterator i = args.begin(); i != args.end(); ++i) {
Expr key = *i; Expr cur = subs.get(i->key);
Expr cur = subs.get(key); if (!subs.get(i->key))
if (!cur)
throw Error(format("unexpected function argument `%1%'") throw Error(format("unexpected function argument `%1%'")
% aterm2String(key)); % aterm2String(i->key));
subs.set(key, args.get(key)); subs.set(i->key, i->value);
} }
/* Check that all arguments are defined. */ /* Check that all arguments are defined. */
for (ATermIterator i(subs.keys()); i; ++i) for (ATermMap::const_iterator i = subs.begin(); i != subs.end(); ++i)
if (subs.get(*i) == undefined) if (i->value == makeUndefined())
throw Error(format("required function argument `%1%' missing") throw Error(format("required function argument `%1%' missing")
% aterm2String(*i)); % aterm2String(i->key));
return substitute(Substitution(0, &subs), body); return substitute(Substitution(0, &subs), body);
} }
@ -85,7 +83,7 @@ ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds)
Pos pos; Pos pos;
/* Create the substitution list. */ /* Create the substitution list. */
ATermMap subs; ATermMap subs(ATgetLength(rbnds) + ATgetLength(nrbnds));
for (ATermIterator i(rbnds); i; ++i) { for (ATermIterator i(rbnds); i; ++i) {
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
subs.set(name, makeSelect(e, name)); subs.set(name, makeSelect(e, name));
@ -98,7 +96,7 @@ ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds)
Substitution subs_(0, &subs); Substitution subs_(0, &subs);
/* Create the non-recursive set. */ /* Create the non-recursive set. */
ATermMap as; ATermMap as(ATgetLength(rbnds) + ATgetLength(nrbnds));
for (ATermIterator i(rbnds); i; ++i) { for (ATermIterator i(rbnds); i; ++i) {
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
as.set(name, makeAttrRHS(substitute(subs_, e2), pos)); as.set(name, makeAttrRHS(substitute(subs_, e2), pos));
@ -118,7 +116,7 @@ static Expr updateAttrs(Expr e1, Expr e2)
{ {
/* Note: e1 and e2 should be in normal form. */ /* Note: e1 and e2 should be in normal form. */
ATermMap attrs; ATermMap attrs(128); /* !!! */
queryAllAttrs(e1, attrs, true); queryAllAttrs(e1, attrs, true);
queryAllAttrs(e2, attrs, true); queryAllAttrs(e2, attrs, true);
@ -217,12 +215,12 @@ string coerceToStringWithContext(EvalState & state,
} }
if (matchAttrs(e, es)) { if (matchAttrs(e, es)) {
ATermMap attrs; ATermMap attrs(128); /* !!! */
queryAllAttrs(e, attrs, false); queryAllAttrs(e, attrs, false);
Expr a = attrs.get("type"); Expr a = attrs.get(toATerm("type"));
if (a && evalString(state, a) == "derivation") { if (a && evalString(state, a) == "derivation") {
a = attrs.get("outPath"); a = attrs.get(toATerm("outPath"));
if (!a) throw Error("output path missing from derivation"); if (!a) throw Error("output path missing from derivation");
context = ATinsert(context, e); context = ATinsert(context, e);
return evalPath(state, a); return evalPath(state, a);
@ -342,7 +340,7 @@ Expr evalExpr2(EvalState & state, Expr e)
else if (matchFunction1(e1, name, e4, pos)) { else if (matchFunction1(e1, name, e4, pos)) {
try { try {
ATermMap subs; ATermMap subs(1);
subs.set(name, e2); subs.set(name, e2);
return evalExpr(state, substitute(Substitution(0, &subs), e4)); return evalExpr(state, substitute(Substitution(0, &subs), e4));
} catch (Error & e) { } catch (Error & e) {
@ -392,7 +390,7 @@ Expr evalExpr2(EvalState & state, Expr e)
/* Withs. */ /* Withs. */
if (matchWith(e, e1, e2, pos)) { if (matchWith(e, e1, e2, pos)) {
ATermMap attrs; ATermMap attrs(128); /* !!! */
try { try {
e1 = evalExpr(state, e1); e1 = evalExpr(state, e1);
queryAllAttrs(e1, attrs); queryAllAttrs(e1, attrs);
@ -442,7 +440,7 @@ Expr evalExpr2(EvalState & state, Expr e)
/* Attribute existence test (?). */ /* Attribute existence test (?). */
if (matchOpHasAttr(e, e1, name)) { if (matchOpHasAttr(e, e1, name)) {
ATermMap attrs; ATermMap attrs(128); /* !!! */
queryAllAttrs(evalExpr(state, e1), attrs); queryAllAttrs(evalExpr(state, e1), attrs);
return makeBool(attrs.get(name) != 0); return makeBool(attrs.get(name) != 0);
} }

View File

@ -5,7 +5,7 @@
string DrvInfo::queryDrvPath(EvalState & state) const string DrvInfo::queryDrvPath(EvalState & state) const
{ {
if (drvPath == "") { if (drvPath == "") {
Expr a = attrs->get("drvPath"); Expr a = attrs->get(toATerm("drvPath"));
(string &) drvPath = a ? evalPath(state, a) : ""; (string &) drvPath = a ? evalPath(state, a) : "";
} }
return drvPath; return drvPath;
@ -15,7 +15,7 @@ string DrvInfo::queryDrvPath(EvalState & state) const
string DrvInfo::queryOutPath(EvalState & state) const string DrvInfo::queryOutPath(EvalState & state) const
{ {
if (outPath == "") { if (outPath == "") {
Expr a = attrs->get("outPath"); Expr a = attrs->get(toATerm("outPath"));
if (!a) throw Error("output path missing"); if (!a) throw Error("output path missing");
(string &) outPath = evalPath(state, a); (string &) outPath = evalPath(state, a);
} }
@ -27,16 +27,16 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
{ {
MetaInfo meta; MetaInfo meta;
Expr a = attrs->get("meta"); Expr a = attrs->get(toATerm("meta"));
if (!a) return meta; /* fine, empty meta information */ if (!a) return meta; /* fine, empty meta information */
ATermMap attrs2; ATermMap attrs2(16); /* !!! */
queryAllAttrs(evalExpr(state, a), attrs2); queryAllAttrs(evalExpr(state, a), attrs2);
for (ATermIterator i(attrs2.keys()); i; ++i) { for (ATermMap::const_iterator i = attrs2.begin(); i != attrs2.end(); ++i) {
ATerm s = coerceToString(evalExpr(state, attrs2.get(*i))); ATerm s = coerceToString(evalExpr(state, i->value));
if (s) if (s)
meta[aterm2String(*i)] = aterm2String(s); meta[aterm2String(i->key)] = aterm2String(s);
/* For future compatibility, ignore attribute values that are /* For future compatibility, ignore attribute values that are
not strings. */ not strings. */
} }
@ -66,10 +66,10 @@ static bool getDerivation(EvalState & state, Expr e,
e = evalExpr(state, e); e = evalExpr(state, e);
if (!matchAttrs(e, es)) return true; if (!matchAttrs(e, es)) return true;
shared_ptr<ATermMap> attrs(new ATermMap()); shared_ptr<ATermMap> attrs(new ATermMap(32)); /* !!! */
queryAllAttrs(e, *attrs, false); queryAllAttrs(e, *attrs, false);
Expr a = attrs->get("type"); Expr a = attrs->get(toATerm("type"));
if (!a || evalString(state, a) != "derivation") return true; if (!a || evalString(state, a) != "derivation") return true;
/* Remove spurious duplicates (e.g., an attribute set like /* Remove spurious duplicates (e.g., an attribute set like
@ -79,11 +79,11 @@ static bool getDerivation(EvalState & state, Expr e,
DrvInfo drv; DrvInfo drv;
a = attrs->get("name"); a = attrs->get(toATerm("name"));
if (!a) throw badTerm("derivation name missing", e); if (!a) throw badTerm("derivation name missing", e);
drv.name = evalString(state, a); drv.name = evalString(state, a);
a = attrs->get("system"); a = attrs->get(toATerm("system"));
if (!a) if (!a)
drv.system = "unknown"; drv.system = "unknown";
else else
@ -128,7 +128,7 @@ static void getDerivations(EvalState & state, Expr e,
abort(); /* can't happen */ abort(); /* can't happen */
} }
getDerivations(state, getDerivations(state,
makeCall(e, makeAttrs(ATermMap())), makeCall(e, makeAttrs(ATermMap(0))),
drvs, doneExprs, attrPath); drvs, doneExprs, attrPath);
return; return;
} }
@ -169,30 +169,30 @@ static void getDerivations(EvalState & state, Expr e,
if (matchAttrs(e, es)) { if (matchAttrs(e, es)) {
if (apType != apNone && apType != apAttr) throw attrError; if (apType != apNone && apType != apAttr) throw attrError;
ATermMap drvMap; ATermMap drvMap(ATgetLength(es));
queryAllAttrs(e, drvMap); queryAllAttrs(e, drvMap);
if (apType == apNone) { if (apType == apNone) {
for (ATermIterator i(drvMap.keys()); i; ++i) { for (ATermMap::const_iterator i = drvMap.begin(); i != drvMap.end(); ++i) {
startNest(nest, lvlDebug, startNest(nest, lvlDebug,
format("evaluating attribute `%1%'") % aterm2String(*i)); format("evaluating attribute `%1%'") % aterm2String(i->key));
if (getDerivation(state, drvMap.get(*i), drvs, doneExprs)) { if (getDerivation(state, i->value, drvs, doneExprs)) {
/* If the value of this attribute is itself an /* If the value of this attribute is itself an
attribute set, should we recurse into it? attribute set, should we recurse into it?
=> Only if it has a `recurseForDerivations = true' => Only if it has a `recurseForDerivations = true'
attribute. */ attribute. */
ATermList es; ATermList es;
Expr e = evalExpr(state, drvMap.get(*i)); Expr e = evalExpr(state, i->value);
if (matchAttrs(e, es)) { if (matchAttrs(e, es)) {
ATermMap attrs; ATermMap attrs(ATgetLength(es));
queryAllAttrs(e, attrs, false); queryAllAttrs(e, attrs, false);
if (attrs.get("recurseForDerivations") && Expr e2 = attrs.get(toATerm("recurseForDerivations"));
evalBool(state, attrs.get("recurseForDerivations"))) if (e2 && evalBool(state, e2))
getDerivations(state, e, drvs, doneExprs, attrPathRest); getDerivations(state, e, drvs, doneExprs, attrPathRest);
} }
} }
} }
} else { } else {
Expr e2 = drvMap.get(attr); Expr e2 = drvMap.get(toATerm(attr));
if (!e2) throw Error(format("attribute `%1%' in selection path not found") % attr); if (!e2) throw Error(format("attribute `%1%' in selection path not found") % attr);
startNest(nest, lvlDebug, startNest(nest, lvlDebug,
format("evaluating attribute `%1%'") % attr); format("evaluating attribute `%1%'") % attr);

View File

@ -6,124 +6,6 @@
#include "nixexpr-ast.cc" #include "nixexpr-ast.cc"
ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct)
: table(0)
{
this->maxLoadPct = maxLoadPct;
table = ATtableCreate(initialSize, maxLoadPct);
if (!table) throw Error("cannot create ATerm table");
}
ATermMap::ATermMap(const ATermMap & map)
: table(0)
{
copy(map);
}
ATermMap::~ATermMap()
{
free();
}
ATermMap & ATermMap::operator = (const ATermMap & map)
{
if (this == &map) return *this;
free();
copy(map);
return *this;
}
void ATermMap::free()
{
if (table) {
ATtableDestroy(table);
table = 0;
}
}
void ATermMap::copy(const ATermMap & map)
{
ATermList keys = map.keys();
/* !!! We adjust for the maximum load pct by allocating twice as
much. Probably a bit too much. */
maxLoadPct = map.maxLoadPct;
table = ATtableCreate(ATgetLength(keys) * 2, maxLoadPct);
if (!table) throw Error("cannot create ATerm table");
add(map, keys);
}
void ATermMap::set(ATerm key, ATerm value)
{
return ATtablePut(table, key, value);
}
void ATermMap::set(const string & key, ATerm value)
{
set(toATerm(key), value);
}
ATerm ATermMap::get(ATerm key) const
{
return ATtableGet(table, key);
}
ATerm ATermMap::get(const string & key) const
{
return get(toATerm(key));
}
void ATermMap::remove(ATerm key)
{
ATtableRemove(table, key);
}
void ATermMap::remove(const string & key)
{
remove(toATerm(key));
}
ATermList ATermMap::keys() const
{
ATermList keys = ATtableKeys(table);
if (!keys) throw Error("cannot query aterm map keys");
return keys;
}
void ATermMap::add(const ATermMap & map)
{
ATermList keys = map.keys();
add(map, keys);
}
void ATermMap::add(const ATermMap & map, ATermList & keys)
{
for (ATermIterator i(keys); i; ++i)
set(*i, map.get(*i));
}
void ATermMap::reset()
{
ATtableReset(table);
}
string showPos(ATerm pos) string showPos(ATerm pos)
{ {
ATerm path; ATerm path;
@ -211,12 +93,12 @@ Expr queryAttr(Expr e, const string & name, ATerm & pos)
Expr makeAttrs(const ATermMap & attrs) Expr makeAttrs(const ATermMap & attrs)
{ {
ATermList bnds = ATempty; ATermList bnds = ATempty;
for (ATermIterator i(attrs.keys()); i; ++i) { for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
Expr e; Expr e;
ATerm pos; ATerm pos;
if (!matchAttrRHS(attrs.get(*i), e, pos)) if (!matchAttrRHS(i->value, e, pos))
abort(); /* can't happen */ abort(); /* can't happen */
bnds = ATinsert(bnds, makeBind(*i, e, pos)); bnds = ATinsert(bnds, makeBind(i->key, e, pos));
} }
return makeAttrs(bnds); return makeAttrs(bnds);
} }
@ -250,7 +132,7 @@ Expr substitute(const Substitution & subs, Expr e)
ATermList formals; ATermList formals;
ATerm body, def; ATerm body, def;
if (matchFunction(e, formals, body, pos)) { if (matchFunction(e, formals, body, pos)) {
ATermMap map; ATermMap map(ATgetLength(formals));
for (ATermIterator i(formals); i; ++i) { for (ATermIterator i(formals); i; ++i) {
if (!matchNoDefFormal(*i, name) && if (!matchNoDefFormal(*i, name) &&
!matchDefFormal(*i, name, def)) !matchDefFormal(*i, name, def))
@ -264,7 +146,7 @@ Expr substitute(const Substitution & subs, Expr e)
} }
if (matchFunction1(e, name, body, pos)) { if (matchFunction1(e, name, body, pos)) {
ATermMap map; ATermMap map(1);
map.set(name, makeRemoved()); map.set(name, makeRemoved());
return makeFunction1(name, substitute(Substitution(&subs, &map), body), pos); return makeFunction1(name, substitute(Substitution(&subs, &map), body), pos);
} }
@ -272,7 +154,7 @@ Expr substitute(const Substitution & subs, Expr e)
/* Idem for a mutually recursive attribute set. */ /* Idem for a mutually recursive attribute set. */
ATermList rbnds, nrbnds; ATermList rbnds, nrbnds;
if (matchRec(e, rbnds, nrbnds)) { if (matchRec(e, rbnds, nrbnds)) {
ATermMap map; ATermMap map(ATgetLength(rbnds) + ATgetLength(nrbnds));
for (ATermIterator i(rbnds); i; ++i) for (ATermIterator i(rbnds); i; ++i)
if (matchBind(*i, name, e2, pos)) map.set(name, makeRemoved()); if (matchBind(*i, name, e2, pos)) map.set(name, makeRemoved());
else abort(); /* can't happen */ else abort(); /* can't happen */

View File

@ -5,6 +5,7 @@
#include <aterm2.h> #include <aterm2.h>
#include "aterm-map.hh"
#include "util.hh" #include "util.hh"
@ -16,44 +17,6 @@ typedef ATerm Expr;
typedef ATerm Pos; typedef ATerm Pos;
/* Mappings from ATerms to ATerms. This is just a wrapper around
ATerm tables. */
class ATermMap
{
private:
unsigned int maxLoadPct;
ATermTable table;
public:
ATermMap(unsigned int initialSize = 64, unsigned int maxLoadPct = 75);
ATermMap(const ATermMap & map);
~ATermMap();
ATermMap & operator = (const ATermMap & map);
void set(ATerm key, ATerm value);
void set(const string & key, ATerm value);
ATerm get(ATerm key) const;
ATerm get(const string & key) const;
void remove(ATerm key);
void remove(const string & key);
ATermList keys() const;
void add(const ATermMap & map);
void reset();
private:
void add(const ATermMap & map, ATermList & keys);
void free();
void copy(const ATermMap & map);
};
/* A STL vector of ATerms. Should be used with great care since it's /* A STL vector of ATerms. Should be used with great care since it's
stored on the heap, and the elements are therefore not roots to the stored on the heap, and the elements are therefore not roots to the
ATerm garbage collector. */ ATerm garbage collector. */

View File

@ -115,7 +115,7 @@ static void checkAttrSets(ATerm e)
ATermList formals; ATermList formals;
ATerm body, pos; ATerm body, pos;
if (matchFunction(e, formals, body, pos)) { if (matchFunction(e, formals, body, pos)) {
ATermMap names; ATermMap names(ATgetLength(formals));
for (ATermIterator i(formals); i; ++i) { for (ATermIterator i(formals); i; ++i) {
ATerm name; ATerm name;
Expr deflt; Expr deflt;
@ -131,13 +131,13 @@ static void checkAttrSets(ATerm e)
ATermList bnds; ATermList bnds;
if (matchAttrs(e, bnds)) { if (matchAttrs(e, bnds)) {
ATermMap names; ATermMap names(ATgetLength(bnds));
checkAttrs(names, bnds); checkAttrs(names, bnds);
} }
ATermList rbnds, nrbnds; ATermList rbnds, nrbnds;
if (matchRec(e, rbnds, nrbnds)) { if (matchRec(e, rbnds, nrbnds)) {
ATermMap names; ATermMap names(ATgetLength(rbnds) + ATgetLength(nrbnds));
checkAttrs(names, rbnds); checkAttrs(names, rbnds);
checkAttrs(names, nrbnds); checkAttrs(names, nrbnds);
} }

View File

@ -234,11 +234,11 @@ static Expr primDerivationStrict(EvalState & state, const ATermVector & args)
{ {
startNest(nest, lvlVomit, "evaluating derivation"); startNest(nest, lvlVomit, "evaluating derivation");
ATermMap attrs; ATermMap attrs(128); /* !!! */
queryAllAttrs(evalExpr(state, args[0]), attrs, true); queryAllAttrs(evalExpr(state, args[0]), attrs, true);
/* Figure out the name already (for stack backtraces). */ /* Figure out the name already (for stack backtraces). */
Expr eDrvName = attrs.get("name"); Expr eDrvName = attrs.get(toATerm("name"));
if (!eDrvName) if (!eDrvName)
throw Error("required attribute `name' missing"); throw Error("required attribute `name' missing");
ATerm posDrvName; ATerm posDrvName;
@ -252,11 +252,11 @@ static Expr primDerivationStrict(EvalState & state, const ATermVector & args)
string outputHashAlgo; string outputHashAlgo;
bool outputHashRecursive = false; bool outputHashRecursive = false;
for (ATermIterator i(attrs.keys()); i; ++i) { for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) {
string key = aterm2String(*i); string key = aterm2String(i->key);
ATerm value; ATerm value;
Expr pos; Expr pos;
ATerm rhs = attrs.get(key); ATerm rhs = i->value;
if (!matchAttrRHS(rhs, value, pos)) abort(); if (!matchAttrRHS(rhs, value, pos)) abort();
startNest(nest, lvlVomit, format("processing attribute `%1%'") % key); startNest(nest, lvlVomit, format("processing attribute `%1%'") % key);
@ -363,9 +363,11 @@ static Expr primDerivationStrict(EvalState & state, const ATermVector & args)
state.drvHashes[drvPath] = hashDerivationModulo(state, drv); state.drvHashes[drvPath] = hashDerivationModulo(state, drv);
/* !!! assumes a single output */ /* !!! assumes a single output */
ATermMap outAttrs; ATermMap outAttrs(2);
outAttrs.set("outPath", makeAttrRHS(makePath(toATerm(outPath)), makeNoPos())); outAttrs.set(toATerm("outPath"),
outAttrs.set("drvPath", makeAttrRHS(makePath(toATerm(drvPath)), makeNoPos())); makeAttrRHS(makePath(toATerm(outPath)), makeNoPos()));
outAttrs.set(toATerm("drvPath"),
makeAttrRHS(makePath(toATerm(drvPath)), makeNoPos()));
return makeAttrs(outAttrs); return makeAttrs(outAttrs);
} }
@ -374,15 +376,18 @@ static Expr primDerivationStrict(EvalState & state, const ATermVector & args)
static Expr primDerivationLazy(EvalState & state, const ATermVector & args) static Expr primDerivationLazy(EvalState & state, const ATermVector & args)
{ {
Expr eAttrs = evalExpr(state, args[0]); Expr eAttrs = evalExpr(state, args[0]);
ATermMap attrs; ATermMap attrs(128); /* !!! */
queryAllAttrs(eAttrs, attrs, true); queryAllAttrs(eAttrs, attrs, true);
attrs.set("type", makeAttrRHS(makeStr(toATerm("derivation")), makeNoPos())); attrs.set(toATerm("type"),
makeAttrRHS(makeStr(toATerm("derivation")), makeNoPos()));
Expr drvStrict = makeCall(makeVar(toATerm("derivation!")), eAttrs); Expr drvStrict = makeCall(makeVar(toATerm("derivation!")), eAttrs);
attrs.set("outPath", makeAttrRHS(makeSelect(drvStrict, toATerm("outPath")), makeNoPos())); attrs.set(toATerm("outPath"),
attrs.set("drvPath", makeAttrRHS(makeSelect(drvStrict, toATerm("drvPath")), makeNoPos())); makeAttrRHS(makeSelect(drvStrict, toATerm("outPath")), makeNoPos()));
attrs.set(toATerm("drvPath"),
makeAttrRHS(makeSelect(drvStrict, toATerm("drvPath")), makeNoPos()));
return makeAttrs(attrs); return makeAttrs(attrs);
} }
@ -627,14 +632,14 @@ static Expr primCurrentTime(EvalState & state, const ATermVector & args)
static Expr primRemoveAttrs(EvalState & state, const ATermVector & args) static Expr primRemoveAttrs(EvalState & state, const ATermVector & args)
{ {
ATermMap attrs; ATermMap attrs(128); /* !!! */
queryAllAttrs(evalExpr(state, args[0]), attrs, true); queryAllAttrs(evalExpr(state, args[0]), attrs, true);
ATermList list = evalList(state, args[1]); ATermList list = evalList(state, args[1]);
for (ATermIterator i(list); i; ++i) for (ATermIterator i(list); i; ++i)
/* It's not an error for *i not to exist. */ /* It's not an error for *i not to exist. */
attrs.remove(evalString(state, *i)); attrs.remove(toATerm(evalString(state, *i)));
return makeAttrs(attrs); return makeAttrs(attrs);
} }

View File

@ -1,7 +1,8 @@
lib_LTLIBRARIES = libutil.la lib_LTLIBRARIES = libutil.la
libutil_la_SOURCES = util.cc util.hh hash.cc hash.hh \ libutil_la_SOURCES = util.cc util.hh hash.cc hash.hh \
archive.cc archive.hh aterm.cc aterm.hh archive.cc archive.hh aterm.cc aterm.hh \
aterm-map.cc aterm-map.hh
if !HAVE_OPENSSL if !HAVE_OPENSSL
libutil_la_SOURCES += \ libutil_la_SOURCES += \

View File

@ -1,114 +1,7 @@
#include <string> #include "aterm-map.hh"
#include <iostream>
#include <assert.h> #include <assert.h>
#include <math.h> #include <stdlib.h>
#include <aterm2.h>
using namespace std;
class ATermMap
{
public:
struct KeyValue
{
ATerm key;
ATerm value;
};
private:
/* Hash table for the map. We use open addressing, i.e., all
key/value pairs are stored directly in the table, and there are
no pointers. Collisions are resolved through probing. */
KeyValue * hashTable;
/* Current size of the hash table. */
unsigned int capacity;
/* Number of elements in the hash table. */
unsigned int count;
/* Maximum number of elements in the hash table. If `count'
exceeds this number, the hash table is expanded. */
unsigned int maxCount;
public:
/* Create a map. `expectedCount' is the number of elements the
map is expected to hold. */
ATermMap(unsigned int expectedCount);
ATermMap(const ATermMap & map);
~ATermMap();
ATermMap & operator = (const ATermMap & map);
void set(ATerm key, ATerm value);
ATerm get(ATerm key) const;
void remove(ATerm key);
unsigned int size();
struct const_iterator
{
const ATermMap & map;
unsigned int pos;
const_iterator(const ATermMap & map, int pos) : map(map)
{
this->pos = pos;
}
bool operator !=(const const_iterator & i)
{
return pos != i.pos;
}
void operator ++()
{
if (pos == map.capacity) return;
do { ++pos;
} while (pos < map.capacity && map.hashTable[pos].value == 0);
}
const KeyValue & operator *()
{
assert(pos < map.capacity);
return map.hashTable[pos];
}
const KeyValue * operator ->()
{
assert(pos < map.capacity);
return &map.hashTable[pos];
}
};
const_iterator begin() const
{
unsigned int i = 0;
while (i < capacity && hashTable[i].value == 0) ++i;
return const_iterator(*this, i);
}
const_iterator end() const
{
return const_iterator(*this, capacity);
}
private:
void init(unsigned int expectedCount);
void free();
void resizeTable(unsigned int expectedCount);
void copy(KeyValue * elements, unsigned int capacity);
inline unsigned int hash1(ATerm key) const;
inline unsigned int hash2(ATerm key) const;
};
static const unsigned int maxLoadFactor = /* 1 / */ 3; static const unsigned int maxLoadFactor = /* 1 / */ 3;
@ -120,7 +13,7 @@ static unsigned int sizeMaxAlloc = 0;
ATermMap::ATermMap(unsigned int expectedCount) ATermMap::ATermMap(unsigned int expectedCount)
{ {
init(expectedCount * 10 / 9); /* slight adjustment */ init(expectedCount);
} }
@ -320,6 +213,7 @@ unsigned int ATermMap::size()
} }
#if 0
int main(int argc, char * * argv) int main(int argc, char * * argv)
{ {
ATerm bottomOfStack; ATerm bottomOfStack;
@ -415,3 +309,4 @@ int main(int argc, char * * argv)
<< nrGetProbes << " " << nrGetProbes << " "
<< (double) nrGetProbes / nrItemsGet << endl; << (double) nrGetProbes / nrItemsGet << endl;
} }
#endif

114
src/libutil/aterm-map.hh Normal file
View File

@ -0,0 +1,114 @@
#ifndef __ATERM_MAP_H
#define __ATERM_MAP_H
#include <aterm2.h>
#include <assert.h>
using namespace std;
class ATermMap
{
public:
struct KeyValue
{
ATerm key;
ATerm value;
};
private:
/* Hash table for the map. We use open addressing, i.e., all
key/value pairs are stored directly in the table, and there are
no pointers. Collisions are resolved through probing. */
KeyValue * hashTable;
/* Current size of the hash table. */
unsigned int capacity;
/* Number of elements in the hash table. */
unsigned int count;
/* Maximum number of elements in the hash table. If `count'
exceeds this number, the hash table is expanded. */
unsigned int maxCount;
public:
/* Create a map. `expectedCount' is the number of elements the
map is expected to hold. */
ATermMap(unsigned int expectedCount);
ATermMap(const ATermMap & map);
~ATermMap();
ATermMap & operator = (const ATermMap & map);
void set(ATerm key, ATerm value);
ATerm get(ATerm key) const;
void remove(ATerm key);
unsigned int size();
struct const_iterator
{
const ATermMap & map;
unsigned int pos;
const_iterator(const ATermMap & map, int pos) : map(map)
{
this->pos = pos;
}
bool operator !=(const const_iterator & i)
{
return pos != i.pos;
}
void operator ++()
{
if (pos == map.capacity) return;
do { ++pos;
} while (pos < map.capacity && map.hashTable[pos].value == 0);
}
const KeyValue & operator *()
{
assert(pos < map.capacity);
return map.hashTable[pos];
}
const KeyValue * operator ->()
{
assert(pos < map.capacity);
return &map.hashTable[pos];
}
};
const_iterator begin() const
{
unsigned int i = 0;
while (i < capacity && hashTable[i].value == 0) ++i;
return const_iterator(*this, i);
}
const_iterator end() const
{
return const_iterator(*this, capacity);
}
private:
void init(unsigned int expectedCount);
void free();
void resizeTable(unsigned int expectedCount);
void copy(KeyValue * elements, unsigned int capacity);
inline unsigned int hash1(ATerm key) const;
inline unsigned int hash2(ATerm key) const;
};
#endif /* !__ATERM_MAP_H */

View File

@ -348,7 +348,7 @@ static void queryInstSources(EvalState & state,
assertStorePath(*i); assertStorePath(*i);
DrvInfo elem; DrvInfo elem;
elem.attrs = shared_ptr<ATermMap>(new ATermMap()); /* ugh... */ elem.attrs = shared_ptr<ATermMap>(new ATermMap(0)); /* ugh... */
string name = baseNameOf(*i); string name = baseNameOf(*i);
unsigned int dash = name.find('-'); unsigned int dash = name.find('-');
if (dash != string::npos) if (dash != string::npos)