Why does scope(success) have to use exceptions?

Era Scarecrow rtcvb32 at yahoo.com
Wed Jan 16 16:06:44 PST 2013


On Wednesday, 16 January 2013 at 23:19:20 UTC, Andrej Mitrovic 
wrote:
> Sample code:
> I was expecting callScope to be lowered down to the handwritten 
> code in callFunc in assembly, but instead it uses exceptions. 
> Here's some simple ASM for callFunc compiled with -c -release 
> -O (no inline):
>

  <snip>

> I'm trying to understand why. If an exception is thrown between 
> one of those assignment statements the stack will unwind and 
> any following assignment statements will not be called, so 
> there shouldn't be a need to check if an exception is thrown. 
> Why doesn't the compiler simply rewrite callScope to look like 
> callFunc?

  Obviously your code won't throw, however that's now how scope 
works.

  TDPL. pg 84-88 explains the lowering of scope is equal to hand 
written try/catch/finally versions; But you don't have to worry 
about making a mistake in the writing and adding more scopes is 
easier. Handling SQL and several tasks that all need to succeed 
or certain steps to be cleaned up afterwards makes perfect sense 
for scope.

[quote]
  Consider a block containing a scope(exit) statement:

   {
     <statements1>
     scope(exit) statement<2>
     <statements3>
   }

  Let's pick the first scope in the block, so we can assume that 
<statements1> itself does not contain scope (but <statement2> and 
<statments3> might). Lowering transforms the code into this:

   {
     <statements1>
     try {
       <statements3>
     } finally {
       <statement2>
     }
   }

  Following the transform, <statements3> and <statement2> are 
further lowered because they may contain additional scope 
statements. (The lowering always ends because the fragments are 
always strictly smaller than the initial sequence.) this means 
that code containing multiple scope(exit) statements is well 
defined, even in weird cases like scope(exit) scope(exit) 
scope(exit) writeln ("?"). In particular let's see what happens 
in the interesting case of two scope(exit) statements in the same 
block.

   }
     <statements1>
     scope(exit) <statement2>
     <statements3>
     scope(exit) <statement4>
     <statements5>
   }

  Let's assume that all statements do not containing additional 
scope(exit) statements. After lowering we obtain

   {
     <statements1>
     try {
       <statements3>
       try {
         <statements5>
       } finally {
         <statement4>
       }
     } finally {
       <statement2>
     }
   }

  The purpose of showing this unwieldly code is to figure out the 
order of execution of multiple scope(exit) statements in the same 
block. Following the flow shows that <statement4> gets executed 
before <statment2>. In general, scope(exit) statements execute in 
a stack, LIFO manner, the reverse of their order in the execution 
flow.

[/quote]

  Only asserts or exceptions would/can manage to decide if the 
block was successful or not; And the scope(s) can then manage 
cleanup (or final code) regardless where it was put without you 
having to do it yourself. If there's never any chance of it 
failing in the function then scope may not be what you want.

  However if compiler knows and can verify the code is unable to 
fail (thus exceptions are not needed) perhaps an enhancement 
request that could remove the unneeded try/catches...


More information about the Digitalmars-d mailing list