* Implemented withs.
This commit is contained in:
parent
9985230c00
commit
110d155778
4 changed files with 38 additions and 15 deletions
|
@ -72,7 +72,8 @@ void run(Strings args)
|
||||||
doTest(state, "let { x = 1; body = x; }");
|
doTest(state, "let { x = 1; body = x; }");
|
||||||
doTest(state, "with { x = 1; }; x");
|
doTest(state, "with { x = 1; }; x");
|
||||||
doTest(state, "let x = 2; in with { x = 1; }; x"); // => 2
|
doTest(state, "let x = 2; in with { x = 1; }; x"); // => 2
|
||||||
doTest(state, "with { x = 1; }; with { x = 2; }; x"); // => 1
|
doTest(state, "with { x = 1; }; with { x = 2; }; x"); // => 2
|
||||||
|
doTest(state, "with { x = 1; }; with { y = 2; }; x"); // => 1
|
||||||
doTest(state, "[ 1 2 3 ]");
|
doTest(state, "[ 1 2 3 ]");
|
||||||
doTest(state, "[ 1 2 ] ++ [ 3 4 5 ]");
|
doTest(state, "[ 1 2 ] ++ [ 3 4 5 ]");
|
||||||
doTest(state, "123 == 123");
|
doTest(state, "123 == 123");
|
||||||
|
|
|
@ -253,8 +253,6 @@ Value * EvalState::lookupVar(Env * env, const Symbol & name)
|
||||||
Bindings::iterator j = i->second.attrs->find(name);
|
Bindings::iterator j = i->second.attrs->find(name);
|
||||||
if (j != i->second.attrs->end()) return &j->second;
|
if (j != i->second.attrs->end()) return &j->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
throwEvalError("urgh! undefined variable `%1%'", name);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,13 +481,15 @@ void ExprList::eval(EvalState & state, Env & env, Value & v)
|
||||||
|
|
||||||
void ExprVar::eval(EvalState & state, Env & env, Value & v)
|
void ExprVar::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
printMsg(lvlError, format("eval var %1% %2% %3%") % fromWith % level % displ);
|
|
||||||
|
|
||||||
if (fromWith) {
|
|
||||||
abort();
|
|
||||||
} else {
|
|
||||||
Env * env2 = &env;
|
Env * env2 = &env;
|
||||||
for (unsigned int l = level; l; --l, env2 = env2->up) ;
|
for (unsigned int l = level; l; --l, env2 = env2->up) ;
|
||||||
|
|
||||||
|
if (fromWith) {
|
||||||
|
Bindings::iterator j = env2->values[0].attrs->find(name);
|
||||||
|
if (j == env2->values[0].attrs->end())
|
||||||
|
throwEvalError("undefined variable `%1%'", name);
|
||||||
|
v = j->second;
|
||||||
|
} else {
|
||||||
state.forceValue(env2->values[displ]);
|
state.forceValue(env2->values[displ]);
|
||||||
v = env2->values[displ];
|
v = env2->values[displ];
|
||||||
}
|
}
|
||||||
|
@ -655,17 +655,26 @@ void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res
|
||||||
|
|
||||||
void ExprWith::eval(EvalState & state, Env & env, Value & v)
|
void ExprWith::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
abort();
|
Env & env2(state.allocEnv(1));
|
||||||
#if 0
|
|
||||||
Env & env2(state.allocEnv());
|
|
||||||
env2.up = &env;
|
env2.up = &env;
|
||||||
|
|
||||||
Value & vAttrs = env2.bindings[state.sWith];
|
state.eval(env, attrs, env2.values[0]);
|
||||||
state.eval(env, attrs, vAttrs);
|
state.forceAttrs(env2.values[0]);
|
||||||
state.forceAttrs(vAttrs);
|
|
||||||
|
/* If there is an enclosing `with', copy all attributes that don't
|
||||||
|
appear in this `with'. */
|
||||||
|
if (prevWith != -1) {
|
||||||
|
Env * env3 = &env;
|
||||||
|
for (unsigned int l = prevWith; l; --l, env3 = env3->up) ;
|
||||||
|
|
||||||
|
foreach (Bindings::iterator, i, *env3->values[0].attrs) {
|
||||||
|
Bindings::iterator j = env2.values[0].attrs->find(i->first);
|
||||||
|
if (j == env2.values[0].attrs->end())
|
||||||
|
(*env2.values[0].attrs)[i->first] = i->second; // !!! sharing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state.eval(env2, body, v);
|
state.eval(env2, body, v);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -264,6 +264,18 @@ void ExprLet::bindVars(const StaticEnv & env)
|
||||||
|
|
||||||
void ExprWith::bindVars(const StaticEnv & env)
|
void ExprWith::bindVars(const StaticEnv & env)
|
||||||
{
|
{
|
||||||
|
/* Does this `with' have an enclosing `with'? If so, record its
|
||||||
|
level so that we can copy the attributes of the enclosing
|
||||||
|
`with'. */
|
||||||
|
const StaticEnv * curEnv;
|
||||||
|
unsigned int level;
|
||||||
|
prevWith = -1;
|
||||||
|
for (curEnv = &env, level = 0; curEnv; curEnv = curEnv->up, level++)
|
||||||
|
if (curEnv->isWith) {
|
||||||
|
prevWith = level;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
attrs->bindVars(env);
|
attrs->bindVars(env);
|
||||||
StaticEnv newEnv(true, &env);
|
StaticEnv newEnv(true, &env);
|
||||||
body->bindVars(newEnv);
|
body->bindVars(newEnv);
|
||||||
|
|
|
@ -170,6 +170,7 @@ struct ExprWith : Expr
|
||||||
{
|
{
|
||||||
Pos pos;
|
Pos pos;
|
||||||
Expr * attrs, * body;
|
Expr * attrs, * body;
|
||||||
|
int prevWith;
|
||||||
ExprWith(const Pos & pos, Expr * attrs, Expr * body) : pos(pos), attrs(attrs), body(body) { };
|
ExprWith(const Pos & pos, Expr * attrs, Expr * body) : pos(pos), attrs(attrs), body(body) { };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue