From ac1e8f40d4a5c380d68bb6f1c7cef6f1e7987c1a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 13 Apr 2010 12:25:42 +0000 Subject: * Use a symbol table to represent identifiers and attribute names efficiently. The symbol table ensures that there is only one copy of each symbol, thus allowing symbols to be compared efficiently using a pointer equality test. --- src/libexpr/eval.cc | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'src/libexpr/eval.cc') diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 99149fd7f9fe..ffeae8d7311b 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -43,8 +43,8 @@ std::ostream & operator << (std::ostream & str, Value & v) break; case tAttrs: str << "{ "; - foreach (Bindings::iterator, i, *v.attrs) - str << i->first << " = " << i->second << "; "; + foreach (Bindings::iterator, i, *v.attrs) + str << (string) i->first << " = " << i->second << "; "; str << "}"; break; case tList: @@ -91,7 +91,14 @@ string showType(Value & v) } -EvalState::EvalState() : baseEnv(allocEnv()) +EvalState::EvalState() + : sWith(symbols.create("")) + , sOutPath(symbols.create("outPath")) + , sDrvPath(symbols.create("drvPath")) + , sType(symbols.create("type")) + , sMeta(symbols.create("meta")) + , sName(symbols.create("name")) + , baseEnv(allocEnv()) { nrValues = nrEnvs = nrEvaluated = recursionDepth = maxRecursionDepth = 0; deepestStack = (char *) -1; @@ -110,9 +117,9 @@ EvalState::~EvalState() void EvalState::addConstant(const string & name, Value & v) { - baseEnv.bindings[name] = v; + baseEnv.bindings[symbols.create(name)] = v; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; - (*baseEnv.bindings["builtins"].attrs)[name2] = v; + (*baseEnv.bindings[symbols.create("builtins")].attrs)[symbols.create(name2)] = v; nrValues += 2; } @@ -124,9 +131,9 @@ void EvalState::addPrimOp(const string & name, v.type = tPrimOp; v.primOp.arity = arity; v.primOp.fun = primOp; - baseEnv.bindings[name] = v; + baseEnv.bindings[symbols.create(name)] = v; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; - (*baseEnv.bindings["builtins"].attrs)[name2] = v; + (*baseEnv.bindings[symbols.create("builtins")].attrs)[symbols.create(name2)] = v; nrValues += 2; } @@ -225,12 +232,12 @@ void mkPath(Value & v, const char * s) } -static Value * lookupWith(Env * env, const Sym & name) +Value * EvalState::lookupWith(Env * env, const Symbol & name) { if (!env) return 0; Value * v = lookupWith(env->up, name); if (v) return v; - Bindings::iterator i = env->bindings.find(""); + Bindings::iterator i = env->bindings.find(sWith); if (i == env->bindings.end()) return 0; Bindings::iterator j = i->second.attrs->find(name); if (j != i->second.attrs->end()) return &j->second; @@ -238,7 +245,7 @@ static Value * lookupWith(Env * env, const Sym & name) } -static Value * lookupVar(Env * env, const Sym & name) +Value * EvalState::lookupVar(Env * env, const Symbol & name) { /* First look for a regular variable binding for `name'. */ for (Env * env2 = env; env2; env2 = env2->up) { @@ -318,7 +325,7 @@ void EvalState::evalFile(const Path & path, Value & v) Expr * e = parseTrees[path]; if (!e) { - e = parseExprFromFile(path); + e = parseExprFromFile(*this, path); parseTrees[path] = e; } @@ -428,9 +435,9 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) /* The inherited attributes, on the other hand, are evaluated in the original environment. */ - foreach (list::iterator, i, inherited) { + foreach (list::iterator, i, inherited) { Value & v2 = env2.bindings[*i]; - mkCopy(v2, *lookupVar(&env, *i)); + mkCopy(v2, *state.lookupVar(&env, *i)); } } @@ -441,9 +448,9 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) mkThunk(v2, env, i->second); } - foreach (list::iterator, i, inherited) { + foreach (list::iterator, i, inherited) { Value & v2 = (*v.attrs)[*i]; - mkCopy(v2, *lookupVar(&env, *i)); + mkCopy(v2, *state.lookupVar(&env, *i)); } } } @@ -459,7 +466,7 @@ void ExprList::eval(EvalState & state, Env & env, Value & v) void ExprVar::eval(EvalState & state, Env & env, Value & v) { - Value * v2 = lookupVar(&env, name); + Value * v2 = state.lookupVar(&env, name); state.forceValue(*v2); v = *v2; } @@ -631,7 +638,7 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v) Env & env2(state.allocEnv()); env2.up = &env; - Value & vAttrs = env2.bindings[""]; + Value & vAttrs = env2.bindings[state.sWith]; state.eval(env, attrs, vAttrs); state.forceAttrs(vAttrs); @@ -871,7 +878,7 @@ string EvalState::forceStringNoCtx(Value & v) bool EvalState::isDerivation(Value & v) { if (v.type != tAttrs) return false; - Bindings::iterator i = v.attrs->find("type"); + Bindings::iterator i = v.attrs->find(sType); return i != v.attrs->end() && forceStringNoCtx(i->second) == "derivation"; } @@ -915,7 +922,7 @@ string EvalState::coerceToString(Value & v, PathSet & context, } if (v.type == tAttrs) { - Bindings::iterator i = v.attrs->find("outPath"); + Bindings::iterator i = v.attrs->find(sOutPath); if (i == v.attrs->end()) throwTypeError("cannot coerce an attribute set (except a derivation) to a string"); return coerceToString(i->second, context, coerceMore, copyToStore); -- cgit 1.4.1