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