Re: scope(success) lowered to try-catch ?

2018-06-18 Thread aliak via Digitalmars-d-learn
On Monday, 18 June 2018 at 12:48:46 UTC, Steven Schveighoffer 
wrote:

On 6/17/18 11:58 PM, Neia Neutuladh wrote:

[...]


Yep, it's a good point. But also not the only way to do this. 
If you are returning void, just a goto would work:


[...]


I'm quite a noob when it comes to compiler stuff, and I see how 
this can be optimized when there're no exceptions, but I wonder 
what scope(success) actually means though without exceptions in 
play. It's just scope(exit) then right or?


Cheers,
- Ali



Re: scope(success) lowered to try-catch ?

2018-06-18 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/17/18 11:58 PM, Neia Neutuladh wrote:

On Sunday, 17 June 2018 at 10:58:29 UTC, Cauterite wrote:

Is there a reason scope(success) needs to set up for exception handling?
Or is this a bug / potential enhancement ?


If you had no exception handling in place, you'd need to duplicate code 
in the output. For instance:


void foo()
{
   scope(success) writeln("success!");
   if (a) return;
   if (b) return;
   throw new Exception;
}

This would have to be lowered to:

void foo()
{
   if (a) { writeln("success!"); return; }
   if (b) { writeln("success!"); return; }
   throw new Exception;
   writeln("success!");  // maybe omitted with flow analysis
}


Yep, it's a good point. But also not the only way to do this. If you are 
returning void, just a goto would work:


void foo()
{
   if(a) { goto L1; }
   if(b) { goto L1; }
   throw new Exception;
L1:
   writeln("success1");
}

If you are returning a value, then you can establish a local variable 
with the return value, and use a goto that way. It's already doing this 
with "did it succeed", so adding another local variable is pretty trivial.


Bottom line is, the compiler understands flow control and can insert 
structures like this without a huge impact.


I also think it's possible for the compiler to detect that a try/catch 
clause is trivially omitted if we do it in the right way.




Now imagine there were 20 places you return from the function early. Now 
imagine this is in a loop body, where you can leave it via goto, break, 
continue, return, or end-of-block. And wrapped in several if statements.


These are all pretty easy to deal with. After all, they are essentially 
glorified gotos.




You generate smaller code with the exception handling system. The 
compiler only has to pay attention to scope guards in the code that 
handles it directly, instead of at every flow control statement. Add to 
that the fact that -betterC is pretty recent and scope guards are more 
than ten years old, and you get this hole in the compiler.


I think the last point here is exactly why it was done this way -- the 
original design of the compiler was to expect there were always 
exception handling, so why not use it?


-Steve


Re: scope(success) lowered to try-catch ?

2018-06-18 Thread Cauterite via Digitalmars-d-learn

On Monday, 18 June 2018 at 03:58:47 UTC, Neia Neutuladh wrote:

...


yeah, at an AST level it makes sense why it was implemented like 
this.
it's unfortunate that there's no straightforward way to express 
'finally(success) {'.


Re: scope(success) lowered to try-catch ?

2018-06-17 Thread Neia Neutuladh via Digitalmars-d-learn

On Sunday, 17 June 2018 at 10:58:29 UTC, Cauterite wrote:
Is there a reason scope(success) needs to set up for exception 
handling?

Or is this a bug / potential enhancement ?


If you had no exception handling in place, you'd need to 
duplicate code in the output. For instance:


void foo()
{
  scope(success) writeln("success!");
  if (a) return;
  if (b) return;
  throw new Exception;
}

This would have to be lowered to:

void foo()
{
  if (a) { writeln("success!"); return; }
  if (b) { writeln("success!"); return; }
  throw new Exception;
  writeln("success!");  // maybe omitted with flow analysis
}

Now imagine there were 20 places you return from the function 
early. Now imagine this is in a loop body, where you can leave it 
via goto, break, continue, return, or end-of-block. And wrapped 
in several if statements.


You generate smaller code with the exception handling system. The 
compiler only has to pay attention to scope guards in the code 
that handles it directly, instead of at every flow control 
statement. Add to that the fact that -betterC is pretty recent 
and scope guards are more than ten years old, and you get this 
hole in the compiler.


Re: scope(success) lowered to try-catch ?

2018-06-17 Thread Mike Franklin via Digitalmars-d-learn

On Sunday, 17 June 2018 at 10:58:29 UTC, Cauterite wrote:


---

// main.d
void main() {
scope(success) {}
}


dmd -betterC main.d

Error: Cannot use try-catch statements with -betterC

---


You can see what the compiler is doing at 
https://run.dlang.io/is/5BZOQV and clicking on the "AST" button.  
It produces the following:


import object;
void main()
{
bool __os2 = false;
try
{
}
catch(Throwable __o3)
{
__os2 = true;
throw __o3;
}
if (!__os2)
{
}
return 0;
}

The compiler could probably lower that to something more 
intelligent so it could be used in -betterC.  I rule it a bug.


Mike




Re: scope(success) lowered to try-catch ?

2018-06-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/17/18 8:24 AM, Timoses wrote:

On Sunday, 17 June 2018 at 10:58:29 UTC, Cauterite wrote:

Hello,
I'm not sure whether I'm missing something obvious here, but is there 
a reason for scope(success) being lowered to a try-catch statement?
I would have expected only scope(exit) and scope(failure) to actually 
interact with exception handling, while scope(success) simply places 
code on the path of normal control flow.


Example (windows x32):

---

// main.d
void main() {
scope(success) {}
}


dmd -betterC main.d

Error: Cannot use try-catch statements with -betterC

---

Regardless of whether -betterC is used, you can see in the disassembly 
that having a scope(success) anywhere in the function causes the SEH 
prologue to be emitted in the code.


Is there a reason scope(success) needs to set up for exception handling?
Or is this a bug / potential enhancement ?


In Andrei's book 'The D Programming Language' the following is written:

{
     
     scope(success) 
     
}
is lowered to
{
     
     bool __succeeded = true;
     try {
     
     } catch(Exception e) {
     __succeeded = false;
     throw e;
     } finally {
     if (__succeeded)  // vice-versa for scope(failure): 
`if (!__succeeded) ...`

     }
}

If it weren't and it would simply be integrated one would have to write

     potentiallyThrowingFunc();
     scope(success) {...};

I suppose? And this seems like breaking how scope works with failure and 
exit?

I think the request isn't to integrate the code immediately, but to do:

{




}

and be just fine. I think the reason the scope(failure) is done that way 
is likely for proper exception chaining in case one of the scope 
statements throws.


-Steve


Re: scope(success) lowered to try-catch ?

2018-06-17 Thread Cauterite via Digitalmars-d-learn

On Sunday, 17 June 2018 at 12:10:33 UTC, Nicholas Wilson wrote:
I suspect scope(success) is lowered because scope(exit) and 
scope(failure)
are, and that would result in a simpler (compiler) 
implementation of it.


does adding nothrow to main fix it? For dcompute I specifically 
allow scope(exit|success) because there will never be any 
exceptions _at all_.


If not, please do submit an issue. Also a better error message 
should be given.


nothrow unfortunately doesn't help; i guess I'll file an issue.
thanks for your input


Re: scope(success) lowered to try-catch ?

2018-06-17 Thread Steven Schveighoffer via Digitalmars-d-learn

On 6/17/18 6:58 AM, Cauterite wrote:

Hello,
I'm not sure whether I'm missing something obvious here, but is there a 
reason for scope(success) being lowered to a try-catch statement?
I would have expected only scope(exit) and scope(failure) to actually 
interact with exception handling, while scope(success) simply places 
code on the path of normal control flow.


Example (windows x32):

---

// main.d
void main() {
 scope(success) {}
}


dmd -betterC main.d

Error: Cannot use try-catch statements with -betterC

---

Regardless of whether -betterC is used, you can see in the disassembly 
that having a scope(success) anywhere in the function causes the SEH 
prologue to be emitted in the code.


Is there a reason scope(success) needs to set up for exception handling?
Or is this a bug / potential enhancement ?


I think you are right, adding scope(success) should just add the 
statements to the end of the scope.


Here's what I think happens: Because scope(anything) needs to put things 
like this:


try
{
   normal code
   scope(success) code
} catch(Exception e) {
   scope(failure) code
   throw e;
} finally {
   scope(exit) code
}

so any time you use a scope statement, it has to set up this framework 
so it can have the correct place to put things (there may be 
scope(failure) or scope(exit) code later). But I think we can fix this.


-Steve


Re: scope(success) lowered to try-catch ?

2018-06-17 Thread Timoses via Digitalmars-d-learn

On Sunday, 17 June 2018 at 10:58:29 UTC, Cauterite wrote:

Hello,
I'm not sure whether I'm missing something obvious here, but is 
there a reason for scope(success) being lowered to a try-catch 
statement?
I would have expected only scope(exit) and scope(failure) to 
actually interact with exception handling, while scope(success) 
simply places code on the path of normal control flow.


Example (windows x32):

---

// main.d
void main() {
scope(success) {}
}


dmd -betterC main.d

Error: Cannot use try-catch statements with -betterC

---

Regardless of whether -betterC is used, you can see in the 
disassembly that having a scope(success) anywhere in the 
function causes the SEH prologue to be emitted in the code.


Is there a reason scope(success) needs to set up for exception 
handling?

Or is this a bug / potential enhancement ?


In Andrei's book 'The D Programming Language' the following is 
written:


{

scope(success) 

}
is lowered to
{

bool __succeeded = true;
try {

} catch(Exception e) {
__succeeded = false;
throw e;
} finally {
if (__succeeded)  // vice-versa for 
scope(failure): `if (!__succeeded) ...`

}
}

If it weren't and it would simply be integrated one would have to 
write


potentiallyThrowingFunc();
scope(success) {...};

I suppose? And this seems like breaking how scope works with 
failure and exit?!


Re: scope(success) lowered to try-catch ?

2018-06-17 Thread Nicholas Wilson via Digitalmars-d-learn

On Sunday, 17 June 2018 at 10:58:29 UTC, Cauterite wrote:

Hello,
I'm not sure whether I'm missing something obvious here, but is 
there a reason for scope(success) being lowered to a try-catch 
statement?
I would have expected only scope(exit) and scope(failure) to 
actually interact with exception handling, while scope(success) 
simply places code on the path of normal control flow.


Example (windows x32):

---

// main.d
void main() {
scope(success) {}
}


dmd -betterC main.d

Error: Cannot use try-catch statements with -betterC

---

Regardless of whether -betterC is used, you can see in the 
disassembly that having a scope(success) anywhere in the 
function causes the SEH prologue to be emitted in the code.


Is there a reason scope(success) needs to set up for exception 
handling?

Or is this a bug / potential enhancement ?


I suspect scope(success) is lowered because scope(exit) and 
scope(failure)
are, and that would result in a simpler (compiler) implementation 
of it.


does adding nothrow to main fix it? For dcompute I specifically 
allow scope(exit|success) because there will never be any 
exceptions _at all_.


If not, please do submit an issue. Also a better error message 
should be given.