aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 0b20883a3..e4e70c38c 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 f1437e465..06ca01ff4 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 385c2d78d..5e7be5fcd 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 bf8271b13..17ea8ee61 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);