Chapter 6. Tutorial II

Table of Contents

6.1. Error Handling - try/catch, protect/unwind
6.2. Dynamic Scoping
6.3. Error Handling - interactive session

This tutorial includes examples related to control flow in Gamma: namely, error handling and dynamic scoping.

6.1. Error Handling - try/catch, protect/unwind

This example demonstrates the error handling mechanisms available in Gamma. There are two basic means of trapping and handling errors.

    Execute a protected block of code, and specify an error handler which is only executed if an error occurs within the protected code. If an error occurs, the error handling code is executed, and the error condition is cleared. This is the try/catch mechanism.

    Execute a protected block of code, and specify a second block of code which must be executed even if an error occurs in the first block. Normally when an error occurs, the execution stack is unwound to the nearest error handler, aborting any intervening execution immediately. If a block of code must be run, even when an error occurs, we want to unwind protect that code. After the error is dealt with, it is passed on up the stack rather than being cleared. This is the protect/unwind mechanism.

The code for the example is shown below.

#!/usr/cogent/bin/gamma

/*
 * Create a function which has an error in it.
 * The symbol zero is not defined.
 */

function sign (x)
{
    if (x < zero)
        princ ("Negative\n");
    else
        princ ("Positive\n");
}

/*
 * Create a function which checks the sign of a number,
 * but ensures that an error will not terminate the program.
 */

function checkit (x)
{
    princ ("\nEntering a TRY, CATCH block...\n");
    try
    {
        sign (x);
    }
    catch
    {
        princ ("Oops: ", _last_error_, "\n");
    }
}

/*
 * Create a function which checks the sign of a number,
 * and which will print a status message whether or not an error
 * occurs, before passing a possible error condition up the stack.
 * The 'princ' statement in this case will always be run, even if
 * an error occurs.
 */

function unwindit (x)
{
    princ ("\nEntering a PROTECT, UNWIND block...\n");
    protect
    {
        sign (x);
    }
    unwind
    {
        princ ("Finished checking the sign\n");
    }
}

/*
 * Attempt to call this function, but if we get an error,
 * simply print the error message and continue.
 */

checkit (-5);

/*
 * Run the same code, but with zero defined
 */

zero = 0;
checkit (-5);

/*
 * Run the unwind protected function.  This should print its unwind
 * message.
 */

unwindit (-5);

/*
 * Make 'zero' undefined again so that the error will occur.  Now we
 * run a function which is unwind protected.  This function will not
 * return since it passes the error up to the global error handler,
 * which causes the program to exit.
 */

zero = _undefined_;
unwindit (-5);

princ ("This message should never be printed\n");