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