about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/primops.cc26
-rw-r--r--tests/lang/eval-okay-builtins.exp1
-rw-r--r--tests/lang/eval-okay-builtins.nix12
3 files changed, 39 insertions, 0 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index dfc565b4317e..bc4db2d81306 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -7,6 +7,30 @@
 #include "nixexpr-ast.hh"
 
 
+static Expr primBuiltins(EvalState & state, const ATermVector & args)
+{
+    /* Return an attribute set containing all primops.  This allows
+       Nix expressions to test for new primops and take appropriate
+       action if they're not available.  For instance, rather than
+       calling a primop `foo' directly, they could say `if builtins ?
+       foo then builtins.foo ... else ...'. */
+
+    ATermMap builtins(128);
+
+    for (ATermMap::const_iterator i = state.primOps.begin();
+         i != state.primOps.end(); ++i)
+    {
+        string name = aterm2String(i->key);
+        if (string(name, 0, 2) == "__")
+            name = string(name, 2);
+        /* !!! should use makePrimOp here, I guess. */
+        builtins.set(toATerm(name), makeAttrRHS(makeVar(i->key), makeNoPos()));
+    }
+
+    return makeAttrs(builtins);
+}
+
+
 /* Load and evaluate an expression from path specified by the
    argument. */ 
 static Expr primImport(EvalState & state, const ATermVector & args)
@@ -660,6 +684,8 @@ static Expr primRelativise(EvalState & state, const ATermVector & args)
 
 void EvalState::addPrimOps()
 {
+    addPrimOp("builtins", 0, primBuiltins);
+        
     addPrimOp("true", 0, primTrue);
     addPrimOp("false", 0, primFalse);
     addPrimOp("null", 0, primNull);
diff --git a/tests/lang/eval-okay-builtins.exp b/tests/lang/eval-okay-builtins.exp
new file mode 100644
index 000000000000..f4f3ba81a101
--- /dev/null
+++ b/tests/lang/eval-okay-builtins.exp
@@ -0,0 +1 @@
+Path("/foo")
diff --git a/tests/lang/eval-okay-builtins.nix b/tests/lang/eval-okay-builtins.nix
new file mode 100644
index 000000000000..e9d65e88a817
--- /dev/null
+++ b/tests/lang/eval-okay-builtins.nix
@@ -0,0 +1,12 @@
+assert builtins ? currentSystem;
+assert !builtins ? __currentSystem;
+
+let {
+
+  x = if builtins ? dirOf then builtins.dirOf /foo/bar else "";
+
+  y = if builtins ? fnord then builtins.fnord "foo" else "";
+
+  body = x + y;
+  
+}