Saturday 27 April 2013

Yet another attempt at try/finally/except

Combined with setjmp/longjmp I previously tried to use a switch statement to hold the try/finally branches of code after noting the similarity between the C# except clauses and a switch/case statement.

I then rather too hastily abandoned this attempt under the impression that the curly braces are an essential part of the switch statement merely because that's how everyone shows them.

As I read further macro tricks I came across the blog of Jens Gusted, author of the unfortunately QT licensed P99 macro set which provides excellent capabilities, including try, catch and except in the syntax form I was seeking which does not involve trailing macros.

So I took a look at how Jens managed it and noticed a few tricks, including use of for (type var=...;...;...) as a way to start an indefinitely chainable single-statement scope that did not need a close-curly-brace but could declare a variable for that scope. But what most caught my eye was his use of the switch statement without curly braces.

It soon became apparent that the switch statement is just a statement, and that the case clauses are merely goto-label placeholders. Curly braces are normally used in switch to form multiple statements into a compound statement.

So if I can express my try and finally/except blocks without the need for me to provide curly braces, there will be no need for me to supply a close-brace.

An examples of brace-less switch statement:
http://stackoverflow.com/questions/8118009/is-there-a-useful-case-using-a-switch-statement-without-braces


switch (x)
    default:
    if (prime(x))
        case 2: case 3: case 5: case 7:
            process_prime(x);
    else
        case 4: case 6: case 8: case 9: case 10:
            process_composite(x);

and blessed day, as Johan Bezem shows further on that page, it allows you to start part-way through a loop, avoiding the continuation test on entry - that is useful!

uint8_t counter;
/* counter will get its value here somewhere */
switch (counter)
    default:
        while (0 < counter)
        {
            case 0:
                /* Perform action */
                counter--;
        }

Also, some people prefer switch(0) default: ... instead of do { ... } while(0) but Jens prefers if (1) { ... } else (void(0))

Try Again

So I repeat my switch based attempt, the parts in bold are provided by the macros:


for(jmp_buf active_jmp_buf; ...; ...)
  switch ((errno=setjmp(active_jmp_buf))) 
  if (0) {
  case 0: // first time around
       {
         ...
         ... throw(123);
         ...
       }
  break; } else default: // break not needed for finally
       {
         ...
       } 

Note that the if/else is bogus, merely a trick to hold two statements without using curly braces to denote a compound statement; although I took care to make it if (0) in order to get legitimate fall-through from the try branch into the finally branch.

I need to finish the for loop so that it only loops once, and perhaps include an extra single-case switch statement within each branch so that misplaced break directives will not affect our exception handling switch statement.

I also wonder if I can have multiple catch clauses like the C# except clauses or if I embed those within a single except clause with an explicit switch statement based on errno.



No comments:

Post a Comment