This commit is contained in:
Eelco Dolstra 2010-03-28 16:57:16 +00:00
parent 3d2b835f30
commit d96cdcea6b

View file

@ -75,6 +75,28 @@ struct Value
}; };
static void mkThunk(Value & v, Env & env, Expr expr)
{
v.type = tThunk;
v.thunk.env = &env;
v.thunk.expr = expr;
}
static void mkInt(Value & v, int n)
{
v.type = tInt;
v.integer = n;
}
static void mkBool(Value & v, bool b)
{
v.type = tBool;
v.boolean = b;
}
std::ostream & operator << (std::ostream & str, Value & v) std::ostream & operator << (std::ostream & str, Value & v)
{ {
switch (v.type) { switch (v.type) {
@ -176,13 +198,6 @@ static Value * lookupVar(Env * env, Sym name)
} }
static void setBoolValue(Value & v, bool b)
{
v.type = tBool;
v.boolean = b;
}
static bool eqValues(Value & v1, Value & v2) static bool eqValues(Value & v1, Value & v2)
{ {
forceValue(v1); forceValue(v1);
@ -223,10 +238,10 @@ static Value * allocValues(unsigned int count)
return new Value[count]; // !!! check destructor return new Value[count]; // !!! check destructor
} }
static Env * allocEnv() static Env & allocEnv()
{ {
nrEnvs++; nrEnvs++;
return new Env; return *(new Env);
} }
@ -250,8 +265,7 @@ static void eval(Env & env, Expr e, Value & v)
int n; int n;
if (matchInt(e, n)) { if (matchInt(e, n)) {
v.type = tInt; mkInt(v, n);
v.integer = n;
return; return;
} }
@ -264,28 +278,24 @@ static void eval(Env & env, Expr e, Value & v)
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
Value & v2 = (*v.attrs)[name]; Value & v2 = (*v.attrs)[name];
nrValues++; nrValues++;
v2.type = tThunk; mkThunk(v2, env, e2);
v2.thunk.env = &env;
v2.thunk.expr = e2;
} }
return; return;
} }
ATermList rbnds, nrbnds; ATermList rbnds, nrbnds;
if (matchRec(e, rbnds, nrbnds)) { if (matchRec(e, rbnds, nrbnds)) {
Env * env2 = allocEnv(); Env & env2(allocEnv());
env2->up = &env; env2.up = &env;
v.type = tAttrs; v.type = tAttrs;
v.attrs = &env2->bindings; v.attrs = &env2.bindings;
ATerm name, e2, pos; ATerm name, e2, pos;
for (ATermIterator i(rbnds); i; ++i) { for (ATermIterator i(rbnds); i; ++i) {
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
Value & v2 = env2->bindings[name]; Value & v2 = env2.bindings[name];
nrValues++; nrValues++;
v2.type = tThunk; mkThunk(v2, env2, e2);
v2.thunk.env = env2;
v2.thunk.expr = e2;
} }
return; return;
@ -327,9 +337,7 @@ static void eval(Env & env, Expr e, Value & v)
unsigned int arity = primOp->primOp.arity; unsigned int arity = primOp->primOp.arity;
Value vLastArg; Value vLastArg;
vLastArg.type = tThunk; mkThunk(vLastArg, env, arg);
vLastArg.thunk.env = &env;
vLastArg.thunk.expr = arg;
/* Put all the arguments in an array. */ /* Put all the arguments in an array. */
Value * vArgs[arity]; Value * vArgs[arity];
@ -343,9 +351,7 @@ static void eval(Env & env, Expr e, Value & v)
} else { } else {
Value * v2 = allocValues(2); Value * v2 = allocValues(2);
v2[0] = v; v2[0] = v;
v2[1].type = tThunk; mkThunk(v2[1], env, arg);
v2[1].thunk.env = &env;
v2[1].thunk.expr = arg;
v.type = tPrimOpApp; v.type = tPrimOpApp;
v.primOpApp.left = &v2[0]; v.primOpApp.left = &v2[0];
v.primOpApp.right = &v2[1]; v.primOpApp.right = &v2[1];
@ -356,17 +362,15 @@ static void eval(Env & env, Expr e, Value & v)
if (v.type != tLambda) throw TypeError("expected function"); if (v.type != tLambda) throw TypeError("expected function");
Env * env2 = allocEnv(); Env & env2(allocEnv());
env2->up = &env; env2.up = &env;
ATermList formals; ATerm ellipsis; ATermList formals; ATerm ellipsis;
if (matchVarPat(v.lambda.pat, name)) { if (matchVarPat(v.lambda.pat, name)) {
Value & vArg = env2->bindings[name]; Value & vArg = env2.bindings[name];
nrValues++; nrValues++;
vArg.type = tThunk; mkThunk(vArg, env, arg);
vArg.thunk.env = &env;
vArg.thunk.expr = arg;
} }
else if (matchAttrsPat(v.lambda.pat, formals, ellipsis, name)) { else if (matchAttrsPat(v.lambda.pat, formals, ellipsis, name)) {
@ -376,7 +380,7 @@ static void eval(Env & env, Expr e, Value & v)
if (name == sNoAlias) if (name == sNoAlias)
vArg = &vArg_; vArg = &vArg_;
else { else {
vArg = &env2->bindings[name]; vArg = &env2.bindings[name];
nrValues++; nrValues++;
} }
@ -394,16 +398,14 @@ static void eval(Env & env, Expr e, Value & v)
Bindings::iterator j = vArg->attrs->find(name); Bindings::iterator j = vArg->attrs->find(name);
Value & v = env2->bindings[name]; Value & v = env2.bindings[name];
nrValues++; nrValues++;
if (j == vArg->attrs->end()) { if (j == vArg->attrs->end()) {
if (!matchDefaultValue(def2, def)) def = 0; if (!matchDefaultValue(def2, def)) def = 0;
if (def == 0) throw TypeError(format("the argument named `%1%' required by the function is missing") if (def == 0) throw TypeError(format("the argument named `%1%' required by the function is missing")
% aterm2String(name)); % aterm2String(name));
v.type = tThunk; mkThunk(v, env2, def);
v.thunk.env = env2;
v.thunk.expr = def;
} else { } else {
attrsUsed++; attrsUsed++;
v.type = tCopy; v.type = tCopy;
@ -421,21 +423,21 @@ static void eval(Env & env, Expr e, Value & v)
else abort(); else abort();
eval(*env2, v.lambda.body, v); eval(env2, v.lambda.body, v);
return; return;
} }
Expr attrs; Expr attrs;
if (matchWith(e, attrs, body, pos)) { if (matchWith(e, attrs, body, pos)) {
Env * env2 = allocEnv(); Env & env2(allocEnv());
env2->up = &env; env2.up = &env;
Value & vAttrs = env2->bindings[sWith]; Value & vAttrs = env2.bindings[sWith];
nrValues++; nrValues++;
eval(env, attrs, vAttrs); eval(env, attrs, vAttrs);
if (vAttrs.type != tAttrs) throw TypeError("`with' should evaluate to an attribute set"); if (vAttrs.type != tAttrs) throw TypeError("`with' should evaluate to an attribute set");
eval(*env2, body, v); eval(env2, body, v);
return; return;
} }
@ -443,25 +445,22 @@ static void eval(Env & env, Expr e, Value & v)
v.type = tList; v.type = tList;
v.list.length = ATgetLength(es); v.list.length = ATgetLength(es);
v.list.elems = allocValues(v.list.length); v.list.elems = allocValues(v.list.length);
for (unsigned int n = 0; n < v.list.length; ++n, es = ATgetNext(es)) { for (unsigned int n = 0; n < v.list.length; ++n, es = ATgetNext(es))
v.list.elems[n].type = tThunk; mkThunk(v.list.elems[n], env, ATgetFirst(es));
v.list.elems[n].thunk.env = &env;
v.list.elems[n].thunk.expr = ATgetFirst(es);
}
return; return;
} }
if (matchOpEq(e, e1, e2)) { if (matchOpEq(e, e1, e2)) {
Value v1; eval(env, e1, v1); Value v1; eval(env, e1, v1);
Value v2; eval(env, e2, v2); Value v2; eval(env, e2, v2);
setBoolValue(v, eqValues(v1, v2)); mkBool(v, eqValues(v1, v2));
return; return;
} }
if (matchOpNEq(e, e1, e2)) { if (matchOpNEq(e, e1, e2)) {
Value v1; eval(env, e1, v1); Value v1; eval(env, e1, v1);
Value v2; eval(env, e2, v2); Value v2; eval(env, e2, v2);
setBoolValue(v, !eqValues(v1, v2)); mkBool(v, !eqValues(v1, v2));
return; return;
} }
@ -519,8 +518,7 @@ static void prim_add(Value * * args, Value & v)
if (args[0]->type != tInt) throw TypeError("integer expected"); if (args[0]->type != tInt) throw TypeError("integer expected");
forceValue(*args[1]); forceValue(*args[1]);
if (args[1]->type != tInt) throw TypeError("integer expected"); if (args[1]->type != tInt) throw TypeError("integer expected");
v.type = tInt; mkInt(v, args[0]->integer + args[1]->integer);
v.integer = args[0]->integer + args[1]->integer;
} }