* Inline some functions and get rid of the indirection through
EvalState::eval(). This gives a 12% speedup on ‘nix-instantiate /etc/nixos/nixos/ -A system --readonly-mode’ (from 1.01s to 0.89s).
This commit is contained in:
		
							parent
							
								
									2bda12ef3b
								
							
						
					
					
						commit
						f491ae97d4
					
				
					 7 changed files with 94 additions and 116 deletions
				
			
		|  | @ -6,7 +6,7 @@ libexpr_la_SOURCES = \ | ||||||
|  names.cc |  names.cc | ||||||
| 
 | 
 | ||||||
| pkginclude_HEADERS = \ | pkginclude_HEADERS = \ | ||||||
|  nixexpr.hh eval.hh lexer-tab.hh parser-tab.hh \ |  nixexpr.hh eval.hh eval-inline.hh lexer-tab.hh parser-tab.hh \ | ||||||
|  get-drvs.hh attr-path.hh value-to-xml.hh common-opts.hh \ |  get-drvs.hh attr-path.hh value-to-xml.hh common-opts.hh \ | ||||||
|  names.hh symbol-table.hh value.hh |  names.hh symbol-table.hh value.hh | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										61
									
								
								src/libexpr/eval-inline.hh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/libexpr/eval-inline.hh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | ||||||
|  | #ifndef __EVAL_INLINE_H | ||||||
|  | #define __EVAL_INLINE_H | ||||||
|  | 
 | ||||||
|  | #include "eval.hh" | ||||||
|  | 
 | ||||||
|  | #define LocalNoInline(f) static f __attribute__((noinline)); f | ||||||
|  | #define LocalNoInlineNoReturn(f) static f __attribute__((noinline, noreturn)); f | ||||||
|  | 
 | ||||||
|  | namespace nix { | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | LocalNoInlineNoReturn(void throwEvalError(const char * s)) | ||||||
|  | { | ||||||
|  |     throw EvalError(s); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s2)) | ||||||
|  | { | ||||||
|  |     throw TypeError(format(s) % s2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void EvalState::forceValue(Value & v) | ||||||
|  | { | ||||||
|  |     if (v.type == tThunk) { | ||||||
|  |         ValueType saved = v.type; | ||||||
|  |         try { | ||||||
|  |             v.type = tBlackhole; | ||||||
|  |             //checkInterrupt();
 | ||||||
|  |             v.thunk.expr->eval(*this, *v.thunk.env, v); | ||||||
|  |         } catch (Error & e) { | ||||||
|  |             v.type = saved; | ||||||
|  |             throw; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else if (v.type == tApp) | ||||||
|  |         callFunction(*v.app.left, *v.app.right, v); | ||||||
|  |     else if (v.type == tBlackhole) | ||||||
|  |         throwEvalError("infinite recursion encountered"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | inline void EvalState::forceAttrs(Value & v) | ||||||
|  | { | ||||||
|  |     forceValue(v); | ||||||
|  |     if (v.type != tAttrs) | ||||||
|  |         throwTypeError("value is %1% while an attribute set was expected", showType(v)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | inline void EvalState::forceList(Value & v) | ||||||
|  | { | ||||||
|  |     forceValue(v); | ||||||
|  |     if (v.type != tList) | ||||||
|  |         throwTypeError("value is %1% while a list was expected", showType(v)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif /* !__EVAL_INLINE_H */ | ||||||
|  | @ -4,6 +4,7 @@ | ||||||
| #include "store-api.hh" | #include "store-api.hh" | ||||||
| #include "derivations.hh" | #include "derivations.hh" | ||||||
| #include "globals.hh" | #include "globals.hh" | ||||||
|  | #include "eval-inline.hh" | ||||||
| 
 | 
 | ||||||
| #include <cstring> | #include <cstring> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | @ -27,10 +28,6 @@ | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #define LocalNoInline(f) static f __attribute__((noinline)); f |  | ||||||
| #define LocalNoInlineNoReturn(f) static f __attribute__((noinline, noreturn)); f |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -227,11 +224,6 @@ void EvalState::addPrimOp(const string & name, | ||||||
|    evaluator.  So here are some helper functions for throwing |    evaluator.  So here are some helper functions for throwing | ||||||
|    exceptions. */ |    exceptions. */ | ||||||
| 
 | 
 | ||||||
| LocalNoInlineNoReturn(void throwEvalError(const char * s)) |  | ||||||
| { |  | ||||||
|     throw EvalError(s); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2)) | LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2)) | ||||||
| { | { | ||||||
|     throw EvalError(format(s) % s2); |     throw EvalError(format(s) % s2); | ||||||
|  | @ -247,11 +239,6 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s)) | ||||||
|     throw TypeError(s); |     throw TypeError(s); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s2)) |  | ||||||
| { |  | ||||||
|     throw TypeError(format(s) % s2); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos, const string & s2)) | LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos, const string & s2)) | ||||||
| { | { | ||||||
|     throw TypeError(format(s) % pos % s2); |     throw TypeError(format(s) % pos % s2); | ||||||
|  | @ -309,7 +296,7 @@ void mkPath(Value & v, const char * s) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Value * EvalState::lookupVar(Env * env, const VarRef & var) | inline Value * EvalState::lookupVar(Env * env, const VarRef & var) | ||||||
| { | { | ||||||
|     for (unsigned int l = var.level; l; --l, env = env->up) ; |     for (unsigned int l = var.level; l; --l, env = env->up) ; | ||||||
|      |      | ||||||
|  | @ -435,7 +422,6 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| void EvalState::evalFile(const Path & path, Value & v) | void EvalState::evalFile(const Path & path, Value & v) | ||||||
| { | { | ||||||
|     FileEvalCache::iterator i = fileEvalCache.find(path); |     FileEvalCache::iterator i = fileEvalCache.find(path); | ||||||
|  | @ -454,61 +440,25 @@ void EvalState::evalFile(const Path & path, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| struct RecursionCounter |  | ||||||
| { |  | ||||||
|     EvalState & state; |  | ||||||
|     RecursionCounter(EvalState & state) : state(state) |  | ||||||
|     { |  | ||||||
|         state.recursionDepth++; |  | ||||||
|         if (state.recursionDepth > state.maxRecursionDepth) |  | ||||||
|             state.maxRecursionDepth = state.recursionDepth; |  | ||||||
|     } |  | ||||||
|     ~RecursionCounter() |  | ||||||
|     { |  | ||||||
|         state.recursionDepth--; |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void EvalState::eval(Env & env, Expr * e, Value & v) |  | ||||||
| { |  | ||||||
|     /* When changing this function, make sure that you don't cause a
 |  | ||||||
|        (large) increase in stack consumption! */ |  | ||||||
| 
 |  | ||||||
|     /* !!! Disable this eventually. */ |  | ||||||
|     RecursionCounter r(*this); |  | ||||||
|     char x; |  | ||||||
|     if (&x < deepestStack) deepestStack = &x; |  | ||||||
|      |  | ||||||
|     //debug(format("eval: %1%") % *e);
 |  | ||||||
| 
 |  | ||||||
|     checkInterrupt(); |  | ||||||
| 
 |  | ||||||
|     nrEvaluated++; |  | ||||||
| 
 |  | ||||||
|     e->eval(*this, env, v); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void EvalState::eval(Expr * e, Value & v) | void EvalState::eval(Expr * e, Value & v) | ||||||
| { | { | ||||||
|     eval(baseEnv, e, v); |     e->eval(*this, baseEnv, v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| bool EvalState::evalBool(Env & env, Expr * e) | inline bool EvalState::evalBool(Env & env, Expr * e) | ||||||
| { | { | ||||||
|     Value v; |     Value v; | ||||||
|     eval(env, e, v); |     e->eval(*this, env, v); | ||||||
|     if (v.type != tBool) |     if (v.type != tBool) | ||||||
|         throwTypeError("value is %1% while a Boolean was expected", showType(v)); |         throwTypeError("value is %1% while a Boolean was expected", showType(v)); | ||||||
|     return v.boolean; |     return v.boolean; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void EvalState::evalAttrs(Env & env, Expr * e, Value & v) | inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v) | ||||||
| { | { | ||||||
|     eval(env, e, v); |     e->eval(*this, env, v); | ||||||
|     if (v.type != tAttrs) |     if (v.type != tAttrs) | ||||||
|         throwTypeError("value is %1% while an attribute set was expected", showType(v)); |         throwTypeError("value is %1% while an attribute set was expected", showType(v)); | ||||||
| } | } | ||||||
|  | @ -622,7 +572,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) | ||||||
|         else |         else | ||||||
|             env2.values[displ++] = i->second.e->maybeThunk(state, env2); |             env2.values[displ++] = i->second.e->maybeThunk(state, env2); | ||||||
| 
 | 
 | ||||||
|     state.eval(env2, body, v); |     body->eval(state, env2, v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -650,7 +600,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) | ||||||
|     Pos * pos = 0; |     Pos * pos = 0; | ||||||
|     Value * vAttrs = &vTmp; |     Value * vAttrs = &vTmp; | ||||||
| 
 | 
 | ||||||
|     state.eval(env, e, vTmp); |     e->eval(state, env, vTmp); | ||||||
| 
 | 
 | ||||||
|     try { |     try { | ||||||
|          |          | ||||||
|  | @ -662,7 +612,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) | ||||||
|                 if (vAttrs->type != tAttrs || |                 if (vAttrs->type != tAttrs || | ||||||
|                     (j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end()) |                     (j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end()) | ||||||
|                 { |                 { | ||||||
|                     state.eval(env, def, v); |                     def->eval(state, env, v); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|  | @ -692,7 +642,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) | ||||||
|     Value vTmp; |     Value vTmp; | ||||||
|     Value * vAttrs = &vTmp; |     Value * vAttrs = &vTmp; | ||||||
| 
 | 
 | ||||||
|     state.eval(env, e, vTmp); |     e->eval(state, env, vTmp); | ||||||
| 
 | 
 | ||||||
|     foreach (AttrPath::const_iterator, i, attrPath) { |     foreach (AttrPath::const_iterator, i, attrPath) { | ||||||
|         state.forceValue(*vAttrs); |         state.forceValue(*vAttrs); | ||||||
|  | @ -722,7 +672,7 @@ void ExprLambda::eval(EvalState & state, Env & env, Value & v) | ||||||
| void ExprApp::eval(EvalState & state, Env & env, Value & v) | void ExprApp::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     Value vFun; |     Value vFun; | ||||||
|     state.eval(env, e1, vFun); |     e1->eval(state, env, vFun); | ||||||
|     state.callFunction(vFun, *(e2->maybeThunk(state, env)), v); |     state.callFunction(vFun, *(e2->maybeThunk(state, env)), v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -814,7 +764,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     try { |     try { | ||||||
|         eval(env2, fun.lambda.fun->body, v); |         fun.lambda.fun->body->eval(*this, env2, v); | ||||||
|     } catch (Error & e) { |     } catch (Error & e) { | ||||||
|         addErrorPrefix(e, "while evaluating the function at %1%:\n", fun.lambda.fun->pos); |         addErrorPrefix(e, "while evaluating the function at %1%:\n", fun.lambda.fun->pos); | ||||||
|         throw; |         throw; | ||||||
|  | @ -857,13 +807,13 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v) | ||||||
|     env2.values[0] = state.allocValue(); |     env2.values[0] = state.allocValue(); | ||||||
|     state.evalAttrs(env, attrs, *env2.values[0]); |     state.evalAttrs(env, attrs, *env2.values[0]); | ||||||
| 
 | 
 | ||||||
|     state.eval(env2, body, v); |     body->eval(state, env2, v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void ExprIf::eval(EvalState & state, Env & env, Value & v) | void ExprIf::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     state.eval(env, state.evalBool(env, cond) ? then : else_, v); |     (state.evalBool(env, cond) ? then : else_)->eval(state, env, v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|      |      | ||||||
|  | @ -871,7 +821,7 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     if (!state.evalBool(env, cond)) |     if (!state.evalBool(env, cond)) | ||||||
|         throwAssertionError("assertion failed at %1%", pos); |         throwAssertionError("assertion failed at %1%", pos); | ||||||
|     state.eval(env, body, v); |     body->eval(state, env, v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|      |      | ||||||
|  | @ -883,16 +833,16 @@ void ExprOpNot::eval(EvalState & state, Env & env, Value & v) | ||||||
| 
 | 
 | ||||||
| void ExprOpEq::eval(EvalState & state, Env & env, Value & v) | void ExprOpEq::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     Value v1; state.eval(env, e1, v1); |     Value v1; e1->eval(state, env, v1); | ||||||
|     Value v2; state.eval(env, e2, v2); |     Value v2; e2->eval(state, env, v2); | ||||||
|     mkBool(v, state.eqValues(v1, v2)); |     mkBool(v, state.eqValues(v1, v2)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void ExprOpNEq::eval(EvalState & state, Env & env, Value & v) | void ExprOpNEq::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     Value v1; state.eval(env, e1, v1); |     Value v1; e1->eval(state, env, v1); | ||||||
|     Value v2; state.eval(env, e2, v2); |     Value v2; e2->eval(state, env, v2); | ||||||
|     mkBool(v, !state.eqValues(v1, v2)); |     mkBool(v, !state.eqValues(v1, v2)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -954,9 +904,9 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) | ||||||
| 
 | 
 | ||||||
| void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) | void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) | ||||||
| { | { | ||||||
|     Value v1; state.eval(env, e1, v1); |     Value v1; e1->eval(state, env, v1); | ||||||
|     state.forceList(v1); |     state.forceList(v1); | ||||||
|     Value v2; state.eval(env, e2, v2); |     Value v2; e2->eval(state, env, v2); | ||||||
|     state.forceList(v2); |     state.forceList(v2); | ||||||
|     state.mkList(v, v1.list.length + v2.list.length); |     state.mkList(v, v1.list.length + v2.list.length); | ||||||
|     for (unsigned int n = 0; n < v1.list.length; ++n) |     for (unsigned int n = 0; n < v1.list.length; ++n) | ||||||
|  | @ -975,7 +925,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) | ||||||
|     Value vStr; |     Value vStr; | ||||||
| 
 | 
 | ||||||
|     foreach (vector<Expr *>::iterator, i, *es) { |     foreach (vector<Expr *>::iterator, i, *es) { | ||||||
|         state.eval(env, *i, vStr); |         (*i)->eval(state, env, vStr); | ||||||
| 
 | 
 | ||||||
|         /* If the first element is a path, then the result will also
 |         /* If the first element is a path, then the result will also
 | ||||||
|            be a path, we don't copy anything (yet - that's done later, |            be a path, we don't copy anything (yet - that's done later, | ||||||
|  | @ -999,25 +949,6 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void EvalState::forceValue(Value & v) |  | ||||||
| { |  | ||||||
|     if (v.type == tThunk) { |  | ||||||
|         ValueType saved = v.type; |  | ||||||
|         try { |  | ||||||
|             v.type = tBlackhole; |  | ||||||
|             eval(*v.thunk.env, v.thunk.expr, v); |  | ||||||
|         } catch (Error & e) { |  | ||||||
|             v.type = saved; |  | ||||||
|             throw; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     else if (v.type == tApp) |  | ||||||
|         callFunction(*v.app.left, *v.app.right, v); |  | ||||||
|     else if (v.type == tBlackhole) |  | ||||||
|         throwEvalError("infinite recursion encountered"); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void EvalState::strictForceValue(Value & v) | void EvalState::strictForceValue(Value & v) | ||||||
| { | { | ||||||
|     forceValue(v); |     forceValue(v); | ||||||
|  | @ -1052,22 +983,6 @@ bool EvalState::forceBool(Value & v) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void EvalState::forceAttrs(Value & v) |  | ||||||
| { |  | ||||||
|     forceValue(v); |  | ||||||
|     if (v.type != tAttrs) |  | ||||||
|         throwTypeError("value is %1% while an attribute set was expected", showType(v)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void EvalState::forceList(Value & v) |  | ||||||
| { |  | ||||||
|     forceValue(v); |  | ||||||
|     if (v.type != tList) |  | ||||||
|         throwTypeError("value is %1% while a list was expected", showType(v)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void EvalState::forceFunction(Value & v) | void EvalState::forceFunction(Value & v) | ||||||
| { | { | ||||||
|     forceValue(v); |     forceValue(v); | ||||||
|  |  | ||||||
|  | @ -138,18 +138,17 @@ public: | ||||||
|     /* Evaluate an expression to normal form, storing the result in
 |     /* Evaluate an expression to normal form, storing the result in
 | ||||||
|        value `v'. */ |        value `v'. */ | ||||||
|     void eval(Expr * e, Value & v); |     void eval(Expr * e, Value & v); | ||||||
|     void eval(Env & env, Expr * e, Value & v); |  | ||||||
| 
 | 
 | ||||||
|     /* Evaluation the expression, then verify that it has the expected
 |     /* Evaluation the expression, then verify that it has the expected
 | ||||||
|        type. */ |        type. */ | ||||||
|     bool evalBool(Env & env, Expr * e); |     inline bool evalBool(Env & env, Expr * e); | ||||||
|     void evalAttrs(Env & env, Expr * e, Value & v); |     inline void evalAttrs(Env & env, Expr * e, Value & v); | ||||||
| 
 | 
 | ||||||
|     /* If `v' is a thunk, enter it and overwrite `v' with the result
 |     /* If `v' is a thunk, enter it and overwrite `v' with the result
 | ||||||
|        of the evaluation of the thunk.  If `v' is a delayed function |        of the evaluation of the thunk.  If `v' is a delayed function | ||||||
|        application, call the function and overwrite `v' with the |        application, call the function and overwrite `v' with the | ||||||
|        result.  Otherwise, this is a no-op. */ |        result.  Otherwise, this is a no-op. */ | ||||||
|     void forceValue(Value & v); |     inline void forceValue(Value & v); | ||||||
| 
 | 
 | ||||||
|     /* Force a value, then recursively force list elements and
 |     /* Force a value, then recursively force list elements and
 | ||||||
|        attributes. */ |        attributes. */ | ||||||
|  | @ -158,8 +157,8 @@ public: | ||||||
|     /* Force `v', and then verify that it has the expected type. */ |     /* Force `v', and then verify that it has the expected type. */ | ||||||
|     int forceInt(Value & v); |     int forceInt(Value & v); | ||||||
|     bool forceBool(Value & v); |     bool forceBool(Value & v); | ||||||
|     void forceAttrs(Value & v); |     inline void forceAttrs(Value & v); | ||||||
|     void forceList(Value & v); |     inline void forceList(Value & v); | ||||||
|     void forceFunction(Value & v); // either lambda or primop
 |     void forceFunction(Value & v); // either lambda or primop
 | ||||||
|     string forceString(Value & v); |     string forceString(Value & v); | ||||||
|     string forceString(Value & v, PathSet & context); |     string forceString(Value & v, PathSet & context); | ||||||
|  | @ -203,7 +202,7 @@ private: | ||||||
|     void addPrimOp(const string & name, |     void addPrimOp(const string & name, | ||||||
|         unsigned int arity, PrimOpFun primOp); |         unsigned int arity, PrimOpFun primOp); | ||||||
| 
 | 
 | ||||||
|     Value * lookupVar(Env * env, const VarRef & var); |     inline Value * lookupVar(Env * env, const VarRef & var); | ||||||
|      |      | ||||||
|     friend class ExprVar; |     friend class ExprVar; | ||||||
|     friend class ExprAttrs; |     friend class ExprAttrs; | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| #include "get-drvs.hh" | #include "get-drvs.hh" | ||||||
| #include "util.hh" | #include "util.hh" | ||||||
|  | #include "eval-inline.hh" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| namespace nix { | namespace nix { | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include "archive.hh" | #include "archive.hh" | ||||||
| #include "value-to-xml.hh" | #include "value-to-xml.hh" | ||||||
| #include "names.hh" | #include "names.hh" | ||||||
|  | #include "eval-inline.hh" | ||||||
| 
 | 
 | ||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
| #include "globals.hh" | #include "globals.hh" | ||||||
| #include "shared.hh" | #include "shared.hh" | ||||||
| #include "eval.hh" | #include "eval.hh" | ||||||
|  | #include "eval-inline.hh" | ||||||
| #include "get-drvs.hh" | #include "get-drvs.hh" | ||||||
| #include "attr-path.hh" | #include "attr-path.hh" | ||||||
| #include "value-to-xml.hh" | #include "value-to-xml.hh" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue