Imagine compiling a Lisp variant. You're handed an AST in the form of an undecorated Lisp structure. You'd like to do only one pass over the AST.
Consider the form: <tt>(fn [a] (fn [b] (+ a b) )</tt> --<tt>fn</tt>== lambda -- returning a lambda expression with the outer parameter <tt>a</tt> closed over.
I can hand-craft this easily (tossing in some gratuitous <tt>int</tt> typing to simplify matters):
<tt>LambdaBuilder outerLb = Utils.Lambda(typeof(Delegate), "ted");
outerLb.DoNotAddContext = true;
ParameterExpression a = outerLb.ClosedOverParameter(typeof(int), "a");
LambdaBuilder innerLb = Utils.Lambda(typeof(int), "fred");
innerLb.DoNotAddContext = true;
ParameterExpression b = Expression.Parameter(typeof(int),"b");
Expression exp = Expression.Add(a, b);
innerLb.Body = exp;
LambdaExpression innerLambda = innerLb.MakeLambda();
outerLb.Body = innerLambda;
LambdaExpression outerLambda = outerLb.MakeLambda();
The problem is that I can't figure out how to do this in one pass. I do not see any way to make the <tt>a</tt> parameter closed
except by creating it using <tt>LambdaBuilder.ClosedOverParameter</tt>. That means I have to know at the time of parameter creation--which needs to be before descending into the nested form in any reasonable approach--that this parameter is to
be closed over, and the only way to know that is to first visit the subform. Hence, two passes.
Given that the only real difference between <tt>ClosedOverParameter</tt> and <tt>Parameter</tt> is the equivalent of the setting of a flag, it would be nice if one could do just that: create the outer param, parse the subform and note
the non-local variable reference, and set the closed-over flag on the way back out.