forked from lix-project/lix
This commit is contained in:
parent
3d2b835f30
commit
d96cdcea6b
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue