[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