* 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) | ||||
| { | ||||
|     state.mkList(v, elems.size()); | ||||
|  |  | |||
|  | @ -244,6 +244,7 @@ private: | |||
| 
 | ||||
|     friend class ExprVar; | ||||
|     friend class ExprAttrs; | ||||
|     friend class ExprLet; | ||||
| 
 | ||||
| public: | ||||
|      | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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 | ||||
|   ; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue