#!/usr/cogent/bin/gamma

/*
 * This example uses the error handling mechanisms from example 4 do
 * demonstrate dynamic scoping.  Most compiled languages use lexical
 * scoping, which means that a variable is defined only where it is
 * visibly declared, either as an external global, file global, or
 * local variable.  Gamma uses dynamic scoping, meaning that a variable
 * is defined in any function which defines it, and in any function which
 * the defining function subsequently calls.  This powerful mechanism
 * allows the programmer to override global variables by defining them
 * in a higher scope, and then calling a function which believes itself
 * to be using a global variable.
 *
 * One useful side_effect of dynamic scoping is that functions and
 * variables do not have to be declared before they are used in other
 * functions.  The function or variable only has to be declared when
 * the other function is actually run.
 *
 * 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)
{
	try
	{
		sign (x);
	}
	catch
	{
		princ ("Oops: ", _last_error_, "\n");
	}
}

/*
 * Create a function which locally declares the variable 'zero', and
 * then calls the checkit function.  Since 'zero' is a local variable,
 * the local value will override the current global definition, which
 * is undefined.
 */

function zero_check (x)
{
	local		zero = 0;
	checkit (x);
}

/*
 * Create a function which sets zero to -10, and calls the checkit
 * function.
 */

function minus_ten_check (x)
{
	local		zero = -10;
	checkit (x);
}

/*
 * Attempt to call the checkit function with zero not defined.
 */

princ ("With 'zero' undefined...\n");
checkit (-5);

/*
 * Now let zero be defined and try again.
 */

princ ("\nWith 'zero' locally defined to 0...\n");
zero_check (-5);

/*
 * Now run with zero defined as -10
 */

princ ("\nWith 'zero' locally defined to -10...\n");
minus_ten_check (-5);

/*
 * Finally, try running checkit again from the global scope.  Note that
 * zero is undefined once again.
 */

princ ("\nOnce again from the global scope...\n");
checkit (-5);
