[Nix-dev] Patch listToSet ? My first try

Marc Weber marco-oweber at gmx.de
Tue Jun 5 22:48:41 CEST 2007


  let set= (builtins.listToSet false [ { attr="test"; value="val";} { attr="test2"; value=[/ab /cd]; }]);
  in set.test

evaluates to
Str("val",[])

and 
  [...]
  in set.test2

evaluates to
List([Path("/ab"),Path("/cd")])

But I'm not sure wether the value part is still lazy. How to check this?
How to register new tests?

Hmm.. When using true ( means rec set) I get:
|| error: while evaluating the attribute `<let-body>' at `/tmp/toSet.nix', line 1:
|| value is an unknown type while an attribute set was expected

Marc


============= diff start ===================================================

Index: src/libexpr/primops.cc
===================================================================
--- src/libexpr/primops.cc      (revision 8834)
+++ src/libexpr/primops.cc      (working copy)
@@ -744,6 +744,7 @@
 }
 
 
+// copied from parser.y TODO where to move this ? niksnut?
 static Expr prim_removeAttrs(EvalState & state, const ATermVector & args)
 {
     ATermMap attrs;
@@ -758,7 +759,76 @@
     return makeAttrs(attrs);
 }
 
+// copied from parser.y TODO where to move this ? niksnut?
+static Expr fixAttrs(int recursive, ATermList as)
+{
+    ATermList bs = ATempty, cs = ATempty;
+    ATermList * is = recursive ? &cs : &bs;
+    for (ATermIterator i(as); i; ++i) {
+        ATermList names;
+        Expr src;
+        ATerm pos;
+        if (matchInherit(*i, src, names, pos)) {
+            bool fromScope = matchScope(src);
+            for (ATermIterator j(names); j; ++j) {
+                Expr rhs = fromScope ? makeVar(*j) : makeSelect(src, *j);
+                *is = ATinsert(*is, makeBind(*j, rhs, pos));
+            }
+        } else bs = ATinsert(bs, *i);
+    }
+    if (recursive)
+        return makeRec(bs, cs);
+    else
+        return makeAttrs(bs);
+}
 
+/* takes 
+ * fst param: bool indicating rec
+ * snd param: list of either [ attr value ] or { attr="attr"; value=value } and returns a set 
+ * [ attr value ] not yet supported.
+ *
+ * TODO! find a new home for the duplicated fixAttrs above !!
+ * */
+static Expr prim_listToSet(EvalState & state, const ATermVector & args)
+{
+    ATerm dummy;
+
+    // getting the rec bool value (first arg
+    //showValue from nixexpr.cc does contain:
+    //
+    //if (matchInt(e, i)) return (format("%1%") % i).str();
+    //if (e == eTrue) return "true";
+    //if (e == eFalse) return "false";
+    //
+    //Thus I think its ok to just use evalExpr and compare to e1/ e2?
+
+    Expr e = evalExpr(state, args[0]);
+    if (!matchBool(e, dummy))
+      // TODO enhance this message (posititon etc ? is this availible?)
+      throw EvalError(format("invalid first argument for listToSet, bool expected")); 
+    bool rec = (e == eTrue); // a simple cast would be enough as eTrue is assgned 1 ande eFalse is assigned 0
+
+    ATermList res = ATempty; // the new map which is to be returned
+
+    ATermList list;
+    if (!matchList(evalExpr(state, args[1]), list))
+      throw EvalError(format("list expected in second argument of listToSet")); 
+
+    for (ATermIterator i(list); i; ++i){
+      // *i should now contain a pointer to the list item expression
+        ATermList attrs;
+        if (matchAttrs(*i, attrs)){
+          Expr e = evalExpr(state, makeSelect(*i, toATerm("attr")));
+          string attr = evalStringNoCtx(state,e); // is evalStringNoCtx correct? or should it have been evalString
+          ATerm value;
+          value = makeSelect(*i, toATerm("value")); // I hope this preserves laziness
+          res = ATinsert(res, makeBind(toATerm(attr), value, makeNoPos()));
+        } // todo; implement attr:value:[] version ?
+        else throw EvalError(format("error while creating a set. passed list item is not a set. { attr=\"name\"; value=nix expr; } expected.")); 
+    } // for
+    return fixAttrs(rec, res);
+}
+
 /*************************************************************
  * Lists
  *************************************************************/
@@ -924,6 +994,7 @@
     addPrimOp("__getAttr", 2, prim_getAttr);
     addPrimOp("__hasAttr", 2, prim_hasAttr);
     addPrimOp("removeAttrs", 2, prim_removeAttrs);
+    addPrimOp("listToSet", 2, prim_listToSet);
 
     // Lists
     addPrimOp("__isList", 1, prim_isList);
Index: tests/lang/eval-fail-assert.nix
===================================================================
--- tests/lang/eval-fail-assert.nix     (revision 8834)
+++ tests/lang/eval-fail-assert.nix     (working copy)
@@ -2,4 +2,4 @@
   x = arg: assert arg == "y"; 123;
 
   body = x "x";
-}
\ No newline at end of file
+}




More information about the nix-dev mailing list