use an expr->StaticEnv table in evalState

This commit is contained in:
Ben Burdette 2022-05-19 10:48:10 -06:00
parent 86ba0a702c
commit 357fb84dba
6 changed files with 68 additions and 56 deletions

View file

@ -136,8 +136,9 @@ ref<EvalState> EvalCommand::getEvalState()
if (error) if (error)
printError("%s\n\n" ANSI_BOLD "Starting REPL to allow you to inspect the current state of the evaluator.\n" ANSI_NORMAL, error->what()); printError("%s\n\n" ANSI_BOLD "Starting REPL to allow you to inspect the current state of the evaluator.\n" ANSI_NORMAL, error->what());
if (expr.staticEnv) { auto se = evalState->getStaticEnv(expr);
auto vm = mapStaticEnvBindings(evalState->symbols, *expr.staticEnv.get(), env); if (se) {
auto vm = mapStaticEnvBindings(evalState->symbols, *se.get(), env);
runRepl(evalState, *vm); runRepl(evalState, *vm);
} }
}; };

View file

@ -441,8 +441,9 @@ void NixRepl::loadDebugTraceEnv(DebugTrace & dt)
{ {
initEnv(); initEnv();
if (dt.expr.staticEnv) { auto se = state->getStaticEnv(dt.expr);
auto vm = mapStaticEnvBindings(state->symbols, *dt.expr.staticEnv.get(), dt.env); if (se) {
auto vm = mapStaticEnvBindings(state->symbols, *se.get(), dt.env);
// add staticenv vars. // add staticenv vars.
for (auto & [name, value] : *(vm.get())) for (auto & [name, value] : *(vm.get()))
@ -516,7 +517,7 @@ bool NixRepl::processLine(std::string line)
else if (debuggerHook && (command == ":env")) { else if (debuggerHook && (command == ":env")) {
for (const auto & [idx, i] : enumerate(state->debugTraces)) { for (const auto & [idx, i] : enumerate(state->debugTraces)) {
if (idx == debugTraceIndex) { if (idx == debugTraceIndex) {
printEnvBindings(state->symbols, i.expr, i.env); printEnvBindings(*state, i.expr, i.env);
break; break;
} }
} }
@ -533,7 +534,7 @@ bool NixRepl::processLine(std::string line)
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": "; std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
showDebugTrace(std::cout, state->positions, i); showDebugTrace(std::cout, state->positions, i);
std::cout << std::endl; std::cout << std::endl;
printEnvBindings(state->symbols, i.expr, i.env); printEnvBindings(*state, i.expr, i.env);
loadDebugTraceEnv(i); loadDebugTraceEnv(i);
break; break;
} }

View file

@ -772,12 +772,12 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env &
} }
} }
// TODO: add accompanying env for With stuff. void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env)
void printEnvBindings(const SymbolTable & st, const Expr & expr, const Env & env)
{ {
// just print the names for now // just print the names for now
if (expr.staticEnv) auto se = es.getStaticEnv(expr);
printEnvBindings(st, *expr.staticEnv.get(), env, 0); if (se)
printEnvBindings(es.symbols, *se, env, 0);
} }
void mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, ValMap & vm) void mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, ValMap & vm)

View file

@ -25,7 +25,7 @@ enum RepairFlag : bool;
typedef void (* PrimOpFun) (EvalState & state, const PosIdx pos, Value * * args, Value & v); typedef void (* PrimOpFun) (EvalState & state, const PosIdx pos, Value * * args, Value & v);
void printEnvBindings(const SymbolTable & st, const Expr & expr, const Env & env); void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env);
void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, int lvl = 0); void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, int lvl = 0);
struct PrimOp struct PrimOp
@ -130,6 +130,16 @@ public:
bool debugStop; bool debugStop;
bool debugQuit; bool debugQuit;
std::list<DebugTrace> debugTraces; std::list<DebugTrace> debugTraces;
std::map<const Expr*, const std::shared_ptr<const StaticEnv> > exprEnvs;
const std::shared_ptr<const StaticEnv> getStaticEnv(const Expr &expr) const
{
auto i = exprEnvs.find(&expr);
if (i != exprEnvs.end())
return i->second;
else
return std::shared_ptr<const StaticEnv>();;
}
template<class E> template<class E>
[[gnu::noinline, gnu::noreturn]] [[gnu::noinline, gnu::noreturn]]

View file

@ -296,38 +296,39 @@ std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath)
/* Computing levels/displacements for variables. */ /* Computing levels/displacements for variables. */
void Expr::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void Expr::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
abort(); abort();
} }
void ExprInt::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprInt::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env;} es.exprEnvs.insert(std::make_pair(this, env));
void ExprFloat::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{
if (debuggerHook)
staticEnv = env;
} }
void ExprString::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprFloat::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
} }
void ExprPath::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprString::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
} }
void ExprVar::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprPath::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
}
void ExprVar::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{
if (debuggerHook)
es.exprEnvs.insert(std::make_pair(this, 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. */
@ -360,10 +361,10 @@ void ExprVar::bindVars(const EvalState & es, const std::shared_ptr<const StaticE
this->level = withLevel; this->level = withLevel;
} }
void ExprSelect::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprSelect::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
e->bindVars(es, env); e->bindVars(es, env);
if (def) def->bindVars(es, env); if (def) def->bindVars(es, env);
@ -372,10 +373,10 @@ void ExprSelect::bindVars(const EvalState & es, const std::shared_ptr<const Stat
i.expr->bindVars(es, env); i.expr->bindVars(es, env);
} }
void ExprOpHasAttr::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
e->bindVars(es, env); e->bindVars(es, env);
for (auto & i : attrPath) for (auto & i : attrPath)
@ -383,10 +384,10 @@ void ExprOpHasAttr::bindVars(const EvalState & es, const std::shared_ptr<const S
i.expr->bindVars(es, env); i.expr->bindVars(es, env);
} }
void ExprAttrs::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
if (recursive) { if (recursive) {
auto newEnv = std::make_shared<StaticEnv>(false, env.get(), recursive ? attrs.size() : 0); auto newEnv = std::make_shared<StaticEnv>(false, env.get(), recursive ? attrs.size() : 0);
@ -416,19 +417,19 @@ void ExprAttrs::bindVars(const EvalState & es, const std::shared_ptr<const Stati
} }
} }
void ExprList::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprList::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
for (auto & i : elems) for (auto & i : elems)
i->bindVars(es, env); i->bindVars(es, env);
} }
void ExprLambda::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprLambda::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
auto newEnv = std::make_shared<StaticEnv>( auto newEnv = std::make_shared<StaticEnv>(
false, env.get(), false, env.get(),
@ -452,20 +453,20 @@ void ExprLambda::bindVars(const EvalState & es, const std::shared_ptr<const Stat
body->bindVars(es, newEnv); body->bindVars(es, newEnv);
} }
void ExprCall::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprCall::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
fun->bindVars(es, env); fun->bindVars(es, env);
for (auto e : args) for (auto e : args)
e->bindVars(es, env); e->bindVars(es, env);
} }
void ExprLet::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
auto newEnv = std::make_shared<StaticEnv>(false, env.get(), attrs->attrs.size()); auto newEnv = std::make_shared<StaticEnv>(false, env.get(), attrs->attrs.size());
@ -481,10 +482,10 @@ void ExprLet::bindVars(const EvalState & es, const std::shared_ptr<const StaticE
body->bindVars(es, newEnv); body->bindVars(es, newEnv);
} }
void ExprWith::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprWith::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, 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
@ -499,53 +500,53 @@ void ExprWith::bindVars(const EvalState & es, const std::shared_ptr<const Static
} }
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
attrs->bindVars(es, env); attrs->bindVars(es, env);
auto newEnv = std::make_shared<StaticEnv>(true, env.get()); auto newEnv = std::make_shared<StaticEnv>(true, env.get());
body->bindVars(es, newEnv); body->bindVars(es, newEnv);
} }
void ExprIf::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprIf::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
cond->bindVars(es, env); cond->bindVars(es, env);
then->bindVars(es, env); then->bindVars(es, env);
else_->bindVars(es, env); else_->bindVars(es, env);
} }
void ExprAssert::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprAssert::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
cond->bindVars(es, env); cond->bindVars(es, env);
body->bindVars(es, env); body->bindVars(es, env);
} }
void ExprOpNot::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprOpNot::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
e->bindVars(es, env); e->bindVars(es, env);
} }
void ExprConcatStrings::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
for (auto & i : *this->es) for (auto & i : *this->es)
i.second->bindVars(es, env); i.second->bindVars(es, env);
} }
void ExprPos::bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) void ExprPos::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
if (debuggerHook) if (debuggerHook)
staticEnv = env; es.exprEnvs.insert(std::make_pair(this, env));
} }

View file

@ -144,18 +144,17 @@ struct Expr
{ {
virtual ~Expr() { }; virtual ~Expr() { };
virtual void show(const SymbolTable & symbols, std::ostream & str) const; virtual void show(const SymbolTable & symbols, std::ostream & str) const;
virtual void bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env); virtual void bindVars(EvalState & es, 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<const StaticEnv> staticEnv;
virtual PosIdx getPos() const { return noPos; } virtual PosIdx getPos() const { return noPos; }
}; };
#define COMMON_METHODS \ #define COMMON_METHODS \
void show(const SymbolTable & symbols, std::ostream & str) const; \ void show(const SymbolTable & symbols, std::ostream & str) const; \
void eval(EvalState & state, Env & env, Value & v); \ void eval(EvalState & state, Env & env, Value & v); \
void bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env); void bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env);
struct ExprInt : Expr struct ExprInt : Expr
{ {
@ -402,7 +401,7 @@ struct ExprOpNot : Expr
{ \ { \
str << "("; e1->show(symbols, str); str << " " s " "; e2->show(symbols, str); str << ")"; \ str << "("; e1->show(symbols, str); str << " " s " "; e2->show(symbols, str); str << ")"; \
} \ } \
void bindVars(const EvalState & es, const std::shared_ptr<const StaticEnv> & env) \ void bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env) \
{ \ { \
e1->bindVars(es, env); e2->bindVars(es, env); \ e1->bindVars(es, env); e2->bindVars(es, env); \
} \ } \