move valmap to hh; add to env
This commit is contained in:
parent
edb5a28024
commit
89264d20e6
3 changed files with 142 additions and 30 deletions
|
@ -78,6 +78,8 @@ void printValue(std::ostream & str, std::set<const Value *> & active, const Valu
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
str << "internal type: " << v.internalType << std::endl;
|
||||||
|
|
||||||
switch (v.internalType) {
|
switch (v.internalType) {
|
||||||
case tInt:
|
case tInt:
|
||||||
str << v.integer;
|
str << v.integer;
|
||||||
|
@ -404,7 +406,7 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store)
|
||||||
|
|
||||||
assert(gcInitialised);
|
assert(gcInitialised);
|
||||||
|
|
||||||
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
|
static_assert(sizeof(Env) <= 16 + sizeof(std::unique_ptr<void*>), "environment must be <= 16 bytes");
|
||||||
|
|
||||||
/* Initialise the Nix expression search path. */
|
/* Initialise the Nix expression search path. */
|
||||||
if (!evalSettings.pureEval) {
|
if (!evalSettings.pureEval) {
|
||||||
|
@ -616,7 +618,7 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::map<std::string, Value *> valmap;
|
// typedef std::map<std::string, Value *> valmap;
|
||||||
|
|
||||||
/*void addEnv(Value * v, valmap &vmap)
|
/*void addEnv(Value * v, valmap &vmap)
|
||||||
{
|
{
|
||||||
|
@ -655,13 +657,44 @@ LocalNoInline(valmap * mapBindings(Bindings &b))
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalNoInline(void addBindings(string prefix, Bindings &b, valmap &valmap))
|
||||||
|
{
|
||||||
|
for (auto i = b.begin(); i != b.end(); ++i)
|
||||||
|
{
|
||||||
|
std::string s = prefix;
|
||||||
|
s += i->name;
|
||||||
|
valmap[s] = i->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LocalNoInline(valmap * mapEnvBindings(Env &env))
|
LocalNoInline(valmap * mapEnvBindings(Env &env))
|
||||||
{
|
{
|
||||||
if (env.values[0]->type() == nAttrs) {
|
// NOT going to use this
|
||||||
return mapBindings(*env.values[0]->attrs);
|
if (env.staticEnv) {
|
||||||
} else {
|
std::cout << "got static env" << std::endl;
|
||||||
return map0();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// std::cout << "envsize: " << env.values.size() << std::endl;
|
||||||
|
|
||||||
|
// std::cout << "size_t size: " << sizeof(size_t) << std::endl;
|
||||||
|
// std::cout << "envsize: " << env.size << std::endl;
|
||||||
|
// std::cout << "envup: " << env.up << std::endl;
|
||||||
|
|
||||||
|
valmap *vm = env.up ? mapEnvBindings(*env.up) : new valmap();
|
||||||
|
|
||||||
|
/*
|
||||||
|
size_t i=0;
|
||||||
|
do {
|
||||||
|
std::cout << "env: " << i << " value: " << showType(*env.values[i]) << std::endl;
|
||||||
|
// std::cout << *env.values[i] << std::endl;
|
||||||
|
++i;
|
||||||
|
} while(i < (std::min(env.size, (size_t)100)));
|
||||||
|
|
||||||
|
|
||||||
|
if (env.values[0]->type() == nAttrs)
|
||||||
|
addBindings(std::to_string((int)env.size), *env.values[0]->attrs, *vm);
|
||||||
|
*/
|
||||||
|
return vm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Every "format" object (even temporary) takes up a few hundred bytes
|
/* Every "format" object (even temporary) takes up a few hundred bytes
|
||||||
|
@ -876,7 +909,6 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||||
return j->value;
|
return j->value;
|
||||||
}
|
}
|
||||||
if (!env->prevWith)
|
if (!env->prevWith)
|
||||||
// TODO: env.attrs?
|
|
||||||
throwUndefinedVarError(var.pos, "undefined variable '%1%'", var.name,
|
throwUndefinedVarError(var.pos, "undefined variable '%1%'", var.name,
|
||||||
mapEnvBindings(*env));
|
mapEnvBindings(*env));
|
||||||
for (size_t l = env->prevWith; l; --l, env = env->up) ;
|
for (size_t l = env->prevWith; l; --l, env = env->up) ;
|
||||||
|
@ -902,14 +934,28 @@ Value * EvalState::allocValue()
|
||||||
|
|
||||||
Env & EvalState::allocEnv(size_t size)
|
Env & EvalState::allocEnv(size_t size)
|
||||||
{
|
{
|
||||||
|
|
||||||
nrEnvs++;
|
nrEnvs++;
|
||||||
nrValuesInEnvs += size;
|
nrValuesInEnvs += size;
|
||||||
Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *));
|
// if (debuggerHook)
|
||||||
env->type = Env::Plain;
|
// {
|
||||||
|
// Env * env = (Env *) allocBytes(sizeof(DebugEnv) + size * sizeof(Value *));
|
||||||
|
// // Env * env = new DebugEnv;
|
||||||
|
// env->type = Env::Plain;
|
||||||
|
// /* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
|
||||||
|
|
||||||
/* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
|
// return *env;
|
||||||
|
// } else {
|
||||||
|
Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *));
|
||||||
|
env->type = Env::Plain;
|
||||||
|
// env->size = size;
|
||||||
|
|
||||||
return *env;
|
/* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */
|
||||||
|
|
||||||
|
return *env;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1126,6 +1172,11 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
env2.up = &env;
|
env2.up = &env;
|
||||||
dynamicEnv = &env2;
|
dynamicEnv = &env2;
|
||||||
|
|
||||||
|
// TODO; deal with the below overrides or whatever
|
||||||
|
if (debuggerHook) {
|
||||||
|
env2.valuemap = mapBindings(attrs);
|
||||||
|
}
|
||||||
|
|
||||||
AttrDefs::iterator overrides = attrs.find(state.sOverrides);
|
AttrDefs::iterator overrides = attrs.find(state.sOverrides);
|
||||||
bool hasOverrides = overrides != attrs.end();
|
bool hasOverrides = overrides != attrs.end();
|
||||||
|
|
||||||
|
@ -1207,6 +1258,9 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||||
Env & env2(state.allocEnv(attrs->attrs.size()));
|
Env & env2(state.allocEnv(attrs->attrs.size()));
|
||||||
env2.up = &env;
|
env2.up = &env;
|
||||||
|
|
||||||
|
if (debuggerHook) {
|
||||||
|
env2.valuemap = mapBindings(attrs);
|
||||||
|
}
|
||||||
/* The recursive attributes are evaluated in the new environment,
|
/* The recursive attributes are evaluated in the new environment,
|
||||||
while the inherited attributes are evaluated in the original
|
while the inherited attributes are evaluated in the original
|
||||||
environment. */
|
environment. */
|
||||||
|
@ -1420,9 +1474,11 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
||||||
|
|
||||||
size_t displ = 0;
|
size_t displ = 0;
|
||||||
|
|
||||||
if (!lambda.matchAttrs)
|
if (!lambda.matchAttrs){
|
||||||
|
// TODO: what is this arg? empty argument?
|
||||||
|
// add empty valmap here?
|
||||||
env2.values[displ++] = &arg;
|
env2.values[displ++] = &arg;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
forceAttrs(arg, pos);
|
forceAttrs(arg, pos);
|
||||||
|
|
||||||
|
@ -1432,23 +1488,51 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v, const Pos & po
|
||||||
/* For each formal argument, get the actual argument. If
|
/* For each formal argument, get the actual argument. If
|
||||||
there is no matching actual argument but the formal
|
there is no matching actual argument but the formal
|
||||||
argument has a default, use the default. */
|
argument has a default, use the default. */
|
||||||
size_t attrsUsed = 0;
|
if (debuggerHook) {
|
||||||
for (auto & i : lambda.formals->formals) {
|
size_t attrsUsed = 0;
|
||||||
Bindings::iterator j = arg.attrs->find(i.name);
|
for (auto & i : lambda.formals->formals) {
|
||||||
if (j == arg.attrs->end()) {
|
Bindings::iterator j = arg.attrs->find(i.name);
|
||||||
if (!i.def)
|
if (j == arg.attrs->end()) {
|
||||||
throwTypeError(
|
if (!i.def)
|
||||||
pos,
|
throwTypeError(
|
||||||
"%1% called without required argument '%2%'",
|
pos,
|
||||||
lambda,
|
"%1% called without required argument '%2%'",
|
||||||
i.name,
|
lambda,
|
||||||
map2("fun", &fun, "arg", &arg));
|
i.name,
|
||||||
env2.values[displ++] = i.def->maybeThunk(*this, env2);
|
map2("fun", &fun, "arg", &arg));
|
||||||
} else {
|
env2.values[displ++] = i.def->maybeThunk(*this, env2);
|
||||||
attrsUsed++;
|
} else {
|
||||||
env2.values[displ++] = j->value;
|
attrsUsed++;
|
||||||
|
env2.values[displ++] = j->value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
auto map = new valmap();
|
||||||
|
|
||||||
|
size_t attrsUsed = 0;
|
||||||
|
for (auto & i : lambda.formals->formals) {
|
||||||
|
Bindings::iterator j = arg.attrs->find(i.name);
|
||||||
|
if (j == arg.attrs->end()) {
|
||||||
|
if (!i.def)
|
||||||
|
throwTypeError(
|
||||||
|
pos,
|
||||||
|
"%1% called without required argument '%2%'",
|
||||||
|
lambda,
|
||||||
|
i.name,
|
||||||
|
map2("fun", &fun, "arg", &arg));
|
||||||
|
env2.values[displ++] = i.def->maybeThunk(*this, env2);
|
||||||
|
} else {
|
||||||
|
attrsUsed++;
|
||||||
|
env2.values[displ++] = j->value;
|
||||||
|
|
||||||
|
// add to debugger name-value map
|
||||||
|
std::string s = i->name;
|
||||||
|
(*map)[s] = i->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env2.valuemap = map;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check that each actual argument is listed as a formal
|
/* Check that each actual argument is listed as a formal
|
||||||
argument (unless the attribute match specifies a `...'). */
|
argument (unless the attribute match specifies a `...'). */
|
||||||
|
@ -1558,6 +1642,8 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
|
||||||
env2.type = Env::HasWithExpr;
|
env2.type = Env::HasWithExpr;
|
||||||
env2.values[0] = (Value *) attrs;
|
env2.values[0] = (Value *) attrs;
|
||||||
|
|
||||||
|
env2.valuemap = mapBindings(attrs)
|
||||||
|
|
||||||
body->eval(state, env2, v);
|
body->eval(state, env2, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1896,14 +1982,36 @@ string EvalState::forceStringNoCtx(Value & v, const Pos & pos)
|
||||||
if (v.string.context) {
|
if (v.string.context) {
|
||||||
if (pos)
|
if (pos)
|
||||||
throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
||||||
v.string.s, v.string.context[0], map1("value", &v));
|
v.string.s, v.string.context[0],
|
||||||
|
// b.has_value() ? mapBindings(*b.get()) : map0());
|
||||||
|
map1("value", &v));
|
||||||
else
|
else
|
||||||
throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
||||||
v.string.s, v.string.context[0], map1("value", &v));
|
v.string.s, v.string.context[0],
|
||||||
|
// b.has_value() ? mapBindings(*b.get()) : map0());
|
||||||
|
map1("value", &v));
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*string EvalState::forceStringNoCtx(std::optional<Bindings*> b, Value & v, const Pos & pos)
|
||||||
|
{
|
||||||
|
string s = forceString(v, pos);
|
||||||
|
if (v.string.context) {
|
||||||
|
if (pos)
|
||||||
|
throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
||||||
|
v.string.s, v.string.context[0],
|
||||||
|
b.has_value() ? mapBindings(*b.get()) : map0());
|
||||||
|
// map1("value", &v));
|
||||||
|
else
|
||||||
|
throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
||||||
|
v.string.s, v.string.context[0],
|
||||||
|
b.has_value() ? mapBindings(*b.get()) : map0());
|
||||||
|
// map1("value", &v));
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
bool EvalState::isDerivation(Value & v)
|
bool EvalState::isDerivation(Value & v)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,12 +33,14 @@ struct PrimOp
|
||||||
const char * doc = nullptr;
|
const char * doc = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, Value *> valmap;
|
||||||
|
|
||||||
struct Env
|
struct Env
|
||||||
{
|
{
|
||||||
Env * up;
|
Env * up;
|
||||||
unsigned short prevWith:14; // nr of levels up to next `with' environment
|
unsigned short prevWith:14; // nr of levels up to next `with' environment
|
||||||
enum { Plain = 0, HasWithExpr, HasWithAttrs } type:2;
|
enum { Plain = 0, HasWithExpr, HasWithAttrs } type:2;
|
||||||
|
std::unique_ptr<valmap> valuemap; // TODO: rename
|
||||||
Value * values[0];
|
Value * values[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -204,6 +206,7 @@ public:
|
||||||
string forceString(Value & v, const Pos & pos = noPos);
|
string forceString(Value & v, const Pos & pos = noPos);
|
||||||
string forceString(Value & v, PathSet & context, const Pos & pos = noPos);
|
string forceString(Value & v, PathSet & context, const Pos & pos = noPos);
|
||||||
string forceStringNoCtx(Value & v, const Pos & pos = noPos);
|
string forceStringNoCtx(Value & v, const Pos & pos = noPos);
|
||||||
|
// string forceStringNoCtx(std::optional<Bindings*> b, Value & v, const Pos & pos = noPos);
|
||||||
|
|
||||||
/* Return true iff the value `v' denotes a derivation (i.e. a
|
/* Return true iff the value `v' denotes a derivation (i.e. a
|
||||||
set with attribute `type = "derivation"'). */
|
set with attribute `type = "derivation"'). */
|
||||||
|
|
|
@ -408,6 +408,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
|
|
||||||
if (auto attr = v.attrs->get(state->symbols.create("description")))
|
if (auto attr = v.attrs->get(state->symbols.create("description")))
|
||||||
state->forceStringNoCtx(*attr->value, *attr->pos);
|
state->forceStringNoCtx(*attr->value, *attr->pos);
|
||||||
|
// state->forceStringNoCtx(std::optional(v.attrs), *attr->value, *attr->pos);
|
||||||
else
|
else
|
||||||
throw Error("template '%s' lacks attribute 'description'", attrPath);
|
throw Error("template '%s' lacks attribute 'description'", attrPath);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue