about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-03-30T14·39+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-03-30T14·39+0000
commitc3aa615a5f4a8bdde5d836ce91d5daa743ded065 (patch)
tree139a8782e58be7af83e06ae9dd6b9e9399b79fcb
parent5b72d8a749e6718986f6e2bfef2ae725981a26ff (diff)
* More primops.
-rw-r--r--src/libexpr/eval-test.cc6
-rw-r--r--src/libexpr/eval.cc32
-rw-r--r--src/libexpr/eval.hh4
-rw-r--r--src/libexpr/primops.cc109
4 files changed, 55 insertions, 96 deletions
diff --git a/src/libexpr/eval-test.cc b/src/libexpr/eval-test.cc
index 0b20883a33..e4e70c38ca 100644
--- a/src/libexpr/eval-test.cc
+++ b/src/libexpr/eval-test.cc
@@ -56,10 +56,12 @@ void run(Strings args)
     doTest("{ x = [ 1 2 ]; } == { x = [ 1 ] ++ [ 2 ]; }");
     doTest("1 != 1");
     doTest("true");
+    doTest("builtins.true");
     doTest("true == false");
     doTest("__head [ 1 2 3 ]");
     doTest("__add 1 2");
     doTest("null");
+    doTest("null");
     doTest("\"foo\"");
     doTest("let s = \"bar\"; in \"foo${s}\"");
     doTest("if true then 1 else 2");
@@ -67,9 +69,9 @@ void run(Strings args)
     doTest("if false || true then 1 else 2");
     doTest("let x = x; in if true || x then 1 else 2");
     doTest("/etc/passwd");
-    doTest("import ./foo.nix");
+    //doTest("import ./foo.nix");
     doTest("map (x: __add 1 x) [ 1 2 3 ]");
-    doTest("map (__add 1) [ 1 2 3 ]");
+    doTest("map (builtins.add 1) [ 1 2 3 ]");
 }
 
 
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index f1437e4657..06ca01ff44 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -95,14 +95,26 @@ EvalState::EvalState() : baseEnv(allocEnv())
 }
 
 
+void EvalState::addConstant(const string & name, Value & v)
+{
+    baseEnv.bindings[toATerm(name)] = v;
+    string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
+    (*baseEnv.bindings[toATerm("builtins")].attrs)[toATerm(name2)] = v;
+    nrValues += 2;
+}
+
+
 void EvalState::addPrimOp(const string & name,
     unsigned int arity, PrimOp primOp)
 {
-    Value & v = baseEnv.bindings[toATerm(name)];
-    nrValues++;
+    Value v;
     v.type = tPrimOp;
     v.primOp.arity = arity;
     v.primOp.fun = primOp;
+    baseEnv.bindings[toATerm(name)] = v;
+    string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
+    (*baseEnv.bindings[toATerm("builtins")].attrs)[toATerm(name2)] = v;
+    nrValues += 2;
 }
 
 
@@ -212,6 +224,14 @@ Env & EvalState::allocEnv()
 }
 
 
+void EvalState::mkList(Value & v, unsigned int length)
+{
+    v.type = tList;
+    v.list.length = length;
+    v.list.elems = allocValues(length);
+}
+
+
 void EvalState::evalFile(const Path & path, Value & v)
 {
     startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
@@ -349,9 +369,7 @@ void EvalState::eval(Env & env, Expr e, Value & v)
     }
 
     if (matchList(e, es)) {
-        v.type = tList;
-        v.list.length = ATgetLength(es);
-        v.list.elems = allocValues(v.list.length);
+        mkList(v, ATgetLength(es));
         for (unsigned int n = 0; n < v.list.length; ++n, es = ATgetNext(es))
             mkThunk(v.list.elems[n], env, ATgetFirst(es));
         return;
@@ -376,9 +394,7 @@ void EvalState::eval(Env & env, Expr e, Value & v)
         forceList(v1);
         Value v2; eval(env, e2, v2);
         forceList(v2);
-        v.type = tList;
-        v.list.length = v1.list.length + v2.list.length;
-        v.list.elems = allocValues(v.list.length);
+        mkList(v, v1.list.length + v2.list.length);
         /* !!! This loses sharing with the original lists.  We could
            use a tCopy node, but that would use more memory. */
         for (unsigned int n = 0; n < v1.list.length; ++n)
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 385c2d78da..5e7be5fcd8 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -196,6 +196,8 @@ private:
 
     void createBaseEnv();
     
+    void addConstant(const string & name, Value & v);
+
     void addPrimOp(const string & name,
         unsigned int arity, PrimOp primOp);
 
@@ -210,6 +212,8 @@ public:
     /* Allocation primitives. */
     Value * allocValues(unsigned int count);
     Env & allocEnv();
+
+    void mkList(Value & v, unsigned int length);
 };
 
 
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index bf8271b130..17ea8ee619 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -20,63 +20,6 @@
 namespace nix {
 
 
-#if 0
-/*************************************************************
- * Constants
- *************************************************************/
-
-
-static Expr prim_builtins(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(state.primOps.size());
-
-    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);
-}
-
-
-/* Boolean constructors. */
-static Expr prim_true(EvalState & state, const ATermVector & args)
-{
-    return eTrue;
-}
-
-
-static Expr prim_false(EvalState & state, const ATermVector & args)
-{
-    return eFalse;
-}
-
-
-/* Return the null value. */
-static Expr prim_null(EvalState & state, const ATermVector & args)
-{
-    return makeNull();
-}
-
-
-static Expr prim_currentTime(EvalState & state, const ATermVector & args)
-{
-    return ATmake("Int(<int>)", time(0));
-}
-#endif
-
-
 /*************************************************************
  * Miscellaneous
  *************************************************************/
@@ -903,17 +846,17 @@ static void prim_head(EvalState & state, Value * * args, Value & v)
 }
 
 
-#if 0
 /* Return a list consisting of everything but the the first element of
    a list. */
-static Expr prim_tail(EvalState & state, const ATermVector & args)
+static void prim_tail(EvalState & state, Value * * args, Value & v)
 {
-    ATermList list = evalList(state, args[0]);
-    if (ATisEmpty(list))
+    state.forceList(*args[0]);
+    if (args[0]->list.length == 0)
         throw Error("`tail' called on an empty list");
-    return makeList(ATgetNext(list));
+    state.mkList(v, args[0]->list.length - 1);
+    for (unsigned int n = 0; n < v.list.length; ++n)
+        v.list.elems[n] = args[0]->list.elems[n + 1];
 }
-#endif
 
 
 /* Apply a function to every element of a list. */
@@ -922,9 +865,7 @@ static void prim_map(EvalState & state, Value * * args, Value & v)
     state.forceFunction(*args[0]);
     state.forceList(*args[1]);
 
-    v.type = tList;
-    v.list.length = args[1]->list.length;
-    v.list.elems = state.allocValues(v.list.length);
+    state.mkList(v, args[1]->list.length);
 
     for (unsigned int n = 0; n < v.list.length; ++n) {
         v.list.elems[n].type = tApp;
@@ -1121,28 +1062,26 @@ void EvalState::createBaseEnv()
         v.type = tAttrs;
         v.attrs = new Bindings;
     }
-    
+
     /* Add global constants such as `true' to the base environment. */
-    {   Value & v = baseEnv.bindings[toATerm("true")];
-        mkBool(v, true);
-    }
-    {   Value & v = baseEnv.bindings[toATerm("false")];
-        mkBool(v, false);
-    }
-    {   Value & v = baseEnv.bindings[toATerm("null")];
-        v.type = tNull;
-    }
-    {   Value & v = (*baseEnv.bindings[toATerm("builtins")].attrs)[toATerm("currentSystem")];
-        mkString(v, strdup(thisSystem.c_str()));
-    }
+    Value v;
+
+    mkBool(v, true);
+    addConstant("true", v);
+    
+    mkBool(v, false);
+    addConstant("false", v);
+    
+    v.type = tNull;
+    addConstant("null", v);
+
+    mkInt(v, time(0));
+    addConstant("__currentTime", v);
 
-#if 0    
-    // Constants
-    addPrimOp("__currentSystem", 0, prim_currentSystem);
-    addPrimOp("__currentTime", 0, prim_currentTime);
+    mkString(v, strdup(thisSystem.c_str()));
+    addConstant("__currentSystem", v);
 
     // Miscellaneous
-#endif
     addPrimOp("import", 1, prim_import);
 #if 0
     addPrimOp("isNull", 1, prim_isNull);
@@ -1193,9 +1132,7 @@ void EvalState::createBaseEnv()
     addPrimOp("__isList", 1, prim_isList);
 #endif
     addPrimOp("__head", 1, prim_head);
-#if 0
     addPrimOp("__tail", 1, prim_tail);
-#endif
     addPrimOp("map", 2, prim_map);
 #if 0
     addPrimOp("__length", 1, prim_length);