guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

15/64: Include position info in function application


From: Ludovic Courtès
Subject: 15/64: Include position info in function application
Date: Mon, 05 Jan 2015 16:38:53 +0000

civodul pushed a commit to branch nix
in repository guix.

commit b72c8d2e5b5bbdc218f7c00694027cdd75b6a584
Author: Eelco Dolstra <address@hidden>
Date:   Fri Apr 4 17:53:52 2014 +0200

    Include position info in function application
    
    This allows error messages like:
    
      error: the anonymous function at `/etc/nixos/configuration.nix:1:1'
        called without required argument `foo', at
        
`/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/lib/modules.nix:77:59'
---
 src/libexpr/eval-inline.hh |    2 +-
 src/libexpr/eval.cc        |   31 +++++++++++++++++++------------
 src/libexpr/eval.hh        |    2 +-
 src/libexpr/nixexpr.cc     |    2 +-
 src/libexpr/nixexpr.hh     |   18 +++++++++++++++++-
 src/libexpr/parser.y       |    6 +++---
 src/libexpr/primops.cc     |    6 +++---
 7 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh
index 5801a20..ffe8fa5 100644
--- a/src/libexpr/eval-inline.hh
+++ b/src/libexpr/eval-inline.hh
@@ -35,7 +35,7 @@ void EvalState::forceValue(Value & v)
         }
     }
     else if (v.type == tApp)
-        callFunction(*v.app.left, *v.app.right, v);
+        callFunction(*v.app.left, *v.app.right, v, noPos);
     else if (v.type == tBlackhole)
         throwEvalError("infinite recursion encountered");
 }
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index bbf4943..d26a0e2 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -130,12 +130,14 @@ string showType(const Value & v)
 }
 
 
+#if HAVE_BOEHMGC
 /* Called when the Boehm GC runs out of memory. */
 static void * oomHandler(size_t requested)
 {
     /* Convert this to a proper C++ exception. */
     throw std::bad_alloc();
 }
+#endif
 
 
 static Symbol getName(const AttrName & name, EvalState & state, Env & env) {
@@ -292,14 +294,19 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, 
const string & s1))
     throw TypeError(format(s) % s1);
 }
 
+LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v, 
const Pos & pos))
+{
+    throw TypeError(format(s) % showType(v) % pos);
+}
+
 LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s1, 
const string & s2))
 {
     throw TypeError(format(s) % s1 % s2);
 }
 
-LocalNoInlineNoReturn(void throwTypeError(const char * s, const ExprLambda & 
fun, const Symbol & s2))
+LocalNoInlineNoReturn(void throwTypeError(const char * s, const ExprLambda & 
fun, const Symbol & s2, const Pos & pos))
 {
-    throw TypeError(format(s) % fun.showNamePos() % s2);
+    throw TypeError(format(s) % fun.showNamePos() % s2 % pos);
 }
 
 LocalNoInlineNoReturn(void throwAssertionError(const char * s, const Pos & 
pos))
@@ -317,9 +324,9 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * 
s, const string & s2))
     e.addPrefix(format(s) % s2);
 }
 
-LocalNoInline(void addErrorPrefix(Error & e, const char * s, const ExprLambda 
& fun))
+LocalNoInline(void addErrorPrefix(Error & e, const char * s, const ExprLambda 
& fun, const Pos & pos))
 {
-    e.addPrefix(format(s) % fun.showNamePos());
+    e.addPrefix(format(s) % fun.showNamePos() % pos);
 }
 
 LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & 
s2, const Pos & pos))
@@ -783,7 +790,7 @@ void ExprApp::eval(EvalState & state, Env & env, Value & v)
     /* FIXME: vFun prevents GCC from doing tail call optimisation. */
     Value vFun;
     e1->eval(state, env, vFun);
-    state.callFunction(vFun, *(e2->maybeThunk(state, env)), v);
+    state.callFunction(vFun, *(e2->maybeThunk(state, env)), v, pos);
 }
 
 
@@ -824,7 +831,7 @@ void EvalState::callPrimOp(Value & fun, Value & arg, Value 
& v)
 }
 
 
-void EvalState::callFunction(Value & fun, Value & arg, Value & v)
+void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & 
pos)
 {
     if (fun.type == tPrimOp || fun.type == tPrimOpApp) {
         callPrimOp(fun, arg, v);
@@ -832,7 +839,7 @@ void EvalState::callFunction(Value & fun, Value & arg, 
Value & v)
     }
 
     if (fun.type != tLambda)
-        throwTypeError("attempt to call something which is not a function but 
%1%", fun);
+        throwTypeError("attempt to call something which is not a function but 
%1%, at %2%", fun, pos);
 
     ExprLambda & lambda(*fun.lambda.fun);
 
@@ -860,8 +867,8 @@ void EvalState::callFunction(Value & fun, Value & arg, 
Value & v)
         foreach (Formals::Formals_::iterator, i, lambda.formals->formals) {
             Bindings::iterator j = arg.attrs->find(i->name);
             if (j == arg.attrs->end()) {
-                if (!i->def) throwTypeError("%1% called without required 
argument `%2%'",
-                    lambda, i->name);
+                if (!i->def) throwTypeError("%1% called without required 
argument `%2%', at %3%",
+                    lambda, i->name, pos);
                 env2.values[displ++] = i->def->maybeThunk(*this, env2);
             } else {
                 attrsUsed++;
@@ -876,7 +883,7 @@ void EvalState::callFunction(Value & fun, Value & arg, 
Value & v)
                user. */
             foreach (Bindings::iterator, i, *arg.attrs)
                 if (lambda.formals->argNames.find(i->name) == 
lambda.formals->argNames.end())
-                    throwTypeError("%1% called with unexpected argument 
`%2%'", lambda, i->name);
+                    throwTypeError("%1% called with unexpected argument `%2%', 
at %3%", lambda, i->name, pos);
             abort(); // can't happen
         }
     }
@@ -890,7 +897,7 @@ void EvalState::callFunction(Value & fun, Value & arg, 
Value & v)
         try {
             lambda.body->eval(*this, env2, v);
         } catch (Error & e) {
-            addErrorPrefix(e, "while evaluating %1%:\n", lambda);
+            addErrorPrefix(e, "while evaluating %1%, called from %2%:\n", 
lambda, pos);
             throw;
         }
     else
@@ -928,7 +935,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & 
fun, Value & res)
 
     actualArgs->attrs->sort();
 
-    callFunction(fun, *actualArgs, res);
+    callFunction(fun, *actualArgs, res, noPos);
 }
 
 
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 58d1318..170b740 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -226,7 +226,7 @@ public:
        elements and attributes are compared recursively. */
     bool eqValues(Value & v1, Value & v2);
 
-    void callFunction(Value & fun, Value & arg, Value & v);
+    void callFunction(Value & fun, Value & arg, Value & v, const Pos & pos);
     void callPrimOp(Value & fun, Value & arg, Value & v);
 
     /* Automatically call a function for which each argument has a
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index bca2b79..ba1f4f0 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -373,7 +373,7 @@ void ExprLambda::setName(Symbol & name)
 
 string ExprLambda::showNamePos() const
 {
-    return (format("%1% at %2%") % (name.set() ? "`" + (string) name + "'" : 
"an anonymous function") % pos).str();
+    return (format("%1% at %2%") % (name.set() ? "`" + (string) name + "'" : 
"anonymous function") % pos).str();
 }
 
 
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index a5c5d05..5275891 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -273,6 +273,23 @@ 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 \
     { \
@@ -289,7 +306,6 @@ struct ExprBuiltin : 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 ab0b862..b8d4d7c 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -224,7 +224,7 @@ void backToString(yyscan_t scanner);
 void backToIndString(yyscan_t scanner);
 
 
-static Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
+static inline Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
 {
     return Pos(data->path, loc.first_line, loc.first_column);
 }
@@ -355,7 +355,7 @@ expr_op
 
 expr_app
   : expr_app expr_select
-    { $$ = new ExprApp($1, $2); }
+    { $$ = new ExprApp(CUR_POS, $1, $2); }
   | expr_select { $$ = $1; }
   ;
 
@@ -367,7 +367,7 @@ expr_select
   | /* Backwards compatibility: because Nixpkgs has a rarely used
        function named ‘or’, allow stuff like ‘map or [...]’. */
     expr_simple OR_KW
-    { $$ = new ExprApp($1, new ExprVar(CUR_POS, data->symbols.create("or"))); }
+    { $$ = new ExprApp(CUR_POS, $1, new ExprVar(CUR_POS, 
data->symbols.create("or"))); }
   | expr_simple { $$ = $1; }
   ;
 
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index ca316f0..422d68f 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -711,7 +711,7 @@ struct FilterFromExpr : PathFilter
         mkString(arg1, path);
 
         Value fun2;
-        state.callFunction(filter, arg1, fun2);
+        state.callFunction(filter, arg1, fun2, noPos);
 
         Value arg2;
         mkString(arg2,
@@ -721,7 +721,7 @@ struct FilterFromExpr : PathFilter
             "unknown" /* not supported, will fail! */);
 
         Value res;
-        state.callFunction(fun2, arg2, res);
+        state.callFunction(fun2, arg2, res, noPos);
 
         return state.forceBool(res);
     }
@@ -1008,7 +1008,7 @@ static void prim_filter(EvalState & state, Value * * 
args, Value & v)
     bool same = true;
     for (unsigned int n = 0; n < args[1]->list.length; ++n) {
         Value res;
-        state.callFunction(*args[0], *args[1]->list.elems[n], res);
+        state.callFunction(*args[0], *args[1]->list.elems[n], res, noPos);
         if (state.forceBool(res))
             vs[k++] = args[1]->list.elems[n];
         else



reply via email to

[Prev in Thread] Current Thread [Next in Thread]