Pass position information to primop calls
For example:
  error: `tail' called on an empty list, at
    /home/eelco/Dev/nixpkgs/pkgs/applications/misc/hello/ex-2/default.nix:13:7
			
			
This commit is contained in:
		
							parent
							
								
									8b31ffd10d
								
							
						
					
					
						commit
						c28de6d96e
					
				
					 5 changed files with 105 additions and 105 deletions
				
			
		|  | @ -1,7 +1,7 @@ | ||||||
| /* This is the implementation of the ‘derivation’ builtin function. | /* This is the implementation of the ‘derivation’ builtin function. | ||||||
|    It's actually a wrapper around the ‘derivationStrict’ primop. */ |    It's actually a wrapper around the ‘derivationStrict’ primop. */ | ||||||
| 
 | 
 | ||||||
| drvAttrs @ { outputs ? [ "out" ], ... }: | drvAttrs @ { outputs ? [ "out" ], name, builder, system, ... }: | ||||||
| 
 | 
 | ||||||
| let | let | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -794,7 +794,7 @@ void ExprApp::eval(EvalState & state, Env & env, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void EvalState::callPrimOp(Value & fun, Value & arg, Value & v) | void EvalState::callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos) | ||||||
| { | { | ||||||
|     /* Figure out the number of arguments still needed. */ |     /* Figure out the number of arguments still needed. */ | ||||||
|     unsigned int argsDone = 0; |     unsigned int argsDone = 0; | ||||||
|  | @ -820,7 +820,7 @@ void EvalState::callPrimOp(Value & fun, Value & arg, Value & v) | ||||||
|         /* And call the primop. */ |         /* And call the primop. */ | ||||||
|         nrPrimOpCalls++; |         nrPrimOpCalls++; | ||||||
|         if (countCalls) primOpCalls[primOp->primOp->name]++; |         if (countCalls) primOpCalls[primOp->primOp->name]++; | ||||||
|         primOp->primOp->fun(*this, vArgs, v); |         primOp->primOp->fun(*this, pos, vArgs, v); | ||||||
|     } else { |     } else { | ||||||
|         Value * fun2 = allocValue(); |         Value * fun2 = allocValue(); | ||||||
|         *fun2 = fun; |         *fun2 = fun; | ||||||
|  | @ -834,7 +834,7 @@ void EvalState::callPrimOp(Value & fun, Value & arg, Value & v) | ||||||
| void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & pos) | void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & pos) | ||||||
| { | { | ||||||
|     if (fun.type == tPrimOp || fun.type == tPrimOpApp) { |     if (fun.type == tPrimOp || fun.type == tPrimOpApp) { | ||||||
|         callPrimOp(fun, arg, v); |         callPrimOp(fun, arg, v, pos); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ public: | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| typedef void (* PrimOpFun) (EvalState & state, Value * * args, Value & v); | typedef void (* PrimOpFun) (EvalState & state, const Pos & pos, Value * * args, Value & v); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| struct PrimOp | struct PrimOp | ||||||
|  | @ -227,7 +227,7 @@ public: | ||||||
|     bool eqValues(Value & v1, Value & v2); |     bool eqValues(Value & v1, Value & v2); | ||||||
| 
 | 
 | ||||||
|     void callFunction(Value & fun, Value & arg, Value & v, const Pos & pos); |     void callFunction(Value & fun, Value & arg, Value & v, const Pos & pos); | ||||||
|     void callPrimOp(Value & fun, Value & arg, Value & v); |     void callPrimOp(Value & fun, Value & arg, Value & v, const Pos & pos); | ||||||
| 
 | 
 | ||||||
|     /* Automatically call a function for which each argument has a
 |     /* Automatically call a function for which each argument has a
 | ||||||
|        default value or has a binding in the `args' map. */ |        default value or has a binding in the `args' map. */ | ||||||
|  | @ -278,7 +278,7 @@ private: | ||||||
|     friend struct ExprOpUpdate; |     friend struct ExprOpUpdate; | ||||||
|     friend struct ExprOpConcatLists; |     friend struct ExprOpConcatLists; | ||||||
|     friend struct ExprSelect; |     friend struct ExprSelect; | ||||||
|     friend void prim_getAttr(EvalState & state, Value * * args, Value & v); |     friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -328,13 +328,13 @@ expr_if | ||||||
| 
 | 
 | ||||||
| expr_op | expr_op | ||||||
|   : '!' expr_op %prec NOT { $$ = new ExprOpNot($2); } |   : '!' expr_op %prec NOT { $$ = new ExprOpNot($2); } | ||||||
| | '-' expr_op %prec NEGATE { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("sub")), new ExprInt(0)), $2); } | | '-' expr_op %prec NEGATE { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprBuiltin(data->symbols.create("sub")), new ExprInt(0)), $2); } | ||||||
|   | expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); } |   | expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); } | ||||||
|   | expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); } |   | expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); } | ||||||
|   | expr_op '<' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $1), $3); } |   | expr_op '<' expr_op { $$ = new ExprApp(CUR_POS, new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $1), $3); } | ||||||
|   | expr_op LEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $3), $1)); } |   | 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(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(new ExprApp(new ExprBuiltin(data->symbols.create("lessThan")), $1), $3)); } |   | 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 AND expr_op { $$ = new ExprOpAnd($1, $3); } | ||||||
|   | expr_op OR expr_op { $$ = new ExprOpOr($1, $3); } |   | expr_op OR expr_op { $$ = new ExprOpOr($1, $3); } | ||||||
|   | expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); } |   | expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); } | ||||||
|  | @ -346,9 +346,9 @@ expr_op | ||||||
|       l->push_back($3); |       l->push_back($3); | ||||||
|       $$ = new ExprConcatStrings(false, l); |       $$ = new ExprConcatStrings(false, l); | ||||||
|     } |     } | ||||||
|   | expr_op '-' expr_op { $$ = new ExprApp(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("sub")), $1), $3); } | ||||||
|   | expr_op '*' expr_op { $$ = new ExprApp(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("mul")), $1), $3); } | ||||||
|   | expr_op '/' expr_op { $$ = new ExprApp(new ExprApp(new ExprBuiltin(data->symbols.create("div")), $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($1, $3); } | ||||||
|   | expr_app |   | expr_app | ||||||
|   ; |   ; | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ std::pair<string, string> decodeContext(const string & s) | ||||||
| 
 | 
 | ||||||
| /* Load and evaluate an expression from path specified by the
 | /* Load and evaluate an expression from path specified by the
 | ||||||
|    argument. */ |    argument. */ | ||||||
| static void prim_import(EvalState & state, Value * * args, Value & v) | static void prim_import(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     Path path = state.coerceToPath(*args[0], context); |     Path path = state.coerceToPath(*args[0], context); | ||||||
|  | @ -48,8 +48,8 @@ static void prim_import(EvalState & state, Value * * args, Value & v) | ||||||
|         Path ctx = decodeContext(*i).first; |         Path ctx = decodeContext(*i).first; | ||||||
|         assert(isStorePath(ctx)); |         assert(isStorePath(ctx)); | ||||||
|         if (!store->isValidPath(ctx)) |         if (!store->isValidPath(ctx)) | ||||||
|             throw EvalError(format("cannot import `%1%', since path `%2%' is not valid") |             throw EvalError(format("cannot import `%1%', since path `%2%' is not valid, at %3%") | ||||||
|                 % path % ctx); |                 % path % ctx % pos); | ||||||
|         if (isDerivation(ctx)) |         if (isDerivation(ctx)) | ||||||
|             try { |             try { | ||||||
|                 /* For performance, prefetch all substitute info. */ |                 /* For performance, prefetch all substitute info. */ | ||||||
|  | @ -94,7 +94,7 @@ static void prim_import(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return a string representing the type of the expression. */ | /* Return a string representing the type of the expression. */ | ||||||
| static void prim_typeOf(EvalState & state, Value * * args, Value & v) | static void prim_typeOf(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     string t; |     string t; | ||||||
|  | @ -118,7 +118,7 @@ static void prim_typeOf(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Determine whether the argument is the null value. */ | /* Determine whether the argument is the null value. */ | ||||||
| static void prim_isNull(EvalState & state, Value * * args, Value & v) | static void prim_isNull(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     mkBool(v, args[0]->type == tNull); |     mkBool(v, args[0]->type == tNull); | ||||||
|  | @ -126,7 +126,7 @@ static void prim_isNull(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Determine whether the argument is a function. */ | /* Determine whether the argument is a function. */ | ||||||
| static void prim_isFunction(EvalState & state, Value * * args, Value & v) | static void prim_isFunction(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     mkBool(v, args[0]->type == tLambda); |     mkBool(v, args[0]->type == tLambda); | ||||||
|  | @ -134,7 +134,7 @@ static void prim_isFunction(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Determine whether the argument is an integer. */ | /* Determine whether the argument is an integer. */ | ||||||
| static void prim_isInt(EvalState & state, Value * * args, Value & v) | static void prim_isInt(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     mkBool(v, args[0]->type == tInt); |     mkBool(v, args[0]->type == tInt); | ||||||
|  | @ -142,7 +142,7 @@ static void prim_isInt(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Determine whether the argument is a string. */ | /* Determine whether the argument is a string. */ | ||||||
| static void prim_isString(EvalState & state, Value * * args, Value & v) | static void prim_isString(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     mkBool(v, args[0]->type == tString); |     mkBool(v, args[0]->type == tString); | ||||||
|  | @ -150,7 +150,7 @@ static void prim_isString(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Determine whether the argument is a Boolean. */ | /* Determine whether the argument is a Boolean. */ | ||||||
| static void prim_isBool(EvalState & state, Value * * args, Value & v) | static void prim_isBool(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     mkBool(v, args[0]->type == tBool); |     mkBool(v, args[0]->type == tBool); | ||||||
|  | @ -184,7 +184,7 @@ typedef list<Value *> ValueList; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_genericClosure(EvalState & state, Value * * args, Value & v) | static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     startNest(nest, lvlDebug, "finding dependencies"); |     startNest(nest, lvlDebug, "finding dependencies"); | ||||||
| 
 | 
 | ||||||
|  | @ -194,7 +194,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v) | ||||||
|     Bindings::iterator startSet = |     Bindings::iterator startSet = | ||||||
|         args[0]->attrs->find(state.symbols.create("startSet")); |         args[0]->attrs->find(state.symbols.create("startSet")); | ||||||
|     if (startSet == args[0]->attrs->end()) |     if (startSet == args[0]->attrs->end()) | ||||||
|         throw EvalError("attribute `startSet' required"); |         throw EvalError(format("attribute `startSet' required, at %1%") % pos); | ||||||
|     state.forceList(*startSet->value); |     state.forceList(*startSet->value); | ||||||
| 
 | 
 | ||||||
|     ValueList workSet; |     ValueList workSet; | ||||||
|  | @ -205,7 +205,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v) | ||||||
|     Bindings::iterator op = |     Bindings::iterator op = | ||||||
|         args[0]->attrs->find(state.symbols.create("operator")); |         args[0]->attrs->find(state.symbols.create("operator")); | ||||||
|     if (op == args[0]->attrs->end()) |     if (op == args[0]->attrs->end()) | ||||||
|         throw EvalError("attribute `operator' required"); |         throw EvalError(format("attribute `operator' required, at %1%") % pos); | ||||||
|     state.forceValue(*op->value); |     state.forceValue(*op->value); | ||||||
| 
 | 
 | ||||||
|     /* Construct the closure by applying the operator to element of
 |     /* Construct the closure by applying the operator to element of
 | ||||||
|  | @ -224,7 +224,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v) | ||||||
|         Bindings::iterator key = |         Bindings::iterator key = | ||||||
|             e->attrs->find(state.symbols.create("key")); |             e->attrs->find(state.symbols.create("key")); | ||||||
|         if (key == e->attrs->end()) |         if (key == e->attrs->end()) | ||||||
|             throw EvalError("attribute `key' required"); |             throw EvalError(format("attribute `key' required, at %1%") % pos); | ||||||
|         state.forceValue(*key->value); |         state.forceValue(*key->value); | ||||||
| 
 | 
 | ||||||
|         if (doneKeys.find(key->value) != doneKeys.end()) continue; |         if (doneKeys.find(key->value) != doneKeys.end()) continue; | ||||||
|  | @ -251,7 +251,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_abort(EvalState & state, Value * * args, Value & v) | static void prim_abort(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     throw Abort(format("evaluation aborted with the following error message: `%1%'") % |     throw Abort(format("evaluation aborted with the following error message: `%1%'") % | ||||||
|  | @ -259,14 +259,14 @@ static void prim_abort(EvalState & state, Value * * args, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_throw(EvalState & state, Value * * args, Value & v) | static void prim_throw(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     throw ThrownError(format("%1%") % state.coerceToString(*args[0], context)); |     throw ThrownError(format("%1%") % state.coerceToString(*args[0], context)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_addErrorContext(EvalState & state, Value * * args, Value & v) | static void prim_addErrorContext(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     try { |     try { | ||||||
|         state.forceValue(*args[1]); |         state.forceValue(*args[1]); | ||||||
|  | @ -281,7 +281,7 @@ static void prim_addErrorContext(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| /* Try evaluating the argument. Success => {success=true; value=something;},
 | /* Try evaluating the argument. Success => {success=true; value=something;},
 | ||||||
|  * else => {success=false; value=false;} */ |  * else => {success=false; value=false;} */ | ||||||
| static void prim_tryEval(EvalState & state, Value * * args, Value & v) | static void prim_tryEval(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.mkAttrs(v, 2); |     state.mkAttrs(v, 2); | ||||||
|     try { |     try { | ||||||
|  | @ -297,7 +297,7 @@ static void prim_tryEval(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return an environment variable.  Use with care. */ | /* Return an environment variable.  Use with care. */ | ||||||
| static void prim_getEnv(EvalState & state, Value * * args, Value & v) | 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]); | ||||||
|     mkString(v, getEnv(name)); |     mkString(v, getEnv(name)); | ||||||
|  | @ -306,7 +306,7 @@ static void prim_getEnv(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| /* Evaluate the first expression and print it on standard error.  Then
 | /* Evaluate the first expression and print it on standard error.  Then
 | ||||||
|    return the second expression.  Useful for debugging. */ |    return the second expression.  Useful for debugging. */ | ||||||
| static void prim_trace(EvalState & state, Value * * args, Value & v) | static void prim_trace(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     if (args[0]->type == tString) |     if (args[0]->type == tString) | ||||||
|  | @ -330,7 +330,7 @@ static void prim_trace(EvalState & state, Value * * args, Value & v) | ||||||
|    derivation; `drvPath' containing the path of the Nix expression; |    derivation; `drvPath' containing the path of the Nix expression; | ||||||
|    and `type' set to `derivation' to indicate that this is a |    and `type' set to `derivation' to indicate that this is a | ||||||
|    derivation. */ |    derivation. */ | ||||||
| static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) | static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     startNest(nest, lvlVomit, "evaluating derivation"); |     startNest(nest, lvlVomit, "evaluating derivation"); | ||||||
| 
 | 
 | ||||||
|  | @ -339,7 +339,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) | ||||||
|     /* Figure out the name first (for stack backtraces). */ |     /* Figure out the name first (for stack backtraces). */ | ||||||
|     Bindings::iterator attr = args[0]->attrs->find(state.sName); |     Bindings::iterator attr = args[0]->attrs->find(state.sName); | ||||||
|     if (attr == args[0]->attrs->end()) |     if (attr == args[0]->attrs->end()) | ||||||
|         throw EvalError("required attribute `name' missing"); |         throw EvalError(format("required attribute `name' missing, at %1%") % pos); | ||||||
|     string drvName; |     string drvName; | ||||||
|     Pos & posDrvName(*attr->pos); |     Pos & posDrvName(*attr->pos); | ||||||
|     try { |     try { | ||||||
|  | @ -404,25 +404,25 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) | ||||||
|                 else if (key == "outputHashMode") { |                 else if (key == "outputHashMode") { | ||||||
|                     if (s == "recursive") outputHashRecursive = true; |                     if (s == "recursive") outputHashRecursive = true; | ||||||
|                     else if (s == "flat") outputHashRecursive = false; |                     else if (s == "flat") outputHashRecursive = false; | ||||||
|                     else throw EvalError(format("invalid value `%1%' for `outputHashMode' attribute") % s); |                     else throw EvalError(format("invalid value `%1%' for `outputHashMode' attribute, at %2%") % s % posDrvName); | ||||||
|                 } |                 } | ||||||
|                 else if (key == "outputs") { |                 else if (key == "outputs") { | ||||||
|                     Strings tmp = tokenizeString<Strings>(s); |                     Strings tmp = tokenizeString<Strings>(s); | ||||||
|                     outputs.clear(); |                     outputs.clear(); | ||||||
|                     foreach (Strings::iterator, j, tmp) { |                     foreach (Strings::iterator, j, tmp) { | ||||||
|                         if (outputs.find(*j) != outputs.end()) |                         if (outputs.find(*j) != outputs.end()) | ||||||
|                             throw EvalError(format("duplicate derivation output `%1%'") % *j); |                             throw EvalError(format("duplicate derivation output `%1%', at %2%") % *j % posDrvName); | ||||||
|                         /* !!! Check whether *j is a valid attribute
 |                         /* !!! Check whether *j is a valid attribute
 | ||||||
|                            name. */ |                            name. */ | ||||||
|                         /* Derivations cannot be named ‘drv’, because
 |                         /* Derivations cannot be named ‘drv’, because
 | ||||||
|                            then we'd have an attribute ‘drvPath’ in |                            then we'd have an attribute ‘drvPath’ in | ||||||
|                            the resulting set. */ |                            the resulting set. */ | ||||||
|                         if (*j == "drv") |                         if (*j == "drv") | ||||||
|                             throw EvalError(format("invalid derivation output name `drv'") % *j); |                             throw EvalError(format("invalid derivation output name `drv', at %1%") % posDrvName); | ||||||
|                         outputs.insert(*j); |                         outputs.insert(*j); | ||||||
|                     } |                     } | ||||||
|                     if (outputs.empty()) |                     if (outputs.empty()) | ||||||
|                         throw EvalError("derivation cannot have an empty set of outputs"); |                         throw EvalError(format("derivation cannot have an empty set of outputs, at %1%") % posDrvName); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -478,24 +478,24 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
|     /* Do we have all required attributes? */ |     /* Do we have all required attributes? */ | ||||||
|     if (drv.builder == "") |     if (drv.builder == "") | ||||||
|         throw EvalError("required attribute `builder' missing"); |         throw EvalError(format("required attribute `builder' missing, at %1%") % posDrvName); | ||||||
|     if (drv.platform == "") |     if (drv.platform == "") | ||||||
|         throw EvalError("required attribute `system' missing"); |         throw EvalError(format("required attribute `system' missing, at %1%") % posDrvName); | ||||||
| 
 | 
 | ||||||
|     /* Check whether the derivation name is valid. */ |     /* Check whether the derivation name is valid. */ | ||||||
|     checkStoreName(drvName); |     checkStoreName(drvName); | ||||||
|     if (isDerivation(drvName)) |     if (isDerivation(drvName)) | ||||||
|         throw EvalError(format("derivation names are not allowed to end in `%1%'") |         throw EvalError(format("derivation names are not allowed to end in `%1%', at %2%") | ||||||
|             % drvExtension); |             % drvExtension % posDrvName); | ||||||
| 
 | 
 | ||||||
|     if (outputHash != "") { |     if (outputHash != "") { | ||||||
|         /* Handle fixed-output derivations. */ |         /* Handle fixed-output derivations. */ | ||||||
|         if (outputs.size() != 1 || *(outputs.begin()) != "out") |         if (outputs.size() != 1 || *(outputs.begin()) != "out") | ||||||
|             throw Error("multiple outputs are not supported in fixed-output derivations"); |             throw Error(format("multiple outputs are not supported in fixed-output derivations, at %1%") % posDrvName); | ||||||
| 
 | 
 | ||||||
|         HashType ht = parseHashType(outputHashAlgo); |         HashType ht = parseHashType(outputHashAlgo); | ||||||
|         if (ht == htUnknown) |         if (ht == htUnknown) | ||||||
|             throw EvalError(format("unknown hash algorithm `%1%'") % outputHashAlgo); |             throw EvalError(format("unknown hash algorithm `%1%', at %2%") % outputHashAlgo % posDrvName); | ||||||
|         Hash h = parseHash16or32(ht, outputHash); |         Hash h = parseHash16or32(ht, outputHash); | ||||||
|         outputHash = printHash(h); |         outputHash = printHash(h); | ||||||
|         if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo; |         if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo; | ||||||
|  | @ -555,7 +555,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Convert the argument to a path.  !!! obsolete? */ | /* Convert the argument to a path.  !!! obsolete? */ | ||||||
| static void prim_toPath(EvalState & state, Value * * args, Value & v) | static void prim_toPath(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     Path path = state.coerceToPath(*args[0], context); |     Path path = state.coerceToPath(*args[0], context); | ||||||
|  | @ -571,7 +571,7 @@ static void prim_toPath(EvalState & state, Value * * args, Value & v) | ||||||
|    /nix/store/newhash-oldhash-oldname.  In the past, `toPath' had |    /nix/store/newhash-oldhash-oldname.  In the past, `toPath' had | ||||||
|    special case behaviour for store paths, but that created weird |    special case behaviour for store paths, but that created weird | ||||||
|    corner cases. */ |    corner cases. */ | ||||||
| static void prim_storePath(EvalState & state, Value * * args, Value & v) | static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     Path path = state.coerceToPath(*args[0], context); |     Path path = state.coerceToPath(*args[0], context); | ||||||
|  | @ -580,7 +580,7 @@ static void prim_storePath(EvalState & state, Value * * args, Value & v) | ||||||
|        e.g. nix-push does the right thing. */ |        e.g. nix-push does the right thing. */ | ||||||
|     if (!isStorePath(path)) path = canonPath(path, true); |     if (!isStorePath(path)) path = canonPath(path, true); | ||||||
|     if (!isInStore(path)) |     if (!isInStore(path)) | ||||||
|         throw EvalError(format("path `%1%' is not in the Nix store") % path); |         throw EvalError(format("path `%1%' is not in the Nix store, at %2%") % path % pos); | ||||||
|     Path path2 = toStorePath(path); |     Path path2 = toStorePath(path); | ||||||
|     if (!settings.readOnlyMode) |     if (!settings.readOnlyMode) | ||||||
|         store->ensurePath(path2); |         store->ensurePath(path2); | ||||||
|  | @ -589,19 +589,19 @@ static void prim_storePath(EvalState & state, Value * * args, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_pathExists(EvalState & state, Value * * args, Value & v) | static void prim_pathExists(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     Path path = state.coerceToPath(*args[0], context); |     Path path = state.coerceToPath(*args[0], context); | ||||||
|     if (!context.empty()) |     if (!context.empty()) | ||||||
|         throw EvalError(format("string `%1%' cannot refer to other paths") % path); |         throw EvalError(format("string `%1%' cannot refer to other paths, at %2%") % path % pos); | ||||||
|     mkBool(v, pathExists(path)); |     mkBool(v, pathExists(path)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return the base name of the given string, i.e., everything
 | /* Return the base name of the given string, i.e., everything
 | ||||||
|    following the last slash. */ |    following the last slash. */ | ||||||
| static void prim_baseNameOf(EvalState & state, Value * * args, Value & v) | static void prim_baseNameOf(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     mkString(v, baseNameOf(state.coerceToString(*args[0], context)), context); |     mkString(v, baseNameOf(state.coerceToString(*args[0], context)), context); | ||||||
|  | @ -611,7 +611,7 @@ static void prim_baseNameOf(EvalState & state, Value * * args, Value & v) | ||||||
| /* Return the directory of the given path, i.e., everything before the
 | /* Return the directory of the given path, i.e., everything before the
 | ||||||
|    last slash.  Return either a path or a string depending on the type |    last slash.  Return either a path or a string depending on the type | ||||||
|    of the argument. */ |    of the argument. */ | ||||||
| static void prim_dirOf(EvalState & state, Value * * args, Value & v) | static void prim_dirOf(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     Path dir = dirOf(state.coerceToPath(*args[0], context)); |     Path dir = dirOf(state.coerceToPath(*args[0], context)); | ||||||
|  | @ -620,12 +620,12 @@ static void prim_dirOf(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return the contents of a file as a string. */ | /* Return the contents of a file as a string. */ | ||||||
| static void prim_readFile(EvalState & state, Value * * args, Value & v) | static void prim_readFile(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     Path path = state.coerceToPath(*args[0], context); |     Path path = state.coerceToPath(*args[0], context); | ||||||
|     if (!context.empty()) |     if (!context.empty()) | ||||||
|         throw EvalError(format("string `%1%' cannot refer to other paths") % path); |         throw EvalError(format("string `%1%' cannot refer to other paths, at %2%") % path % pos); | ||||||
|     mkString(v, readFile(path).c_str()); |     mkString(v, readFile(path).c_str()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -638,7 +638,7 @@ static void prim_readFile(EvalState & state, Value * * args, Value & v) | ||||||
| /* Convert the argument (which can be any Nix expression) to an XML
 | /* Convert the argument (which can be any Nix expression) to an XML
 | ||||||
|    representation returned in a string.  Not all Nix expressions can |    representation returned in a string.  Not all Nix expressions can | ||||||
|    be sensibly or completely represented (e.g., functions). */ |    be sensibly or completely represented (e.g., functions). */ | ||||||
| static void prim_toXML(EvalState & state, Value * * args, Value & v) | static void prim_toXML(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     std::ostringstream out; |     std::ostringstream out; | ||||||
|     PathSet context; |     PathSet context; | ||||||
|  | @ -650,7 +650,7 @@ static void prim_toXML(EvalState & state, Value * * args, Value & v) | ||||||
| /* Convert the argument (which can be any Nix expression) to a JSON
 | /* Convert the argument (which can be any Nix expression) to a JSON
 | ||||||
|    string.  Not all Nix expressions can be sensibly or completely |    string.  Not all Nix expressions can be sensibly or completely | ||||||
|    represented (e.g., functions). */ |    represented (e.g., functions). */ | ||||||
| static void prim_toJSON(EvalState & state, Value * * args, Value & v) | static void prim_toJSON(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     std::ostringstream out; |     std::ostringstream out; | ||||||
|     PathSet context; |     PathSet context; | ||||||
|  | @ -661,7 +661,7 @@ static void prim_toJSON(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| /* Store a string in the Nix store as a source file that can be used
 | /* Store a string in the Nix store as a source file that can be used
 | ||||||
|    as an input by derivations. */ |    as an input by derivations. */ | ||||||
| static void prim_toFile(EvalState & state, Value * * args, Value & v) | static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     string name = state.forceStringNoCtx(*args[0]); |     string name = state.forceStringNoCtx(*args[0]); | ||||||
|  | @ -673,7 +673,7 @@ static void prim_toFile(EvalState & state, Value * * args, Value & v) | ||||||
|         Path path = *i; |         Path path = *i; | ||||||
|         if (path.at(0) == '=') path = string(path, 1); |         if (path.at(0) == '=') path = string(path, 1); | ||||||
|         if (isDerivation(path)) |         if (isDerivation(path)) | ||||||
|             throw EvalError(format("in `toFile': the file `%1%' cannot refer to derivation outputs") % name); |             throw EvalError(format("in `toFile': the file `%1%' cannot refer to derivation outputs, at %2%") % name % pos); | ||||||
|         refs.insert(path); |         refs.insert(path); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -728,16 +728,16 @@ struct FilterFromExpr : PathFilter | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_filterSource(EvalState & state, Value * * args, Value & v) | static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     Path path = state.coerceToPath(*args[1], context); |     Path path = state.coerceToPath(*args[1], context); | ||||||
|     if (!context.empty()) |     if (!context.empty()) | ||||||
|         throw EvalError(format("string `%1%' cannot refer to other paths") % path); |         throw EvalError(format("string `%1%' cannot refer to other paths, at %2%") % path % pos); | ||||||
| 
 | 
 | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     if (args[0]->type != tLambda) |     if (args[0]->type != tLambda) | ||||||
|         throw TypeError(format("first argument in call to `filterSource' is not a function but %1%") % showType(*args[0])); |         throw TypeError(format("first argument in call to `filterSource' is not a function but %1%, at %2%") % showType(*args[0]) % pos); | ||||||
| 
 | 
 | ||||||
|     FilterFromExpr filter(state, *args[0]); |     FilterFromExpr filter(state, *args[0]); | ||||||
| 
 | 
 | ||||||
|  | @ -756,7 +756,7 @@ static void prim_filterSource(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| /* Return the names of the attributes in a set as a sorted list of
 | /* Return the names of the attributes in a set as a sorted list of
 | ||||||
|    strings. */ |    strings. */ | ||||||
| static void prim_attrNames(EvalState & state, Value * * args, Value & v) | static void prim_attrNames(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceAttrs(*args[0]); |     state.forceAttrs(*args[0]); | ||||||
| 
 | 
 | ||||||
|  | @ -773,14 +773,14 @@ static void prim_attrNames(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Dynamic version of the `.' operator. */ | /* Dynamic version of the `.' operator. */ | ||||||
| void prim_getAttr(EvalState & state, Value * * args, Value & v) | void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     string attr = state.forceStringNoCtx(*args[0]); |     string attr = state.forceStringNoCtx(*args[0]); | ||||||
|     state.forceAttrs(*args[1]); |     state.forceAttrs(*args[1]); | ||||||
|     // !!! Should we create a symbol here or just do a lookup?
 |     // !!! Should we create a symbol here or just do a lookup?
 | ||||||
|     Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr)); |     Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr)); | ||||||
|     if (i == args[1]->attrs->end()) |     if (i == args[1]->attrs->end()) | ||||||
|         throw EvalError(format("attribute `%1%' missing") % attr); |         throw EvalError(format("attribute `%1%' missing, at %2%") % attr % pos); | ||||||
|     // !!! add to stack trace?
 |     // !!! add to stack trace?
 | ||||||
|     if (state.countCalls && i->pos) state.attrSelects[*i->pos]++; |     if (state.countCalls && i->pos) state.attrSelects[*i->pos]++; | ||||||
|     state.forceValue(*i->value); |     state.forceValue(*i->value); | ||||||
|  | @ -789,7 +789,7 @@ void prim_getAttr(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return position information of the specified attribute. */ | /* Return position information of the specified attribute. */ | ||||||
| void prim_unsafeGetAttrPos(EvalState & state, Value * * args, Value & v) | void prim_unsafeGetAttrPos(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     string attr = state.forceStringNoCtx(*args[0]); |     string attr = state.forceStringNoCtx(*args[0]); | ||||||
|     state.forceAttrs(*args[1]); |     state.forceAttrs(*args[1]); | ||||||
|  | @ -802,7 +802,7 @@ void prim_unsafeGetAttrPos(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Dynamic version of the `?' operator. */ | /* Dynamic version of the `?' operator. */ | ||||||
| static void prim_hasAttr(EvalState & state, Value * * args, Value & v) | 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]); | ||||||
|     state.forceAttrs(*args[1]); |     state.forceAttrs(*args[1]); | ||||||
|  | @ -811,14 +811,14 @@ static void prim_hasAttr(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Determine whether the argument is a set. */ | /* Determine whether the argument is a set. */ | ||||||
| static void prim_isAttrs(EvalState & state, Value * * args, Value & v) | static void prim_isAttrs(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     mkBool(v, args[0]->type == tAttrs); |     mkBool(v, args[0]->type == tAttrs); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_removeAttrs(EvalState & state, Value * * args, Value & v) | static void prim_removeAttrs(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceAttrs(*args[0]); |     state.forceAttrs(*args[0]); | ||||||
|     state.forceList(*args[1]); |     state.forceList(*args[1]); | ||||||
|  | @ -846,7 +846,7 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v) | ||||||
|    "nameN"; value = valueN;}] is transformed to {name1 = value1; |    "nameN"; value = valueN;}] is transformed to {name1 = value1; | ||||||
|    ... nameN = valueN;}.  In case of duplicate occurences of the same |    ... nameN = valueN;}.  In case of duplicate occurences of the same | ||||||
|    name, the first takes precedence. */ |    name, the first takes precedence. */ | ||||||
| static void prim_listToAttrs(EvalState & state, Value * * args, Value & v) | static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceList(*args[0]); |     state.forceList(*args[0]); | ||||||
| 
 | 
 | ||||||
|  | @ -860,14 +860,14 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
|         Bindings::iterator j = v2.attrs->find(state.sName); |         Bindings::iterator j = v2.attrs->find(state.sName); | ||||||
|         if (j == v2.attrs->end()) |         if (j == v2.attrs->end()) | ||||||
|             throw TypeError("`name' attribute missing in a call to `listToAttrs'"); |             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); | ||||||
| 
 | 
 | ||||||
|         Symbol sym = state.symbols.create(name); |         Symbol sym = state.symbols.create(name); | ||||||
|         if (seen.find(sym) == seen.end()) { |         if (seen.find(sym) == seen.end()) { | ||||||
|             Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue)); |             Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue)); | ||||||
|             if (j2 == v2.attrs->end()) |             if (j2 == v2.attrs->end()) | ||||||
|                 throw TypeError("`value' attribute missing in a call to `listToAttrs'"); |                 throw TypeError(format("`value' attribute missing in a call to `listToAttrs', at %1%") % pos); | ||||||
| 
 | 
 | ||||||
|             v.attrs->push_back(Attr(sym, j2->value, j2->pos)); |             v.attrs->push_back(Attr(sym, j2->value, j2->pos)); | ||||||
|             seen.insert(sym); |             seen.insert(sym); | ||||||
|  | @ -881,7 +881,7 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v) | ||||||
| /* Return the right-biased intersection of two sets as1 and as2,
 | /* Return the right-biased intersection of two sets as1 and as2,
 | ||||||
|    i.e. a set that contains every attribute from as2 that is also a |    i.e. a set that contains every attribute from as2 that is also a | ||||||
|    member of as1. */ |    member of as1. */ | ||||||
| static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v) | static void prim_intersectAttrs(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceAttrs(*args[0]); |     state.forceAttrs(*args[0]); | ||||||
|     state.forceAttrs(*args[1]); |     state.forceAttrs(*args[1]); | ||||||
|  | @ -909,11 +909,11 @@ static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v) | ||||||
|       functionArgs (x: ...) |       functionArgs (x: ...) | ||||||
|    => { } |    => { } | ||||||
| */ | */ | ||||||
| static void prim_functionArgs(EvalState & state, Value * * args, Value & v) | static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     if (args[0]->type != tLambda) |     if (args[0]->type != tLambda) | ||||||
|         throw TypeError("`functionArgs' requires a function"); |         throw TypeError(format("`functionArgs' requires a function, at %1%") % pos); | ||||||
| 
 | 
 | ||||||
|     if (!args[0]->lambda.fun->matchAttrs) { |     if (!args[0]->lambda.fun->matchAttrs) { | ||||||
|         state.mkAttrs(v, 0); |         state.mkAttrs(v, 0); | ||||||
|  | @ -934,45 +934,45 @@ static void prim_functionArgs(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Determine whether the argument is a list. */ | /* Determine whether the argument is a list. */ | ||||||
| static void prim_isList(EvalState & state, Value * * args, Value & v) | static void prim_isList(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     mkBool(v, args[0]->type == tList); |     mkBool(v, args[0]->type == tList); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void elemAt(EvalState & state, Value & list, int n, Value & v) | static void elemAt(EvalState & state, const Pos & pos, Value & list, int n, Value & v) | ||||||
| { | { | ||||||
|     state.forceList(list); |     state.forceList(list); | ||||||
|     if (n < 0 || n >= list.list.length) |     if (n < 0 || n >= list.list.length) | ||||||
|         throw Error(format("list index %1% is out of bounds") % n); |         throw Error(format("list index %1% is out of bounds, at %2%") % n % pos); | ||||||
|     state.forceValue(*list.list.elems[n]); |     state.forceValue(*list.list.elems[n]); | ||||||
|     v = *list.list.elems[n]; |     v = *list.list.elems[n]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return the n-1'th element of a list. */ | /* Return the n-1'th element of a list. */ | ||||||
| static void prim_elemAt(EvalState & state, Value * * args, Value & v) | static void prim_elemAt(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     elemAt(state, *args[0], state.forceInt(*args[1]), v); |     elemAt(state, pos, *args[0], state.forceInt(*args[1]), v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return the first element of a list. */ | /* Return the first element of a list. */ | ||||||
| static void prim_head(EvalState & state, Value * * args, Value & v) | static void prim_head(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     elemAt(state, *args[0], 0, v); |     elemAt(state, pos, *args[0], 0, v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return a list consisting of everything but the the first element of
 | /* Return a list consisting of everything but the the first element of
 | ||||||
|    a list.  Warning: this function takes O(n) time, so you probably |    a list.  Warning: this function takes O(n) time, so you probably | ||||||
|    don't want to use it!  */ |    don't want to use it!  */ | ||||||
| static void prim_tail(EvalState & state, Value * * args, Value & v) | static void prim_tail(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceList(*args[0]); |     state.forceList(*args[0]); | ||||||
|     if (args[0]->list.length == 0) |     if (args[0]->list.length == 0) | ||||||
|         throw Error("`tail' called on an empty list"); |         throw Error(format("`tail' called on an empty list, at %1%") % pos); | ||||||
|     state.mkList(v, args[0]->list.length - 1); |     state.mkList(v, args[0]->list.length - 1); | ||||||
|     for (unsigned int n = 0; n < v.list.length; ++n) |     for (unsigned int n = 0; n < v.list.length; ++n) | ||||||
|         v.list.elems[n] = args[0]->list.elems[n + 1]; |         v.list.elems[n] = args[0]->list.elems[n + 1]; | ||||||
|  | @ -980,7 +980,7 @@ static void prim_tail(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Apply a function to every element of a list. */ | /* Apply a function to every element of a list. */ | ||||||
| static void prim_map(EvalState & state, Value * * args, Value & v) | static void prim_map(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceFunction(*args[0]); |     state.forceFunction(*args[0]); | ||||||
|     state.forceList(*args[1]); |     state.forceList(*args[1]); | ||||||
|  | @ -996,7 +996,7 @@ static void prim_map(EvalState & state, Value * * args, Value & v) | ||||||
| /* Filter a list using a predicate; that is, return a list containing
 | /* Filter a list using a predicate; that is, return a list containing
 | ||||||
|    every element from the list for which the predicate function |    every element from the list for which the predicate function | ||||||
|    returns true. */ |    returns true. */ | ||||||
| static void prim_filter(EvalState & state, Value * * args, Value & v) | static void prim_filter(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceFunction(*args[0]); |     state.forceFunction(*args[0]); | ||||||
|     state.forceList(*args[1]); |     state.forceList(*args[1]); | ||||||
|  | @ -1025,7 +1025,7 @@ static void prim_filter(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return true if a list contains a given element. */ | /* Return true if a list contains a given element. */ | ||||||
| static void prim_elem(EvalState & state, Value * * args, Value & v) | static void prim_elem(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     bool res = false; |     bool res = false; | ||||||
|     state.forceList(*args[1]); |     state.forceList(*args[1]); | ||||||
|  | @ -1039,7 +1039,7 @@ static void prim_elem(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Concatenate a list of lists. */ | /* Concatenate a list of lists. */ | ||||||
| static void prim_concatLists(EvalState & state, Value * * args, Value & v) | static void prim_concatLists(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceList(*args[0]); |     state.forceList(*args[0]); | ||||||
|     state.concatLists(v, args[0]->list.length, args[0]->list.elems); |     state.concatLists(v, args[0]->list.length, args[0]->list.elems); | ||||||
|  | @ -1047,7 +1047,7 @@ static void prim_concatLists(EvalState & state, Value * * args, Value & v) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return the length of a list.  This is an O(1) time operation. */ | /* Return the length of a list.  This is an O(1) time operation. */ | ||||||
| static void prim_length(EvalState & state, Value * * args, Value & v) | static void prim_length(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceList(*args[0]); |     state.forceList(*args[0]); | ||||||
|     mkInt(v, args[0]->list.length); |     mkInt(v, args[0]->list.length); | ||||||
|  | @ -1059,33 +1059,33 @@ static void prim_length(EvalState & state, Value * * args, Value & v) | ||||||
|  *************************************************************/ |  *************************************************************/ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_add(EvalState & state, Value * * args, Value & v) | static void prim_add(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     mkInt(v, state.forceInt(*args[0]) + state.forceInt(*args[1])); |     mkInt(v, state.forceInt(*args[0]) + state.forceInt(*args[1])); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_sub(EvalState & state, Value * * args, Value & v) | static void prim_sub(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     mkInt(v, state.forceInt(*args[0]) - state.forceInt(*args[1])); |     mkInt(v, state.forceInt(*args[0]) - state.forceInt(*args[1])); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_mul(EvalState & state, Value * * args, Value & v) | static void prim_mul(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     mkInt(v, state.forceInt(*args[0]) * state.forceInt(*args[1])); |     mkInt(v, state.forceInt(*args[0]) * state.forceInt(*args[1])); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_div(EvalState & state, Value * * args, Value & v) | static void prim_div(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     NixInt i2 = state.forceInt(*args[1]); |     NixInt i2 = state.forceInt(*args[1]); | ||||||
|     if (i2 == 0) throw EvalError("division by zero"); |     if (i2 == 0) throw EvalError(format("division by zero, at %1%") % pos); | ||||||
|     mkInt(v, state.forceInt(*args[0]) / i2); |     mkInt(v, state.forceInt(*args[0]) / i2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_lessThan(EvalState & state, Value * * args, Value & v) | static void prim_lessThan(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     state.forceValue(*args[0]); |     state.forceValue(*args[0]); | ||||||
|     state.forceValue(*args[1]); |     state.forceValue(*args[1]); | ||||||
|  | @ -1102,7 +1102,7 @@ static void prim_lessThan(EvalState & state, Value * * args, Value & v) | ||||||
| /* Convert the argument to a string.  Paths are *not* copied to the
 | /* Convert the argument to a string.  Paths are *not* copied to the
 | ||||||
|    store, so `toString /foo/bar' yields `"/foo/bar"', not |    store, so `toString /foo/bar' yields `"/foo/bar"', not | ||||||
|    `"/nix/store/whatever..."'. */ |    `"/nix/store/whatever..."'. */ | ||||||
| static void prim_toString(EvalState & state, Value * * args, Value & v) | static void prim_toString(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     string s = state.coerceToString(*args[0], context, true, false); |     string s = state.coerceToString(*args[0], context, true, false); | ||||||
|  | @ -1114,20 +1114,20 @@ static void prim_toString(EvalState & state, Value * * args, Value & v) | ||||||
|    at character position `min(start, stringLength str)' inclusive and |    at character position `min(start, stringLength str)' inclusive and | ||||||
|    ending at `min(start + len, stringLength str)'.  `start' must be |    ending at `min(start + len, stringLength str)'.  `start' must be | ||||||
|    non-negative. */ |    non-negative. */ | ||||||
| static void prim_substring(EvalState & state, Value * * args, Value & v) | static void prim_substring(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     int start = state.forceInt(*args[0]); |     int start = state.forceInt(*args[0]); | ||||||
|     int len = state.forceInt(*args[1]); |     int len = state.forceInt(*args[1]); | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     string s = state.coerceToString(*args[2], context); |     string s = state.coerceToString(*args[2], context); | ||||||
| 
 | 
 | ||||||
|     if (start < 0) throw EvalError("negative start position in `substring'"); |     if (start < 0) throw EvalError(format("negative start position in `substring', at %1%") % pos); | ||||||
| 
 | 
 | ||||||
|     mkString(v, start >= s.size() ? "" : string(s, start, len), context); |     mkString(v, start >= s.size() ? "" : string(s, start, len), context); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_stringLength(EvalState & state, Value * * args, Value & v) | static void prim_stringLength(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     string s = state.coerceToString(*args[0], context); |     string s = state.coerceToString(*args[0], context); | ||||||
|  | @ -1135,7 +1135,7 @@ static void prim_stringLength(EvalState & state, Value * * args, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_unsafeDiscardStringContext(EvalState & state, Value * * args, Value & v) | static void prim_unsafeDiscardStringContext(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     string s = state.coerceToString(*args[0], context); |     string s = state.coerceToString(*args[0], context); | ||||||
|  | @ -1149,7 +1149,7 @@ static void prim_unsafeDiscardStringContext(EvalState & state, Value * * args, V | ||||||
|    source-only deployment).  This primop marks the string context so |    source-only deployment).  This primop marks the string context so | ||||||
|    that builtins.derivation adds the path to drv.inputSrcs rather than |    that builtins.derivation adds the path to drv.inputSrcs rather than | ||||||
|    drv.inputDrvs. */ |    drv.inputDrvs. */ | ||||||
| static void prim_unsafeDiscardOutputDependency(EvalState & state, Value * * args, Value & v) | static void prim_unsafeDiscardOutputDependency(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     PathSet context; |     PathSet context; | ||||||
|     string s = state.coerceToString(*args[0], context); |     string s = state.coerceToString(*args[0], context); | ||||||
|  | @ -1166,12 +1166,12 @@ static void prim_unsafeDiscardOutputDependency(EvalState & state, Value * * args | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /* Return the cryptographic hash of a string in base-16. */ | /* Return the cryptographic hash of a string in base-16. */ | ||||||
| static void prim_hashString(EvalState & state, Value * * args, Value & v) | 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]); | ||||||
|     HashType ht = parseHashType(type); |     HashType ht = parseHashType(type); | ||||||
|     if (ht == htUnknown) |     if (ht == htUnknown) | ||||||
|       throw Error(format("unknown hash type `%1%'") % type); |       throw Error(format("unknown hash type `%1%', at %2%") % type % pos); | ||||||
| 
 | 
 | ||||||
|     PathSet context; // discarded
 |     PathSet context; // discarded
 | ||||||
|     string s = state.forceString(*args[1], context); |     string s = state.forceString(*args[1], context); | ||||||
|  | @ -1185,7 +1185,7 @@ static void prim_hashString(EvalState & state, Value * * args, Value & v) | ||||||
|  *************************************************************/ |  *************************************************************/ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_parseDrvName(EvalState & state, Value * * args, Value & v) | 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]); | ||||||
|     DrvName parsed(name); |     DrvName parsed(name); | ||||||
|  | @ -1196,7 +1196,7 @@ static void prim_parseDrvName(EvalState & state, Value * * args, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| static void prim_compareVersions(EvalState & state, Value * * args, Value & v) | static void prim_compareVersions(EvalState & state, const Pos & pos, Value * * args, Value & v) | ||||||
| { | { | ||||||
|     string version1 = state.forceStringNoCtx(*args[0]); |     string version1 = state.forceStringNoCtx(*args[0]); | ||||||
|     string version2 = state.forceStringNoCtx(*args[1]); |     string version2 = state.forceStringNoCtx(*args[1]); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue