shared_ptr for StaticEnv

This commit is contained in:
Ben Burdette 2021-09-14 10:49:22 -06:00
parent 176911102c
commit 21071bfdeb
8 changed files with 57 additions and 69 deletions

View file

@ -1,16 +0,0 @@
# Built-in Functions
This section lists the functions built into the Nix expression
evaluator. (The built-in function `derivation` is discussed above.)
Some built-ins, such as `derivation`, are always in scope of every Nix
expression; you can just access them right away. But to prevent
polluting the namespace too much, most built-ins are not in
scope. Instead, you can access them through the `builtins` built-in
value, which is a set that contains all built-in functions and values.
For instance, `derivation` is also available as `builtins.derivation`.
- `derivation` *attrs*; `builtins.derivation` *attrs*\
`derivation` is described in [its own section](derivations.md).
EvalCommand::getEvalState()0

View file

@ -53,7 +53,8 @@ struct NixRepl
Strings loadedFiles; Strings loadedFiles;
const static int envSize = 32768; const static int envSize = 32768;
StaticEnv staticEnv; std::shared_ptr<StaticEnv> staticEnv;
// StaticEnv staticEnv;
Env * env; Env * env;
int displ; int displ;
StringSet varNames; StringSet varNames;
@ -92,7 +93,7 @@ string removeWhitespace(string s)
NixRepl::NixRepl(ref<EvalState> state) NixRepl::NixRepl(ref<EvalState> state)
: state(state) : state(state)
, staticEnv(false, &state->staticBaseEnv) , staticEnv(new StaticEnv(false, state->staticBaseEnv.get()))
, historyFile(getDataDir() + "/nix/repl-history") , historyFile(getDataDir() + "/nix/repl-history")
{ {
curDir = absPath("."); curDir = absPath(".");
@ -567,10 +568,10 @@ void NixRepl::initEnv()
env = &state->allocEnv(envSize); env = &state->allocEnv(envSize);
env->up = &state->baseEnv; env->up = &state->baseEnv;
displ = 0; displ = 0;
staticEnv.vars.clear(); staticEnv->vars.clear();
varNames.clear(); varNames.clear();
for (auto & i : state->staticBaseEnv.vars) for (auto & i : state->staticBaseEnv->vars)
varNames.insert(i.first); varNames.insert(i.first);
} }
@ -605,7 +606,7 @@ void NixRepl::addVarToScope(const Symbol & name, Value * v)
{ {
if (displ >= envSize) if (displ >= envSize)
throw Error("environment full; cannot add more variables"); throw Error("environment full; cannot add more variables");
staticEnv.vars[name] = displ; staticEnv->vars[name] = displ;
env->values[displ++] = v; env->values[displ++] = v;
varNames.insert((string) name); varNames.insert((string) name);
} }

View file

@ -401,7 +401,7 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
, store(store) , store(store)
, regexCache(makeRegexCache()) , regexCache(makeRegexCache())
, baseEnv(allocEnv(128)) , baseEnv(allocEnv(128))
, staticBaseEnv(false, 0) , staticBaseEnv(new StaticEnv(false, 0))
{ {
countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0"; countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0";
@ -538,7 +538,7 @@ Value * EvalState::addConstant(const string & name, Value & v)
{ {
Value * v2 = allocValue(); Value * v2 = allocValue();
*v2 = v; *v2 = v;
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; staticBaseEnv->vars[symbols.create(name)] = baseEnvDispl;
baseEnv.values[baseEnvDispl++] = v2; baseEnv.values[baseEnvDispl++] = v2;
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v2)); baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v2));
@ -564,7 +564,7 @@ Value * EvalState::addPrimOp(const string & name,
Value * v = allocValue(); Value * v = allocValue();
v->mkPrimOp(new PrimOp { .fun = primOp, .arity = arity, .name = sym }); v->mkPrimOp(new PrimOp { .fun = primOp, .arity = arity, .name = sym });
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; staticBaseEnv->vars[symbols.create(name)] = baseEnvDispl;
baseEnv.values[baseEnvDispl++] = v; baseEnv.values[baseEnvDispl++] = v;
baseEnv.values[0]->attrs->push_back(Attr(sym, v)); baseEnv.values[0]->attrs->push_back(Attr(sym, v));
return v; return v;
@ -590,7 +590,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
Value * v = allocValue(); Value * v = allocValue();
v->mkPrimOp(new PrimOp(std::move(primOp))); v->mkPrimOp(new PrimOp(std::move(primOp)));
staticBaseEnv.vars[envName] = baseEnvDispl; staticBaseEnv->vars[envName] = baseEnvDispl;
baseEnv.values[baseEnvDispl++] = v; baseEnv.values[baseEnvDispl++] = v;
baseEnv.values[0]->attrs->push_back(Attr(primOp.name, v)); baseEnv.values[0]->attrs->push_back(Attr(primOp.name, v));
return v; return v;

View file

@ -23,6 +23,7 @@ enum RepairFlag : bool;
typedef void (* PrimOpFun) (EvalState & state, const Pos & pos, Value * * args, Value & v); typedef void (* PrimOpFun) (EvalState & state, const Pos & pos, Value * * args, Value & v);
extern std::function<void(const Error & error, const Env & env)> debuggerHook;
struct PrimOp struct PrimOp
{ {
@ -154,10 +155,10 @@ public:
/* Parse a Nix expression from the specified file. */ /* Parse a Nix expression from the specified file. */
Expr * parseExprFromFile(const Path & path); Expr * parseExprFromFile(const Path & path);
Expr * parseExprFromFile(const Path & path, StaticEnv & staticEnv); Expr * parseExprFromFile(const Path & path, std::shared_ptr<StaticEnv> & staticEnv);
/* Parse a Nix expression from the specified string. */ /* Parse a Nix expression from the specified string. */
Expr * parseExprFromString(std::string_view s, const Path & basePath, StaticEnv & staticEnv); Expr * parseExprFromString(std::string_view s, const Path & basePath, std::shared_ptr<StaticEnv> & staticEnv);
Expr * parseExprFromString(std::string_view s, const Path & basePath); Expr * parseExprFromString(std::string_view s, const Path & basePath);
Expr * parseStdin(); Expr * parseStdin();
@ -238,7 +239,7 @@ public:
Env & baseEnv; Env & baseEnv;
/* The same, but used during parsing to resolve variables. */ /* The same, but used during parsing to resolve variables. */
StaticEnv staticBaseEnv; // !!! should be private std::shared_ptr<StaticEnv> staticBaseEnv; // !!! should be private
private: private:
@ -277,7 +278,7 @@ private:
friend struct ExprLet; friend struct ExprLet;
Expr * parse(const char * text, FileOrigin origin, const Path & path, Expr * parse(const char * text, FileOrigin origin, const Path & path,
const Path & basePath, StaticEnv & staticEnv); const Path & basePath, std::shared_ptr<StaticEnv> & staticEnv);
public: public:

View file

@ -237,35 +237,35 @@ Pos noPos;
/* Computing levels/displacements for variables. */ /* Computing levels/displacements for variables. */
void Expr::bindVars(const StaticEnv & env) void Expr::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
abort(); abort();
} }
void ExprInt::bindVars(const StaticEnv & env) void ExprInt::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
} }
void ExprFloat::bindVars(const StaticEnv & env) void ExprFloat::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
} }
void ExprString::bindVars(const StaticEnv & env) void ExprString::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
} }
void ExprPath::bindVars(const StaticEnv & env) void ExprPath::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
} }
void ExprVar::bindVars(const StaticEnv & env) void ExprVar::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
/* Check whether the variable appears in the environment. If so, /* Check whether the variable appears in the environment. If so,
set its level and displacement. */ set its level and displacement. */
const StaticEnv * curEnv; const StaticEnv * curEnv;
unsigned int level; unsigned int level;
int withLevel = -1; int withLevel = -1;
for (curEnv = &env, level = 0; curEnv; curEnv = curEnv->up, level++) { for (curEnv = env.get(), level = 0; curEnv; curEnv = curEnv->up, level++) {
if (curEnv->isWith) { if (curEnv->isWith) {
if (withLevel == -1) withLevel = level; if (withLevel == -1) withLevel = level;
} else { } else {
@ -291,7 +291,7 @@ void ExprVar::bindVars(const StaticEnv & env)
this->level = withLevel; this->level = withLevel;
} }
void ExprSelect::bindVars(const StaticEnv & env) void ExprSelect::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
e->bindVars(env); e->bindVars(env);
if (def) def->bindVars(env); if (def) def->bindVars(env);
@ -300,7 +300,7 @@ void ExprSelect::bindVars(const StaticEnv & env)
i.expr->bindVars(env); i.expr->bindVars(env);
} }
void ExprOpHasAttr::bindVars(const StaticEnv & env) void ExprOpHasAttr::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
e->bindVars(env); e->bindVars(env);
for (auto & i : attrPath) for (auto & i : attrPath)
@ -308,17 +308,17 @@ void ExprOpHasAttr::bindVars(const StaticEnv & env)
i.expr->bindVars(env); i.expr->bindVars(env);
} }
void ExprAttrs::bindVars(const StaticEnv & env) void ExprAttrs::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
const StaticEnv * dynamicEnv = &env; const StaticEnv * dynamicEnv = env.get();
StaticEnv newEnv(false, &env); auto newEnv = std::shared_ptr<StaticEnv>(new StaticEnv(false, env.get())); // also make shared_ptr?
if (recursive) { if (recursive) {
dynamicEnv = &newEnv; dynamicEnv = newEnv.get();
unsigned int displ = 0; unsigned int displ = 0;
for (auto & i : attrs) for (auto & i : attrs)
newEnv.vars[i.first] = i.second.displ = displ++; newEnv->vars[i.first] = i.second.displ = displ++;
for (auto & i : attrs) for (auto & i : attrs)
i.second.e->bindVars(i.second.inherited ? env : newEnv); i.second.e->bindVars(i.second.inherited ? env : newEnv);
@ -329,28 +329,28 @@ void ExprAttrs::bindVars(const StaticEnv & env)
i.second.e->bindVars(env); i.second.e->bindVars(env);
for (auto & i : dynamicAttrs) { for (auto & i : dynamicAttrs) {
i.nameExpr->bindVars(*dynamicEnv); i.nameExpr->bindVars(newEnv);
i.valueExpr->bindVars(*dynamicEnv); i.valueExpr->bindVars(newEnv);
} }
} }
void ExprList::bindVars(const StaticEnv & env) void ExprList::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
for (auto & i : elems) for (auto & i : elems)
i->bindVars(env); i->bindVars(env);
} }
void ExprLambda::bindVars(const StaticEnv & env) void ExprLambda::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
StaticEnv newEnv(false, &env); auto newEnv = std::shared_ptr<StaticEnv>(new StaticEnv(false, env.get())); // also make shared_ptr?
unsigned int displ = 0; unsigned int displ = 0;
if (!arg.empty()) newEnv.vars[arg] = displ++; if (!arg.empty()) newEnv->vars[arg] = displ++;
if (matchAttrs) { if (matchAttrs) {
for (auto & i : formals->formals) for (auto & i : formals->formals)
newEnv.vars[i.name] = displ++; newEnv->vars[i.name] = displ++;
for (auto & i : formals->formals) for (auto & i : formals->formals)
if (i.def) i.def->bindVars(newEnv); if (i.def) i.def->bindVars(newEnv);
@ -359,13 +359,13 @@ void ExprLambda::bindVars(const StaticEnv & env)
body->bindVars(newEnv); body->bindVars(newEnv);
} }
void ExprLet::bindVars(const StaticEnv & env) void ExprLet::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
StaticEnv newEnv(false, &env); auto newEnv = std::shared_ptr<StaticEnv>(new StaticEnv(false, env.get())); // also make shared_ptr?
unsigned int displ = 0; unsigned int displ = 0;
for (auto & i : attrs->attrs) for (auto & i : attrs->attrs)
newEnv.vars[i.first] = i.second.displ = displ++; newEnv->vars[i.first] = i.second.displ = displ++;
for (auto & i : attrs->attrs) for (auto & i : attrs->attrs)
i.second.e->bindVars(i.second.inherited ? env : newEnv); i.second.e->bindVars(i.second.inherited ? env : newEnv);
@ -373,7 +373,7 @@ void ExprLet::bindVars(const StaticEnv & env)
body->bindVars(newEnv); body->bindVars(newEnv);
} }
void ExprWith::bindVars(const StaticEnv & env) void ExprWith::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
/* Does this `with' have an enclosing `with'? If so, record its /* Does this `with' have an enclosing `with'? If so, record its
level so that `lookupVar' can look up variables in the previous level so that `lookupVar' can look up variables in the previous
@ -381,42 +381,42 @@ void ExprWith::bindVars(const StaticEnv & env)
const StaticEnv * curEnv; const StaticEnv * curEnv;
unsigned int level; unsigned int level;
prevWith = 0; prevWith = 0;
for (curEnv = &env, level = 1; curEnv; curEnv = curEnv->up, level++) for (curEnv = env.get(), level = 1; curEnv; curEnv = curEnv->up, level++)
if (curEnv->isWith) { if (curEnv->isWith) {
prevWith = level; prevWith = level;
break; break;
} }
attrs->bindVars(env); attrs->bindVars(env);
StaticEnv newEnv(true, &env); auto newEnv = std::shared_ptr<StaticEnv>(new StaticEnv(false, env.get())); // also make shared_ptr?
body->bindVars(newEnv); body->bindVars(newEnv);
} }
void ExprIf::bindVars(const StaticEnv & env) void ExprIf::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
cond->bindVars(env); cond->bindVars(env);
then->bindVars(env); then->bindVars(env);
else_->bindVars(env); else_->bindVars(env);
} }
void ExprAssert::bindVars(const StaticEnv & env) void ExprAssert::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
cond->bindVars(env); cond->bindVars(env);
body->bindVars(env); body->bindVars(env);
} }
void ExprOpNot::bindVars(const StaticEnv & env) void ExprOpNot::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
e->bindVars(env); e->bindVars(env);
} }
void ExprConcatStrings::bindVars(const StaticEnv & env) void ExprConcatStrings::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
for (auto & i : *es) for (auto & i : *es)
i->bindVars(env); i->bindVars(env);
} }
void ExprPos::bindVars(const StaticEnv & env) void ExprPos::bindVars(const std::shared_ptr<const StaticEnv> &env)
{ {
} }

View file

@ -79,10 +79,12 @@ struct Expr
{ {
virtual ~Expr() { }; virtual ~Expr() { };
virtual void show(std::ostream & str) const; virtual void show(std::ostream & str) const;
virtual void bindVars(const StaticEnv & env); virtual void bindVars(const std::shared_ptr<const StaticEnv> & env);
virtual void eval(EvalState & state, Env & env, Value & v); virtual void eval(EvalState & state, Env & env, Value & v);
virtual Value * maybeThunk(EvalState & state, Env & env); virtual Value * maybeThunk(EvalState & state, Env & env);
virtual void setName(Symbol & name); virtual void setName(Symbol & name);
std::shared_ptr<StaticEnv> staticenv;
}; };
std::ostream & operator << (std::ostream & str, const Expr & e); std::ostream & operator << (std::ostream & str, const Expr & e);
@ -90,7 +92,7 @@ std::ostream & operator << (std::ostream & str, const Expr & e);
#define COMMON_METHODS \ #define COMMON_METHODS \
void show(std::ostream & str) const; \ void show(std::ostream & str) const; \
void eval(EvalState & state, Env & env, Value & v); \ void eval(EvalState & state, Env & env, Value & v); \
void bindVars(const StaticEnv & env); void bindVars(const std::shared_ptr<const StaticEnv> & env);
struct ExprInt : Expr struct ExprInt : Expr
{ {
@ -301,7 +303,7 @@ struct ExprOpNot : Expr
{ \ { \
str << "(" << *e1 << " " s " " << *e2 << ")"; \ str << "(" << *e1 << " " s " " << *e2 << ")"; \
} \ } \
void bindVars(const StaticEnv & env) \ void bindVars(const std::shared_ptr<const StaticEnv> & env) \
{ \ { \
e1->bindVars(env); e2->bindVars(env); \ e1->bindVars(env); e2->bindVars(env); \
} \ } \

View file

@ -570,7 +570,7 @@ namespace nix {
Expr * EvalState::parse(const char * text, FileOrigin origin, Expr * EvalState::parse(const char * text, FileOrigin origin,
const Path & path, const Path & basePath, StaticEnv & staticEnv) const Path & path, const Path & basePath, std::shared_ptr<StaticEnv> & staticEnv)
{ {
yyscan_t scanner; yyscan_t scanner;
ParseData data(*this); ParseData data(*this);
@ -633,13 +633,13 @@ Expr * EvalState::parseExprFromFile(const Path & path)
} }
Expr * EvalState::parseExprFromFile(const Path & path, StaticEnv & staticEnv) Expr * EvalState::parseExprFromFile(const Path & path, std::shared_ptr<StaticEnv> & staticEnv)
{ {
return parse(readFile(path).c_str(), foFile, path, dirOf(path), staticEnv); return parse(readFile(path).c_str(), foFile, path, dirOf(path), staticEnv);
} }
Expr * EvalState::parseExprFromString(std::string_view s, const Path & basePath, StaticEnv & staticEnv) Expr * EvalState::parseExprFromString(std::string_view s, const Path & basePath, std::shared_ptr<StaticEnv> & staticEnv)
{ {
return parse(s.data(), foString, "", basePath, staticEnv); return parse(s.data(), foString, "", basePath, staticEnv);
} }

View file

@ -186,11 +186,11 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
Env * env = &state.allocEnv(vScope->attrs->size()); Env * env = &state.allocEnv(vScope->attrs->size());
env->up = &state.baseEnv; env->up = &state.baseEnv;
StaticEnv staticEnv(false, &state.staticBaseEnv); auto staticEnv = std::shared_ptr<StaticEnv>(new StaticEnv(false, state.staticBaseEnv.get()));
unsigned int displ = 0; unsigned int displ = 0;
for (auto & attr : *vScope->attrs) { for (auto & attr : *vScope->attrs) {
staticEnv.vars[attr.name] = displ; staticEnv->vars[attr.name] = displ;
env->values[displ++] = attr.value; env->values[displ++] = attr.value;
} }