Re: Try/Catch

new topic     » goto parent     » topic index » view thread      » older message » newer message
dcuny said...
petelomax said...

I would think that you need some kind of stack unwind.

I think you misunderstand. I meant to state the very obvious - RTFatal currently stops code execution, and that behavior would have to be altered in order to handle exceptions.

I'd suggested that opcodes be put in place to check the return status from a routine that might set a fatal condition.

Well, most things can run out of memory and all variables can be unassigned, so that's at least 80% of all opcodes. That strategy will make programs nearly twice as big and half as fast.
Anyway, when you get what I mean by stack unwind, I am sure you will agree it is quite essential.

dcuny said...

You can't simply perform a call stack unwind because traditional try/catch blocks can potentially be nested.

Plus, you need to handle the exception at the local level, where the exception took place. How is unwinding to a prior call helpful, if a local resource needs to taken care of? The prior call can't see into the routine with an exception.

You have to unwind the stack to the context where the exception handling code can execute:

function fdiv(atom a, atom b) 
    return a/b 
end function 
function g(atom c, atom d) 
    return fdiv(c,d) 
end function 
function h(atom e, atom f) 
    return fdiv(e,f) 
end function 
procedure p() 
    try 
        ? g(i,j) 
    catch 
        puts(1,"error in g(i,j)") 
    end try 
end procedure 
procedure q() 
    try 
        ? h(k,l) 
    catch 
        puts(1,"error in h(k,l)") 
    end try 
end procedure 

When you execute/resume at the exception handling code (puts) in p()/q(), the context/call stack must be unwound to that of p/q, not left as it was in fdiv. There may well be a saved context that the exception handler can examine, but the actively running context/stack frame as the exception handling code executes cannot be one from a completely different routine. In Eu, I doubt there is any way round the fact that by the time the puts is executed, a,b,c,d,e, and f may all have been deallocated.

dcuny said...
petelomax said...

All excellent arguments for not adding finally (an awful, stupid, confusing concept) to Euphoria.

Please explain your issue with finally.

I do not like anything which looks like it is doing something else. If I see return x, or throw(blah), then I expect it to do just that, not nip down and execute some other block of code first, or worse, have a return 1 quietly overridden by a return 2 in the finally block.

dcuny said...

For handling system resources, it's essential that they be released correctly. finally guarantees that this will have the opportunity to happen.

How is this bad thing?

I don't understand. Is proper, obvious, clear and straightforward code not going to be executed?
What "guarantee" are you offering that is not already there?
Are you intending to have filtering such that handlers only deal with certain exceptions and implicitly re-throw any not explicitly dealt with?

dcuny said...
petelomax said...

If the main point of exception handling is to separate error handling code from the main logic, what is wrong with putting such things in a separate routine?

The point of structured exception handling is to handle exceptions in a structured manner.

One huge problem with calling cleanup() is that it hasn't got access to the local variables.

How do you close a resource in cleanup() when you don't have the handle to it?

cleanup(handle), or as below

dcuny said...

How do you save the user's current work when #cleanup() can't see the data structure the user was working on?

cleanup(data_structure_the_user_was_working_on), or as below

dcuny said...

How can you handle the exception at a level the exception didn't happen on?

I have no idea what that means. You handle exceptions in the exception handling code, after the call stack has been appropriately unwound to the correct/calling level.
In the above example, the puts() occurs in p() or q(), and not in fdiv() where the error actually happened.

dcuny said...
petelomax said...

It makes me madder than hell to think of such a horrible backward construct being added to Eu, if two simple calls would do.

That's a big "if".

Often, to simple calls won't do.

How you you pass the context of the current call to your cleanup() routine?

cleanup(context), or as below

dcuny said...

Having try/catch scoped to a block inside the offending call solves that problem.

petelomax said...

Of course if you are not re-throwing an exception, which I would have thought is more likely anyway, or are prepared to use a simple flag/return value, <such code> can and should just go after the end try.

I'm not sure I follow you here. Whether you re-throw an exception depends entirely on what the exception was, and how it should be handled.

If you are prepared to use the odd control flag and/or result variable, you can write all your cleanup code locally, and you don't need a cleanup() with umpteen parameters.

dcuny said...
petelomax said...

Of course the other burning question is why someone might want exception handling

Because exceptions need to be handled.

Halting isn't a robust way of handling exceptions.

petelomax said...
  • to write good quality robust code, but without the messiness of error code handling

You've lost me here. try/catch is error handling. Euphoria currently hasn't got solid error handling.
What "error code handling" are you referring to?

try/catch is exception handling. Euphoria has always had perfectly good error code handling, by which I mean open() returns -1, get() returns GET_FAIL, or that you can test for divide by zero first.

Hopefully some parts of what I am saying are helpful, and not too antagonistic.

Pete

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu