about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-04-04T19·14+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-04-04T19·14+0200
commita5fe73094016973a50741db0c5d51ca96c14147b (patch)
tree28393198f2cd307db18ec160d7139b2e77077ddd /src/libexpr
parent27b44b8cf7072b09a1929ee44ba784b1c8d5211a (diff)
forceString: Show position info
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval.cc33
-rw-r--r--src/libexpr/eval.hh4
-rw-r--r--src/libexpr/get-drvs.cc9
-rw-r--r--src/libexpr/nixexpr.cc2
-rw-r--r--src/libexpr/nixexpr.hh4
-rw-r--r--src/libexpr/primops.cc24
6 files changed, 46 insertions, 30 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 5c88a34a92ca..30a8793ee735 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -140,7 +140,8 @@ static void * oomHandler(size_t requested)
 #endif
 
 
-static Symbol getName(const AttrName & name, EvalState & state, Env & env) {
+static Symbol getName(const AttrName & name, EvalState & state, Env & env)
+{
     if (name.symbol.set()) {
         return name.symbol;
     } else {
@@ -279,6 +280,11 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, con
     throw EvalError(format(s) % s2 % s3);
 }
 
+LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, const string & s3, const Pos & pos))
+{
+    throw EvalError(format(s) % s2 % s3 % pos);
+}
+
 LocalNoInlineNoReturn(void throwEvalError(const char * s, const Symbol & sym, const Pos & p1, const Pos & p2))
 {
     throw EvalError(format(s) % sym % p1 % p2);
@@ -1172,11 +1178,15 @@ void EvalState::forceFunction(Value & v, const Pos & pos)
 }
 
 
-string EvalState::forceString(Value & v)
+string EvalState::forceString(Value & v, const Pos & pos)
 {
     forceValue(v);
-    if (v.type != tString)
-        throwTypeError("value is %1% while a string was expected", v);
+    if (v.type != tString) {
+        if (pos)
+            throwTypeError("value is %1% while a string was expected, at %2%", v, pos);
+        else
+            throwTypeError("value is %1% while a string was expected", v);
+    }
     return string(v.string.s);
 }
 
@@ -1197,12 +1207,17 @@ string EvalState::forceString(Value & v, PathSet & context)
 }
 
 
-string EvalState::forceStringNoCtx(Value & v)
+string EvalState::forceStringNoCtx(Value & v, const Pos & pos)
 {
-    string s = forceString(v);
-    if (v.string.context)
-        throwEvalError("the string `%1%' is not allowed to refer to a store path (such as `%2%')",
-            v.string.s, v.string.context[0]);
+    string s = forceString(v, pos);
+    if (v.string.context) {
+        if (pos)
+            throwEvalError("the string `%1%' is not allowed to refer to a store path (such as `%2%'), at %3%",
+                v.string.s, v.string.context[0], pos);
+        else
+            throwEvalError("the string `%1%' is not allowed to refer to a store path (such as `%2%')",
+                v.string.s, v.string.context[0]);
+    }
     return s;
 }
 
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 248805004c6b..1d53f498215c 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -165,9 +165,9 @@ public:
     inline void forceList(Value & v);
     inline void forceList(Value & v, const Pos & pos);
     void forceFunction(Value & v, const Pos & pos); // either lambda or primop
-    string forceString(Value & v);
+    string forceString(Value & v, const Pos & pos = noPos);
     string forceString(Value & v, PathSet & context);
-    string forceStringNoCtx(Value & v);
+    string forceStringNoCtx(Value & v, const Pos & pos = noPos);
 
     /* Return true iff the value `v' denotes a derivation (i.e. a
        set with attribute `type = "derivation"'). */
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 4e7690063a0b..88ea68a5f0bf 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -41,7 +41,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs()
             /* For each output... */
             for (unsigned int j = 0; j < i->value->list.length; ++j) {
                 /* Evaluate the corresponding set. */
-                string name = state->forceStringNoCtx(*i->value->list.elems[j]);
+                string name = state->forceStringNoCtx(*i->value->list.elems[j], *i->pos);
                 Bindings::iterator out = attrs->find(state->symbols.create(name));
                 if (out == attrs->end()) continue; // FIXME: throw error?
                 state->forceAttrs(*out->value);
@@ -199,11 +199,8 @@ static bool getDerivation(EvalState & state, Value & v,
 
         Bindings::iterator i2 = v.attrs->find(state.sSystem);
 
-        DrvInfo drv(
-            state,
-            state.forceStringNoCtx(*i->value),
-            attrPath,
-            i2 == v.attrs->end() ? "unknown" : state.forceStringNoCtx(*i2->value),
+        DrvInfo drv(state, state.forceStringNoCtx(*i->value), attrPath,
+            i2 == v.attrs->end() ? "unknown" : state.forceStringNoCtx(*i2->value, *i2->pos),
             v.attrs);
 
         drvs.push_back(drv);
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 92f46b30a370..d40250d8777d 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -145,7 +145,7 @@ void ExprPos::show(std::ostream & str)
 
 std::ostream & operator << (std::ostream & str, const Pos & pos)
 {
-    if (!pos.line)
+    if (!pos)
         str << "undefined position";
     else
         str << (format("%1%:%2%:%3%") % pos.file % pos.line % pos.column).str();
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 527589147e9c..9234e2970ffa 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -28,6 +28,10 @@ struct Pos
     Pos() : line(0), column(0) { };
     Pos(const Symbol & file, unsigned int line, unsigned int column)
         : file(file), line(line), column(column) { };
+    operator bool() const
+    {
+        return line != 0;
+    }
     bool operator < (const Pos & p2) const
     {
         if (!line) return p2.line;
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 2aa45525e6d5..00833403d7a7 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -299,7 +299,7 @@ static void prim_tryEval(EvalState & state, const Pos & pos, Value * * args, Val
 /* Return an environment variable.  Use with care. */
 static void prim_getEnv(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
-    string name = state.forceStringNoCtx(*args[0]);
+    string name = state.forceStringNoCtx(*args[0], pos);
     mkString(v, getEnv(name));
 }
 
@@ -343,7 +343,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
     string drvName;
     Pos & posDrvName(*attr->pos);
     try {
-        drvName = state.forceStringNoCtx(*attr->value);
+        drvName = state.forceStringNoCtx(*attr->value, pos);
     } catch (Error & e) {
         e.addPrefix(format("while evaluating the derivation attribute `name' at %1%:\n") % posDrvName);
         throw;
@@ -664,7 +664,7 @@ static void prim_toJSON(EvalState & state, const Pos & pos, Value * * args, Valu
 static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
     PathSet context;
-    string name = state.forceStringNoCtx(*args[0]);
+    string name = state.forceStringNoCtx(*args[0], pos);
     string contents = state.forceString(*args[1], context);
 
     PathSet refs;
@@ -775,7 +775,7 @@ static void prim_attrNames(EvalState & state, const Pos & pos, Value * * args, V
 /* Dynamic version of the `.' operator. */
 void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
-    string attr = state.forceStringNoCtx(*args[0]);
+    string attr = state.forceStringNoCtx(*args[0], pos);
     state.forceAttrs(*args[1], pos);
     // !!! Should we create a symbol here or just do a lookup?
     Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr));
@@ -791,7 +791,7 @@ void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v)
 /* Return position information of the specified attribute. */
 void prim_unsafeGetAttrPos(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
-    string attr = state.forceStringNoCtx(*args[0]);
+    string attr = state.forceStringNoCtx(*args[0], pos);
     state.forceAttrs(*args[1], pos);
     Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr));
     if (i == args[1]->attrs->end())
@@ -804,7 +804,7 @@ void prim_unsafeGetAttrPos(EvalState & state, const Pos & pos, Value * * args, V
 /* Dynamic version of the `?' operator. */
 static void prim_hasAttr(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
-    string attr = state.forceStringNoCtx(*args[0]);
+    string attr = state.forceStringNoCtx(*args[0], pos);
     state.forceAttrs(*args[1], pos);
     mkBool(v, args[1]->attrs->find(state.symbols.create(attr)) != args[1]->attrs->end());
 }
@@ -826,7 +826,7 @@ static void prim_removeAttrs(EvalState & state, const Pos & pos, Value * * args,
     /* Get the attribute names to be removed. */
     std::set<Symbol> names;
     for (unsigned int i = 0; i < args[1]->list.length; ++i) {
-        state.forceStringNoCtx(*args[1]->list.elems[i]);
+        state.forceStringNoCtx(*args[1]->list.elems[i], pos);
         names.insert(state.symbols.create(args[1]->list.elems[i]->string.s));
     }
 
@@ -861,7 +861,7 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args,
         Bindings::iterator j = v2.attrs->find(state.sName);
         if (j == v2.attrs->end())
             throw TypeError(format("`name' attribute missing in a call to `listToAttrs', at %1%") % pos);
-        string name = state.forceStringNoCtx(*j->value);
+        string name = state.forceStringNoCtx(*j->value, pos);
 
         Symbol sym = state.symbols.create(name);
         if (seen.find(sym) == seen.end()) {
@@ -1168,7 +1168,7 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & po
 /* Return the cryptographic hash of a string in base-16. */
 static void prim_hashString(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
-    string type = state.forceStringNoCtx(*args[0]);
+    string type = state.forceStringNoCtx(*args[0], pos);
     HashType ht = parseHashType(type);
     if (ht == htUnknown)
       throw Error(format("unknown hash type `%1%', at %2%") % type % pos);
@@ -1187,7 +1187,7 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
 
 static void prim_parseDrvName(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
-    string name = state.forceStringNoCtx(*args[0]);
+    string name = state.forceStringNoCtx(*args[0], pos);
     DrvName parsed(name);
     state.mkAttrs(v, 2);
     mkString(*state.allocAttr(v, state.sName), parsed.name);
@@ -1198,8 +1198,8 @@ static void prim_parseDrvName(EvalState & state, const Pos & pos, Value * * args
 
 static void prim_compareVersions(EvalState & state, const Pos & pos, Value * * args, Value & v)
 {
-    string version1 = state.forceStringNoCtx(*args[0]);
-    string version2 = state.forceStringNoCtx(*args[1]);
+    string version1 = state.forceStringNoCtx(*args[0], pos);
+    string version2 = state.forceStringNoCtx(*args[1], pos);
     mkInt(v, compareVersions(version1, version2));
 }