about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2003-11-03T20·30+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2003-11-03T20·30+0000
commit0690c1c9c01dd5889dbfccf2da6cb99f5c4e151b (patch)
treec388986ad9539ecf0a238fabfec07873e553021f
parentff3132427839888933c3779844bf35ca9e189cb9 (diff)
* Work around problems with the ATerm library.
  The ATerm library doesn't search the heap for pointers to ATerms
  when garbage collecting.  As a result, C++ containers such as
  `map<ATerm, ATerm>' will cause pointer to be hidden from the garbage
  collector, causing crashes.  Instead, we now use ATermTables.

-rw-r--r--src/fix-ng/eval.cc56
-rw-r--r--src/fix-ng/eval.hh3
-rw-r--r--src/fix-ng/fix-expr.cc122
-rw-r--r--src/fix-ng/fix-expr.hh40
-rw-r--r--src/fix-ng/primops.cc16
5 files changed, 182 insertions, 55 deletions
diff --git a/src/fix-ng/eval.cc b/src/fix-ng/eval.cc
index 726bc5daeb44..90b7ff29f261 100644
--- a/src/fix-ng/eval.cc
+++ b/src/fix-ng/eval.cc
@@ -5,6 +5,7 @@
 
 
 EvalState::EvalState()
+    : normalForms(32768, 75)
 {
     blackHole = ATmake("BlackHole()");
     if (!blackHole) throw Error("cannot build black hole");
@@ -20,32 +21,43 @@ Expr getAttr(EvalState & state, Expr e, const string & name)
 /* Substitute an argument set into the body of a function. */
 static Expr substArgs(Expr body, ATermList formals, Expr arg)
 {
-    Subs subs;
+    ATermMap subs;
     Expr undefined = ATmake("Undefined");
 
     /* Get the formal arguments. */
     while (!ATisEmpty(formals)) {
+        ATerm t = ATgetFirst(formals);
         char * s;
-        if (!ATmatch(ATgetFirst(formals), "<str>", &s))
+        if (!ATmatch(t, "<str>", &s))
             abort(); /* can't happen */
-        subs[s] = undefined;
+        subs.set(t, undefined);
         formals = ATgetNext(formals);
     }
 
     /* Get the actual arguments, and check that they match with the
        formals. */
-    Attrs args;
+    ATermMap args;
     queryAllAttrs(arg, args);
-    for (Attrs::iterator i = args.begin(); i != args.end(); i++) {
-        if (subs.find(i->first) == subs.end())
-            throw badTerm(format("argument `%1%' not declared") % i->first, arg);
-        subs[i->first] = i->second;
+    for (ATermList keys = args.keys(); !ATisEmpty(keys); 
+         keys = ATgetNext(keys))
+    {
+        Expr key = ATgetFirst(keys);
+        Expr cur = subs.get(key);
+        if (!cur)
+            throw badTerm(format("argument `%1%' not declared")
+                % aterm2String(key), arg);
+        subs.set(key, args.get(key));
     }
 
     /* Check that all arguments are defined. */
-    for (Subs::iterator i = subs.begin(); i != subs.end(); i++)
-        if (i->second == undefined)
-            throw badTerm(format("formal argument `%1%' missing") % i->first, arg);
+    for (ATermList keys = subs.keys(); !ATisEmpty(keys); 
+         keys = ATgetNext(keys))
+    {
+        Expr key = ATgetFirst(keys);
+        if (subs.get(key) == undefined)
+            throw badTerm(format("formal argument `%1%' missing")
+                % aterm2String(key), arg);
+    }
     
     return substitute(subs, body);
 }
@@ -59,26 +71,26 @@ static Expr substArgs(Expr body, ATermList formals, Expr arg)
 ATerm expandRec(ATerm e, ATermList bnds)
 {
     /* Create the substitution list. */
-    Subs subs;
+    ATermMap subs;
     ATermList bs = bnds;
     while (!ATisEmpty(bs)) {
         char * s;
         Expr e2;
         if (!ATmatch(ATgetFirst(bs), "Bind(<str>, <term>)", &s, &e2))
             abort(); /* can't happen */
-        subs[s] = ATmake("Select(<term>, <str>)", e, s);
+        subs.set(s, ATmake("Select(<term>, <str>)", e, s));
         bs = ATgetNext(bs);
     }
 
     /* Create the non-recursive set. */
-    Attrs as;
+    ATermMap as;
     bs = bnds;
     while (!ATisEmpty(bs)) {
         char * s;
         Expr e2;
         if (!ATmatch(ATgetFirst(bs), "Bind(<str>, <term>)", &s, &e2))
             abort(); /* can't happen */
-        as[s] = substitute(subs, e2);
+        as.set(s, substitute(subs, e2));
         bs = ATgetNext(bs);
     }
 
@@ -205,18 +217,18 @@ Expr evalExpr(EvalState & state, Expr e)
 
     /* Consult the memo table to quickly get the normal form of
        previously evaluated expressions. */
-    NormalForms::iterator i = state.normalForms.find(e);
-    if (i != state.normalForms.end()) {
-        if (i->second == state.blackHole)
+    Expr nf = state.normalForms.get(e);
+    if (nf) {
+        if (nf == state.blackHole)
             throw badTerm("infinite recursion", e);
         state.nrCached++;
-        return i->second;
+        return nf;
     }
 
     /* Otherwise, evaluate and memoize. */
-    state.normalForms[e] = state.blackHole;
-    Expr nf = evalExpr2(state, e);
-    state.normalForms[e] = nf;
+    state.normalForms.set(e, state.blackHole);
+    nf = evalExpr2(state, e);
+    state.normalForms.set(e, nf);
     return nf;
 }
 
diff --git a/src/fix-ng/eval.hh b/src/fix-ng/eval.hh
index 364f28471b79..9be3ae2da073 100644
--- a/src/fix-ng/eval.hh
+++ b/src/fix-ng/eval.hh
@@ -7,13 +7,12 @@
 #include "expr.hh"
 
 
-typedef map<Expr, Expr> NormalForms;
 typedef map<Path, PathSet> DrvPaths;
 typedef map<Path, Hash> DrvHashes;
 
 struct EvalState 
 {
-    NormalForms normalForms;
+    ATermMap normalForms;
     DrvPaths drvPaths;
     DrvHashes drvHashes; /* normalised derivation hashes */
     Expr blackHole;
diff --git a/src/fix-ng/fix-expr.cc b/src/fix-ng/fix-expr.cc
index 6333595c631b..814e186b410c 100644
--- a/src/fix-ng/fix-expr.cc
+++ b/src/fix-ng/fix-expr.cc
@@ -2,6 +2,91 @@
 #include "expr.hh"
 
 
+ATermMap::ATermMap(unsigned int initialSize, unsigned int maxLoadPct)
+{
+    table = ATtableCreate(initialSize, maxLoadPct);
+    if (!table) throw Error("cannot create ATerm table");
+}
+
+
+ATermMap::ATermMap(const ATermMap & map)
+    : table(0)
+{
+    ATermList keys = map.keys();
+
+    /* !!! adjust allocation for load pct */
+    table = ATtableCreate(ATgetLength(keys), map.maxLoadPct);
+    if (!table) throw Error("cannot create ATerm table");
+
+    for (; !ATisEmpty(keys); keys = ATgetNext(keys)) {
+        ATerm key = ATgetFirst(keys);
+        set(key, map.get(key));
+    }
+}
+
+
+ATermMap::~ATermMap()
+{
+    if (table) ATtableDestroy(table);
+}
+
+
+void ATermMap::set(ATerm key, ATerm value)
+{
+    return ATtablePut(table, key, value);
+}
+
+
+void ATermMap::set(const string & key, ATerm value)
+{
+    set(string2ATerm(key), value);
+}
+
+
+ATerm ATermMap::get(ATerm key) const
+{
+    return ATtableGet(table, key);
+}
+
+
+ATerm ATermMap::get(const string & key) const
+{
+    return get(string2ATerm(key));
+}
+
+
+void ATermMap::remove(ATerm key)
+{
+    ATtableRemove(table, key);
+}
+
+
+void ATermMap::remove(const string & key)
+{
+    remove(string2ATerm(key));
+}
+
+
+ATermList ATermMap::keys() const
+{
+    ATermList keys = ATtableKeys(table);
+    if (!keys) throw Error("cannot query aterm map keys");
+    return keys;
+}
+
+
+ATerm string2ATerm(const string & s)
+{
+    return (ATerm) ATmakeAppl0(ATmakeAFun((char *) s.c_str(), 0, ATtrue));
+}
+
+
+string aterm2String(ATerm t)
+{
+    return ATgetName(ATgetAFun(t));
+}
+    
+
 ATerm bottomupRewrite(TermFun & f, ATerm e)
 {
     if (ATgetType(e) == AT_APPL) {
@@ -31,7 +116,7 @@ ATerm bottomupRewrite(TermFun & f, ATerm e)
 }
 
 
-void queryAllAttrs(Expr e, Attrs & attrs)
+void queryAllAttrs(Expr e, ATermMap & attrs)
 {
     ATermList bnds;
     if (!ATmatch(e, "Attrs([<list>])", &bnds))
@@ -42,7 +127,7 @@ void queryAllAttrs(Expr e, Attrs & attrs)
         Expr e;
         if (!ATmatch(ATgetFirst(bnds), "Bind(<str>, <term>)", &s, &e))
             abort(); /* can't happen */
-        attrs[s] = e;
+        attrs.set(s, e);
         bnds = ATgetNext(bnds);
     }
 }
@@ -50,33 +135,32 @@ void queryAllAttrs(Expr e, Attrs & attrs)
 
 Expr queryAttr(Expr e, const string & name)
 {
-    Attrs attrs;
+    ATermMap attrs;
     queryAllAttrs(e, attrs);
-    Attrs::iterator i = attrs.find(name);
-    return i == attrs.end() ? 0 : i->second;
+    return attrs.get(name);
 }
 
 
-Expr makeAttrs(const Attrs & attrs)
+Expr makeAttrs(const ATermMap & attrs)
 {
-    ATermList bnds = ATempty;
-    for (Attrs::const_iterator i = attrs.begin(); i != attrs.end(); i++)
+    ATermList bnds = ATempty, keys = attrs.keys();
+    while (!ATisEmpty(keys)) {
+        Expr key = ATgetFirst(keys);
         bnds = ATinsert(bnds, 
-            ATmake("Bind(<str>, <term>)", i->first.c_str(), i->second));
+            ATmake("Bind(<term>, <term>)", key, attrs.get(key)));
+        keys = ATgetNext(keys);
+    }
     return ATmake("Attrs(<term>)", ATreverse(bnds));
 }
 
 
-ATerm substitute(Subs & subs, ATerm e)
+Expr substitute(const ATermMap & subs, Expr e)
 {
     char * s;
 
     if (ATmatch(e, "Var(<str>)", &s)) {
-        Subs::iterator i = subs.find(s);
-        if (i == subs.end())
-            return e;
-        else
-            return i->second;
+        Expr sub = subs.get(s);
+        return sub ? sub : e;
     }
 
     /* In case of a function, filter out all variables bound by this
@@ -84,11 +168,11 @@ ATerm substitute(Subs & subs, ATerm e)
     ATermList formals;
     ATerm body;
     if (ATmatch(e, "Function([<list>], <term>)", &formals, &body)) {
-        Subs subs2(subs);
+        ATermMap subs2(subs);
         ATermList fs = formals;
         while (!ATisEmpty(fs)) {
             if (!ATmatch(ATgetFirst(fs), "<str>", &s)) abort();
-            subs2.erase(s);
+            subs2.remove(s);
             fs = ATgetNext(fs);
         }
         return ATmake("Function(<term>, <term>)", formals,
@@ -98,13 +182,13 @@ ATerm substitute(Subs & subs, ATerm e)
     /* Idem for a mutually recursive attribute set. */
     ATermList bindings;
     if (ATmatch(e, "Rec([<list>])", &bindings)) {
-        Subs subs2(subs);
+        ATermMap subs2(subs);
         ATermList bnds = bindings;
         while (!ATisEmpty(bnds)) {
             Expr e;
             if (!ATmatch(ATgetFirst(bnds), "Bind(<str>, <term>)", &s, &e))
                 abort(); /* can't happen */
-            subs2.erase(s);
+            subs2.remove(s);
             bnds = ATgetNext(bnds);
         }
         return ATmake("Rec(<term>)", substitute(subs2, (ATerm) bindings));
diff --git a/src/fix-ng/fix-expr.hh b/src/fix-ng/fix-expr.hh
index 700f7beca906..93a010abeda6 100644
--- a/src/fix-ng/fix-expr.hh
+++ b/src/fix-ng/fix-expr.hh
@@ -14,6 +14,38 @@
 typedef ATerm Expr;
 
 
+/* 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 = 16, unsigned int maxLoadPct = 75);
+    ATermMap(const ATermMap & map);
+    ~ATermMap();
+
+    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;
+};
+
+
+/* Convert a string to an ATerm (i.e., a quoted nullary function
+   applicaton). */
+ATerm string2ATerm(const string & s);
+string aterm2String(ATerm t);
+
+
 /* Generic bottomup traversal over ATerms.  The traversal first
    recursively descends into subterms, and then applies the given term
    function to the resulting term. */
@@ -25,19 +57,17 @@ ATerm bottomupRewrite(TermFun & f, ATerm e);
 
 /* Query all attributes in an attribute set expression.  The
    expression must be in normal form. */
-typedef map<string, Expr> Attrs;
-void queryAllAttrs(Expr e, Attrs & attrs);
+void queryAllAttrs(Expr e, ATermMap & attrs);
 
 /* Query a specific attribute from an attribute set expression.  The
    expression must be in normal form. */
 Expr queryAttr(Expr e, const string & name);
 
 /* Create an attribute set expression from an Attrs value. */
-Expr makeAttrs(const Attrs & attrs);
+Expr makeAttrs(const ATermMap & attrs);
 
 /* Perform a set of substitutions on an expression. */
-typedef map<string, Expr> Subs;
-ATerm substitute(Subs & subs, ATerm e);
+Expr substitute(const ATermMap & subs, Expr e);
 
 
 #endif /* !__FIXEXPR_H */
diff --git a/src/fix-ng/primops.cc b/src/fix-ng/primops.cc
index f887d265f326..ef0fd354ef6d 100644
--- a/src/fix-ng/primops.cc
+++ b/src/fix-ng/primops.cc
@@ -123,7 +123,7 @@ Expr primDerivation(EvalState & state, Expr args)
 {
     Nest nest(lvlVomit, "evaluating derivation");
 
-    Attrs attrs;
+    ATermMap attrs;
     args = evalExpr(state, args);
     queryAllAttrs(args, attrs);
 
@@ -136,9 +136,11 @@ Expr primDerivation(EvalState & state, Expr args)
     Hash outHash;
     bool outHashGiven = false;
 
-    for (Attrs::iterator i = attrs.begin(); i != attrs.end(); i++) {
-        string key = i->first;
-        Expr value = i->second;
+    for (ATermList keys = attrs.keys(); !ATisEmpty(keys); 
+         keys = ATgetNext(keys))
+    {
+        string key = aterm2String(ATgetFirst(keys));
+        Expr value = attrs.get(key);
         Nest nest(lvlVomit, format("processing attribute `%1%'") % key);
 
         /* The `args' attribute is special: it supplies the
@@ -198,9 +200,9 @@ Expr primDerivation(EvalState & state, Expr args)
     msg(lvlChatty, format("instantiated `%1%' -> `%2%'")
         % drvName % drvPath);
 
-    attrs["outPath"] = ATmake("Path(<str>)", outPath.c_str());
-    attrs["drvPath"] = ATmake("Path(<str>)", drvPath.c_str());
-    attrs["type"] = ATmake("Str(\"derivation\")");
+    attrs.set("outPath", ATmake("Path(<str>)", outPath.c_str()));
+    attrs.set("drvPath", ATmake("Path(<str>)", drvPath.c_str()));
+    attrs.set("type", ATmake("Str(\"derivation\")"));
 
     return makeAttrs(attrs);
 }