mirror of
https://github.com/NixOS/nix.git
synced 2025-11-15 15:02:42 +01:00
Remove a word from Env
This commit is contained in:
parent
ae5b76a5a4
commit
e392ff53e9
4 changed files with 55 additions and 31 deletions
|
|
@ -523,8 +523,6 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
|||
{
|
||||
for (size_t l = var.level; l; --l, env = env->up) ;
|
||||
|
||||
assert(((Object *) env)->type == tEnv);
|
||||
|
||||
if (!var.fromWith) {
|
||||
auto v = env->values[var.displ];
|
||||
if (v) gc.assertObject(v);
|
||||
|
|
@ -532,12 +530,12 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
|||
}
|
||||
|
||||
while (1) {
|
||||
if (env->type == Env::HasWithExpr) {
|
||||
if (env->type == tWithExprEnv) {
|
||||
if (noEval) return 0;
|
||||
auto v = allocValue();
|
||||
evalAttrs(*env->up, (Expr *) env->values[0], *v);
|
||||
env->values[0] = v;
|
||||
env->type = Env::HasWithAttrs;
|
||||
env->type = tWithAttrsEnv;
|
||||
}
|
||||
Bindings::iterator j = env->values[0]->attrs->find(var.name);
|
||||
if (j != env->values[0]->attrs->end()) {
|
||||
|
|
@ -545,9 +543,9 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
|||
gc.assertObject(j->value);
|
||||
return j->value;
|
||||
}
|
||||
if (!env->prevWith)
|
||||
if (!env->getPrevWith())
|
||||
throwUndefinedVarError("undefined variable '%1%' at %2%", var.name, var.pos);
|
||||
for (size_t l = env->prevWith; l; --l, env = env->up) ;
|
||||
for (size_t l = env->getPrevWith(); l; --l, env = env->up) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -559,15 +557,11 @@ Ptr<Value> EvalState::allocValue()
|
|||
}
|
||||
|
||||
|
||||
Ptr<Env> EvalState::allocEnv(size_t size)
|
||||
Ptr<Env> EvalState::allocEnv(size_t size, size_t prevWith, Tag type)
|
||||
{
|
||||
if (size > std::numeric_limits<decltype(Env::size)>::max()) // FIXME
|
||||
throw Error("environment size %d is too big", size);
|
||||
|
||||
nrEnvs++;
|
||||
nrValuesInEnvs += size;
|
||||
|
||||
return gc.alloc<Env>(Env::wordsFor(size), size);
|
||||
return gc.alloc<Env>(Env::wordsFor(size), type, size, prevWith);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1181,12 +1175,9 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
|||
|
||||
void ExprWith::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
auto env2 = state.allocEnv(1);
|
||||
auto env2 = state.allocEnv(1, prevWith, tWithExprEnv);
|
||||
env2->up = &env;
|
||||
env2->prevWith = prevWith;
|
||||
env2->type = Env::HasWithExpr;
|
||||
env2->values[0] = (Value *) attrs;
|
||||
|
||||
body->eval(state, env2, v);
|
||||
}
|
||||
|
||||
|
|
@ -1880,10 +1871,10 @@ size_t valueSize(Value & v)
|
|||
if (seen.find(&env) != seen.end()) return 0;
|
||||
seen.insert(&env);
|
||||
|
||||
size_t sz = sizeof(Env) + sizeof(Value *) * env.size;
|
||||
size_t sz = sizeof(Env) + sizeof(Value *) * env.getSize();
|
||||
|
||||
if (env.type != Env::HasWithExpr)
|
||||
for (size_t i = 0; i < env.size; ++i)
|
||||
if (env.type != tWithExprEnv)
|
||||
for (size_t i = 0; i < env.getSize(); ++i)
|
||||
if (env.values[i])
|
||||
sz += doValue(*env.values[i]);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,16 +36,23 @@ struct PrimOp
|
|||
struct Env : Object
|
||||
{
|
||||
Env * up;
|
||||
// FIXME: use misc field
|
||||
unsigned short size; // used by ‘valueSize’
|
||||
unsigned short prevWith:14; // nr of levels up to next `with' environment
|
||||
enum { Plain = 0, HasWithExpr, HasWithAttrs } type:2; // FIXME: fold into type?
|
||||
Value * values[0];
|
||||
|
||||
private:
|
||||
|
||||
Env(unsigned short size) : Object(tEnv, 0), size(size) {
|
||||
for (auto i = 0; i < size; i++)
|
||||
constexpr static size_t maxSize = 1 << 16;
|
||||
constexpr static size_t maxPrevWith = 1 << 10;
|
||||
|
||||
Env(Tag type, size_t size, size_t prevWith)
|
||||
: Object(type, size | (prevWith << 16))
|
||||
{
|
||||
if (size >= maxSize)
|
||||
throw Error("environment size %d is too big", size);
|
||||
|
||||
if (prevWith >= maxPrevWith)
|
||||
throw Error("too many nesting levels");
|
||||
|
||||
for (size_t i = 0; i < size; i++)
|
||||
values[i] = nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -53,14 +60,24 @@ private:
|
|||
|
||||
public:
|
||||
|
||||
unsigned short getPrevWith() const
|
||||
{
|
||||
return getMisc() >> 16;
|
||||
}
|
||||
|
||||
unsigned short getSize() const
|
||||
{
|
||||
return getMisc() & 0xffff;
|
||||
}
|
||||
|
||||
Size words() const
|
||||
{
|
||||
return wordsFor(size);
|
||||
return wordsFor(getSize());
|
||||
}
|
||||
|
||||
static Size wordsFor(unsigned short size)
|
||||
{
|
||||
return 3 + size; // FIXME
|
||||
return 2 + size;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -276,7 +293,7 @@ public:
|
|||
|
||||
/* Allocation primitives. */
|
||||
Ptr<Value> allocValue();
|
||||
Ptr<Env> allocEnv(size_t size);
|
||||
Ptr<Env> allocEnv(size_t size, size_t prevWith = 0, Tag type = tEnv);
|
||||
|
||||
// Note: the resulting Value is only reachable as long as vAttrs
|
||||
// is reachable.
|
||||
|
|
|
|||
|
|
@ -82,9 +82,21 @@ void GC::gc()
|
|||
case tEnv: {
|
||||
auto obj2 = (Env *) obj;
|
||||
push(obj2->up);
|
||||
if (obj2->type != Env::HasWithExpr)
|
||||
for (auto i = obj2->values; i < obj2->values + obj2->size; ++i)
|
||||
push(*i);
|
||||
for (auto i = obj2->values; i < obj2->values + obj2->getSize(); ++i)
|
||||
push(*i);
|
||||
break;
|
||||
}
|
||||
|
||||
case tWithExprEnv: {
|
||||
auto obj2 = (Env *) obj;
|
||||
push(obj2->up);
|
||||
break;
|
||||
}
|
||||
|
||||
case tWithAttrsEnv: {
|
||||
auto obj2 = (Env *) obj;
|
||||
push(obj2->up);
|
||||
push(obj2->values[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -229,6 +241,8 @@ std::pair<Size, Size> GC::Arena::freeUnmarked()
|
|||
objSize = ((PtrList<Value> *) obj)->words();
|
||||
break;
|
||||
case tEnv:
|
||||
case tWithExprEnv:
|
||||
case tWithAttrsEnv:
|
||||
objSize = ((Env *) obj)->words();
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ enum Tag {
|
|||
tBindings,
|
||||
tValueList,
|
||||
tEnv,
|
||||
tWithExprEnv,
|
||||
tWithAttrsEnv,
|
||||
|
||||
// Value tags
|
||||
tInt,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue