transparent lambda

Peter Levart peter.levart at marand.si
Mon Jan 4 03:33:14 PST 2010


On Monday 04 January 2010 11:07:45 Peter Levart wrote:
> Here's another example:
> 
> #int() one = null;
> synchronized int sum(int n) {
>   if (one == null) one = #() { return 1; };
>   return n == 0 ? 0 : sum(n-1) + one();
> }
> 

> The compiler could generate the following code for the above example:
> 

Ops, not entirely correct.

So here's the first "refinement" that should make the generated code correct (changes to previous code are: try/catch wraps the whole method body not each lambda invocation):

#int() one = null;
synchronized int sum(int n) {
  #int() $tmpLambda = null;
  try {

    if (one == null) {
      $tmpLambda = new #int()() { 
        public int invoke() { throw new NonLocalReturnInt(this, 1); }
      };
      one = $tmpLambda;
    }

    return n == 0 ? 0 : sum(n-1) + one();

  }
  catch (NonLocalReturnInt $nlr) {
    if ($tmlLambda == $nlr.lambda)
      return $nlr.retval; 
    else 
      throw $nlr;
  }
}

Each lambda expression that contains a non-local return statement and is specified in a method or constructor reserves a "$tmpLambda" slot on the stack which is filled-in with a reference to the lambda when the lambda expression is evaluated. The "NonLocalReturn" exception also contains a reference to the lambda that initiated the non-local transfer. The body of each method/constructor that contains lambda expressions with non-local returns is wrapped in a try/catch that catches the "NonLocalReturn" and checks it's "lambda" reference with all the "$tmpLambda" slots. If any of them matches, "NonLocalReturn" is translated into a return from the method/constructor else it is re-thrown.

Regards, Peter


More information about the closures-dev mailing list