Hi Eelco,

On 1/7/12 1:21 PM, Eelco Dolstra wrote:
I've been thinking about a special ‘ignore’ value:

derivation {
   CFLAGS = if system == "i686-darwin" then "bla" else ignore;
}

This value would be like ‘null’, except that if a derivation attribute evaluates
to ‘ignore’, it wouldn't be added to the environment of the builder.


Neat idea. I've attached a patch for a simple implementation of this, what do you think? Note that trying to explicitly coerce ignore to string will cause an error in this implementation.

Cheers,
Shea
Index: src/libexpr/value.hh
===================================================================
--- src/libexpr/value.hh        (revision 31429)
+++ src/libexpr/value.hh        (working copy)
@@ -12,6 +12,7 @@
     tString,
     tPath,
     tNull,
+    tIgnore,
     tAttrs,
     tList,
     tThunk,
@@ -39,7 +40,7 @@
     {
         int integer;
         bool boolean;
-        
+
         /* Strings in the evaluator carry a so-called `context' (the
            ATermList) which is a list of strings representing store
            paths.  This is to allow users to write things like
Index: src/libexpr/eval.cc
===================================================================
--- src/libexpr/eval.cc (revision 31429)
+++ src/libexpr/eval.cc (working copy)
@@ -72,6 +72,9 @@
     case tNull:
         str << "null";
         break;
+    case tIgnore:
+        str << "ignore";
+        break;
     case tAttrs: {
         str << "{ ";
         typedef std::map<string, Value *> Sorted;
@@ -117,6 +120,7 @@
         case tString: return "a string";
         case tPath: return "a path";
         case tNull: return "null";
+        case tIgnore: return "ignore";
         case tAttrs: return "an attribute set";
         case tList: return "a list";
         case tThunk: return "a thunk";
@@ -1238,6 +1242,9 @@
         case tNull:
             return true;
 
+        case tIgnore:
+            return true;
+
         case tList:
             if (v1.list.length != v2.list.length) return false;
             for (unsigned int n = 0; n < v1.list.length; ++n)
Index: src/libexpr/primops.cc
===================================================================
--- src/libexpr/primops.cc      (revision 31429)
+++ src/libexpr/primops.cc      (working copy)
@@ -55,6 +55,14 @@
 }
 
 
+/* Determine whether the argument is the ignore value. */
+static void prim_isIgnore(EvalState & state, Value * * args, Value & v)
+{
+    state.forceValue(*args[0]);
+    mkBool(v, args[0]->type == tIgnore);
+}
+
+
 /* Determine whether the argument is a function. */
 static void prim_isFunction(EvalState & state, Value * * args, Value & v)
 {
@@ -288,51 +296,54 @@
 
         try {
 
-            /* The `args' attribute is special: it supplies the
-               command-line arguments to the builder. */
-            if (key == "args") {
-                state.forceList(*i->value);
-                for (unsigned int n = 0; n < i->value->list.length; ++n) {
-                    string s = state.coerceToString(*i->value->list.elems[n], 
context, true);
-                    drv.args.push_back(s);
+            /* If the attribute is the 'ignore' constant, ignore it */
+            state.forceValue(*i->value);
+            if (i->value->type != tIgnore) {
+                /* The `args' attribute is special: it supplies the
+                   command-line arguments to the builder. */
+                if (key == "args") {
+                    state.forceList(*i->value);
+                    for (unsigned int n = 0; n < i->value->list.length; ++n) {
+                        string s = 
state.coerceToString(*i->value->list.elems[n], context, true);
+                        drv.args.push_back(s);
+                    }
                 }
-            }
 
-            /* All other attributes are passed to the builder through
-               the environment. */
-            else {
-                string s = state.coerceToString(*i->value, context, true);
-                drv.env[key] = s;
-                if (key == "builder") drv.builder = s;
-                else if (i->name == state.sSystem) drv.platform = s;
-                else if (i->name == state.sName) drvName = s;
-                else if (key == "outputHash") outputHash = s;
-                else if (key == "outputHashAlgo") outputHashAlgo = s;
-                else if (key == "outputHashMode") {
-                    if (s == "recursive") outputHashRecursive = true; 
-                    else if (s == "flat") outputHashRecursive = false;
-                    else throw EvalError(format("invalid value `%1%' for 
`outputHashMode' attribute") % s);
-                }
-                else if (key == "outputs") {
-                    Strings tmp = tokenizeString(s);
-                    outputs.clear();
-                    foreach (Strings::iterator, j, tmp) {
-                        if (outputs.find(*j) != outputs.end())
-                            throw EvalError(format("duplicate derivation 
output `%1%'") % *j);
-                        /* !!! Check whether *j is a valid attribute
-                           name. */
-                        /* Derivations cannot be named ‘drv’, because
-                           then we'd have an attribute ‘drvPath’ in
-                           the resulting set. */
-                        if (*j == "drv")
-                            throw EvalError(format("invalid derivation output 
name `drv'") % *j);
-                        outputs.insert(*j);
+                /* All other attributes are passed to the builder through
+                   the environment. */
+                else {
+                    string s = state.coerceToString(*i->value, context, true);
+                    drv.env[key] = s;
+                    if (key == "builder") drv.builder = s;
+                    else if (i->name == state.sSystem) drv.platform = s;
+                    else if (i->name == state.sName) drvName = s;
+                    else if (key == "outputHash") outputHash = s;
+                    else if (key == "outputHashAlgo") outputHashAlgo = s;
+                    else if (key == "outputHashMode") {
+                        if (s == "recursive") outputHashRecursive = true; 
+                        else if (s == "flat") outputHashRecursive = false;
+                        else throw EvalError(format("invalid value `%1%' for 
`outputHashMode' attribute") % s);
+                    } 
+                    else if (key == "outputs") {
+                        Strings tmp = tokenizeString(s);
+                        outputs.clear();
+                        foreach (Strings::iterator, j, tmp) {
+                            if (outputs.find(*j) != outputs.end())
+                                throw EvalError(format("duplicate derivation 
output `%1%'") % *j);
+                            /* !!! Check whether *j is a valid attribute
+                               name. */
+                            /* Derivations cannot be named ‘drv’, because
+                               then we'd have an attribute ‘drvPath’ in
+                               the resulting set. */
+                            if (*j == "drv")
+                                throw EvalError(format("invalid derivation 
output name `drv'") % *j);
+                            outputs.insert(*j);
+                        }
+                        if (outputs.empty())
+                            throw EvalError("derivation cannot have an empty 
set of outputs");
                     }
-                    if (outputs.empty())
-                        throw EvalError("derivation cannot have an empty set 
of outputs");
                 }
             }
-
         } catch (Error & e) {
             e.addPrefix(format("while evaluating the derivation attribute 
`%1%' at %2%:\n")
                 % key % *i->pos);
@@ -1023,6 +1034,9 @@
     v.type = tNull;
     addConstant("null", v);
 
+    v.type = tIgnore;
+    addConstant("ignore", v);
+
     mkInt(v, time(0));
     addConstant("__currentTime", v);
 
@@ -1032,6 +1046,7 @@
     // Miscellaneous
     addPrimOp("import", 1, prim_import);
     addPrimOp("isNull", 1, prim_isNull);
+    addPrimOp("__isIgnore", 1, prim_isIgnore);
     addPrimOp("__isFunction", 1, prim_isFunction);
     addPrimOp("__isString", 1, prim_isString);
     addPrimOp("__isInt", 1, prim_isInt);
Index: src/libexpr/value-to-xml.cc
===================================================================
--- src/libexpr/value-to-xml.cc (revision 31429)
+++ src/libexpr/value-to-xml.cc (working copy)
@@ -81,6 +81,10 @@
             doc.writeEmptyElement("null");
             break;
 
+        case tIgnore:
+            doc.writeEmptyElement("ignore");
+            break;
+
         case tAttrs:
             if (state.isDerivation(v)) {
                 XMLAttrs xmlAttrs;
_______________________________________________
nix-dev mailing list
[email protected]
http://lists.science.uu.nl/mailman/listinfo/nix-dev

Reply via email to