about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/eval.cc24
-rw-r--r--src/libexpr/eval.hh3
-rw-r--r--src/libexpr/nixexpr.hh20
-rw-r--r--src/libexpr/parser.y10
-rw-r--r--src/libexpr/primops.cc2
5 files changed, 28 insertions, 31 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index e0451dfa7701..44d75bd8c03b 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -574,6 +574,16 @@ inline bool EvalState::evalBool(Env & env, Expr * e)
 }
 
 
+inline bool EvalState::evalBool(Env & env, Expr * e, const Pos & pos)
+{
+    Value v;
+    e->eval(*this, env, v);
+    if (v.type != tBool)
+        throwTypeError("value is %1% while a Boolean was expected, at %2%", v, pos);
+    return v.boolean;
+}
+
+
 inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v)
 {
     e->eval(*this, env, v);
@@ -975,7 +985,7 @@ void ExprIf::eval(EvalState & state, Env & env, Value & v)
 
 void ExprAssert::eval(EvalState & state, Env & env, Value & v)
 {
-    if (!state.evalBool(env, cond))
+    if (!state.evalBool(env, cond, pos))
         throwAssertionError("assertion failed at %1%", pos);
     body->eval(state, env, v);
 }
@@ -1016,19 +1026,19 @@ void ExprOpNEq::eval(EvalState & state, Env & env, Value & v)
 
 void ExprOpAnd::eval(EvalState & state, Env & env, Value & v)
 {
-    mkBool(v, state.evalBool(env, e1) && state.evalBool(env, e2));
+    mkBool(v, state.evalBool(env, e1, pos) && state.evalBool(env, e2, pos));
 }
 
 
 void ExprOpOr::eval(EvalState & state, Env & env, Value & v)
 {
-    mkBool(v, state.evalBool(env, e1) || state.evalBool(env, e2));
+    mkBool(v, state.evalBool(env, e1, pos) || state.evalBool(env, e2, pos));
 }
 
 
 void ExprOpImpl::eval(EvalState & state, Env & env, Value & v)
 {
-    mkBool(v, !state.evalBool(env, e1) || state.evalBool(env, e2));
+    mkBool(v, !state.evalBool(env, e1, pos) || state.evalBool(env, e2, pos));
 }
 
 
@@ -1073,18 +1083,18 @@ void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v)
     Value v1; e1->eval(state, env, v1);
     Value v2; e2->eval(state, env, v2);
     Value * lists[2] = { &v1, &v2 };
-    state.concatLists(v, 2, lists);
+    state.concatLists(v, 2, lists, pos);
 }
 
 
-void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists)
+void EvalState::concatLists(Value & v, unsigned int nrLists, Value * * lists, const Pos & pos)
 {
     nrListConcats++;
 
     Value * nonEmpty = 0;
     unsigned int len = 0;
     for (unsigned int n = 0; n < nrLists; ++n) {
-        forceList(*lists[n]);
+        forceList(*lists[n], pos);
         unsigned int l = lists[n]->list.length;
         len += l;
         if (l) nonEmpty = lists[n];
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index d1bd27f162cf..6d4cb8abe8d1 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -145,6 +145,7 @@ public:
     /* Evaluation the expression, then verify that it has the expected
        type. */
     inline bool evalBool(Env & env, Expr * e);
+    inline bool evalBool(Env & env, Expr * e, const Pos & pos);
     inline void evalAttrs(Env & env, Expr * e, Value & v);
 
     /* If `v' is a thunk, enter it and overwrite `v' with the result
@@ -246,7 +247,7 @@ public:
     void mkThunk_(Value & v, Expr * expr);
     void mkPos(Value & v, Pos * pos);
 
-    void concatLists(Value & v, unsigned int nrLists, Value * * lists);
+    void concatLists(Value & v, unsigned int nrLists, Value * * lists, const Pos & pos);
 
     /* Print statistics. */
     void printStats();
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index d781d92ba78a..f07b85c8343c 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -277,28 +277,13 @@ struct ExprBuiltin : Expr
     COMMON_METHODS
 };
 
-struct ExprApp : Expr
-{
-    Pos pos;
-    Expr * e1, * e2;
-    ExprApp(Expr * e1, Expr * e2) : e1(e1), e2(e2) { };
-    ExprApp(const Pos & pos, Expr * e1, Expr * e2) : pos(pos), e1(e1), e2(e2) { };
-    void show(std::ostream & str)
-    {
-        str << *e1 << " " << *e2;
-    }
-    void bindVars(const StaticEnv & env)
-    {
-        e1->bindVars(env); e2->bindVars(env);
-    }
-    void eval(EvalState & state, Env & env, Value & v);
-};
-
 #define MakeBinOp(name, s) \
     struct Expr##name : Expr \
     { \
+        Pos pos; \
         Expr * e1, * e2; \
         Expr##name(Expr * e1, Expr * e2) : e1(e1), e2(e2) { }; \
+        Expr##name(const Pos & pos, Expr * e1, Expr * e2) : pos(pos), e1(e1), e2(e2) { }; \
         void show(std::ostream & str) \
         { \
             str << *e1 << " " s " " << *e2; \
@@ -310,6 +295,7 @@ struct ExprApp : Expr
         void eval(EvalState & state, Env & env, Value & v); \
     };
 
+MakeBinOp(App, "")
 MakeBinOp(OpEq, "==")
 MakeBinOp(OpNEq, "!=")
 MakeBinOp(OpAnd, "&&")
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index d39d0c0a75bf..021f8b0266bc 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -335,10 +335,10 @@ expr_op
   | expr_op LEQ expr_op { $$ = new ExprOpNot(new ExprApp(CUR_POS, new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $3), $1)); }
   | expr_op '>' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $3), $1); }
   | expr_op GEQ expr_op { $$ = new ExprOpNot(new ExprApp(CUR_POS, new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $1), $3)); }
-  | expr_op AND expr_op { $$ = new ExprOpAnd($1, $3); }
-  | expr_op OR expr_op { $$ = new ExprOpOr($1, $3); }
-  | expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); }
-  | expr_op UPDATE expr_op { $$ = new ExprOpUpdate($1, $3); }
+  | expr_op AND expr_op { $$ = new ExprOpAnd(CUR_POS, $1, $3); }
+  | expr_op OR expr_op { $$ = new ExprOpOr(CUR_POS, $1, $3); }
+  | expr_op IMPL expr_op { $$ = new ExprOpImpl(CUR_POS, $1, $3); }
+  | expr_op UPDATE expr_op { $$ = new ExprOpUpdate(CUR_POS, $1, $3); }
   | expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); }
   | expr_op '+' expr_op
     { vector<Expr *> * l = new vector<Expr *>;
@@ -349,7 +349,7 @@ expr_op
   | expr_op '-' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprBuiltin(data->symbols.create("sub")), $1), $3); }
   | expr_op '*' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprBuiltin(data->symbols.create("mul")), $1), $3); }
   | expr_op '/' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprBuiltin(data->symbols.create("div")), $1), $3); }
-  | expr_op CONCAT expr_op { $$ = new ExprOpConcatLists($1, $3); }
+  | expr_op CONCAT expr_op { $$ = new ExprOpConcatLists(CUR_POS, $1, $3); }
   | expr_app
   ;
 
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 84ef967ffa91..b4e75648f8ab 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1042,7 +1042,7 @@ static void prim_elem(EvalState & state, const Pos & pos, Value * * args, Value
 static void prim_concatLists(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
     state.forceList(*args[0], pos);
-    state.concatLists(v, args[0]->list.length, args[0]->list.elems);
+    state.concatLists(v, args[0]->list.length, args[0]->list.elems, pos);
 }