Thread overview
Return in finally
Mar 07, 2007
BCS
Mar 07, 2007
BCS
Mar 08, 2007
Ary Manzana
March 07, 2007
While programatically porting Java ...

A finally block cannot contain another try/catch block. This is allowed in Java. The solution i use is this:

int f(){
  try{
  } finally {
    (){ // start definition of an unnamed function literal
      try{
      } finally {
        // (1)
      }
    }(); // call it.
  }
  return 1;
}

Now, i have the first time the situation where at (1) a return statement
 occurs. This is not allowed in an a finally block at all [2], and
withing the function literal it would not end the surrounding function.

Any idea, how to simulate
1.) try/catch/finally in a finally
2.) make a return from within a finally
??


[2] not allowed in D, but it is allowed in Java
March 07, 2007
Frank Benoit (keinfarbton) wrote:
> While programatically porting Java ...
> 
> A finally block cannot contain another try/catch block. This is allowed
> in Java. The solution i use is this:
> 
> int f(){
>   try{
>   } finally {
>     (){ // start definition of an unnamed function literal
>       try{
>       } finally {
>         // (1)
>       }
>     }(); // call it.
>   }
>   return 1;
> }
> 
> Now, i have the first time the situation where at (1) a return statement
>  occurs. This is not allowed in an a finally block at all [2], and
> withing the function literal it would not end the surrounding function.
> 
> Any idea, how to simulate
> 1.) try/catch/finally in a finally
> 2.) make a return from within a finally
> ??
> 
> 
> [2] not allowed in D, but it is allowed in Java



try
{
...
}
finally
{
...
return;
...
}

|
|
v

try
{
...
}
catch(Object e)
{
...
return;
...
throw e;
}

bad practice in hand work, but this is auto gen code.


March 07, 2007
If i understand your idea right...

class FinallyException : Object {} // Special excecption to enter a
finally block.
class Throwable : Exception {} // Base of all Java Exceptions

Now, instead of finally use only catch blocks

catch( FinallyException fe ){
 ...
}

Hm, i need to think more about it...
The FinallyException can be used to transport a thrown exception
At (1),(2) and (3) a return(val) or throw can happen.

// Java ==========================
try{
  // (1)
} catch( IOException e ){
  // (2)
} finally {
  // (3)
}

// D ==========================
auto fe = new FinallyException();
try{
  try{
    // (1)
    throw fe;
  } catch( IOException e ){
    try{
    // (2)
    } catch( Object e ) {
      fe.store(e);
      throw fe;
    }
  }

}catch( FinallyException fe ){
  // (3)
}
fe.throwIfHasException();


Does this work? oh, my brain hurts :)

Another thought, what about the performance, if an exception is always thrown to reach the "finally" block? is that an issue?

March 07, 2007
// D ==========================
int func(){
  ...
  {
    Tioport_ResultState!(int) tioport_result_001;
    try{
      try{
        // (1)
      } catch( IOException e ){
        // (2)
      }
    } catch( Object e ) {
      // catch and store for rethrow after Finally_001
      tioport_result_001.setException( e );
    }
    Finally_001:
    {
      // (3)
    }
    tioport_result_001.checkException(); // throw if one was stored
    return tioport_result_001.get();
  }
}

In (1) und (2) replace all "return;" with "goto Finally_001;". "return
expr;" with "{ tioport_result_001.set( expr ); goto Finally_001; }"

If in (3) a return or throw occurs, it hides previous returns/throws,
like java does.

This approach do not throw an exception in normal run.

What do you think?
Do I miss a less complicated way?
March 07, 2007
Frank Benoit (keinfarbton) wrote:
> If i understand your idea right...
> 
> class FinallyException : Object {} // Special excecption to enter a
> finally block.
> class Throwable : Exception {} // Base of all Java Exceptions
> 
> Now, instead of finally use only catch blocks
> 
> catch( FinallyException fe ){
>  ...
> }
> 

There is no need for special excption types, Object will catch everything. Err. However it won't catch a normal exit.

Fud, It's not quite as clean as I thought.
March 08, 2007
Frank Benoit (keinfarbton) escribió:
> Any idea, how to simulate
> 2.) make a return from within a finally
> ??

Maybe you can do something like this:

Java
-------------------------------------------------
int func() {
	try {
	} finally {
		return 1;
	}
}
-------------------------------------------------

D
-------------------------------------------------
import std.boxer;

int func() {
	Box finallyReturn;
	try {
	} finally {
		finallyReturn = box(1);
	}
	if (finallyReturn.type !is null) {
		return unbox!(int)(finallyReturn);
	}
}
-------------------------------------------------

You have to be careful, though. After every block that has a return statement you have to proceed only if the box's type is null. For example:

Java
-------------------------------------------------
int func() {
	try {
	} finally {
		if (someCondition) {
			return 1;
		}
		doSomeStuff();
		return 2;
	}
}
-------------------------------------------------

D
-------------------------------------------------
import std.boxer;

int func() {
	Box finallyReturn;
	try {
	} finally {
		if (someCondition) {
			finallyReturn = box(1);
		}
		if (finallyReturn.type is null) {
			doSomeStuff();
			finallyReturn = box(2);
		}
	}
	if (finallyReturn.type !is null) {
		return unbox!(int)(finallyReturn);
	}
}
-------------------------------------------------

Does this work?
March 08, 2007
> Does this work?

yes, this would handle the return, but it would not allow a second try/catch in the finally block.

What i use now is this:
// D ==========================
int func(){
  ...
  {
    bool   tioport_stat_set_1;
    int    tioport_stat_val_1;
    Object tioport_stat_exc_1;
    try{
      try{
        // (1)
      tryend_1:;
      } catch( IOException e ){
        // (2)
      }
      catchend_1:;
    } catch( Object e ) {
      tioport_stat_exc_1 = e;
    }
    {
      // (3)
    }
    if(tioport_stat_exc_1 !is null) throw tioport_stat_exc_1;
    if(tioport_stat_set_1) return tioport_stat_val_1;
  }
}

In (1) und (2) replace all "return expr;" with
{ tioport_stat_set_1 = true;
  tioport_stat_val_1 = expr; // if has a return val
  goto tryend_1;             // or catchend_1
}

Now the finally block is a normal code block.
It is possible to have more try/catch in the finally block.
It is possible to return/throw from the finally block