* Evaluate lets directly (i.e. without desugaring to `rec { attrs...;

<let-body> = e; }.<let-body>).  This prevents the unnecessary
  allocation of an attribute set.
This commit is contained in:
Eelco Dolstra 2010-04-13 13:42:25 +00:00
parent ac1e8f40d4
commit 7d47498b5e
5 changed files with 45 additions and 1 deletions

View file

@ -456,6 +456,31 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
}
void ExprLet::eval(EvalState & state, Env & env, Value & v)
{
/* Create a new environment that contains the attributes in this
`let'. */
Env & env2(state.allocEnv());
env2.up = &env;
/* The recursive attributes are evaluated in the new
environment. */
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) {
Value & v2 = env2.bindings[i->first];
mkThunk(v2, env2, i->second);
}
/* The inherited attributes, on the other hand, are evaluated in
the original environment. */
foreach (list<Symbol>::iterator, i, attrs->inherited) {
Value & v2 = env2.bindings[*i];
mkCopy(v2, *state.lookupVar(&env, *i));
}
state.eval(env2, body, v);
}
void ExprList::eval(EvalState & state, Env & env, Value & v)
{
state.mkList(v, elems.size());

View file

@ -244,6 +244,7 @@ private:
friend class ExprVar;
friend class ExprAttrs;
friend class ExprLet;
public:

View file

@ -87,6 +87,16 @@ void ExprLambda::show(std::ostream & str)
str << ": " << *body << ")";
}
void ExprLet::show(std::ostream & str)
{
str << "let ";
foreach (list<Symbol>::iterator, i, attrs->inherited)
str << "inherit " << *i << "; ";
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
str << i->first << " = " << *i->second << "; ";
str << "in " << *body;
}
void ExprWith::show(std::ostream & str)
{
str << "with " << *attrs << "; " << *body;

View file

@ -139,6 +139,14 @@ struct ExprLambda : Expr
COMMON_METHODS
};
struct ExprLet : Expr
{
ExprAttrs * attrs;
Expr * body;
ExprLet(ExprAttrs * attrs, Expr * body) : attrs(attrs), body(body) { };
COMMON_METHODS
};
struct ExprWith : Expr
{
Pos pos;

View file

@ -306,7 +306,7 @@ expr_function
| WITH expr ';' expr_function
{ $$ = new ExprWith(CUR_POS, $2, $4); }
| LET binds IN expr_function
{ $2->attrs[data->sLetBody] = $4; $2->recursive = true; $$ = new ExprSelect($2, data->sLetBody); }
{ $$ = new ExprLet($2, $4); }
| expr_if
;