* 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:
parent
ac1e8f40d4
commit
7d47498b5e
5 changed files with 45 additions and 1 deletions
|
@ -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)
|
void ExprList::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
state.mkList(v, elems.size());
|
state.mkList(v, elems.size());
|
||||||
|
|
|
@ -244,6 +244,7 @@ private:
|
||||||
|
|
||||||
friend class ExprVar;
|
friend class ExprVar;
|
||||||
friend class ExprAttrs;
|
friend class ExprAttrs;
|
||||||
|
friend class ExprLet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,16 @@ void ExprLambda::show(std::ostream & str)
|
||||||
str << ": " << *body << ")";
|
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)
|
void ExprWith::show(std::ostream & str)
|
||||||
{
|
{
|
||||||
str << "with " << *attrs << "; " << *body;
|
str << "with " << *attrs << "; " << *body;
|
||||||
|
|
|
@ -139,6 +139,14 @@ struct ExprLambda : Expr
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ExprLet : Expr
|
||||||
|
{
|
||||||
|
ExprAttrs * attrs;
|
||||||
|
Expr * body;
|
||||||
|
ExprLet(ExprAttrs * attrs, Expr * body) : attrs(attrs), body(body) { };
|
||||||
|
COMMON_METHODS
|
||||||
|
};
|
||||||
|
|
||||||
struct ExprWith : Expr
|
struct ExprWith : Expr
|
||||||
{
|
{
|
||||||
Pos pos;
|
Pos pos;
|
||||||
|
|
|
@ -306,7 +306,7 @@ expr_function
|
||||||
| WITH expr ';' expr_function
|
| WITH expr ';' expr_function
|
||||||
{ $$ = new ExprWith(CUR_POS, $2, $4); }
|
{ $$ = new ExprWith(CUR_POS, $2, $4); }
|
||||||
| LET binds IN expr_function
|
| LET binds IN expr_function
|
||||||
{ $2->attrs[data->sLetBody] = $4; $2->recursive = true; $$ = new ExprSelect($2, data->sLetBody); }
|
{ $$ = new ExprLet($2, $4); }
|
||||||
| expr_if
|
| expr_if
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue