#!/usr/cogent/bin/gamma

/*
 * This example demonstrates the error handling mechanisms available in
 * Gamma.  There are two basic means of trapping and handling errors.
 *
 * 1) 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.
 * 2) 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.
 *
 * This file is best viewed with a tab width of 4.
 */

/*
 * 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 should never happen.\n");
